mirror of
https://github.com/limine-bootloader/limine
synced 2024-12-24 14:56:49 +03:00
Some work on ACPI and use EBDA start as end of usable conventional memory
This commit is contained in:
parent
a7980f3dc4
commit
a909fd821c
135
bootsect/gdt.inc
135
bootsect/gdt.inc
@ -1,85 +1,90 @@
|
||||
%define DIV_ROUNDUP(a, b) (((a) + ((b) - 1)) / (b))
|
||||
%define ALIGN_UP(x, a) (DIV_ROUNDUP((x), (a)) * (a))
|
||||
|
||||
; The GDT is copied to <start of EBDA> - gdt.size, which will also serve
|
||||
; as the upper limit for balloc()
|
||||
load_gdt:
|
||||
pusha
|
||||
push es
|
||||
push ds
|
||||
push 0x7ff0
|
||||
pop es
|
||||
mov ax, word [0x40e] ; 0x40e contains the value of a segment pointing to the EBDA
|
||||
sub ax, ALIGN_UP(gdt.size, 16) / 16
|
||||
mov es, ax
|
||||
mov word [gdt.ptr], ax
|
||||
shl dword [gdt.ptr], 4
|
||||
xor di, di
|
||||
push 0
|
||||
pop ds
|
||||
mov si, GDT.GDTStart
|
||||
mov cx, GDT.GDTEnd - GDT.GDTStart
|
||||
mov ds, di
|
||||
mov si, gdt.start
|
||||
mov cx, gdt.size
|
||||
rep movsb
|
||||
lgdt [GDT]
|
||||
pop ds
|
||||
lgdt [gdt]
|
||||
pop es
|
||||
popa
|
||||
ret
|
||||
|
||||
GDT:
|
||||
gdt:
|
||||
dw .size - 1 ; GDT size
|
||||
.ptr:
|
||||
dd 0 ; GDT start address (calculated at runtime)
|
||||
|
||||
dw .GDTEnd - .GDTStart - 1 ; GDT size
|
||||
dd 0x7ff00 ; GDT start
|
||||
.start:
|
||||
; Null descriptor (required)
|
||||
dw 0x0000 ; Limit
|
||||
dw 0x0000 ; Base (low 16 bits)
|
||||
db 0x00 ; Base (mid 8 bits)
|
||||
db 00000000b ; Access
|
||||
db 00000000b ; Granularity
|
||||
db 0x00 ; Base (high 8 bits)
|
||||
|
||||
.GDTStart:
|
||||
; 16-bit code
|
||||
dw 0xffff ; Limit
|
||||
dw 0x0000 ; Base (low 16 bits)
|
||||
db 0x00 ; Base (mid 8 bits)
|
||||
db 10011010b ; Access
|
||||
db 00000000b ; Granularity
|
||||
db 0x00 ; Base (high 8 bits)
|
||||
|
||||
; Null descriptor (required)
|
||||
; 16-bit data
|
||||
dw 0xffff ; Limit
|
||||
dw 0x0000 ; Base (low 16 bits)
|
||||
db 0x00 ; Base (mid 8 bits)
|
||||
db 10010010b ; Access
|
||||
db 00000000b ; Granularity
|
||||
db 0x00 ; Base (high 8 bits)
|
||||
|
||||
.NullDescriptor:
|
||||
; 32-bit code
|
||||
dw 0xffff ; Limit
|
||||
dw 0x0000 ; Base (low 16 bits)
|
||||
db 0x00 ; Base (mid 8 bits)
|
||||
db 10011010b ; Access
|
||||
db 11001111b ; Granularity
|
||||
db 0x00 ; Base (high 8 bits)
|
||||
|
||||
dw 0x0000 ; Limit
|
||||
dw 0x0000 ; Base (low 16 bits)
|
||||
db 0x00 ; Base (mid 8 bits)
|
||||
db 00000000b ; Access
|
||||
db 00000000b ; Granularity
|
||||
db 0x00 ; Base (high 8 bits)
|
||||
; 32-bit data
|
||||
dw 0xffff ; Limit
|
||||
dw 0x0000 ; Base (low 16 bits)
|
||||
db 0x00 ; Base (mid 8 bits)
|
||||
db 10010010b ; Access
|
||||
db 11001111b ; Granularity
|
||||
db 0x00 ; Base (high 8 bits)
|
||||
|
||||
; 16-bit code
|
||||
dw 0xffff ; Limit
|
||||
dw 0x0000 ; Base (low 16 bits)
|
||||
db 0x00 ; Base (mid 8 bits)
|
||||
db 10011010b ; Access
|
||||
db 00000000b ; Granularity
|
||||
db 0x00 ; Base (high 8 bits)
|
||||
; 64-bit code
|
||||
dw 0x0000 ; Limit
|
||||
dw 0x0000 ; Base (low 16 bits)
|
||||
db 0x00 ; Base (mid 8 bits)
|
||||
db 10011010b ; Access
|
||||
db 00100000b ; Granularity
|
||||
db 0x00 ; Base (high 8 bits)
|
||||
|
||||
; 16-bit data
|
||||
dw 0xffff ; Limit
|
||||
dw 0x0000 ; Base (low 16 bits)
|
||||
db 0x00 ; Base (mid 8 bits)
|
||||
db 10010010b ; Access
|
||||
db 00000000b ; Granularity
|
||||
db 0x00 ; Base (high 8 bits)
|
||||
; 64-bit data
|
||||
dw 0x0000 ; Limit
|
||||
dw 0x0000 ; Base (low 16 bits)
|
||||
db 0x00 ; Base (mid 8 bits)
|
||||
db 10010010b ; Access
|
||||
db 00000000b ; Granularity
|
||||
db 0x00 ; Base (high 8 bits)
|
||||
|
||||
; 32-bit code
|
||||
dw 0xFFFF ; Limit
|
||||
dw 0x0000 ; Base (low 16 bits)
|
||||
db 0x00 ; Base (mid 8 bits)
|
||||
db 10011010b ; Access
|
||||
db 11001111b ; Granularity
|
||||
db 0x00 ; Base (high 8 bits)
|
||||
.end:
|
||||
|
||||
; 32-bit data
|
||||
dw 0xFFFF ; Limit
|
||||
dw 0x0000 ; Base (low 16 bits)
|
||||
db 0x00 ; Base (mid 8 bits)
|
||||
db 10010010b ; Access
|
||||
db 11001111b ; Granularity
|
||||
db 0x00 ; Base (high 8 bits)
|
||||
|
||||
; 64 bit code
|
||||
dw 0x0000 ; Limit
|
||||
dw 0x0000 ; Base (low 16 bits)
|
||||
db 0x00 ; Base (mid 8 bits)
|
||||
db 10011010b ; Access
|
||||
db 00100000b ; Granularity
|
||||
db 0x00 ; Base (high 8 bits)
|
||||
|
||||
; 64 bit data
|
||||
dw 0x0000 ; Limit
|
||||
dw 0x0000 ; Base (low 16 bits)
|
||||
db 0x00 ; Base (mid 8 bits)
|
||||
db 10010010b ; Access
|
||||
db 00000000b ; Granularity
|
||||
db 0x00 ; Base (high 8 bits)
|
||||
|
||||
.GDTEnd:
|
||||
.size: equ .end - .start
|
||||
|
BIN
limine.bin
BIN
limine.bin
Binary file not shown.
@ -4,14 +4,24 @@
|
||||
#include <lib/libc.h>
|
||||
#include <lib/print.h>
|
||||
|
||||
void *get_rsdp(void) {
|
||||
for (size_t i = 0x80000; i < 0x100000; i += 16) {
|
||||
if (i == 0xa0000) {
|
||||
/* skip video mem and mapped hardware */
|
||||
i = 0xe0000 - 16;
|
||||
continue;
|
||||
// Following function based on https://github.com/qword-os/lai/blob/master/helpers/pc-bios.c's function lai_bios_calc_checksum()
|
||||
uint8_t acpi_checksum(void *ptr, size_t size) {
|
||||
uint8_t sum = 0, *_ptr = ptr;
|
||||
for (size_t i = 0; i < size; i++)
|
||||
sum += _ptr[i];
|
||||
return sum;
|
||||
}
|
||||
|
||||
void *acpi_get_rsdp(void) {
|
||||
size_t ebda = EBDA;
|
||||
|
||||
for (size_t i = ebda; i < 0x100000; i += 16) {
|
||||
if (i == ebda + 1024) {
|
||||
// We probed the 1st KiB of the EBDA as per spec, move onto 0xe0000
|
||||
i = 0xe0000;
|
||||
}
|
||||
if (!strncmp((char *)i, "RSD PTR ", 8)) {
|
||||
if (!memcmp((char *)i, "RSD PTR ", 8)
|
||||
&& !acpi_checksum((void *)i, sizeof(struct rsdp))) {
|
||||
print("acpi: Found RSDP at %x\n", i);
|
||||
return (void *)i;
|
||||
}
|
||||
|
@ -1,6 +1,46 @@
|
||||
#ifndef __LIB__ACPI_H__
|
||||
#define __LIB__ACPI_H__
|
||||
|
||||
void *get_rsdp(void);
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define EBDA ((size_t)(*((uint16_t *)0x40e)) * 16)
|
||||
|
||||
struct sdt {
|
||||
char signature[4];
|
||||
uint32_t length;
|
||||
uint8_t rev;
|
||||
uint8_t checksum;
|
||||
char oem_id[6];
|
||||
char oem_table_id[8];
|
||||
uint32_t oem_rev;
|
||||
uint32_t creator_id;
|
||||
uint32_t creator_rev;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct rsdp {
|
||||
char signature[8];
|
||||
uint8_t checksum;
|
||||
char oem_id[6];
|
||||
uint8_t rev;
|
||||
uint32_t rsdt_addr;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct rsdp_rev2 {
|
||||
struct rsdp rsdp;
|
||||
uint32_t length;
|
||||
uint64_t xsdt_addr;
|
||||
uint8_t ext_checksum;
|
||||
uint8_t reserved[3];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct rsdt {
|
||||
struct sdt sdt;
|
||||
char ptrs_start[];
|
||||
} __attribute__((packed));
|
||||
|
||||
uint8_t acpi_checksum(void *ptr, size_t size);
|
||||
void *acpi_get_rsdp(void);
|
||||
void *acpi_get_table(const char *signature);
|
||||
|
||||
#endif
|
||||
|
@ -48,7 +48,7 @@ __attribute__((noreturn)) void panic(const char *fmt, ...) {
|
||||
|
||||
extern symbol bss_end;
|
||||
static size_t bump_allocator_base = (size_t)bss_end;
|
||||
#define BUMP_ALLOCATOR_LIMIT ((size_t)0x7ff00)
|
||||
static size_t bump_allocator_limit = 0;
|
||||
|
||||
void brewind(size_t count) {
|
||||
bump_allocator_base -= count;
|
||||
@ -58,12 +58,21 @@ void *balloc(size_t count) {
|
||||
return balloc_aligned(count, 4);
|
||||
}
|
||||
|
||||
// Only power of 2 alignments
|
||||
void *balloc_aligned(size_t count, size_t alignment) {
|
||||
if (!bump_allocator_limit) {
|
||||
// The balloc limit is the beginning of the GDT
|
||||
struct {
|
||||
uint16_t limit;
|
||||
uint32_t ptr;
|
||||
} __attribute__((packed)) gdtr;
|
||||
asm volatile ("sgdt %0" :: "m"(gdtr));
|
||||
bump_allocator_limit = gdtr.ptr;
|
||||
}
|
||||
|
||||
size_t new_base = ALIGN_UP(bump_allocator_base, alignment);
|
||||
void *ret = (void *)new_base;
|
||||
new_base += count;
|
||||
if (new_base >= BUMP_ALLOCATOR_LIMIT)
|
||||
if (new_base >= bump_allocator_limit)
|
||||
panic("Memory allocation failed");
|
||||
bump_allocator_base = new_base;
|
||||
|
||||
|
@ -4,25 +4,6 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define ALIGN_UP(x, a) ({ \
|
||||
typeof(x) value = x; \
|
||||
typeof(a) align = a; \
|
||||
if ((value & (align - 1)) != 0) { \
|
||||
value &= ~(align - 1); \
|
||||
value += align; \
|
||||
} \
|
||||
value; \
|
||||
})
|
||||
|
||||
#define ALIGN_DOWN(x, a) ({ \
|
||||
typeof(x) value = x; \
|
||||
typeof(a) align = a; \
|
||||
if ((value & (align - 1)) != 0) { \
|
||||
value &= ~(align - 1); \
|
||||
} \
|
||||
value; \
|
||||
})
|
||||
|
||||
uint8_t bcd_to_int(uint8_t val);
|
||||
|
||||
int cpuid(uint32_t leaf, uint32_t subleaf,
|
||||
@ -48,8 +29,22 @@ uint64_t strtoui(const char *s);
|
||||
|
||||
#define DIV_ROUNDUP(a, b) (((a) + ((b) - 1)) / (b))
|
||||
|
||||
typedef void *symbol[];
|
||||
#define ALIGN_UP(x, a) ({ \
|
||||
typeof(x) value = x; \
|
||||
typeof(a) align = a; \
|
||||
value = DIV_ROUNDUP(value, align) * align; \
|
||||
value; \
|
||||
})
|
||||
|
||||
#define ALIGN_DOWN(x, a) ({ \
|
||||
typeof(x) value = x; \
|
||||
typeof(a) align = a; \
|
||||
value = (value / align) * align; \
|
||||
value; \
|
||||
})
|
||||
|
||||
#define SIZEOF_ARRAY(array) (sizeof(array) / sizeof(array[0]))
|
||||
|
||||
typedef void *symbol[];
|
||||
|
||||
#endif
|
||||
|
@ -213,7 +213,7 @@ void stivale_load(char *cmdline, int boot_drive) {
|
||||
print(" End: %X\n", m->end);
|
||||
}
|
||||
|
||||
stivale_struct.rsdp = (uint64_t)(size_t)get_rsdp();
|
||||
stivale_struct.rsdp = (uint64_t)(size_t)acpi_get_rsdp();
|
||||
|
||||
stivale_struct.cmdline = (uint64_t)(size_t)cmdline;
|
||||
|
||||
@ -326,6 +326,14 @@ __attribute__((noreturn)) void stivale_spinup(int bits, bool level5pg,
|
||||
"mov gs, ax\n\t"
|
||||
"mov ss, ax\n\t"
|
||||
|
||||
// Since we don't really know what is now present in the upper
|
||||
// 32 bits of the 64 bit registers, clear up the upper bits
|
||||
// of the registers we use to store stack pointer and instruction
|
||||
// pointer
|
||||
"mov esi, esi\n\t"
|
||||
"mov ebx, ebx\n\t"
|
||||
"mov edi, edi\n\t"
|
||||
|
||||
"push 0x30\n\t"
|
||||
"push [rsi]\n\t"
|
||||
"pushfq\n\t"
|
||||
|
@ -328,7 +328,7 @@ void stivale2_load(char *cmdline, int boot_drive) {
|
||||
struct stivale2_struct_tag_rsdp *tag = balloc(sizeof(struct stivale2_struct_tag_rsdp));
|
||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_RSDP_ID;
|
||||
|
||||
tag->rsdp = (uint64_t)(size_t)get_rsdp();
|
||||
tag->rsdp = (uint64_t)(size_t)acpi_get_rsdp();
|
||||
|
||||
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user