1 // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2 /* Copyright 2020 IBM Corp. */
3 #include <skiboot.h>
4 #include "secboot_tpm.h"
5
6 /* Offset into the SECBOOT PNOR partition to write "TPMNV" data */
7 static size_t fakenv_offset = sizeof(struct secboot);
8
9 struct fake_tpmnv {
10 struct {
11 struct secboot_header header;
12 char vars[2048]; // Hardcode the size to 2048 for now
13 } vars;
14 struct tpmnv_control control;
15 int defined[2];
16 } __attribute__((packed));
17
18 static struct fake_tpmnv fakenv;
19 static int tpm_ready;
20
21
nv_index_address(int index)22 static inline void *nv_index_address(int index)
23 {
24 switch (index) {
25 case SECBOOT_TPMNV_VARS_INDEX:
26 return &fakenv.vars;
27 case SECBOOT_TPMNV_CONTROL_INDEX:
28 return &fakenv.control;
29 default:
30 return 0;
31 }
32 }
33
34
tpm_init(void)35 static int tpm_init(void)
36 {
37 int rc;
38
39 if (tpm_ready)
40 return 0;
41
42 rc = flash_secboot_read(&fakenv, fakenv_offset, sizeof(struct fake_tpmnv));
43 if (rc)
44 return rc;
45
46 tpm_ready = 1;
47
48 return 0;
49 }
50
fakenv_read(TPMI_RH_NV_INDEX nvIndex,void * buf,size_t bufsize,uint16_t off)51 static int fakenv_read(TPMI_RH_NV_INDEX nvIndex, void *buf,
52 size_t bufsize, uint16_t off)
53 {
54 if (tpm_init())
55 return OPAL_INTERNAL_ERROR;
56
57 memcpy(buf, nv_index_address(nvIndex) + off, bufsize);
58
59 return 0;
60 }
61
fakenv_write(TPMI_RH_NV_INDEX nvIndex,void * buf,size_t bufsize,uint16_t off)62 static int fakenv_write(TPMI_RH_NV_INDEX nvIndex, void *buf,
63 size_t bufsize, uint16_t off)
64 {
65 if (tpm_init())
66 return OPAL_INTERNAL_ERROR;
67
68 memcpy(nv_index_address(nvIndex) + off, buf, bufsize);
69
70 /* Just write the whole NV struct for now */
71 return flash_secboot_write(fakenv_offset, &fakenv, sizeof(struct fake_tpmnv));
72 }
73
fakenv_definespace(TPMI_RH_NV_INDEX nvIndex,uint16_t dataSize)74 static int fakenv_definespace(TPMI_RH_NV_INDEX nvIndex, uint16_t dataSize)
75 {
76 if (tpm_init())
77 return OPAL_INTERNAL_ERROR;
78
79 (void) dataSize;
80
81 switch (nvIndex) {
82 case SECBOOT_TPMNV_VARS_INDEX:
83 fakenv.defined[0] = 1;
84 return 0;
85 case SECBOOT_TPMNV_CONTROL_INDEX:
86 fakenv.defined[1] = 1;
87 return 0;
88 }
89
90 return OPAL_INTERNAL_ERROR;
91 }
92
fakenv_writelock(TPMI_RH_NV_INDEX nvIndex)93 static int fakenv_writelock(TPMI_RH_NV_INDEX nvIndex)
94 {
95 if (tpm_init())
96 return OPAL_INTERNAL_ERROR;
97
98 (void) nvIndex;
99
100 return 0;
101 }
102
fakenv_get_defined_indices(TPMI_RH_NV_INDEX ** indices,size_t * count)103 static int fakenv_get_defined_indices(TPMI_RH_NV_INDEX **indices, size_t *count)
104 {
105 if (tpm_init())
106 return OPAL_INTERNAL_ERROR;
107
108 *indices = zalloc(sizeof(fakenv.defined));
109 if (*indices == NULL)
110 return OPAL_NO_MEM;
111
112 *count = 0;
113
114 if (fakenv.defined[0]) {
115 *indices[0] = SECBOOT_TPMNV_VARS_INDEX;
116 (*count)++;
117 }
118 if (fakenv.defined[1]) {
119 *indices[1] = SECBOOT_TPMNV_CONTROL_INDEX;
120 (*count)++;
121 }
122
123 return 0;
124 }
125
fakenv_undefinespace(TPMI_RH_NV_INDEX index)126 static int fakenv_undefinespace(TPMI_RH_NV_INDEX index)
127 {
128 if (tpm_init())
129 return OPAL_INTERNAL_ERROR;
130
131 switch (index) {
132 case SECBOOT_TPMNV_VARS_INDEX:
133 fakenv.defined[0] = 0;
134 memset(&fakenv.vars, 0, sizeof(fakenv.vars));
135 return 0;
136 case SECBOOT_TPMNV_CONTROL_INDEX:
137 fakenv.defined[1] = 0;
138 memset(&fakenv.control, 0, sizeof(fakenv.control));
139 return 0;
140 }
141
142 return -1;
143 }
144
fakenv_readpublic(TPMI_RH_NV_INDEX index,TPMS_NV_PUBLIC * nv_public,TPM2B_NAME * nv_name)145 static int fakenv_readpublic(TPMI_RH_NV_INDEX index, TPMS_NV_PUBLIC *nv_public,
146 TPM2B_NAME *nv_name)
147 {
148 if (tpm_init())
149 return OPAL_INTERNAL_ERROR;
150
151 (void) nv_public;
152
153 switch (index) {
154 case SECBOOT_TPMNV_VARS_INDEX:
155 memcpy(&nv_name->t.name, tpmnv_vars_name, sizeof(TPM2B_NAME));
156 break;
157 case SECBOOT_TPMNV_CONTROL_INDEX:
158 memcpy(&nv_name->t.name, tpmnv_control_name, sizeof(TPM2B_NAME));
159 break;
160 default:
161 return OPAL_INTERNAL_ERROR;
162 }
163
164 return 0;
165 }
166
167 struct tpmnv_ops_s tpmnv_ops = {
168 .read = fakenv_read,
169 .write = fakenv_write,
170 .writelock = fakenv_writelock,
171 .definespace = fakenv_definespace,
172 .getindices = fakenv_get_defined_indices,
173 .undefinespace = fakenv_undefinespace,
174 .readpublic = fakenv_readpublic,
175 };
176