diff options
author | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
---|---|---|
committer | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/qboot/code32seg.c | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/qboot/code32seg.c')
-rw-r--r-- | roms/qboot/code32seg.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/roms/qboot/code32seg.c b/roms/qboot/code32seg.c new file mode 100644 index 000000000..e829c0332 --- /dev/null +++ b/roms/qboot/code32seg.c @@ -0,0 +1,75 @@ +#include <stddef.h> +#include "bios.h" +#include "pci.h" +#include "processor-flags.h" + +#define PCI_FUNC_NOT_SUPPORTED 0x81 +#define PCI_BAD_VENDOR_ID 0x83 +#define PCI_DEVICE_NOT_FOUND 0x86 +#define PCI_BUFFER_TOO_SMALL 0x89 + +/* + * The PCIBIOS handler must be position independent. To read a flat pointer, + * we use the instruction pointer to retrieve the address corresponding to + * physical address 0 (i.e., what Linux calls PAGE_OFFSET). + */ + +static inline void *from_flat_ptr(void *p) +{ + return p + pic_base(); +} + +#define FLAT_VAR(x) (*(typeof(&(x))) from_flat_ptr(&(x))) + +#pragma GCC optimize("no-jump-tables") + +bioscall void pcibios_handler(struct bios32regs *args) +{ + switch (args->eax) { + /* discovery */ + case 0xb101: + args->eax = 0x01; + args->ebx = 0x210; + args->ecx = FLAT_VAR(max_bus); + args->edx = 0x20494350; + goto success; + + /* config space access */ + case 0xb108: + args->ecx = pci_config_readb(args->ebx, args->edi); + goto success; + case 0xb109: + args->ecx = pci_config_readw(args->ebx, args->edi); + goto success; + case 0xb10a: + args->ecx = pci_config_readl(args->ebx, args->edi); + goto success; + case 0xb10b: + pci_config_writeb(args->ebx, args->edi, args->ecx); + goto success; + case 0xb10c: + pci_config_writew(args->ebx, args->edi, args->ecx); + goto success; + case 0xb10d: + pci_config_writel(args->ebx, args->edi, args->ecx); + goto success; + + /* find device id, find class code */ + case 0xb102: + case 0xb103: + args->eax &= ~0xff00; + args->eax |= PCI_DEVICE_NOT_FOUND << 8; + break; + + default: + args->eax &= ~0xff00; + args->eax |= PCI_FUNC_NOT_SUPPORTED << 8; + break; + } + args->eflags |= X86_EFLAGS_CF; + return; + +success: + /* On entry, CF=0 */ + args->eax &= ~0xff00; /* clear ah */ +} |