diff options
| author | 2026-08-18 12:15:05 +0200 | |
|---|---|---|
| committer | 2026-08-18 12:15:05 +0200 | |
| commit | 132d3236bb884433bf94e961f6d32264e0334aec (patch) | |
| tree | 06638976b06f019ea4037175ff228f8271057c44 /bootloader/main.c | |
Diffstat (limited to '')
| -rw-r--r-- | bootloader/main.c | 396 |
1 files changed, 396 insertions, 0 deletions
diff --git a/bootloader/main.c b/bootloader/main.c new file mode 100644 index 0000000..e196777 --- /dev/null +++ b/bootloader/main.c @@ -0,0 +1,396 @@ +#include <efi.h> +#include <efilib.h> +#include <efidef.h> +#include <string.h> + +#include "disk.h" +#include "vga.h" +#include "vmmem.h" +#include "ELF.h" +#include "memorytypes.h" +#include "paging_struct.h" +#include "paging.h" +#include "other.h" + +// pixel struct information(hardcoded to what qemu exposes) +typedef struct _Pixel +{ + UINT8 B; + UINT8 G; + UINT8 R; + UINT8 Z; +} Pixel; + +// struct that is going to be passed to the kernel about general system information +typedef struct _OSDATA +{ + UINT32 Magic; // magic number to check + + UINT32 FBWidth; // with of the framebuffer + UINT32 FBHeight; // height + UINT32 PixelSize; // size of each pixel(an rgb pixel might have a bigger size) + void * FBAddr; // address of the linear framebuffer + + void * MEMMap; // pointer to the system memory map + + void * RAMDisk; // pointer to a ramdisk loaded from the hdd + + void* RSDP; +} OSDATA; + +extern void BootDisableInterrupts(void); // asm code is not correct(callee doesn't set the stack correctly) +typedef void (*kfn)(OSDATA *); // typedef to setup the entry point of the kernel and do a "jump" into it + + + +void +EFIAPI +efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) +{ + __asm__("hlt"); + + // Memory Map + UINTN mapsize = 0; + UINTN allocsize = 0; + EFI_MEMORY_DESCRIPTOR * map = NULL; + UINTN mapkey = 0; + UINTN descriptorsize = 0; + UINT32 version = 0; + + + InitializeLib(ImageHandle, SystemTable); + uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); // clear the screen + //Pixel * fb = SetVideoMode(1024, 768, 32); + Pixel * fb = SetVideoMode(800, 600, 24); + + PrintImageAddr(ImageHandle); + + // Print(L"Number of tables: %d\n", SystemTable->NumberOfTableEntries); + + EFI_GUID acpi_10 = ACPI_TABLE_GUID; + EFI_GUID acpi_20 = ACPI_20_TABLE_GUID; + void* acpi20table = NULL; + + + for(int i = 0; i < SystemTable->NumberOfTableEntries; i++) + { + if(AreEqual(&(SystemTable->ConfigurationTable[i].VendorGuid), &acpi_10, sizeof(EFI_GUID))) + { + // Print(L"ACPI 1.0 Found\n"); + } + if(AreEqual(&(SystemTable->ConfigurationTable[i].VendorGuid), &acpi_20, sizeof(EFI_GUID))) + { + // Print(L"ACPI 2.0 Found\n"); + acpi20table = SystemTable->ConfigurationTable[i].VendorTable; // <- this should be the RSDP + } + } + + // some uefi implementations time out with their default setting, disable the timer + BS->SetWatchdogTimer(0, 0, 0, NULL); + + + //Print(L"Firmware Vendor: %s Rev: 0x%08x\n", ST->FirmwareVendor, ST->FirmwareRevision); + + //while(1){}; + + // allocate the datat for the kernel(need to specify memory time not to be a generic loader data type) + OSDATA * osdata = AllocatePool(sizeof(OSDATA)); + + if(osdata == NULL) + { + Print(L"Os Data allocation failed\n"); + } + + int32_t kernel_size; + + ELF * kernel = LoadFile(L"kernel.bin", MEM_KERNEL, &kernel_size); // we set the memory type to the one from the kernel + + { + PH* ph = (PH*)(((uint64_t)kernel) + kernel->e_phoff); // use this to know how much and what pages to map + uint64_t phcount = (((uint64_t)kernel) + kernel->e_phnum); + + //kernel_size = ph->p_filesz; + uint64_t size = (uint64_t)(kernel_size = ph->p_memsz); + uint64_t entry = (uint64_t)(kernel + ph->p_offset); + + /* + Print(L"Kernel Size: 0x%llX\n", size); + Print(L"Kernel Entry: 0x%llX\n", entry); + Print(L"Program Header Count: 0x%llX\n", phcount); + */ + } + + // print general information about the kernel elf header + //PrintELFInfo(kernel); + Loaded_ELF* loaded_kernel = LoadELF(kernel); + + + // attempt to allocate the memory map, first try is going to be too small + // as such the firmware will return the correct size + EFI_STATUS memret = EFI_SUCCESS; + EFI_STATUS bootstatus = EFI_SUCCESS; + + uefi_call_wrapper(BS->GetMemoryMap, 5, &mapsize, map, &mapkey, &descriptorsize, &version); + + + // as the allocation will probably modify the memory map allocate 4kb more(one page) + // so that the new memory map probably fits + allocsize = mapsize + 10*4098; + + mapsize = allocsize; + + uefi_call_wrapper(BS->AllocatePool, 3, EfiLoaderData, allocsize, (void**)&map); + + uefi_call_wrapper(BS->GetMemoryMap, 5, &mapsize, map, &mapkey, &descriptorsize, &version); + + // set virtual addresses in here + // try some paging + initCR3(); + + //uint64_t address = 0; + //uint64_t max = 0x400000000ull;//0x20000000; + // EFI_MEMORY_DESCRIPTOR * mapiterator = map; + + uint64_t elements = mapsize/descriptorsize; + + printCR3(); + + //Print(L"elements: %d\n", elements); + + + + for(int entry = 0; entry < elements; ++entry) + { + // mapiterator = (EFI_MEMORY_DESCRIPTOR*)(((EFI_PHYSICAL_ADDRESS)mapiterator + descriptorsize)); + + EFI_MEMORY_DESCRIPTOR* mapiterator = (EFI_MEMORY_DESCRIPTOR*)(((uint8_t*)map) + entry*descriptorsize); + + // EFI_MEMORY_DESCRIPTOR* mapiterator = &(map[entry]); + uint64_t page = mapiterator->PhysicalStart; + + uint64_t Pstart = mapiterator->PhysicalStart; + uint64_t Vstart = mapiterator->VirtualStart; + uint64_t Npages = mapiterator->NumberOfPages; + uint64_t Tpage = mapiterator->Type; + uint64_t Att = mapiterator->Attribute; + + //if(Pstart != Vstart) + /* + if(Vstart != 0) + { + Print(L"\n"); + Print(L"---------------------------------------\n"); + Print(L"NON MATCHING PHYSICAL AND VIRTUAL PAGES\n"); + Print(L"Physical Start: 0x%llX\n", Pstart); + Print(L"Virtual Start: 0x%llX\n", Vstart); + Print(L"Number of Pages: 0x%llX\n", Npages); + Print(L"Type of Page: 0x%llX\n", Tpage); + Print(L"---------------------------------------\n"); + Print(L"\n"); + } + */ + + // if((Npages > 0) && (Vstart != 0)) + // if(Vstart != 0) + // if((Pstart == 0) && (Vstart == 0)) + // if(Pstart == Vstart) + if(Tpage == EfiConventionalMemory) // free pages + { + Print(L"\n"); + Print(L"---------------------------------------\n"); + Print(L"MAPPED MEMORY\n"); + Print(L"Physical Start: 0x%llX\n", Pstart); + Print(L"Virtual Start: 0x%llX\n", Vstart); + Print(L"Number of Pages: 0x%llX\n", Npages); + Print(L"Type of Page: 0x%llX\n", Tpage); + Print(L"Attribute of Page: 0x%llX\n", Att); + Print(L"---------------------------------------\n"); + Print(L"\n"); + } + + //Print(L"page: 0x%llX\n", page); + /* for(int pageentry = 0; pageentry < mapiterator->NumberOfPages; pageentry++) + { + //Print(L"SetAddr\n"); + SetVirtualAddress(page, page); + page += 0x1000; + } */ + } + + while(1) {}; + + uint64_t maxaddr = 0x0000001000000000ull; + for(uint64_t page = 0x0; page < maxaddr; page += 0x1000) + { + SetVirtualAddress(page, page); // <- This is chanigng the memorymap 100% + } + + // need to map the physical address the kernel is in to -2GB virtual + //uint64_t startvm = 0xffffffff7fffffffull; + //uint64_t startvm = kernel->e_entry; + //uint64_t currentvm = 0; + + //PH* ph = (PH*)(((uint64_t)kernel) + kernel->e_phoff); // use this to know how much and what pages to map + + //kernel_size = ph->p_filesz; + //kernel_size = ph->p_memsz; + + /* + while(currentvm < kernel_size) + { + SetVirtualAddress((uint64_t)kernel + ph->p_offset + currentvm, startvm + currentvm); + + currentvm += 0x1000; + } + */ + + Print(L"BEFORE MAPPING KERNEL ENTRY: 0x%llX\n", loaded_kernel->entry); + + for(int i = 0; i < loaded_kernel->ph_num; i++) + { + Loaded_PH* ph = &(loaded_kernel->ph[i]); + Print(L"MAPPING PH: 0x%llX\n", (uint64_t)ph->vaddr); + uint64_t mapsize = ph->mem_size; + uint64_t mapped = 0; + while(mapped < mapsize) + { + SetVirtualAddress((uint64_t)ph->data + mapped, (uint64_t)ph->vaddr + mapped); + mapped += 0x1000; + } + } + + // now map already allocated 8KB for the Kernel Stack + + + //printCR3(); + + //Print(L"kernel: 0x%llx\n", kernel); + + // the call to exit boot services tells the firmware we are ready to take control of the system + + // never ever call Print after the next line + // after the first call boot services can be partially disabled + // loop until the firmware reports a successful exit, the specification allows for partial shutdowns + // so more than one call might be necessary(on qemu with OVMF it is) + while((bootstatus = uefi_call_wrapper(BS->ExitBootServices, 2, ImageHandle, mapkey)) != EFI_SUCCESS) // <- actually we need an up to date mapkey, so maybe we could actually get a memorymap before, create a OS liked memory map and exit services? + { + + mapsize = allocsize; + + while((memret = uefi_call_wrapper(BS->GetMemoryMap, 5, &mapsize, map, &mapkey, &descriptorsize, &version)) == EFI_BUFFER_TOO_SMALL) + { + + allocsize = allocsize + 2*4096; // add 8kb(2 pages) + + uefi_call_wrapper(BS->FreePool, 1, map); + + uefi_call_wrapper(BS->AllocatePool, 3, EfiLoaderData, allocsize, (void**)&map); + + mapsize = allocsize; + } + } + + SetCrc(&(SystemTable->Hdr)); // As we exited boot services we need to set the CRC32 again + + // as we can't print to the screen the way of showing the return status of this function + // is to write a red or green square on the top left corner of the screen + if(SetVM(mapsize, descriptorsize, version, map, kernel) != EFI_SUCCESS) + { + int i = 0; + int j = 0; + + for(i = 0; i < 256; ++i) + { + for(j = 0; j < 256; ++j) + { + Pixel p; + p.R = 255; + p.G = 0; + p.B = 0; + //p.Z = 255; + fb[j + 800*i] = p; + } + } + } else + { + int i = 0; + int j = 0; + + for(i = 0; i < 64; ++i) + { + for(j = 0; j < 64; ++j) + { + Pixel p; + p.R = 0; + p.G = 255; + p.B = 0; + //p.Z = 255; + fb[j + 800*i] = p; + } + } + } + + // we should now set s Print(L"Calling ExitBootServices\n");oe virtual mapping + //BootDisableInterrupts(); + + + //OSDATA * osdata = (OSDATA*)(640*1024); + + + + osdata->Magic = 0xDDEE; + osdata->FBWidth = 1024; + osdata->FBHeight = 768; + osdata->FBAddr = fb; + osdata->PixelSize = 24; + osdata->MEMMap = map; + osdata->RAMDisk = NULL; + osdata->RSDP = acpi20table; + + // this while only serves not to call the kernel for now + // after calling exit boot services we can't return to the uefi environment because it's been destroyed + // + + //kernel = (ELF*)0x280000000; // correct virtual pointer to 10GB (Sign: 0 PML4: 0 PDP:10 PD:0 Page:0) + + // kfn kernel_jump = (void*)kernel->e_entry;//(void*)((EFI_PHYSICAL_ADDRESS)kernel + kernel->EntryPoint); + kfn kernel_jump = (void*)loaded_kernel->entry;//(void*)((EFI_PHYSICAL_ADDRESS)kernel + kernel->EntryPoint); + + + writeCR3(); + //while(1){} + { + int i = 0; + int j = 0; + + for(i = 0; i < 256; ++i) + { + for(j = 0; j < 256; ++j) + { + Pixel p; + p.R = 255; + p.G = 255; + p.B = 255; + p.Z = 255; + fb[j + 800*i] = p; + } + } + } + + // disable interrupts + __asm__("cli"); + + //writeCR3(); + + + //__asm__("hlt"); + + kernel_jump(osdata); + + while(1){} + + __asm__("hlt"); // sanity in case the kernel exists, should throw an error somehow + // not as if the kernel shouldn't have this same code at the end of the main though + + // we should never ever reach this point(if kernel exists, it should shutdown the computer) +} |
