mirror of
https://github.com/limine-bootloader/limine
synced 2024-12-25 15:26:50 +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:
|
load_gdt:
|
||||||
pusha
|
pusha
|
||||||
push es
|
push es
|
||||||
push ds
|
push ds
|
||||||
push 0x7ff0
|
mov ax, word [0x40e] ; 0x40e contains the value of a segment pointing to the EBDA
|
||||||
pop es
|
sub ax, ALIGN_UP(gdt.size, 16) / 16
|
||||||
|
mov es, ax
|
||||||
|
mov word [gdt.ptr], ax
|
||||||
|
shl dword [gdt.ptr], 4
|
||||||
xor di, di
|
xor di, di
|
||||||
push 0
|
mov ds, di
|
||||||
pop ds
|
mov si, gdt.start
|
||||||
mov si, GDT.GDTStart
|
mov cx, gdt.size
|
||||||
mov cx, GDT.GDTEnd - GDT.GDTStart
|
|
||||||
rep movsb
|
rep movsb
|
||||||
lgdt [GDT]
|
|
||||||
pop ds
|
pop ds
|
||||||
|
lgdt [gdt]
|
||||||
pop es
|
pop es
|
||||||
popa
|
popa
|
||||||
ret
|
ret
|
||||||
|
|
||||||
GDT:
|
gdt:
|
||||||
|
dw .size - 1 ; GDT size
|
||||||
|
.ptr:
|
||||||
|
dd 0 ; GDT start address (calculated at runtime)
|
||||||
|
|
||||||
dw .GDTEnd - .GDTStart - 1 ; GDT size
|
.start:
|
||||||
dd 0x7ff00 ; GDT 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
|
; 32-bit data
|
||||||
dw 0x0000 ; Base (low 16 bits)
|
dw 0xffff ; Limit
|
||||||
db 0x00 ; Base (mid 8 bits)
|
dw 0x0000 ; Base (low 16 bits)
|
||||||
db 00000000b ; Access
|
db 0x00 ; Base (mid 8 bits)
|
||||||
db 00000000b ; Granularity
|
db 10010010b ; Access
|
||||||
db 0x00 ; Base (high 8 bits)
|
db 11001111b ; Granularity
|
||||||
|
db 0x00 ; Base (high 8 bits)
|
||||||
|
|
||||||
; 16-bit code
|
; 64-bit code
|
||||||
dw 0xffff ; Limit
|
dw 0x0000 ; Limit
|
||||||
dw 0x0000 ; Base (low 16 bits)
|
dw 0x0000 ; Base (low 16 bits)
|
||||||
db 0x00 ; Base (mid 8 bits)
|
db 0x00 ; Base (mid 8 bits)
|
||||||
db 10011010b ; Access
|
db 10011010b ; Access
|
||||||
db 00000000b ; Granularity
|
db 00100000b ; Granularity
|
||||||
db 0x00 ; Base (high 8 bits)
|
db 0x00 ; Base (high 8 bits)
|
||||||
|
|
||||||
; 16-bit data
|
; 64-bit data
|
||||||
dw 0xffff ; Limit
|
dw 0x0000 ; Limit
|
||||||
dw 0x0000 ; Base (low 16 bits)
|
dw 0x0000 ; Base (low 16 bits)
|
||||||
db 0x00 ; Base (mid 8 bits)
|
db 0x00 ; Base (mid 8 bits)
|
||||||
db 10010010b ; Access
|
db 10010010b ; Access
|
||||||
db 00000000b ; Granularity
|
db 00000000b ; Granularity
|
||||||
db 0x00 ; Base (high 8 bits)
|
db 0x00 ; Base (high 8 bits)
|
||||||
|
|
||||||
; 32-bit code
|
.end:
|
||||||
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)
|
|
||||||
|
|
||||||
; 32-bit data
|
.size: equ .end - .start
|
||||||
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:
|
|
||||||
|
BIN
limine.bin
BIN
limine.bin
Binary file not shown.
@ -4,14 +4,24 @@
|
|||||||
#include <lib/libc.h>
|
#include <lib/libc.h>
|
||||||
#include <lib/print.h>
|
#include <lib/print.h>
|
||||||
|
|
||||||
void *get_rsdp(void) {
|
// Following function based on https://github.com/qword-os/lai/blob/master/helpers/pc-bios.c's function lai_bios_calc_checksum()
|
||||||
for (size_t i = 0x80000; i < 0x100000; i += 16) {
|
uint8_t acpi_checksum(void *ptr, size_t size) {
|
||||||
if (i == 0xa0000) {
|
uint8_t sum = 0, *_ptr = ptr;
|
||||||
/* skip video mem and mapped hardware */
|
for (size_t i = 0; i < size; i++)
|
||||||
i = 0xe0000 - 16;
|
sum += _ptr[i];
|
||||||
continue;
|
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);
|
print("acpi: Found RSDP at %x\n", i);
|
||||||
return (void *)i;
|
return (void *)i;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,46 @@
|
|||||||
#ifndef __LIB__ACPI_H__
|
#ifndef __LIB__ACPI_H__
|
||||||
#define __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
|
#endif
|
||||||
|
@ -48,7 +48,7 @@ __attribute__((noreturn)) void panic(const char *fmt, ...) {
|
|||||||
|
|
||||||
extern symbol bss_end;
|
extern symbol bss_end;
|
||||||
static size_t bump_allocator_base = (size_t)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) {
|
void brewind(size_t count) {
|
||||||
bump_allocator_base -= count;
|
bump_allocator_base -= count;
|
||||||
@ -58,12 +58,21 @@ void *balloc(size_t count) {
|
|||||||
return balloc_aligned(count, 4);
|
return balloc_aligned(count, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only power of 2 alignments
|
|
||||||
void *balloc_aligned(size_t count, size_t alignment) {
|
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);
|
size_t new_base = ALIGN_UP(bump_allocator_base, alignment);
|
||||||
void *ret = (void *)new_base;
|
void *ret = (void *)new_base;
|
||||||
new_base += count;
|
new_base += count;
|
||||||
if (new_base >= BUMP_ALLOCATOR_LIMIT)
|
if (new_base >= bump_allocator_limit)
|
||||||
panic("Memory allocation failed");
|
panic("Memory allocation failed");
|
||||||
bump_allocator_base = new_base;
|
bump_allocator_base = new_base;
|
||||||
|
|
||||||
|
@ -4,25 +4,6 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.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);
|
uint8_t bcd_to_int(uint8_t val);
|
||||||
|
|
||||||
int cpuid(uint32_t leaf, uint32_t subleaf,
|
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))
|
#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]))
|
#define SIZEOF_ARRAY(array) (sizeof(array) / sizeof(array[0]))
|
||||||
|
|
||||||
|
typedef void *symbol[];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -213,7 +213,7 @@ void stivale_load(char *cmdline, int boot_drive) {
|
|||||||
print(" End: %X\n", m->end);
|
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;
|
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 gs, ax\n\t"
|
||||||
"mov ss, 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 0x30\n\t"
|
||||||
"push [rsi]\n\t"
|
"push [rsi]\n\t"
|
||||||
"pushfq\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));
|
struct stivale2_struct_tag_rsdp *tag = balloc(sizeof(struct stivale2_struct_tag_rsdp));
|
||||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_RSDP_ID;
|
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);
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user