From f86662005e373ce1b0fd546af495f12bbe74ad0b Mon Sep 17 00:00:00 2001 From: "Sergey Semyonov (Serge)" Date: Mon, 17 Oct 2011 12:16:37 +0000 Subject: [PATCH] acpinfo git-svn-id: svn://kolibrios.org@2293 a494cfbc-eb01-0410-851d-a64ba20cac60 --- drivers/devman/acpinfo/Makefile | 50 +++++++ drivers/devman/acpinfo/_utils.c | 50 +++++++ drivers/devman/acpinfo/acpi.c | 164 ++++++++++++++++++++ drivers/devman/acpinfo/acpi.h | 250 +++++++++++++++++++++++++++++++ drivers/devman/acpinfo/acpi.lds | 56 +++++++ drivers/devman/acpinfo/main.c | 71 +++++++++ drivers/devman/acpinfo/types.h | 0 drivers/devman/acpinfo/utils.asm | 79 ++++++++++ 8 files changed, 720 insertions(+) create mode 100644 drivers/devman/acpinfo/Makefile create mode 100644 drivers/devman/acpinfo/_utils.c create mode 100644 drivers/devman/acpinfo/acpi.c create mode 100644 drivers/devman/acpinfo/acpi.h create mode 100644 drivers/devman/acpinfo/acpi.lds create mode 100644 drivers/devman/acpinfo/main.c create mode 100644 drivers/devman/acpinfo/types.h create mode 100644 drivers/devman/acpinfo/utils.asm diff --git a/drivers/devman/acpinfo/Makefile b/drivers/devman/acpinfo/Makefile new file mode 100644 index 0000000000..acd9d0fe22 --- /dev/null +++ b/drivers/devman/acpinfo/Makefile @@ -0,0 +1,50 @@ + + +CC = gcc +FASM = e:/fasm/fasm.exe + +CFLAGS = -c -O2 -fomit-frame-pointer -fno-builtin-printf + + +DRV_DIR = $(CURDIR)/../.. + +DRV_INCLUDES = $(DRV_DIR)/include + +INCLUDES = -I$(DRV_INCLUDES) -I$(DRV_DIR)/include/linux + +DEFINES = -D__KERNEL__ -DCONFIG_X86_32 + +LDFLAGS = -nostdlib -shared -s -Map acpi.map --image-base 0\ + --file-alignment 512 --section-alignment 4096 + +LIBPATH:= -L$(DRV_DIR)/ddk + +LIBS:= -lgcc -lddk -lcore + + +NAME= acpi + +NAME_SRCS= main.c \ + acpi.c \ + utils.asm + + +all: $(NAME).dll + +NAME_OBJS = $(patsubst %.S, %.o, $(patsubst %.asm, %.o,\ + $(patsubst %.c, %.o, $(NAME_SRCS)))) + + +$(NAME).dll: $(NAME_OBJS) acpi.lds Makefile + ld $(LIBPATH) $(LDFLAGS) -T acpi.lds -o $@ $(NAME_OBJS) $(LIBS) + +%.o : %.c $(HFILES) Makefile + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ $< + +%.o : %.S $(HFILES) Makefile + as -o $@ $< + +%.o : %.asm $(HFILES) Makefile + fasm $< $@ + + diff --git a/drivers/devman/acpinfo/_utils.c b/drivers/devman/acpinfo/_utils.c new file mode 100644 index 0000000000..00c4375f8f --- /dev/null +++ b/drivers/devman/acpinfo/_utils.c @@ -0,0 +1,50 @@ +#include +#include +#include "acpi.h" + +extern acpi_rsdp_t* acpi_rsdp; +extern acpi_rsdt_t* acpi_rsdt; + +addr_t acpi_ioapic; +addr_t acpi_local_apic; + +u8_t __fastcall acpi_table_checksum(u32_t length, u8_t *buffer); + +acpi_rsdp_t* acpi_locate() +{ + /** @todo checksum, check version */ + addr_t p; + + for (p = ACPI_HI_RSDP_WINDOW_START; p < ACPI_HI_RSDP_WINDOW_END; p+=16) + { + acpi_rsdp_t* r = (acpi_rsdp_t*) p; + if ((r->sig[0] == 0x20445352) && + (r->sig[1] == 0x20525450) && + acpi_table_checksum(ACPI_RSDP_CHECKSUM_LENGTH, (u8_t*)r)==0 ) + { + return r; + }; + }; + /* not found */ + return NULL; +}; + +addr_t __fastcall rsdt_find(acpi_rsdt_t *rsdt, u32_t sig) +{ + addr_t head = 0; + u32_t i; + + for (i = 0; i < ((rsdt->header.len-sizeof(acpi_thead_t))/ + sizeof(rsdt->ptrs[0])); i++) + { + acpi_thead_t* t= (acpi_thead_t*)acpi_remap_table(rsdt->ptrs[i]); + + if (t->sig == sig) + { + head = rsdt->ptrs[i]; + break; + }; + } + return head; +}; + diff --git a/drivers/devman/acpinfo/acpi.c b/drivers/devman/acpinfo/acpi.c new file mode 100644 index 0000000000..92ceb1ae7c --- /dev/null +++ b/drivers/devman/acpinfo/acpi.c @@ -0,0 +1,164 @@ +#include +#include +#include "acpi.h" + +extern acpi_rsdp_t* acpi_rsdp; +extern acpi_rsdt_t* acpi_rsdt; + +addr_t acpi_ioapic; +addr_t acpi_local_apic; + +u8_t __fastcall acpi_table_checksum(u32_t length, u8_t *buffer); + +u8_t __fastcall acpi_table_checksum(u32_t length, u8_t *buffer) +{ + u8_t sum = 0; + u8_t *end = buffer + length; + + while (buffer < end) + { + sum = (u8_t)(sum + *(buffer++)); + } + + return sum; +}; + +void* acpi_remap_table(addr_t table) +{ + addr_t ptr; + + if( (table >= acpi_rsdp->rsdt_ptr)&& + (table < acpi_rsdp->rsdt_ptr+0x10000)) + ptr = (table - acpi_rsdp->rsdt_ptr+(addr_t)acpi_rsdt); + return (void*)ptr; +}; + + +void print_rsdt(acpi_rsdt_t *rsdt) +{ + u32_t i; + dbgprintf("ACPI RSD Table\n"); + for (i = 0; i < ((rsdt->header.len-sizeof(acpi_thead_t))/ + sizeof(rsdt->ptrs[0])); i++) + { + acpi_thead_t* t = (acpi_thead_t*)acpi_remap_table(rsdt->ptrs[i]); + char *p = (char*)&t->sig; + dbgprintf("sig %d: %c%c%c%c base %x\n", i, + p[0],p[1],p[2],p[3], t); + }; +}; + + +void print_madt (acpi_madt_t * madt) +{ + u32_t i; + + acpi_local_apic = madt->local_apic_addr; + + dbgprintf ("Local APIC at 0x%x\n\n", acpi_local_apic); + + for (i = 0; i < (madt->header.len - sizeof (acpi_madt_t));) + { + acpi_madt_hdr_t * h = (acpi_madt_hdr_t*) &madt->data[i]; + switch (h->type) + { + case 0: + { + // Local APIC + acpi_madt_lapic_t * lapic = (acpi_madt_lapic_t *) h; + dbgprintf ("Local APIC "); + dbgprintf ("[Id: 0x%x, CPU Id: 0x%x, %s]\n", + lapic->id, lapic->apic_processor_id, + lapic->flags.enabled ? "enabled" : "disabled"); + break; + } + case 1: + { + // I/O Apic + acpi_madt_ioapic_t * ioapic = (acpi_madt_ioapic_t *) h; + + acpi_ioapic = ioapic->address; + + dbgprintf ("I/O APIC "); + dbgprintf ("[Id: 0x%x, IRQ base: %d, Addr: 0x%x]\n", + ioapic->id, ioapic->irq_base, acpi_ioapic); + break; + } + case 2: + { + // Interrupt Source Override + acpi_madt_irq_t * irq = (acpi_madt_irq_t *) h; + polarity_t p = irq_get_polarity(irq); + trigger_mode_t t = irq_get_trigger_mode(irq); + + dbgprintf ("Interrupt Override "); + dbgprintf ("[%s, Bus IRQ: %d, Glob IRQ: %d, Pol: %s, Trigger: %s]\n", + irq->src_bus == 0 ? "ISA" : "unknown bus", + irq->src_irq, irq->dest, + p == conform_polarity ? "conform" : + p == active_high ? "active high" : + p == active_low ? "active low" : "?", + t == conform_trigger ? "conform" : + t == edge ? "edge" : + t == level ? "level" : "?"); + break; + } + case 3: + { + // NMI Source + + acpi_madt_nmi_t * nmi = (acpi_madt_nmi_t *) h; + polarity_t p = nmi_get_polarity(nmi); + trigger_mode_t t = nmi_get_trigger_mode(nmi); + dbgprintf ("NMI Source "); + dbgprintf ("[Glob IRQ: %d, Pol: %s, Trigger: %s]\n", + nmi->irq, + p == conform_polarity ? "conform" : + p == active_high ? "active high" : + p == active_low ? "active low" : "?", + t == conform_trigger ? "conform" : + t == edge ? "edge" : + t == level ? "level" : "?"); + + break; + } + case 4: + { + // Local APIC NMI + acpi_lapic_nmi_t *nmi = (acpi_lapic_nmi_t *) h; + + polarity_t p = lapic_nmi_get_polarity(nmi); + trigger_mode_t t = lapic_nmi_get_trigger_mode(nmi); + + dbgprintf ("Local APIC NMI\n"); + + dbgprintf ("[CPU id: %d, LINT#: %d Pol: %s, Trigger: %s]\n", + nmi->apic_processor_id, + nmi->lint, + p == conform_polarity ? "conform" : + p == active_high ? "active high" : + p == active_low ? "active low" : "?", + t == conform_trigger ? "conform" : + t == edge ? "edge" : + t == level ? "level" : "?"); + break; + } + case 5: + { + // Local APIC Address Override + dbgprintf ("Local APIC Address Override\n"); + break; + } + case 8: + { + // Platform Interrupt Source + dbgprintf ("Platform Interrupt Source\n"); + break; + } + } + + i += h->len; + } +}; + + diff --git a/drivers/devman/acpinfo/acpi.h b/drivers/devman/acpinfo/acpi.h new file mode 100644 index 0000000000..3f213ca377 --- /dev/null +++ b/drivers/devman/acpinfo/acpi.h @@ -0,0 +1,250 @@ + +#define ACPI_NAME_SIZE 4 +#define ACPI_OEM_ID_SIZE 6 +#define ACPI_OEM_TABLE_ID_SIZE 8 + +typedef struct __attribute__((packed)) +{ + u8_t type; + u8_t len; +}acpi_madt_hdr_t; + +typedef struct __attribute__((packed)) +{ + acpi_madt_hdr_t header; + + u8_t apic_processor_id; + u8_t id; + struct { + u32_t enabled : 1; + u32_t : 31; + } flags; +}acpi_madt_lapic_t; + +typedef struct __attribute__((packed)) +{ + acpi_madt_hdr_t header; + + u8_t id; /* APIC id */ + u8_t _rsvd_3; + + u32_t address; /* physical address */ + u32_t irq_base; /* global irq number base */ +}acpi_madt_ioapic_t; + +typedef enum { + conform_polarity = 0, + active_high = 1, + reserved_polarity = 2, + active_low = 3 +}polarity_t ; + +typedef enum { + conform_trigger = 0, + edge = 1, + reserved_trigger = 2, + level = 3 +}trigger_mode_t; + +typedef struct __attribute__((packed)) +{ + acpi_madt_hdr_t header; + + u8_t src_bus; /* source bus, fixed 0=ISA */ + u8_t src_irq; /* source bus irq */ + u32_t dest; /* global irq number */ + union { + u16_t flags; /* irq flags */ + struct { + u16_t polarity : 2; + u16_t trigger_mode : 2; + u16_t reserved : 12; + } x; + }; +}acpi_madt_irq_t; + +static inline polarity_t irq_get_polarity(acpi_madt_irq_t *irq) +{ return (polarity_t) irq->x.polarity; } + +static inline trigger_mode_t irq_get_trigger_mode(acpi_madt_irq_t *irq) +{ return (trigger_mode_t) irq->x.trigger_mode; } + + +typedef struct __attribute__((packed)) +{ + acpi_madt_hdr_t header; + + union { + u16_t flags; + struct { + u16_t polarity : 2; + u16_t trigger_mode : 2; + u16_t reserved : 12; + } x; + }; + u32_t irq; + +}acpi_madt_nmi_t; + +static inline polarity_t nmi_get_polarity(acpi_madt_nmi_t *nmi) +{ return (polarity_t) nmi->x.polarity; } + +static inline trigger_mode_t nmi_get_trigger_mode(acpi_madt_nmi_t *nmi) +{ return (trigger_mode_t) nmi->x.trigger_mode; } + +typedef struct __attribute__((packed)) +{ + acpi_madt_hdr_t header; + + u8_t apic_processor_id; + + union { + u16_t flags; + struct { + u16_t polarity : 2; + u16_t trigger_mode : 2; + u16_t reserved : 12; + } x; + }; + u8_t lint; + +}acpi_lapic_nmi_t; + +static inline polarity_t lapic_nmi_get_polarity(acpi_lapic_nmi_t *nmi) +{ return (polarity_t) nmi->x.polarity; } + +static inline trigger_mode_t lapic_nmi_get_trigger_mode(acpi_lapic_nmi_t *nmi) +{ return (trigger_mode_t) nmi->x.trigger_mode; } + + +typedef struct __attribute__((packed)) +{ + u32_t sig; + u32_t len; + u8_t rev; + u8_t csum; + char oem_id[ACPI_OEM_ID_SIZE]; + char oem_tid[ACPI_OEM_TABLE_ID_SIZE]; + u32_t oem_rev; + u32_t creator_id; + u32_t creator_rev; +}acpi_thead_t; + + +typedef struct __attribute__((packed)) +{ + acpi_thead_t header; + u32_t local_apic_addr; + u32_t apic_flags; + u8_t data[0]; +} acpi_madt_t; + +typedef struct __attribute__((packed)) +{ + acpi_thead_t header; + u32_t ptrs[0]; +}acpi_rsdt_t; + +typedef struct __attribute__((packed)) +{ + acpi_thead_t header; + u64_t ptrs[0]; +}acpi_xsdt_t; + +typedef struct +{ + u32_t sig[2]; + u8_t csum; + char oemid[6]; + u8_t rev; + u32_t rsdt_ptr; + u32_t rsdt_len; + u64_t xsdt_ptr; + u8_t xcsum; + u8_t _rsvd_33[3]; +}acpi_rsdp_t; + +typedef struct __attribute__((packed)) +{ + u8_t SpaceId; /* Address space where struct or register exists */ + u8_t BitWidth; /* Size in bits of given register */ + u8_t BitOffset; /* Bit offset within the register */ + u8_t AccessWidth; /* Minimum Access size (ACPI 3.0) */ + u64_t Address; /* 64-bit address of struct or register */ + +} acpi_address_t; + +typedef struct __attribute__((packed)) +{ + acpi_thead_t Header; /* Common ACPI table header */ + u32_t Facs; /* 32-bit physical address of FACS */ + u32_t Dsdt; /* 32-bit physical address of DSDT */ + u8_t Model; /* System Interrupt Model (ACPI 1.0) - not used in ACPI 2.0+ */ + u8_t PreferredProfile; /* Conveys preferred power management profile to OSPM. */ + u16_t SciInterrupt; /* System vector of SCI interrupt */ + u32_t SmiCommand; /* 32-bit Port address of SMI command port */ + u8_t AcpiEnable; /* Value to write to smi_cmd to enable ACPI */ + u8_t AcpiDisable; /* Value to write to smi_cmd to disable ACPI */ + u8_t S4BiosRequest; /* Value to write to SMI CMD to enter S4BIOS state */ + u8_t PstateControl; /* Processor performance state control*/ + u32_t Pm1aEventBlock; /* 32-bit Port address of Power Mgt 1a Event Reg Blk */ + u32_t Pm1bEventBlock; /* 32-bit Port address of Power Mgt 1b Event Reg Blk */ + u32_t Pm1aControlBlock; /* 32-bit Port address of Power Mgt 1a Control Reg Blk */ + u32_t Pm1bControlBlock; /* 32-bit Port address of Power Mgt 1b Control Reg Blk */ + u32_t Pm2ControlBlock; /* 32-bit Port address of Power Mgt 2 Control Reg Blk */ + u32_t PmTimerBlock; /* 32-bit Port address of Power Mgt Timer Ctrl Reg Blk */ + u32_t Gpe0Block; /* 32-bit Port address of General Purpose Event 0 Reg Blk */ + u32_t Gpe1Block; /* 32-bit Port address of General Purpose Event 1 Reg Blk */ + u8_t Pm1EventLength; /* Byte Length of ports at Pm1xEventBlock */ + u8_t Pm1ControlLength; /* Byte Length of ports at Pm1xControlBlock */ + u8_t Pm2ControlLength; /* Byte Length of ports at Pm2ControlBlock */ + u8_t PmTimerLength; /* Byte Length of ports at PmTimerBlock */ + u8_t Gpe0BlockLength; /* Byte Length of ports at Gpe0Block */ + u8_t Gpe1BlockLength; /* Byte Length of ports at Gpe1Block */ + u8_t Gpe1Base; /* Offset in GPE number space where GPE1 events start */ + u8_t CstControl; /* Support for the _CST object and C States change notification */ + u16_t C2Latency; /* Worst case HW latency to enter/exit C2 state */ + u16_t C3Latency; /* Worst case HW latency to enter/exit C3 state */ + u16_t FlushSize; /* Processor's memory cache line width, in bytes */ + u16_t FlushStride; /* Number of flush strides that need to be read */ + u8_t DutyOffset; /* Processor duty cycle index in processor's P_CNT reg*/ + u8_t DutyWidth; /* Processor duty cycle value bit width in P_CNT register.*/ + u8_t DayAlarm; /* Index to day-of-month alarm in RTC CMOS RAM */ + u8_t MonthAlarm; /* Index to month-of-year alarm in RTC CMOS RAM */ + u8_t Century; /* Index to century in RTC CMOS RAM */ + u16_t BootFlags; /* IA-PC Boot Architecture Flags. See Table 5-10 for description */ + u8_t Reserved; /* Reserved, must be zero */ + u32_t Flags; /* Miscellaneous flag bits (see below for individual flags) */ + acpi_address_t ResetRegister; /* 64-bit address of the Reset register */ + u8_t ResetValue; /* Value to write to the ResetRegister port to reset the system */ + u8_t Reserved4[3]; /* Reserved, must be zero */ + u64_t XFacs; /* 64-bit physical address of FACS */ + u64_t XDsdt; /* 64-bit physical address of DSDT */ + acpi_address_t XPm1aEventBlock; /* 64-bit Extended Power Mgt 1a Event Reg Blk address */ + acpi_address_t XPm1bEventBlock; /* 64-bit Extended Power Mgt 1b Event Reg Blk address */ + acpi_address_t XPm1aControlBlock; /* 64-bit Extended Power Mgt 1a Control Reg Blk address */ + acpi_address_t XPm1bControlBlock; /* 64-bit Extended Power Mgt 1b Control Reg Blk address */ + acpi_address_t XPm2ControlBlock; /* 64-bit Extended Power Mgt 2 Control Reg Blk address */ + acpi_address_t XPmTimerBlock; /* 64-bit Extended Power Mgt Timer Ctrl Reg Blk address */ + acpi_address_t XGpe0Block; /* 64-bit Extended General Purpose Event 0 Reg Blk address */ + acpi_address_t XGpe1Block; /* 64-bit Extended General Purpose Event 1 Reg Blk address */ +} acpi_fadt_t; + + +#define OS_BASE 0x80000000 + +#define ACPI_HI_RSDP_WINDOW_START (OS_BASE+0x000E0000) +#define ACPI_HI_RSDP_WINDOW_END (OS_BASE+0x00100000) +#define ACPI_RSDP_CHECKSUM_LENGTH 20 +#define ACPI_RSDP_XCHECKSUM_LENGTH 36 + +#define ACPI_MADT_SIGN 0x43495041 + +#define addr_offset(addr, off) \ + (addr_t)((addr_t)(addr) + (addr_t)(off)) + +#define ACPI_ADDR(x) \ + (addr_t)((addr_t)(x)+OS_BASE) + +#define acpi_remap(x) (x) + diff --git a/drivers/devman/acpinfo/acpi.lds b/drivers/devman/acpinfo/acpi.lds new file mode 100644 index 0000000000..8bb43eefae --- /dev/null +++ b/drivers/devman/acpinfo/acpi.lds @@ -0,0 +1,56 @@ + + +OUTPUT_FORMAT(pei-i386) + +ENTRY("_drvEntry") + +SECTIONS +{ + . = SIZEOF_HEADERS; + . = ALIGN(__section_alignment__); + + .text __image_base__ + ( __section_alignment__ < 0x1000 ? . : __section_alignment__ ) : + + { + *(.text) *(.rdata) + } + + .data ALIGN(__section_alignment__) : + { + *(.data) + } + + .bss ALIGN(__section_alignment__): + { + *(.bss) + *(COMMON) + } + + /DISCARD/ : + { + *(.debug$S) + *(.debug$T) + *(.debug$F) + *(.drectve) + *(.edata) + } + + .idata ALIGN(__section_alignment__): + { + SORT(*)(.idata$2) + SORT(*)(.idata$3) + /* These zeroes mark the end of the import list. */ + LONG (0); LONG (0); LONG (0); LONG (0); LONG (0); + SORT(*)(.idata$4) + SORT(*)(.idata$5) + SORT(*)(.idata$6) + SORT(*)(.idata$7) + } + + .reloc ALIGN(__section_alignment__) : + { + *(.reloc) + } + +} + diff --git a/drivers/devman/acpinfo/main.c b/drivers/devman/acpinfo/main.c new file mode 100644 index 0000000000..9f52a04b55 --- /dev/null +++ b/drivers/devman/acpinfo/main.c @@ -0,0 +1,71 @@ + +#include +#include +#include "acpi.h" + +acpi_rsdp_t* acpi_locate(); + +acpi_rsdp_t* acpi_rsdp; +acpi_rsdt_t* acpi_rsdt; +acpi_madt_t* acpi_madt; + +addr_t acpi_rsdt_base; +addr_t acpi_madt_base; +addr_t acpi_lapic_base; +addr_t acpi_ioapic_base; + +addr_t __fastcall rsdt_find(acpi_rsdt_t *rsdt, u32_t sig); + +u32_t drvEntry(int action, char *cmdline) +{ + u32_t ret; + + if(action != 1) + return 0; + + if( !dbg_open("/rd/1/drivers/acpi.log") ) + { + printf("Can't open /rd/1/drivers/acpi.log\nExit\n"); + return 0; + } + + acpi_rsdp = acpi_locate(); + + if (unlikely(acpi_rsdp == NULL)) + { + dbgprintf("No ACPI RSD table\n"); + return 0; + }; + + dbgprintf("rsd base address %x\n", acpi_rsdp); + + acpi_rsdt_base = acpi_rsdp->rsdt_ptr; + acpi_rsdt = (acpi_rsdt_t*)(MapIoMem(acpi_rsdt_base,0x10000,5)); + + dbgprintf("rsdt base 0x%x, kernel 0x%x\n", acpi_rsdt_base, acpi_rsdt); + + if (unlikely(acpi_rsdt == NULL)) + { + dbgprintf("Invalid ACPI RSD table\n"); + return 0; + }; + +// print_rsdt(acpi_rsdt); + + acpi_madt_base = rsdt_find(acpi_rsdt, ACPI_MADT_SIGN); + + if( unlikely(acpi_madt_base == 0) ) + { + dbgprintf("No ACPI MAD Table\n"); + return 0; + }; + + acpi_madt =(acpi_madt_t*)acpi_remap_table(acpi_madt_base); + + dbgprintf("madt base 0x%x, kernel 0x%x\n", acpi_madt_base, acpi_madt); + +// print_madt(acpi_madt); + + return 0; +}; + diff --git a/drivers/devman/acpinfo/types.h b/drivers/devman/acpinfo/types.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/drivers/devman/acpinfo/utils.asm b/drivers/devman/acpinfo/utils.asm new file mode 100644 index 0000000000..e381ef9315 --- /dev/null +++ b/drivers/devman/acpinfo/utils.asm @@ -0,0 +1,79 @@ +format MS COFF + +extrn _acpi_rsdt_base + +public _acpi_locate +public @rsdt_find@8 + +OS_BASE equ 0x80000000 + +ACPI_HI_RSDP_WINDOW_START equ (OS_BASE+0x000E0000) +ACPI_HI_RSDP_WINDOW_END equ (OS_BASE+0x00100000) +ACPI_RSDP_CHECKSUM_LENGTH equ 20 + +section '.text' code readable executable align 16 + + +_acpi_locate: + push ebx + mov ebx, ACPI_HI_RSDP_WINDOW_START +.check: + cmp [ebx], dword 0x20445352 + jne .next + cmp [ebx+4], dword 0x20525450 + jne .next + + mov edx, ebx + mov ecx, ACPI_RSDP_CHECKSUM_LENGTH + xor eax, eax +.sum: + add al, [edx] + inc edx + loop .sum + + test al, al + jnz .next + + mov eax, ebx + pop ebx + ret +.next: + add ebx, 16 + cmp ebx, ACPI_HI_RSDP_WINDOW_END + jb .check + + pop ebx + xor eax, eax + ret + +align 4 +@rsdt_find@8: ;ecx= rsdt edx= SIG + push ebx + push esi + + lea ebx, [ecx+36] + mov esi, [ecx+4] + add esi, ecx +.next: + mov eax, [ebx] + sub eax, [_acpi_rsdt_base] + add eax, ecx + + cmp [eax], edx + je .done + + add ebx, 4 + cmp ebx, esi + jb .next + + xor eax, eax + pop esi + pop ebx + ret + +.done: + mov eax, [ebx] + pop esi + pop ebx + ret +