Untitled

 avatar
unknown
plain_text
3 years ago
4.7 kB
12
Indexable
    struct PACKED PageDirectoryEntry
    {
        bool Present : 1;
        bool ReadWrite : 1;
        bool UserSuper : 1;
        bool WriteThrough : 1;
        bool CacheDisabled : 1;
        bool Accessed : 1;
        bool ignore0 : 1; 
        bool LargerPages : 1;
        bool ingore1 : 1;
        uint8_t Available : 3;
        uint64_t Address : 52;
    };

    struct PageTable
    { 
        PageDirectoryEntry entries [512];
    } ALIGNED(0x1000);

    void map_memory(PageTable* PML4, void* virtual_address, void* physical_address)
    {
        uint64_t vaddr = (uint64_t)virtual_address;
        vaddr >>= 12;
        auto P_i = vaddr & 0x1ff;
        vaddr >>= 9;
        auto PT_i = vaddr & 0x1ff;
        vaddr >>= 9;
        auto PD_i = vaddr & 0x1ff;
        vaddr >>= 9;
        auto PDP_i = vaddr & 0x1ff;

        PageDirectoryEntry PDE;

        PDE = PML4->entries[PDP_i];
        PageTable* PDP;

        if (!PDE.Present)
        {
            PDP = (PageTable*)EFIMemory::allocate(0x1000);
            memset(PDP, 0, 0x1000);
            PDE.Address = (uint64_t)PDP >> 12;
            PDE.Present = true;
            PDE.ReadWrite = true;
            PML4->entries[PDP_i] = PDE;
        }
        else
        {
            PDP = (PageTable*)((uint64_t)PDE.Address << 12);
        }

        PDE = PDP->entries[PD_i];
        PageTable* PD;

        if (!PDE.Present)
        {
            PD = (PageTable*)EFIMemory::allocate(0x1000);
            memset(PD, 0, 0x1000);
            PDE.Address = (uint64_t)PD >> 12;
            PDE.Present = true;
            PDE.ReadWrite = true;
            PDP->entries[PD_i] = PDE;
        }
        else
        {
            PD = (PageTable*)((uint64_t)PDE.Address << 12);
        }

        PDE = PD->entries[PT_i];
        PageTable* PT;

        if (!PDE.Present)
        {
            PT = (PageTable*)EFIMemory::allocate(0x1000);
            memset(PT, 0, 0x1000);
            PDE.Address = (uint64_t)PT >> 12;
            PDE.Present = true;
            PDE.ReadWrite = true;
            PD->entries[PT_i] = PDE;
        }
        else
        {
            PT = (PageTable*)((uint64_t)PDE.Address << 12);
        }

        PDE = PT->entries[P_i];
        PDE.Address = (uint64_t)physical_address >> 12;
        PDE.Present = true;
        PDE.ReadWrite = true;
        PT->entries[P_i] = PDE;
    }

    EFI_STATUS EFIAPI efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE* system_table)
    {
        PageTable* pml4 = nullptr;
        system_table->BootServices->AllocatePages(AllocateAnyPages, EfiLoaderData, 1, (EFI_PHYSICAL_ADDRESS*)&pml4);

        if(pml4 == nullptr)
            return EFI_SUCCESS;

        EFI_Memory& memory = efi_data.memory;

        UINTN map_key = 0;
        UINT32 descriptor_version = 0;

        system_table->BootServices->GetMemoryMap(
            &memory.map_size,
            memory.map,
            &map_key,
            &memory.descriptor_size,
            &descriptor_version
        );

        system_table->BootServices->AllocatePool(EfiLoaderData, memory.map_size, reinterpret_cast<void**>(&memory.map));

        system_table->BootServices->GetMemoryMap(
            &memory.map_size,
            memory.map,
            &map_key,
            &memory.descriptor_size,
            &descriptor_version
        );

        size_t num_of_map_entries = memory.map_size / memory.descriptor_size;

        for (size_t entry = 0; entry < num_of_map_entries; entry++)
        {
            EFI_MEMORY_DESCRIPTOR* mem_desc = (EFI_MEMORY_DESCRIPTOR*)((uint64_t)memory.map + (entry * memory.descriptor_size));

            for (size_t p = 0; p < mem_desc->NumberOfPages; p++)
            {
                void* addr = (void*)((uint64_t)mem_desc->PhysicalStart + (p * 0x1000));
                map_memory(pml4, addr, addr);
            }
        }

        system_table->BootServices->GetMemoryMap(
            &memory.map_size,
            memory.map,
            &map_key,
            &memory.descriptor_size,
            &descriptor_version
        );

        system_table->BootServices->AllocatePool(EfiLoaderData, memory.map_size, reinterpret_cast<void**>(&memory.map));

        system_table->BootServices->GetMemoryMap(
            &memory.map_size,
            memory.map,
            &map_key,
            &memory.descriptor_size,
            &descriptor_version
        );

        system_table->BootServices->ExitBootServices(image_handle, map_key);

        asm ("mov %0, %%cr3" : : "r" (pml4));