#include #include #include #include #include "../../../tools/limine/limine.h" #include "../../kernel.h" void init_limine(); static volatile struct limine_entry_point_request EntryPointRequest = { .id = LIMINE_ENTRY_POINT_REQUEST, .revision = 0, .response = NULL, .entry = init_limine}; static volatile struct limine_bootloader_info_request BootloaderInfoRequest = { .id = LIMINE_BOOTLOADER_INFO_REQUEST, .revision = 0}; static volatile struct limine_terminal_request TerminalRequest = { .id = LIMINE_TERMINAL_REQUEST, .revision = 0}; static volatile struct limine_framebuffer_request FramebufferRequest = { .id = LIMINE_FRAMEBUFFER_REQUEST, .revision = 0}; static volatile struct limine_memmap_request MemmapRequest = { .id = LIMINE_MEMMAP_REQUEST, .revision = 0}; static volatile struct limine_kernel_address_request KernelAddressRequest = { .id = LIMINE_KERNEL_ADDRESS_REQUEST, .revision = 0}; static volatile struct limine_rsdp_request RsdpRequest = { .id = LIMINE_RSDP_REQUEST, .revision = 0}; static volatile struct limine_kernel_file_request KernelFileRequest = { .id = LIMINE_KERNEL_FILE_REQUEST, .revision = 0}; static volatile struct limine_module_request ModuleRequest = { .id = LIMINE_MODULE_REQUEST, .revision = 0}; static volatile struct limine_smbios_request SmbiosRequest = { .id = LIMINE_SMBIOS_REQUEST, .revision = 0}; SafeFunction NIF void init_limine() { struct BootInfo binfo; struct limine_bootloader_info_response *BootloaderInfoResponse = BootloaderInfoRequest.response; info("Bootloader: %s %s", BootloaderInfoResponse->name, BootloaderInfoResponse->version); struct limine_terminal_response *TerminalResponse = TerminalRequest.response; if (TerminalResponse == NULL || TerminalResponse->terminal_count < 1) { warn("No terminal available."); while (1) asmv("hlt"); } TerminalResponse->write(TerminalResponse->terminals[0], "\033[37mPlease wait... ", 20); struct limine_framebuffer_response *FrameBufferResponse = FramebufferRequest.response; struct limine_memmap_response *MemmapResponse = MemmapRequest.response; struct limine_kernel_address_response *KernelAddressResponse = KernelAddressRequest.response; struct limine_rsdp_response *RsdpResponse = RsdpRequest.response; struct limine_kernel_file_response *KernelFileResponse = KernelFileRequest.response; struct limine_module_response *ModuleResponse = ModuleRequest.response; struct limine_smbios_response *SmbiosResponse = SmbiosRequest.response; if (FrameBufferResponse == NULL || FrameBufferResponse->framebuffer_count < 1) { error("No framebuffer available [%p;%ld]", FrameBufferResponse, (FrameBufferResponse == NULL) ? 0 : FrameBufferResponse->framebuffer_count); TerminalResponse->write(TerminalResponse->terminals[0], "No framebuffer available", 24); while (1) asmv("hlt"); } if (MemmapResponse == NULL || MemmapResponse->entry_count < 1) { error("No memory map available [%p;%ld]", MemmapResponse, (MemmapResponse == NULL) ? 0 : MemmapResponse->entry_count); TerminalResponse->write(TerminalResponse->terminals[0], "No memory map available", 23); while (1) asmv("hlt"); } if (KernelAddressResponse == NULL) { error("No kernel address available [%p]", KernelAddressResponse); TerminalResponse->write(TerminalResponse->terminals[0], "No kernel address available", 27); while (1) asmv("hlt"); } if (RsdpResponse == NULL || RsdpResponse->address == 0) { error("No RSDP address available [%p;%p]", RsdpResponse, (RsdpResponse == NULL) ? 0 : RsdpResponse->address); TerminalResponse->write(TerminalResponse->terminals[0], "No RSDP address available", 25); while (1) asmv("hlt"); } if (KernelFileResponse == NULL || KernelFileResponse->kernel_file == NULL) { error("No kernel file available [%p;%p]", KernelFileResponse, (KernelFileResponse == NULL) ? 0 : KernelFileResponse->kernel_file); TerminalResponse->write(TerminalResponse->terminals[0], "No kernel file available", 24); while (1) asmv("hlt"); } if (ModuleResponse == NULL || ModuleResponse->module_count < 1) { error("No module information available [%p;%ld]", ModuleResponse, (ModuleResponse == NULL) ? 0 : ModuleResponse->module_count); TerminalResponse->write(TerminalResponse->terminals[0], "No module information available", 31); while (1) asmv("hlt"); } for (uint64_t i = 0; i < FrameBufferResponse->framebuffer_count; i++) { struct limine_framebuffer *framebuffer = FrameBufferResponse->framebuffers[i]; binfo.Framebuffer[i].BaseAddress = (void *)((uint64_t)framebuffer->address - 0xffff800000000000); binfo.Framebuffer[i].Width = framebuffer->width; binfo.Framebuffer[i].Height = framebuffer->height; binfo.Framebuffer[i].Pitch = framebuffer->pitch; binfo.Framebuffer[i].BitsPerPixel = framebuffer->bpp; binfo.Framebuffer[i].MemoryModel = framebuffer->memory_model; binfo.Framebuffer[i].RedMaskSize = framebuffer->red_mask_size; binfo.Framebuffer[i].RedMaskShift = framebuffer->red_mask_shift; binfo.Framebuffer[i].GreenMaskSize = framebuffer->green_mask_size; binfo.Framebuffer[i].GreenMaskShift = framebuffer->green_mask_shift; binfo.Framebuffer[i].BlueMaskSize = framebuffer->blue_mask_size; binfo.Framebuffer[i].BlueMaskShift = framebuffer->blue_mask_shift; binfo.Framebuffer[i].ExtendedDisplayIdentificationData = framebuffer->edid; binfo.Framebuffer[i].EDIDSize = framebuffer->edid_size; debug("Framebuffer %d: %dx%d %d bpp", i, framebuffer->width, framebuffer->height, framebuffer->bpp); debug("More info:\nAddress: %p\nPitch: %ld\nMemoryModel: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d\nEDID: %p\nEDIDSize: %d", (uint64_t)framebuffer->address - 0xffff800000000000, framebuffer->pitch, framebuffer->memory_model, framebuffer->red_mask_size, framebuffer->red_mask_shift, framebuffer->green_mask_size, framebuffer->green_mask_shift, framebuffer->blue_mask_size, framebuffer->blue_mask_shift, framebuffer->edid, framebuffer->edid_size); } binfo.Memory.Entries = MemmapResponse->entry_count; for (uint64_t i = 0; i < MemmapResponse->entry_count; i++) { if (MemmapResponse->entry_count > MAX_MEMORY_ENTRIES) { warn("Too many memory entries, skipping the rest..."); break; } struct limine_memmap_entry *entry = MemmapResponse->entries[i]; binfo.Memory.Size += entry->length; switch (entry->type) { case LIMINE_MEMMAP_USABLE: binfo.Memory.Entry[i].BaseAddress = (void *)entry->base; binfo.Memory.Entry[i].Length = entry->length; binfo.Memory.Entry[i].Type = Usable; break; case LIMINE_MEMMAP_RESERVED: binfo.Memory.Entry[i].BaseAddress = (void *)entry->base; binfo.Memory.Entry[i].Length = entry->length; binfo.Memory.Entry[i].Type = Reserved; break; case LIMINE_MEMMAP_ACPI_RECLAIMABLE: binfo.Memory.Entry[i].BaseAddress = (void *)entry->base; binfo.Memory.Entry[i].Length = entry->length; binfo.Memory.Entry[i].Type = ACPIReclaimable; break; case LIMINE_MEMMAP_ACPI_NVS: binfo.Memory.Entry[i].BaseAddress = (void *)entry->base; binfo.Memory.Entry[i].Length = entry->length; binfo.Memory.Entry[i].Type = ACPINVS; break; case LIMINE_MEMMAP_BAD_MEMORY: binfo.Memory.Entry[i].BaseAddress = (void *)entry->base; binfo.Memory.Entry[i].Length = entry->length; binfo.Memory.Entry[i].Type = BadMemory; break; case LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE: binfo.Memory.Entry[i].BaseAddress = (void *)entry->base; binfo.Memory.Entry[i].Length = entry->length; binfo.Memory.Entry[i].Type = BootloaderReclaimable; break; case LIMINE_MEMMAP_KERNEL_AND_MODULES: binfo.Memory.Entry[i].BaseAddress = (void *)entry->base; binfo.Memory.Entry[i].Length = entry->length; binfo.Memory.Entry[i].Type = KernelAndModules; break; case LIMINE_MEMMAP_FRAMEBUFFER: binfo.Memory.Entry[i].BaseAddress = (void *)entry->base; binfo.Memory.Entry[i].Length = entry->length; binfo.Memory.Entry[i].Type = Framebuffer; break; default: binfo.Memory.Entry[i].BaseAddress = (void *)entry->base; binfo.Memory.Entry[i].Length = entry->length; binfo.Memory.Entry[i].Type = Unknown; break; } } for (uint64_t i = 0; i < ModuleResponse->module_count; i++) { if (i > MAX_MODULES) { warn("Too many modules, skipping the rest..."); break; } binfo.Modules[i].Address = (void *)((uint64_t)ModuleResponse->modules[i]->address - 0xffff800000000000); strncpy(binfo.Modules[i].Path, ModuleResponse->modules[i]->path, strlen(ModuleResponse->modules[i]->path) + 1); strncpy(binfo.Modules[i].CommandLine, ModuleResponse->modules[i]->cmdline, strlen(ModuleResponse->modules[i]->cmdline) + 1); binfo.Modules[i].Size = ModuleResponse->modules[i]->size; debug("Module %d:\nAddress: %p\nPath: %s\nCommand Line: %s\nSize: %ld", i, (uint64_t)ModuleResponse->modules[i]->address - 0xffff800000000000, ModuleResponse->modules[i]->path, ModuleResponse->modules[i]->cmdline, ModuleResponse->modules[i]->size); } binfo.RSDP = (struct RSDPInfo *)((uint64_t)RsdpResponse->address - 0xffff800000000000); trace("RSDP: %p(%p) [Signature: %.8s] [OEM: %.6s]", RsdpResponse->address, binfo.RSDP, binfo.RSDP->Signature, binfo.RSDP->OEMID); debug("SMBIOS: %p %p", SmbiosResponse->entry_32, SmbiosResponse->entry_64); if (SmbiosResponse->entry_32 != NULL) binfo.SMBIOSPtr = (void *)((uint64_t)SmbiosResponse->entry_32 - 0xffff800000000000); else if (SmbiosResponse->entry_64 != NULL) binfo.SMBIOSPtr = (void *)((uint64_t)SmbiosResponse->entry_64 - 0xffff800000000000); else binfo.SMBIOSPtr = NULL; binfo.Kernel.PhysicalBase = (void *)KernelAddressResponse->physical_base; binfo.Kernel.VirtualBase = (void *)KernelAddressResponse->virtual_base; binfo.Kernel.FileBase = KernelFileResponse->kernel_file->address; strncpy(binfo.Kernel.CommandLine, KernelFileResponse->kernel_file->cmdline, strlen(KernelFileResponse->kernel_file->cmdline) + 1); binfo.Kernel.Size = KernelFileResponse->kernel_file->size; trace("Kernel physical address: %p", KernelAddressResponse->physical_base); trace("Kernel virtual address: %p", KernelAddressResponse->virtual_base); strncpy(binfo.Bootloader.Name, BootloaderInfoResponse->name, strlen(BootloaderInfoResponse->name) + 1); strncpy(binfo.Bootloader.Version, BootloaderInfoResponse->version, strlen(BootloaderInfoResponse->version) + 1); // Call kernel entry point Entry(&binfo); }