soc/amd/common/psp_smi_flash: implement SPI read/write/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 Reviewed-on: https://review.coreboot.org/c/coreboot/+/83777 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Martin Roth <martin.roth@amd.corp-partner.google.com>
This commit is contained in:
@@ -85,6 +85,25 @@ static void set_psp_spi_info(struct mbox_pspv2_cmd_spi_info *cmd_buf,
|
|||||||
write64(&cmd_buf->req.num_blocks, num_blocks);
|
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)
|
static const char *id_to_region_name(u64 target_nv_id)
|
||||||
{
|
{
|
||||||
switch (target_nv_id) {
|
switch (target_nv_id) {
|
||||||
@@ -197,37 +216,127 @@ enum mbox_p2c_status psp_smi_spi_read(struct mbox_default_buffer *buffer)
|
|||||||
{
|
{
|
||||||
struct mbox_pspv2_cmd_spi_read_write *const cmd_buf =
|
struct mbox_pspv2_cmd_spi_read_write *const cmd_buf =
|
||||||
(struct mbox_pspv2_cmd_spi_read_write *)buffer;
|
(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");
|
printk(BIOS_SPEW, "PSP: SPI read request\n");
|
||||||
|
|
||||||
if (!is_valid_psp_spi_read_write(cmd_buf))
|
if (!is_valid_psp_spi_read_write(cmd_buf))
|
||||||
return MBOX_PSP_COMMAND_PROCESS_ERROR;
|
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)
|
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 *const cmd_buf =
|
||||||
(struct mbox_pspv2_cmd_spi_read_write *)buffer;
|
(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");
|
printk(BIOS_SPEW, "PSP: SPI write request\n");
|
||||||
|
|
||||||
if (!is_valid_psp_spi_read_write(cmd_buf))
|
if (!is_valid_psp_spi_read_write(cmd_buf))
|
||||||
return MBOX_PSP_COMMAND_PROCESS_ERROR;
|
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)
|
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 *const cmd_buf =
|
||||||
(struct mbox_pspv2_cmd_spi_erase *)buffer;
|
(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");
|
printk(BIOS_SPEW, "PSP: SPI erase request\n");
|
||||||
|
|
||||||
if (!is_valid_psp_spi_erase(cmd_buf))
|
if (!is_valid_psp_spi_erase(cmd_buf))
|
||||||
return MBOX_PSP_COMMAND_PROCESS_ERROR;
|
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;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user