Name of user not set #1002476 has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/35365 )
Change subject: emulation/qemu-i440fx: use fw_cfg_dma for fw_cfg_read ......................................................................
emulation/qemu-i440fx: use fw_cfg_dma for fw_cfg_read
- configure DMA fw_cfg - add support to read using fw_cfg_dma - provide fw config version id info in logs
Change-Id: I0be5355b124af40aba62c0840790d46ed0fe80a2 Signed-off-by: Himanshu Sahdev himanshusah@hcl.com --- M src/mainboard/emulation/qemu-i440fx/fw_cfg.c M src/mainboard/emulation/qemu-i440fx/fw_cfg_if.h 2 files changed, 69 insertions(+), 3 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/65/35365/1
diff --git a/src/mainboard/emulation/qemu-i440fx/fw_cfg.c b/src/mainboard/emulation/qemu-i440fx/fw_cfg.c index 3acb11e..330c6c0 100644 --- a/src/mainboard/emulation/qemu-i440fx/fw_cfg.c +++ b/src/mainboard/emulation/qemu-i440fx/fw_cfg.c @@ -24,13 +24,18 @@
#define FW_CFG_PORT_CTL 0x0510 #define FW_CFG_PORT_DATA 0x0511 +#define FW_CFG_DMA_ADDR_HIGH 0x0514 +#define FW_CFG_DMA_ADDR_LOW 0x0518
static int fw_cfg_detected; +static uint8_t fw_ver; + +static void fw_cfg_dma(int control, void *buf, int len);
static int fw_cfg_present(void) { static const char qsig[] = "QEMU"; - unsigned char sig[4]; + unsigned char sig[FW_CFG_SIG_SIZE]; int detected = 0;
if (fw_cfg_detected == 0) { @@ -38,6 +43,10 @@ detected = memcmp(sig, qsig, 4) == 0; printk(BIOS_INFO, "QEMU: firmware config interface %s\n", detected ? "detected" : "not found"); + if (detected) { + fw_cfg_get(FW_CFG_ID, &fw_ver, sizeof(fw_ver)); + printk(BIOS_INFO, "Firmware config version id: %d\n", fw_ver); + } fw_cfg_detected = detected + 1; } return fw_cfg_detected - 1; @@ -50,7 +59,10 @@
static void fw_cfg_read(void *dst, int dstlen) { - insb(FW_CFG_PORT_DATA, dst, dstlen); + if (fw_ver & FW_CFG_VERSION_DMA) + fw_cfg_dma(FW_CFG_DMA_CTL_READ, dst, dstlen); + else + insb(FW_CFG_PORT_DATA, dst, dstlen); }
void fw_cfg_get(uint16_t entry, void *dst, int dstlen) @@ -500,3 +512,22 @@ fw_cfg_smbios_init(); memcpy(uuid, type1_uuid, 16); } + +/* + * Configure DMA setup + */ + +static void fw_cfg_dma(int control, void *buf, int len) +{ + volatile FwCfgDmaAccess dma; + uint32_t dma_desc_addr; + + dma.control = be32_to_cpu(control); + dma.length = be32_to_cpu(len); + dma.address = be64_to_cpu((uintptr_t)buf); + + dma_desc_addr = (uint32_t)&dma; + outl(be32_to_cpu(dma_desc_addr), FW_CFG_DMA_ADDR_LOW); + while (be32_to_cpu(dma.control) & ~FW_CFG_DMA_CTL_ERROR) + asm(""); +} diff --git a/src/mainboard/emulation/qemu-i440fx/fw_cfg_if.h b/src/mainboard/emulation/qemu-i440fx/fw_cfg_if.h index 46aee9b3d..3590943 100644 --- a/src/mainboard/emulation/qemu-i440fx/fw_cfg_if.h +++ b/src/mainboard/emulation/qemu-i440fx/fw_cfg_if.h @@ -64,11 +64,24 @@
#define FW_CFG_INVALID 0xffff
+/* width in bytes of fw_cfg control register */ +#define FW_CFG_CTL_SIZE 0x02 + +/* fw_cfg "file name" is up to 56 characters (including terminating nul) */ +#define FW_CFG_MAX_FILE_PATH 56 + +/* size in bytes of fw_cfg signature */ +#define FW_CFG_SIG_SIZE 4 + +/* FW_CFG_ID bits */ +#define FW_CFG_VERSION 0x01 +#define FW_CFG_VERSION_DMA 0x02 + typedef struct FWCfgFile { uint32_t size; /* file size */ uint16_t select; /* write this to 0x510 to read it */ uint16_t reserved; - char name[56]; + char name[FW_CFG_MAX_FILE_PATH]; } FWCfgFile;
typedef struct FWCfgFiles { @@ -93,4 +106,26 @@ uint16_t fieldoffset; } FwCfgSmbios;
+/* FW_CFG_ID bits */ +#define FW_CFG_VERSION 0x01 +#define FW_CFG_VERSION_DMA 0x02 + +/* FW_CFG_DMA_CONTROL bits */ +#define FW_CFG_DMA_CTL_ERROR 0x01 +#define FW_CFG_DMA_CTL_READ 0x02 +#define FW_CFG_DMA_CTL_SKIP 0x04 +#define FW_CFG_DMA_CTL_SELECT 0x08 +#define FW_CFG_DMA_CTL_WRITE 0x10 + +#define FW_CFG_DMA_SIGNATURE 0x51454d5520434647ULL /* "QEMU CFG" */ + +/* Control as first field allows for different structures selected by this + * field, which might be useful in the future + */ +typedef struct FwCfgDmaAccess { + uint32_t control; + uint32_t length; + uint64_t address; +} FwCfgDmaAccess; + #endif /* FW_CFG_IF_H */