xref: /aosp_15_r20/external/coreboot/src/soc/amd/phoenix/psp_verstage/chipset.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include "2api.h"
4 #include <arch/hlt.h>
5 #include <bl_uapp/bl_errorcodes_public.h>
6 #include <bl_uapp/bl_syscall_public.h>
7 #include <boot_device.h>
8 #include <cbfs.h>
9 #include <console/console.h>
10 #include <psp_verstage.h>
11 #include <security/vboot/misc.h>
12 #include <security/vboot/vbnv.h>
13 
14 #define PSP_FW_HASH_FILE_NAME(slot, id) "apu/amdfw_" slot "_hash" id
15 /*
16  * We can't pass pointer to hash table in the SPI.
17  * The AMD PSP team specifically required that whole hash table
18  * should be copied into memory before passing them to the PSP
19  * to reduce window of TOCTOU.
20  */
21 #define MAX_NUM_HASH_ENTRIES 64
22 static struct psp_fw_hash_table hash_table;
23 static struct psp_fw_entry_hash_256 hash_256[MAX_NUM_HASH_ENTRIES];
24 static struct psp_fw_entry_hash_384 hash_384[MAX_NUM_HASH_ENTRIES];
25 
26 static struct psp_fw_hash_table_v2 hash_table_v2;
27 static struct psp_fw_entry_hash_256_v2 hash_256_v2[MAX_NUM_HASH_ENTRIES];
28 static struct psp_fw_entry_hash_384_v2 hash_384_v2[MAX_NUM_HASH_ENTRIES];
29 
update_one_psp_fw_hash_table_v1(enum verstage_cmd_id cmd,uint8_t * spi_ptr)30 static void update_one_psp_fw_hash_table_v1(enum verstage_cmd_id cmd, uint8_t *spi_ptr)
31 {
32 	uint32_t len;
33 
34 	memcpy(&hash_table, spi_ptr, offsetof(struct psp_fw_hash_table, fw_hash_256));
35 
36 	if (hash_table.no_of_entries_256 > MAX_NUM_HASH_ENTRIES ||
37 			hash_table.no_of_entries_384 > MAX_NUM_HASH_ENTRIES) {
38 		printk(BIOS_ERR, "Too many entries in AMD Firmware hash table"
39 				 " (SHA256:%d, SHA384:%d)\n", hash_table.no_of_entries_256,
40 				 hash_table.no_of_entries_384);
41 		return;
42 	}
43 
44 	if (hash_table.no_of_entries_256 == 0 && hash_table.no_of_entries_384 == 0) {
45 		printk(BIOS_ERR, "No entries in AMD Firmware hash table"
46 				 " (SHA256:%d, SHA384:%d)\n", hash_table.no_of_entries_256,
47 				 hash_table.no_of_entries_384);
48 		return;
49 	}
50 
51 	spi_ptr += offsetof(struct psp_fw_hash_table, fw_hash_256);
52 
53 	hash_table.fw_hash_256 = hash_256;
54 	hash_table.fw_hash_384 = hash_384;
55 	len = sizeof(struct psp_fw_entry_hash_256) * hash_table.no_of_entries_256;
56 	memcpy(hash_256, spi_ptr, len);
57 
58 	spi_ptr += len;
59 	len = sizeof(struct psp_fw_entry_hash_384) * hash_table.no_of_entries_384;
60 	memcpy(hash_384, spi_ptr, len);
61 
62 	svc_set_fw_hash_table(cmd, &hash_table);
63 }
64 
update_one_psp_fw_hash_table_v2(enum verstage_cmd_id cmd,uint8_t * spi_ptr)65 static void update_one_psp_fw_hash_table_v2(enum verstage_cmd_id cmd, uint8_t *spi_ptr)
66 {
67 	uint32_t len;
68 
69 	memcpy(&hash_table_v2, spi_ptr, offsetof(struct psp_fw_hash_table_v2, fw_hash_256));
70 
71 	if (hash_table_v2.no_of_entries_256 > MAX_NUM_HASH_ENTRIES ||
72 			hash_table_v2.no_of_entries_384 > MAX_NUM_HASH_ENTRIES) {
73 		printk(BIOS_ERR, "Too many entries in AMD Firmware hash table"
74 				 " (SHA256:%d, SHA384:%d)\n", hash_table_v2.no_of_entries_256,
75 				 hash_table_v2.no_of_entries_384);
76 		return;
77 	}
78 
79 	if (hash_table_v2.no_of_entries_256 == 0 && hash_table_v2.no_of_entries_384 == 0) {
80 		printk(BIOS_ERR, "No entries in AMD Firmware hash table"
81 				 " (SHA256:%d, SHA384:%d)\n", hash_table_v2.no_of_entries_256,
82 				 hash_table_v2.no_of_entries_384);
83 		return;
84 	}
85 
86 	spi_ptr += offsetof(struct psp_fw_hash_table_v2, fw_hash_256);
87 
88 	hash_table_v2.fw_hash_256 = hash_256_v2;
89 	hash_table_v2.fw_hash_384 = hash_384_v2;
90 	len = sizeof(struct psp_fw_entry_hash_256_v2) * hash_table_v2.no_of_entries_256;
91 	memcpy(hash_256_v2, spi_ptr, len);
92 
93 	spi_ptr += len;
94 	len = sizeof(struct psp_fw_entry_hash_384_v2) * hash_table_v2.no_of_entries_384;
95 	memcpy(hash_384_v2, spi_ptr, len);
96 
97 	svc_set_fw_hash_table(cmd, &hash_table_v2);
98 }
99 
update_one_psp_fw_hash_table(enum verstage_cmd_id cmd,const char * fname)100 static void update_one_psp_fw_hash_table(enum verstage_cmd_id cmd, const char *fname)
101 {
102 	void *hash_file = cbfs_map(fname, NULL);
103 	uint16_t version;
104 
105 	if (!hash_file) {
106 		printk(BIOS_ERR, "AMD Firmware hash table %s not found\n", fname);
107 		/*
108 		 * If we don't supply hash table, the PSP will refuse to boot.
109 		 * So returning here is safe to do.
110 		 */
111 		return;
112 	}
113 
114 	memcpy(&version, hash_file, sizeof(version));
115 	assert(version <= 2);
116 	switch (version) {
117 	case 1:
118 		update_one_psp_fw_hash_table_v1(cmd, hash_file);
119 		break;
120 	case 2:
121 		update_one_psp_fw_hash_table_v2(cmd, hash_file);
122 		break;
123 	default:
124 		printk(BIOS_ERR, "%s: Unexpected version %d\n", __func__, version);
125 	}
126 	cbfs_unmap(hash_file);
127 	rdev_munmap(boot_device_ro(), hash_file);
128 }
129 
update_psp_fw_hash_tables(void)130 void update_psp_fw_hash_tables(void)
131 {
132 	struct vb2_context *ctx = vboot_get_context();
133 
134 	if (vboot_is_firmware_slot_a(ctx)) {
135 		update_one_psp_fw_hash_table(CMD_SET_FW_HASH_TABLE_STAGE1,
136 					     PSP_FW_HASH_FILE_NAME("a", ""));
137 		update_one_psp_fw_hash_table(CMD_SET_FW_HASH_TABLE_STAGE2,
138 					     PSP_FW_HASH_FILE_NAME("a", "1"));
139 		update_one_psp_fw_hash_table(CMD_SET_FW_HASH_TABLE_TOS,
140 					     PSP_FW_HASH_FILE_NAME("a", "2"));
141 	} else {
142 		update_one_psp_fw_hash_table(CMD_SET_FW_HASH_TABLE_STAGE1,
143 					     PSP_FW_HASH_FILE_NAME("b", ""));
144 		update_one_psp_fw_hash_table(CMD_SET_FW_HASH_TABLE_STAGE2,
145 					     PSP_FW_HASH_FILE_NAME("b", "1"));
146 		update_one_psp_fw_hash_table(CMD_SET_FW_HASH_TABLE_TOS,
147 					     PSP_FW_HASH_FILE_NAME("b", "2"));
148 	}
149 }
150 
update_psp_bios_dir(uint32_t * psp_dir_offset,uint32_t * bios_dir_offset)151 uint32_t update_psp_bios_dir(uint32_t *psp_dir_offset, uint32_t *bios_dir_offset)
152 {
153 	return svc_update_psp_bios_dir(psp_dir_offset, bios_dir_offset);
154 }
155 
save_uapp_data(void * address,uint32_t size)156 uint32_t save_uapp_data(void *address, uint32_t size)
157 {
158 	return svc_save_uapp_data(address, size);
159 }
160 
get_bios_dir_addr(struct embedded_firmware * ef_table)161 uint32_t get_bios_dir_addr(struct embedded_firmware *ef_table)
162 {
163 	return 0;
164 }
165 
platform_set_sha_op(enum vb2_hash_algorithm hash_alg,struct sha_generic_data * sha_op)166 int platform_set_sha_op(enum vb2_hash_algorithm hash_alg,
167 			struct sha_generic_data *sha_op)
168 {
169 	if (hash_alg == VB2_HASH_SHA256) {
170 		sha_op->SHAType = SHA_TYPE_256;
171 		sha_op->DigestLen = 32;
172 	} else if (hash_alg == VB2_HASH_SHA384) {
173 		sha_op->SHAType = SHA_TYPE_384;
174 		sha_op->DigestLen = 48;
175 	} else {
176 		return -1;
177 	}
178 	return 0;
179 }
180 
platform_report_mode(int developer_mode_enabled)181 void platform_report_mode(int developer_mode_enabled)
182 {
183 	printk(BIOS_INFO, "Reporting %s mode\n",
184 	       developer_mode_enabled ? "Developer" : "Normal");
185 	if (developer_mode_enabled)
186 		svc_set_platform_boot_mode(CHROME_BOOK_BOOT_MODE_DEVELOPER);
187 	else
188 		svc_set_platform_boot_mode(CHROME_BOOK_BOOT_MODE_NORMAL);
189 }
190 
report_prev_boot_status_to_vboot(void)191 void report_prev_boot_status_to_vboot(void)
192 {
193 	uint32_t boot_status = 0;
194 	int ret;
195 	struct vb2_context *ctx = vboot_get_context();
196 
197 	/* Already in recovery mode. No need to report previous boot status. */
198 	if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE)
199 		return;
200 
201 	ret = svc_get_prev_boot_status(&boot_status);
202 	if (ret != BL_OK || boot_status) {
203 		printk(BIOS_ERR, "PSPFW failure in previous boot: %d:%#8x\n", ret, boot_status);
204 		vbnv_init();
205 		vb2api_previous_boot_fail(ctx, VB2_RECOVERY_FW_VENDOR_BLOB,
206 					  boot_status ? (int)boot_status : ret);
207 	}
208 }
209 
report_hsp_secure_state(void)210 void report_hsp_secure_state(void)
211 {
212 	uint32_t hsp_secure_state;
213 	int ret;
214 
215 	ret = svc_get_hsp_secure_state(&hsp_secure_state);
216 	if (ret != BL_OK) {
217 		printk(BIOS_ERR, "Error reading HSP Secure state: %d\n", ret);
218 		hlt();
219 	}
220 
221 	printk(BIOS_INFO, "HSP Secure state: %#8x\n", hsp_secure_state);
222 }
223