Attention is currently required from: Fred Reitberger, Jason Glenesk, Matt DeVillier, ritul guru.
Hello ritul guru,
I'd like you to do a code review. Please visit
https://review.coreboot.org/c/coreboot/+/83777?usp=email
to review the following change.
Change subject: soc/amd/common/psp_smi_flash: implement SPI read/wrire/erase command ......................................................................
soc/amd/common/psp_smi_flash: implement SPI read/wrire/erase command
Use coreboot's SPI flash access infrastructure to do the flash read, write, or erase operations as requested from the PSP.
This patch is a modified version of parts of CB:65523.
Document #55758 Rev. 2.04 was used as a reference.
Test=When selecting SOC_AMD_COMMON_BLOCK_PSP_SMI, Mandolin still builds
Signed-off-by: Felix Held felix-coreboot@felixheld.de Signed-off-by: Ritul Guru ritul.bits@gmail.com Change-Id: I4957a6d316015cc7037acf52facb6cc69188d446 --- M src/soc/amd/common/block/psp/psp_smi_flash.c 1 file changed, 112 insertions(+), 3 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/77/83777/1
diff --git a/src/soc/amd/common/block/psp/psp_smi_flash.c b/src/soc/amd/common/block/psp/psp_smi_flash.c index 420fb94..2d075ef 100644 --- a/src/soc/amd/common/block/psp/psp_smi_flash.c +++ b/src/soc/amd/common/block/psp/psp_smi_flash.c @@ -85,6 +85,25 @@ write64(&cmd_buf->req.num_blocks, num_blocks); }
+static void get_psp_spi_read_write(struct mbox_pspv2_cmd_spi_read_write *cmd_buf, + u64 *target_nv_id, u64 *lba, u64 *offset, + u64 *num_bytes, u8 **data) +{ + *target_nv_id = read64(&cmd_buf->req.target_nv_id); + *lba = read64(&cmd_buf->req.lba); + *offset = read64(&cmd_buf->req.offset); + *num_bytes = read64(&cmd_buf->req.num_bytes); + *data = cmd_buf->req.buffer; +} + +static void get_psp_spi_erase(struct mbox_pspv2_cmd_spi_erase *cmd_buf, + u64 *target_nv_id, u64 *lba, u64 *num_blocks) +{ + *target_nv_id = read64(&cmd_buf->req.target_nv_id); + *lba = read64(&cmd_buf->req.lba); + *num_blocks = read64(&cmd_buf->req.num_blocks); +} + static const char *id_to_region_name(u64 target_nv_id) { switch (target_nv_id) { @@ -197,37 +216,127 @@ { struct mbox_pspv2_cmd_spi_read_write *const cmd_buf = (struct mbox_pspv2_cmd_spi_read_write *)buffer; + enum mbox_p2c_status ret; + u64 target_nv_id; + u64 lba; + u64 offset; + u64 num_bytes; + u8 *data; + size_t addr; + const struct spi_flash *flash; + struct region_device store;
printk(BIOS_SPEW, "PSP: SPI read request\n");
if (!is_valid_psp_spi_read_write(cmd_buf)) return MBOX_PSP_COMMAND_PROCESS_ERROR;
- return MBOX_PSP_UNSUPPORTED; + if (!spi_controller_available()) { + printk(BIOS_NOTICE, "PSP: SPI controller busy\n"); + return MBOX_PSP_SPI_BUSY; + } + + get_psp_spi_read_write(cmd_buf, &target_nv_id, &lba, &offset, &num_bytes, &data); + + ret = find_psp_spi_flash_device_region(target_nv_id, &store, &flash); + + if (ret != MBOX_PSP_SUCCESS) + return ret; + + addr = (lba * flash->sector_size) + offset; + + printk(BIOS_SPEW, "PSP: SPI read 0x%llx bytes at 0x%zx\n", num_bytes, addr); + + if (rdev_readat(&store, data, addr, (size_t)num_bytes) != (size_t)num_bytes) { + printk(BIOS_ERR, "PSP: Failed to read NVRAM data\n"); + return MBOX_PSP_COMMAND_PROCESS_ERROR; + } + + return MBOX_PSP_SUCCESS; }
enum mbox_p2c_status psp_smi_spi_write(struct mbox_default_buffer *buffer) { struct mbox_pspv2_cmd_spi_read_write *const cmd_buf = (struct mbox_pspv2_cmd_spi_read_write *)buffer; + enum mbox_p2c_status ret; + u64 target_nv_id; + u64 lba; + u64 offset; + u64 num_bytes; + u8 *data; + size_t addr; + const struct spi_flash *flash; + struct region_device store;
printk(BIOS_SPEW, "PSP: SPI write request\n");
if (!is_valid_psp_spi_read_write(cmd_buf)) return MBOX_PSP_COMMAND_PROCESS_ERROR;
- return MBOX_PSP_UNSUPPORTED; + if (!spi_controller_available()) { + printk(BIOS_NOTICE, "PSP: SPI controller busy\n"); + return MBOX_PSP_SPI_BUSY; + } + + get_psp_spi_read_write(cmd_buf, &target_nv_id, &lba, &offset, &num_bytes, &data); + + ret = find_psp_spi_flash_device_region(target_nv_id, &store, &flash); + + if (ret != MBOX_PSP_SUCCESS) + return ret; + + addr = (lba * flash->sector_size) + offset; + + printk(BIOS_SPEW, "PSP: SPI write 0x%llx bytes at 0x%zx\n", num_bytes, addr); + + if (rdev_writeat(&store, data, addr, (size_t)num_bytes) != (size_t)num_bytes) { + printk(BIOS_ERR, "PSP: Failed to write NVRAM data\n"); + return MBOX_PSP_COMMAND_PROCESS_ERROR; + } + + return MBOX_PSP_SUCCESS; }
enum mbox_p2c_status psp_smi_spi_erase(struct mbox_default_buffer *buffer) { struct mbox_pspv2_cmd_spi_erase *const cmd_buf = (struct mbox_pspv2_cmd_spi_erase *)buffer; + enum mbox_p2c_status ret; + u64 target_nv_id; + u64 lba; + u64 num_blocks; + size_t addr; + size_t num_bytes; + const struct spi_flash *flash; + struct region_device store;
printk(BIOS_SPEW, "PSP: SPI erase request\n");
if (!is_valid_psp_spi_erase(cmd_buf)) return MBOX_PSP_COMMAND_PROCESS_ERROR;
- return MBOX_PSP_UNSUPPORTED; + if (!spi_controller_available()) { + printk(BIOS_NOTICE, "PSP: SPI controller busy\n"); + return MBOX_PSP_SPI_BUSY; + } + + get_psp_spi_erase(cmd_buf, &target_nv_id, &lba, &num_blocks); + + ret = find_psp_spi_flash_device_region(target_nv_id, &store, &flash); + + if (ret != MBOX_PSP_SUCCESS) + return ret; + + addr = lba * flash->sector_size; + num_bytes = (size_t)num_blocks * flash->sector_size; + + printk(BIOS_SPEW, "PSP: SPI erase 0x%zx bytes at 0x%zx\n", num_bytes, addr); + + if (rdev_eraseat(&store, addr, num_bytes) != num_bytes) { + printk(BIOS_ERR, "PSP: Failed to erase SPI NVRAM data\n"); + return MBOX_PSP_COMMAND_PROCESS_ERROR; + } + + return MBOX_PSP_SUCCESS; }