@@ -73,6 +73,8 @@ asm(
#define BIOS_CFG_DMA_CTL_SKIP 0x04
#define BIOS_CFG_DMA_CTL_SELECT 0x08
+#define BIOS_CFG_CTL 0x510
+#define BIOS_CFG_DATA 0x511
#define BIOS_CFG_DMA_ADDR_HIGH 0x514
#define BIOS_CFG_DMA_ADDR_LOW 0x518
@@ -87,6 +89,16 @@ typedef struct FWCfgDmaAccess {
uint64_t address;
} __attribute__((packed)) FWCfgDmaAccess;
+static inline void outw(uint16_t value, uint16_t port) {
+ asm("outw %w0, %w1" : : "a"(value), "Nd"(port));
+}
+
+static inline uint32_t inl(uint16_t port) {
+ uint32_t value;
+ __asm__ __volatile__("inl %w1, %0" : "=a"(value) : "Nd"(port));
+ return value;
+}
+
static inline void outl(uint32_t value, uint16_t port) {
asm("outl %0, %w1" : : "a"(value), "Nd"(port));
}
@@ -124,6 +136,15 @@ static inline uint32_t be32_to_cpu(uint32_t x) {
static void bios_cfg_read_entry(void *buf, uint16_t entry, uint32_t len)
{
+ if (inl(BIOS_CFG_DMA_ADDR_LOW) != 0x47464320) {
+ // Legacy PIO fw_cfg
+ outw(entry, BIOS_CFG_CTL);
+ asm volatile("movw %w0, %%es" :: "r"(0) : "memory");
+ asm volatile("rep insb (%%dx), %%es:(%%edi)"
+ : "+c"(len), "+D"(buf) : "d"(BIOS_CFG_DATA) : "memory");
+ return;
+ }
+
FWCfgDmaAccess access;
uint32_t control = (entry << 16) | BIOS_CFG_DMA_CTL_SELECT
| BIOS_CFG_DMA_CTL_READ;