ditto
This commit is contained in:
parent
50f5723733
commit
2fe554dffd
196
kernel/rsdp.c
Normal file
196
kernel/rsdp.c
Normal file
|
@ -0,0 +1,196 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "memory.c"
|
||||
#include "vga.c"
|
||||
|
||||
struct rsdp_t {
|
||||
char signature[8];
|
||||
uint8_t checksum;
|
||||
char oem_id[6];
|
||||
uint8_t revision;
|
||||
uint32_t rsdt_address;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct xsdp_t {
|
||||
char signature[8];
|
||||
uint8_t checksum;
|
||||
char oem_id[6];
|
||||
uint8_t revision;
|
||||
uint32_t unused;
|
||||
uint32_t length;
|
||||
uint32_t xsdt_addr_hi;
|
||||
uint32_t xsdt_addr_lo;
|
||||
uint8_t checksum_ext;
|
||||
uint8_t unused_[3]
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct acpi_header_t {
|
||||
char signature[4];
|
||||
uint32_t length;
|
||||
uint8_t revision;
|
||||
uint8_t checksum;
|
||||
char oem_id[6];
|
||||
char oem_table_id[8];
|
||||
uint32_t oem_revision;
|
||||
uint32_t creator_id;
|
||||
uint32_t creator_division;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct GenericAddressStructure
|
||||
{
|
||||
uint8_t AddressSpace;
|
||||
uint8_t BitWidth;
|
||||
uint8_t BitOffset;
|
||||
uint8_t AccessSize;
|
||||
uint64_t Address;
|
||||
};
|
||||
|
||||
struct fadt_t
|
||||
{
|
||||
struct acpi_header_t header;
|
||||
uint32_t firmware_ctl;
|
||||
uint32_t dsdt_ptr;
|
||||
|
||||
uint8_t reserved;
|
||||
|
||||
uint8_t PreferredPowerManagementProfile;
|
||||
uint16_t SCI_Interrupt;
|
||||
uint32_t SMI_CommandPort;
|
||||
uint8_t AcpiEnable;
|
||||
uint8_t AcpiDisable;
|
||||
uint8_t S4BIOS_REQ;
|
||||
uint8_t PSTATE_Control;
|
||||
uint32_t PM1aEventBlock;
|
||||
uint32_t PM1bEventBlock;
|
||||
uint32_t PM1aControlBlock;
|
||||
uint32_t PM1bControlBlock;
|
||||
uint32_t PM2ControlBlock;
|
||||
uint32_t PMTimerBlock;
|
||||
uint32_t GPE0Block;
|
||||
uint32_t GPE1Block;
|
||||
uint8_t PM1EventLength;
|
||||
uint8_t PM1ControlLength;
|
||||
uint8_t PM2ControlLength;
|
||||
uint8_t PMTimerLength;
|
||||
uint8_t GPE0Length;
|
||||
uint8_t GPE1Length;
|
||||
uint8_t GPE1Base;
|
||||
uint8_t CStateControl;
|
||||
uint16_t WorstC2Latency;
|
||||
uint16_t WorstC3Latency;
|
||||
uint16_t FlushSize;
|
||||
uint16_t FlushStride;
|
||||
uint8_t DutyOffset;
|
||||
uint8_t DutyWidth;
|
||||
uint8_t DayAlarm;
|
||||
uint8_t MonthAlarm;
|
||||
uint8_t Century;
|
||||
|
||||
// reserved in ACPI 1.0; used since ACPI 2.0+
|
||||
uint16_t BootArchitectureFlags;
|
||||
|
||||
uint8_t Reserved2;
|
||||
uint32_t Flags;
|
||||
|
||||
// 12 byte structure; see below for details
|
||||
struct GenericAddressStructure ResetReg;
|
||||
|
||||
uint8_t ResetValue;
|
||||
uint8_t Reserved3[3];
|
||||
|
||||
// 64bit pointers - Available on ACPI 2.0+
|
||||
uint64_t X_FirmwareControl;
|
||||
uint64_t X_Dsdt;
|
||||
|
||||
struct GenericAddressStructure X_PM1aEventBlock;
|
||||
struct GenericAddressStructure X_PM1bEventBlock;
|
||||
struct GenericAddressStructure X_PM1aControlBlock;
|
||||
struct GenericAddressStructure X_PM1bControlBlock;
|
||||
struct GenericAddressStructure X_PM2ControlBlock;
|
||||
struct GenericAddressStructure X_PMTimerBlock;
|
||||
struct GenericAddressStructure X_GPE0Block;
|
||||
struct GenericAddressStructure X_GPE1Block;
|
||||
};
|
||||
|
||||
struct rsdt_t {
|
||||
struct acpi_header_t header;
|
||||
uint32_t pointer[64];
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
uint8_t validate(struct rsdp_t *ptr) {
|
||||
char sig[] = "RSD PTR ";
|
||||
if (!memseq(ptr->signature, sig, 8)) return 0;
|
||||
|
||||
uint8_t *rsdp_bytes = (uint8_t *) ptr;
|
||||
uint8_t sum = 0;
|
||||
for(uint8_t i = 0; i < 20; i++) {
|
||||
sum += rsdp_bytes[i];
|
||||
}
|
||||
|
||||
if (sum == 0 && ptr->revision == 2) {
|
||||
printf_nolock("ACPI v2+ not yet supported :(\n");
|
||||
for(;;){}
|
||||
// TODO: test with ACPI 2 System
|
||||
struct xsdp_t *r2_ptr = (struct xsdp_t*) ptr;
|
||||
|
||||
uint8_t *xsdp_bytes = ((uint8_t *) r2_ptr) + 8;
|
||||
uint8_t x_sum = 0;
|
||||
for(uint8_t i = 0; i < 16; i++) {
|
||||
sum += xsdp_bytes[i];
|
||||
}
|
||||
}
|
||||
|
||||
return sum == 0;
|
||||
}
|
||||
|
||||
char* find_table(struct rsdt_t* table, char* sig) {
|
||||
uint32_t entries = (table->header.length - sizeof table->header) / 4;
|
||||
for (uint32_t i = 0; i < entries; i++) {
|
||||
struct acpi_header_t* entry = (struct acpi_header_t*) table->pointer[i];
|
||||
if (memseq(entry->signature, sig, 4)) {
|
||||
printf_nolock("Found %s / %s\n", entry->oem_id, entry->signature);
|
||||
printf_nolock("Signature: %s\n", entry->signature);
|
||||
printf_nolock("Length : %d\n", entry->length);
|
||||
printf_nolock("Oem ID : %s\n", entry->oem_id);
|
||||
printf_nolock("Checksum : %d\n", entry->checksum);
|
||||
return (void*)entry;
|
||||
}
|
||||
}
|
||||
|
||||
printf_nolock("Not Found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void find_rsdp() {
|
||||
struct rsdp_t *ptr;
|
||||
|
||||
volatile uint8_t found = 0;
|
||||
for (uint32_t addr = 0x00000000; addr <= 0x000FFFFF; addr++) {
|
||||
ptr = (struct rsdp_t *) addr;
|
||||
|
||||
if (validate(ptr)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
uint8_t* ebda = (uint8_t*)(*((uint16_t*)0x40e) << 4);
|
||||
for (uint32_t i = 0; i <= 1024; i += 16) {
|
||||
ptr = (struct rsdp_t*) ebda;
|
||||
if (validate(ptr)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf_nolock("RSDP Found %s / %s / %d\n", ptr->oem_id, ptr->signature);
|
||||
|
||||
struct fadt_t* fadt = (struct fadt_t*) find_table((struct rsdt_t*) ptr->rsdt_address, "FACP");
|
||||
|
||||
facp.
|
||||
}
|
Loading…
Reference in a new issue