aboutsummaryrefslogtreecommitdiffstats
path: root/roms/qboot/code32seg.c
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
commitaf1a266670d040d2f4083ff309d732d648afba2a (patch)
tree2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/qboot/code32seg.c
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/qboot/code32seg.c')
-rw-r--r--roms/qboot/code32seg.c75
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 */
+}