fix: plug memory map leak, save sp_el0, dynamic UART, kill loop

- Bootloader: reallocate memory map buffer when ExitBootServices fails,
  so GetMemoryMap doesn't scribble past the old allocation on retry.
- vectors.S: actually store sp_el0 into the exception frame. Previously
  it was read into x24 and then… vanished. EL0 tasks would wake up with
  a corrupted stack pointer. Not great.
- Serial: split hardcoded 0x09000000 into a fallback default; add
  SerialUpdate() so the DTB-parsed UART address actually gets used.
- DTB: add bounds check on reserved[] with PMM's 3 extra slots accounted
  for, so malformed/overstuffed DTBs don't silently corrupt memory.
- PMM.h: bump kVMMaxReservedRegions 128→256, define kPMMReservedRegionCount.
- Types.h: remove `#define loop while(1)`. while(true) is fine.
- Rename IOSerial* → Serial* — the IO prefix was redundant, Serial.c
  already lives under IO/.
This commit is contained in:
karina
2026-05-03 00:32:30 +04:00
parent 7ff9f4ad4c
commit 6dd68f8162
11 changed files with 47 additions and 28 deletions
+6
View File
@@ -192,6 +192,7 @@ static efi_status_t populate_memory_map(Bootinfo* boot_info) {
while (1) { while (1) {
status = gBS->GetMemoryMap(&map_size, map, &map_key, &descriptor_size, &descriptor_version); status = gBS->GetMemoryMap(&map_size, map, &map_key, &descriptor_size, &descriptor_version);
if (EFI_ERROR(status)) { if (EFI_ERROR(status)) {
gBS->FreePool(map);
return status; return status;
} }
@@ -206,7 +207,12 @@ static efi_status_t populate_memory_map(Bootinfo* boot_info) {
return EFI_SUCCESS; return EFI_SUCCESS;
} }
gBS->FreePool(map);
map_size += 2 * descriptor_size; map_size += 2 * descriptor_size;
status = gBS->AllocatePool(EfiLoaderData, map_size, (void**)&map);
if (EFI_ERROR(status)) {
return status;
}
} }
} }
+4 -3
View File
@@ -2,8 +2,9 @@
#include <Types.h> #include <Types.h>
enum { enum {
kUARTBaseAddress = 0x09000000, // TODO: make it dynamic by parsing DTB kUARTBaseAddress = 0x09000000,
}; };
Int32 IOSerialPutCharacter(ASCII character); void SerialUpdate(UInt64 address);
Int32 IOSerialPutString(const ASCII* string); Int32 SerialPutCharacter(ASCII character);
Int32 SerialPutString(const ASCII* string);
-1
View File
@@ -31,4 +31,3 @@ typedef UInt64 Size;
typedef char ASCII; typedef char ASCII;
typedef _Bool Boolean; typedef _Bool Boolean;
#define loop while (1)
+2 -1
View File
@@ -4,7 +4,8 @@
enum { enum {
kVMPageSize = 4096, kVMPageSize = 4096,
kVMBlocksPerByte = 8, kVMBlocksPerByte = 8,
kVMMaxReservedRegions = 128, kVMMaxReservedRegions = 256,
kPMMReservedRegionCount = 3,
}; };
typedef struct { typedef struct {
+3
View File
@@ -28,6 +28,9 @@ void DTBParse(Pointer dtb, VMBootMemoryMap* bootMap) {
Boolean inReservedMemory = false; Boolean inReservedMemory = false;
while (true) { while (true) {
if (bootMap->reservedCount + kPMMReservedRegionCount >= kVMMaxReservedRegions) {
OSPanic("Too many reserved memory regions!"); // should never occur but jic
}
UInt32 token = BytesSwap32(*(UInt32*)structs); UInt32 token = BytesSwap32(*(UInt32*)structs);
structs += 4; structs += 4;
+1
View File
@@ -54,6 +54,7 @@ ExceptionsTrapEntry:
stp x30, x21, [sp, #16 * 15] stp x30, x21, [sp, #16 * 15]
stp x22, x23, [sp, #16 * 16] stp x22, x23, [sp, #16 * 16]
stp x24, xzr, [sp, #16 * 17]
mov x0, sp mov x0, sp
bl ExceptionsHandler bl ExceptionsHandler
+11 -5
View File
@@ -2,22 +2,28 @@
#include <Arch/IO.h> #include <Arch/IO.h>
#include <Arch/CPU.h> #include <Arch/CPU.h>
Int32 IOSerialPutCharacter(ASCII character) { static UInt64 sUARTAddress = kUARTBaseAddress;
void SerialUpdate(UInt64 address) {
sUARTAddress = address;
}
Int32 SerialPutCharacter(ASCII character) {
// TXFF -- TRansmit FIFO Full for PL011 is 5 bit of FR reg (0x18) // TXFF -- TRansmit FIFO Full for PL011 is 5 bit of FR reg (0x18)
UInt64 uartFR = kUARTBaseAddress + 0x18; UInt64 uartFR = sUARTAddress + 0x18;
while ((IOAddressRead32(uartFR) & (1 << 5)) != 0) { while ((IOAddressRead32(uartFR) & (1 << 5)) != 0) {
CPUYield(); CPUYield();
} }
IOAddressWrite32(kUARTBaseAddress, character); IOAddressWrite32(sUARTAddress, character);
return character; return character;
} }
Int32 IOSerialPutString(const ASCII* string) { Int32 SerialPutString(const ASCII* string) {
Int i = 0; Int i = 0;
while (string[i] != '\0') { while (string[i] != '\0') {
IOSerialPutCharacter(string[i]); SerialPutCharacter(string[i]);
i++; i++;
} }
+2
View File
@@ -3,6 +3,7 @@
#include <Arch/Timer.h> #include <Arch/Timer.h>
#include <Arch/CPU.h> #include <Arch/CPU.h>
#include <Arch/GIC.h> #include <Arch/GIC.h>
#include <IO/Serial.h>
#include <VM/PMM.h> #include <VM/PMM.h>
#include <VM/VMM.h> #include <VM/VMM.h>
#include <VM/Heap.h> #include <VM/Heap.h>
@@ -20,6 +21,7 @@ void KernelMain(Bootinfo* bootinfo) {
bootMap.reservedCount = 0; bootMap.reservedCount = 0;
DTBParse(bootinfo->dtb, &bootMap); DTBParse(bootinfo->dtb, &bootMap);
SerialUpdate(bootMap.UART.base);
PMMInitialize(&bootMap); PMMInitialize(&bootMap);
VMMInitialize(&bootMap, bootinfo); VMMInitialize(&bootMap, bootinfo);
+1 -1
View File
@@ -11,5 +11,5 @@ void OSLog(const ASCII* format, ...) {
StringFormatVariadic(buffer, kOSLogBufferSize, format, args); StringFormatVariadic(buffer, kOSLogBufferSize, format, args);
va_end(args); va_end(args);
IOSerialPutString(buffer); SerialPutString(buffer);
} }
+1 -1
View File
@@ -40,7 +40,7 @@ static const ASCII* sFunMessages[] = {
}; };
__attribute__((noreturn)) static void Halt() { __attribute__((noreturn)) static void Halt() {
loop { while (true) {
CPUDisableInterrupts(); CPUDisableInterrupts();
CPUWaitForInterrupt(); CPUWaitForInterrupt();
} }
+1 -1
View File
@@ -89,7 +89,7 @@ Address SchedulerNext(Address stackPointer) {
if (gOSSchedulerCurrentTask->sleepTicks > 0) gOSSchedulerCurrentTask->sleepTicks--; if (gOSSchedulerCurrentTask->sleepTicks > 0) gOSSchedulerCurrentTask->sleepTicks--;
OSTask* nextTask = gOSSchedulerCurrentTask->next; OSTask* nextTask = gOSSchedulerCurrentTask->next;
loop { while (true) {
if (nextTask->state == OSTaskStateDead) { if (nextTask->state == OSTaskStateDead) {
nextTask = nextTask->next; nextTask = nextTask->next;
if (nextTask == gOSSchedulerCurrentTask) OSPanic("No running tasks"); if (nextTask == gOSSchedulerCurrentTask) OSPanic("No running tasks");