diff options
| author | 2026-08-18 12:15:05 +0200 | |
|---|---|---|
| committer | 2026-08-18 12:15:05 +0200 | |
| commit | 132d3236bb884433bf94e961f6d32264e0334aec (patch) | |
| tree | 06638976b06f019ea4037175ff228f8271057c44 /bootloader | |
Diffstat (limited to '')
| -rw-r--r-- | bootloader/.gitignore | 1 | ||||
| -rw-r--r-- | bootloader/ELF.c | 78 | ||||
| -rw-r--r-- | bootloader/ELF.h | 56 | ||||
| -rw-r--r-- | bootloader/Makefile | 49 | ||||
| -rw-r--r-- | bootloader/README.md | 27 | ||||
| -rw-r--r-- | bootloader/bootloader.pro | 30 | ||||
| -rw-r--r-- | bootloader/bootloader.pro.user | 274 | ||||
| -rw-r--r-- | bootloader/deployment.pri | 191 | ||||
| -rw-r--r-- | bootloader/disk.c | 98 | ||||
| -rw-r--r-- | bootloader/disk.h | 9 | ||||
| -rw-r--r-- | bootloader/main.c | 396 | ||||
| -rw-r--r-- | bootloader/memory.c | 29 | ||||
| -rw-r--r-- | bootloader/memory.h | 14 | ||||
| -rw-r--r-- | bootloader/memorytypes.h | 12 | ||||
| -rw-r--r-- | bootloader/misc.s | 10 | ||||
| -rw-r--r-- | bootloader/other.c | 42 | ||||
| -rw-r--r-- | bootloader/other.h | 12 | ||||
| -rw-r--r-- | bootloader/paging.c | 295 | ||||
| -rw-r--r-- | bootloader/paging.h | 17 | ||||
| -rw-r--r-- | bootloader/paging_struct.h | 189 | ||||
| -rw-r--r-- | bootloader/vga.c | 108 | ||||
| -rw-r--r-- | bootloader/vga.h | 16 | ||||
| -rw-r--r-- | bootloader/vmmem.c | 25 | ||||
| -rw-r--r-- | bootloader/vmmem.h | 9 |
24 files changed, 1987 insertions, 0 deletions
diff --git a/bootloader/.gitignore b/bootloader/.gitignore new file mode 100644 index 0000000..335ec95 --- /dev/null +++ b/bootloader/.gitignore @@ -0,0 +1 @@ +*.tar.gz diff --git a/bootloader/ELF.c b/bootloader/ELF.c new file mode 100644 index 0000000..dd2bc62 --- /dev/null +++ b/bootloader/ELF.c @@ -0,0 +1,78 @@ +#include "ELF.h" +#include "memorytypes.h" + +#include <efi.h> +#include <efilib.h> +#include <efidef.h> + +UINTN EFIAPI elf_ceil2(float x) +{ + UINTN ret = x; + if (x - (int)x > 0) { + x += 1; + ret = (int)x; + } + + return ret; +} + +void EFIAPI PrintELFInfo(ELF * file) +{ + Print(L"LoadAddress: 0x%x\n", file); + + Print(L"Kernel Entry Point: 0x%llx\n", file->e_entry); + + Print(L"program Header offset: %d\n", file->e_phoff); + Print(L"Program Header Size: %d\n", file->e_phentsize); + Print(L"Program Header number: %d\n", file->e_phnum); + Print(L"== FILE PH START: 0x%llx ==\n", (uint64_t)file + file->e_phoff); + + for(uint64_t i = 0; i < file->e_phnum; i++) + { + Print(L"====== PH %d\n", (uint64_t)(i+1)); + PH* ph = (PH*)(((uint64_t)file) + file->e_phoff+i*file->e_phentsize); + Print(L"TOTAL LOAD offset: 0x%llx\n", (uint64_t)(file) + ph->p_offset); + Print(L"UNCAST LOAD offset: 0x%llx\n", (uint64_t)(file + ph->p_offset)); + Print(L"LOAD offset: 0x%llx\n", ph->p_offset); + Print(L"LOAD vaddr: 0x%llx\n", ph->p_vaddr); + Print(L"LOAD paddr: 0x%llx\n", ph->p_paddr); + Print(L"LOAD size in file: 0x%llx\n", ph->p_filesz); + Print(L"LOAD size in memory: 0x%llx\n", ph->p_memsz); + } +} + +Loaded_ELF* EFIAPI LoadELF(ELF* file) +{ + Print(L"Loading ELF file into memory\n"); + Loaded_ELF* loaded_elf; + + uefi_call_wrapper(BS->AllocatePool, 3, EfiLoaderData, sizeof(Loaded_ELF), (void**)&loaded_elf); + + loaded_elf->ph_num = file->e_phnum; + loaded_elf->entry = file->e_entry; + uefi_call_wrapper(BS->AllocatePool, 3, EfiLoaderData, file->e_phnum*sizeof(Loaded_PH), (void**)&(loaded_elf->ph)); + + Print(L"Loading Program Segments...\n"); + for(uint32_t i = 0; i < file->e_phnum; i++) + { + PH* ph = (PH*)(((uint64_t)file) + file->e_phoff+i*file->e_phentsize); + loaded_elf->ph[i].mem_size = ph->p_memsz; + loaded_elf->ph[i].vaddr = ph->p_vaddr; + + uint64_t pages = (ph->p_memsz/1024)/4; + + // uefi_call_wrapper(BS->AllocatePool, 3, EfiLoaderData, ph->p_memsz, (void**)&(loaded_elf->ph[i].data)); // <- wrong, need to allocate aligned pages + UINTN ipages = elf_ceil2(pages); + EFI_PHYSICAL_ADDRESS tmp; + + /*EFI_STATUS allocstatus = */uefi_call_wrapper(BS->AllocatePages, 4, AllocateAnyPages, MEM_KERNEL, ipages, &tmp); + loaded_elf->ph[i].data = (void*)tmp; + + // Print(L"PH: %d Addr: 0x%llX\n", i, file + ph->p_offset); + Print(L"LOADED PH: %d Addr: 0x%llX\n", i, loaded_elf->ph[i].data); + uefi_call_wrapper(BS->CopyMem, 3, loaded_elf->ph[i].data, (void*)((uint64_t)(file) + ph->p_offset), ph->p_filesz); + } + Print(L"\nFinished Loading ELF file into memory\n\n"); + + return loaded_elf; +} diff --git a/bootloader/ELF.h b/bootloader/ELF.h new file mode 100644 index 0000000..c379a91 --- /dev/null +++ b/bootloader/ELF.h @@ -0,0 +1,56 @@ +#ifndef ELF_H +#define ELF_H + +#include <efi.h> + +#define ELFMAGIC 0x464C457F + +// Elf header struct +typedef struct ELF +{ + UINT8 e_ident[16]; + UINT16 e_type; + UINT16 e_machine; + UINT32 e_version; + UINT64 e_entry; + UINT64 e_phoff; + UINT64 e_shoff; + UINT32 e_flags; + UINT16 e_ehsize; + UINT16 e_phentsize; + UINT16 e_phnum; + UINT16 e_shentsize; + UINT16 e_shnum; + UINT16 e_shstrndx; +} ELF; + +typedef struct PH +{ + UINT32 p_type; + UINT32 p_flags; + UINT64 p_offset; + UINT64 p_vaddr; + UINT64 p_paddr; + UINT64 p_filesz; + UINT64 p_memsz; + UINT64 p_align; +} PH; + +typedef struct Loaded_PH +{ + UINT64 mem_size; + UINT64 vaddr; + void* data; +} Loaded_PH; + +typedef struct Loaded_ELF +{ + UINT64 ph_num; + UINT64 entry; + Loaded_PH* ph; +} Loaded_ELF; + +void EFIAPI PrintELFInfo(ELF * file); +Loaded_ELF* EFIAPI LoadELF(ELF* file); + +#endif diff --git a/bootloader/Makefile b/bootloader/Makefile new file mode 100644 index 0000000..cd7cbba --- /dev/null +++ b/bootloader/Makefile @@ -0,0 +1,49 @@ +#CC = gcc-4.8.3 + +#ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) +EFI_ARCH = x86_64 +ARCH = x86-64 + +OBJS = main.o misc.o ELF.o disk.o vga.o vmmem.o paging.o memory.o other.o +TARGET = hello.efi + +EFIINC = /usr/include/efi +EFIINCS = -I$(EFIINC) -I$(EFIINC)/$(EFI_ARCH) -I$(EFIINC)/protocol +LIB = /usr/lib +EFILIB = /usr/lib +EFI_CRT_OBJS = $(EFILIB)/crt0-efi-$(EFI_ARCH).o +EFI_LDS = $(EFILIB)/elf_$(EFI_ARCH)_efi.lds + +CFLAGS = $(EFIINCS) -fno-stack-protector -fpic \ + -fshort-wchar -mno-red-zone -Wall -ggdb3 -O0 -fpic -ffreestanding -fno-stack-protector -fno-stack-check -fshort-wchar -mno-red-zone -maccumulate-outgoing-args -mno-avx -mno-sse +ifeq ($(ARCH),x86-64) + CFLAGS += -DEFI_FUNCTION_WRAPPER +endif + +LDFLAGS = -T $(EFI_LDS) -shared \ + -Bsymbolic -L $(EFILIB) -L $(LIB) $(EFI_CRT_OBJS) +# -nostdlib -znocombreloc -T $(EFI_LDS) -shared \ + +.PHONY: all debug clean + +all: $(TARGET) + +hello.so: $(OBJS) + ld $(LDFLAGS) $(OBJS) -o $@ -lefi -lgnuefi + +%.efi: %.so + objcopy -v -j .text -j .sdata -j .data -j .rodata -j .dynamic \ + -j .dynsym -j .rel -j .rela -j .rel.* -j .rela.* -j .reloc \ + --output-target=efi-app-x86_64 --subsystem=10 $^ $@ +# --target=efi-app-$(ARCH) $^ $@ + +debug: all + objcopy -j .text -j .sdata -j .data -j .dynamic \ + -j .dynsym -j .rel -j .rela -j .reloc \ + -j .debug_info -j .debug_abbrev -j .debug_loc \ + -j .debug_aranges -j .debug_line -j .debug_macinfo -j .debug_str\ + --target=pei-$(ARCH) hello.so hello-debug.so +# --target=efi-app-$(ARCH) hello.so hello-debug.so + +clean: + rm *.so *.efi *.o diff --git a/bootloader/README.md b/bootloader/README.md new file mode 100644 index 0000000..4251b2f --- /dev/null +++ b/bootloader/README.md @@ -0,0 +1,27 @@ + +UEFI Bootloader +--------------- + +UEFI is a replacement to the BIOS, not only as the system firmware but also changes how the computer boots. +previously the computer would start in 16 bits mode, then jump to 32 and then to 64, all that process being the responsibility of the bootloader. +If the system is of 64 bits and the uefi firmware is also of 64 bits the system boot directly into 64 bits, meaning the bootloader binary +must be a 64 bits executable. + +It also removes old interfaces like VGA and VESA when dealing with the gpu, but in turn provides alternate ways of talking with the hardware +all those new interfaces are defined as protocols, which you need to ask for to the firmware, as such to load a file instead of parsing the disk and +reading the filesystem directly, you ask for the appropiate protocol that is able of understandding the disk and the filesystem, and then you use the API +of that protocol to load the file. + + +Steps +----- + +* firmware load the bootloader and starts executin the entry point, at this stage the bootloader is a regular program. +* clean up the screen and setup a more appropiate video mode +* allocate memory for the arguments that will be passed to the kernel +* load the kernel file form disk +* parse the ELF header of the kernel +* obtain the system memory map(is needed to exit the boot services) +* exit boot services, this destroys the uefi environment and we can no longer use anything that requires the boot services(and we can no longer return to the firmware) +* fill the the struct that will be passed to the kernel +* jump into the kernel with the information extracted from the ELF header diff --git a/bootloader/bootloader.pro b/bootloader/bootloader.pro new file mode 100644 index 0000000..0a3c1f6 --- /dev/null +++ b/bootloader/bootloader.pro @@ -0,0 +1,30 @@ +TEMPLATE = app +CONFIG += console +CONFIG -= app_bundle +CONFIG -= qt + +INCLUDEPATH += /usr/include/efi + +SOURCES += main.c misc.s \ + disk.c \ + ELF.c \ + vga.c \ + vmmem.c \ + memory.c \ + paging.c \ + other.c + +include(deployment.pri) +qtcAddDeployment() + +HEADERS += \ + ELF.h \ + disk.h \ + vga.h \ + vmmem.h \ + memory.h \ + memorytypes.h \ + paging_struct.h \ + paging.h \ + other.h + diff --git a/bootloader/bootloader.pro.user b/bootloader/bootloader.pro.user new file mode 100644 index 0000000..082affd --- /dev/null +++ b/bootloader/bootloader.pro.user @@ -0,0 +1,274 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE QtCreatorProject> +<!-- Written by QtCreator 3.6.0, 2016-02-15T01:15:17. --> +<qtcreator> + <data> + <variable>EnvironmentId</variable> + <value type="QByteArray">{2c3e9189-5d42-4938-9849-c0bb2ac935ae}</value> + </data> + <data> + <variable>ProjectExplorer.Project.ActiveTarget</variable> + <value type="int">0</value> + </data> + <data> + <variable>ProjectExplorer.Project.EditorSettings</variable> + <valuemap type="QVariantMap"> + <value type="bool" key="EditorConfiguration.AutoIndent">true</value> + <value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value> + <value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value> + <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0"> + <value type="QString" key="language">Cpp</value> + <valuemap type="QVariantMap" key="value"> + <value type="QByteArray" key="CurrentPreferences">CppGlobal</value> + </valuemap> + </valuemap> + <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1"> + <value type="QString" key="language">QmlJS</value> + <valuemap type="QVariantMap" key="value"> + <value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value> + </valuemap> + </valuemap> + <value type="int" key="EditorConfiguration.CodeStyle.Count">2</value> + <value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value> + <value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value> + <value type="int" key="EditorConfiguration.IndentSize">4</value> + <value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value> + <value type="int" key="EditorConfiguration.MarginColumn">80</value> + <value type="bool" key="EditorConfiguration.MouseHiding">true</value> + <value type="bool" key="EditorConfiguration.MouseNavigation">true</value> + <value type="int" key="EditorConfiguration.PaddingMode">1</value> + <value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value> + <value type="bool" key="EditorConfiguration.ShowMargin">false</value> + <value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value> + <value type="bool" key="EditorConfiguration.SpacesForTabs">true</value> + <value type="int" key="EditorConfiguration.TabKeyBehavior">0</value> + <value type="int" key="EditorConfiguration.TabSize">8</value> + <value type="bool" key="EditorConfiguration.UseGlobal">true</value> + <value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value> + <value type="bool" key="EditorConfiguration.addFinalNewLine">true</value> + <value type="bool" key="EditorConfiguration.cleanIndentation">true</value> + <value type="bool" key="EditorConfiguration.cleanWhitespace">true</value> + <value type="bool" key="EditorConfiguration.inEntireDocument">false</value> + </valuemap> + </data> + <data> + <variable>ProjectExplorer.Project.PluginSettings</variable> + <valuemap type="QVariantMap"/> + </data> + <data> + <variable>ProjectExplorer.Project.Target.0</variable> + <valuemap type="QVariantMap"> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">GCC</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">GCC</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{d432c706-8e6f-4f4f-92f1-4099cda2d690}</value> + <value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value> + <value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value> + <value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value> + <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0"> + <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/ornitorrincos/os/build-bootloader-GCC-Debug</value> + <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0"> + <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0"> + <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value> + <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value> + <value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value> + <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value> + <value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value> + <value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value> + </valuemap> + <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1"> + <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value> + <valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"> + <value type="QString">-w</value> + <value type="QString">-r</value> + </valuelist> + <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value> + <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value> + <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value> + </valuemap> + <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value> + </valuemap> + <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1"> + <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0"> + <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value> + <valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"> + <value type="QString">-w</value> + <value type="QString">-r</value> + </valuelist> + <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value> + <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value> + <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value> + </valuemap> + <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value> + </valuemap> + <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value> + <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value> + <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value> + <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value> + <value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value> + </valuemap> + <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1"> + <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/ornitorrincos/os/build-bootloader-GCC-Release</value> + <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0"> + <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0"> + <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value> + <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value> + <value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value> + <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value> + <value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value> + <value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value> + </valuemap> + <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1"> + <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value> + <valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"> + <value type="QString">-w</value> + <value type="QString">-r</value> + </valuelist> + <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value> + <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value> + <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value> + </valuemap> + <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value> + </valuemap> + <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1"> + <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0"> + <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value> + <valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"> + <value type="QString">-w</value> + <value type="QString">-r</value> + </valuelist> + <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value> + <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value> + <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value> + </valuemap> + <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value> + </valuemap> + <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value> + <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value> + <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value> + <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value> + <value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value> + </valuemap> + <value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">2</value> + <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0"> + <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0"> + <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value> + </valuemap> + <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy locally</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value> + </valuemap> + <value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value> + <valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/> + <valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0"> + <value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value> + <value type="uint" key="Analyzer.QmlProfiler.FlushInterval">0</value> + <value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value> + <value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value> + <valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/> + <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value> + <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value> + <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value> + <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value> + <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value> + <value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value> + <value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value> + <value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value> + <value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value> + <value type="int" key="Analyzer.Valgrind.NumCallers">25</value> + <valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/> + <value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value> + <value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value> + <value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value> + <value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value> + <value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value> + <valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds"> + <value type="int">0</value> + <value type="int">1</value> + <value type="int">2</value> + <value type="int">3</value> + <value type="int">4</value> + <value type="int">5</value> + <value type="int">6</value> + <value type="int">7</value> + <value type="int">8</value> + <value type="int">9</value> + <value type="int">10</value> + <value type="int">11</value> + <value type="int">12</value> + <value type="int">13</value> + <value type="int">14</value> + </valuelist> + <value type="int" key="PE.EnvironmentAspect.Base">2</value> + <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">bootloader</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">bootloader2</value> + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:/home/ornitorrincos/OS-github/bootloader/bootloader.pro</value> + <value type="bool" key="QmakeProjectManager.QmakeRunConfiguration.UseLibrarySearchPath">true</value> + <value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value> + <value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">bootloader.pro</value> + <value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value> + <value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal">true</value> + <value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory"></value> + <value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value> + <value type="bool" key="RunConfiguration.UseCppDebugger">false</value> + <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value> + <value type="bool" key="RunConfiguration.UseMultiProcess">false</value> + <value type="bool" key="RunConfiguration.UseQmlDebugger">false</value> + <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value> + </valuemap> + <value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value> + </valuemap> + </data> + <data> + <variable>ProjectExplorer.Project.TargetCount</variable> + <value type="int">1</value> + </data> + <data> + <variable>ProjectExplorer.Project.Updater.FileVersion</variable> + <value type="int">18</value> + </data> + <data> + <variable>Version</variable> + <value type="int">18</value> + </data> +</qtcreator> diff --git a/bootloader/deployment.pri b/bootloader/deployment.pri new file mode 100644 index 0000000..5f1749f --- /dev/null +++ b/bootloader/deployment.pri @@ -0,0 +1,191 @@ +# This file was generated by an application wizard of Qt Creator. +# The code below handles deployment to Android and Maemo, aswell as copying +# of the application data to shadow build directories on desktop. +# It is recommended not to modify this file, since newer versions of Qt Creator +# may offer an updated version of it. + +defineTest(qtcAddDeployment) { +for(deploymentfolder, DEPLOYMENTFOLDERS) { + item = item$${deploymentfolder} + greaterThan(QT_MAJOR_VERSION, 4) { + itemsources = $${item}.files + } else { + itemsources = $${item}.sources + } + $$itemsources = $$eval($${deploymentfolder}.source) + itempath = $${item}.path + $$itempath= $$eval($${deploymentfolder}.target) + export($$itemsources) + export($$itempath) + DEPLOYMENT += $$item +} + +MAINPROFILEPWD = $$PWD + +android-no-sdk { + for(deploymentfolder, DEPLOYMENTFOLDERS) { + item = item$${deploymentfolder} + itemfiles = $${item}.files + $$itemfiles = $$eval($${deploymentfolder}.source) + itempath = $${item}.path + $$itempath = /data/user/qt/$$eval($${deploymentfolder}.target) + export($$itemfiles) + export($$itempath) + INSTALLS += $$item + } + + target.path = /data/user/qt + + export(target.path) + INSTALLS += target +} else:android { + for(deploymentfolder, DEPLOYMENTFOLDERS) { + item = item$${deploymentfolder} + itemfiles = $${item}.files + $$itemfiles = $$eval($${deploymentfolder}.source) + itempath = $${item}.path + $$itempath = /assets/$$eval($${deploymentfolder}.target) + export($$itemfiles) + export($$itempath) + INSTALLS += $$item + } + + x86 { + target.path = /libs/x86 + } else: armeabi-v7a { + target.path = /libs/armeabi-v7a + } else { + target.path = /libs/armeabi + } + + export(target.path) + INSTALLS += target +} else:win32 { + copyCommand = + for(deploymentfolder, DEPLOYMENTFOLDERS) { + source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source) + source = $$replace(source, /, \\) + sourcePathSegments = $$split(source, \\) + target = $$OUT_PWD/$$eval($${deploymentfolder}.target)/$$last(sourcePathSegments) + target = $$replace(target, /, \\) + target ~= s,\\\\\\.?\\\\,\\, + !isEqual(source,$$target) { + !isEmpty(copyCommand):copyCommand += && + isEqual(QMAKE_DIR_SEP, \\) { + copyCommand += $(COPY_DIR) \"$$source\" \"$$target\" + } else { + source = $$replace(source, \\\\, /) + target = $$OUT_PWD/$$eval($${deploymentfolder}.target) + target = $$replace(target, \\\\, /) + copyCommand += test -d \"$$target\" || mkdir -p \"$$target\" && cp -r \"$$source\" \"$$target\" + } + } + } + !isEmpty(copyCommand) { + copyCommand = @echo Copying application data... && $$copyCommand + copydeploymentfolders.commands = $$copyCommand + first.depends = $(first) copydeploymentfolders + export(first.depends) + export(copydeploymentfolders.commands) + QMAKE_EXTRA_TARGETS += first copydeploymentfolders + } +} else:ios { + copyCommand = + for(deploymentfolder, DEPLOYMENTFOLDERS) { + source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source) + source = $$replace(source, \\\\, /) + target = $CODESIGNING_FOLDER_PATH/$$eval($${deploymentfolder}.target) + target = $$replace(target, \\\\, /) + sourcePathSegments = $$split(source, /) + targetFullPath = $$target/$$last(sourcePathSegments) + targetFullPath ~= s,/\\.?/,/, + !isEqual(source,$$targetFullPath) { + !isEmpty(copyCommand):copyCommand += && + copyCommand += mkdir -p \"$$target\" + copyCommand += && cp -r \"$$source\" \"$$target\" + } + } + !isEmpty(copyCommand) { + copyCommand = echo Copying application data... && $$copyCommand + !isEmpty(QMAKE_POST_LINK): QMAKE_POST_LINK += ";" + QMAKE_POST_LINK += "$$copyCommand" + export(QMAKE_POST_LINK) + } +} else:unix { + maemo5 { + desktopfile.files = $${TARGET}.desktop + desktopfile.path = /usr/share/applications/hildon + icon.files = $${TARGET}64.png + icon.path = /usr/share/icons/hicolor/64x64/apps + } else:!isEmpty(MEEGO_VERSION_MAJOR) { + desktopfile.files = $${TARGET}_harmattan.desktop + desktopfile.path = /usr/share/applications + icon.files = $${TARGET}80.png + icon.path = /usr/share/icons/hicolor/80x80/apps + } else { # Assumed to be a Desktop Unix + copyCommand = + for(deploymentfolder, DEPLOYMENTFOLDERS) { + source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source) + source = $$replace(source, \\\\, /) + macx { + target = $$OUT_PWD/$${TARGET}.app/Contents/Resources/$$eval($${deploymentfolder}.target) + } else { + target = $$OUT_PWD/$$eval($${deploymentfolder}.target) + } + target = $$replace(target, \\\\, /) + sourcePathSegments = $$split(source, /) + targetFullPath = $$target/$$last(sourcePathSegments) + targetFullPath ~= s,/\\.?/,/, + !isEqual(source,$$targetFullPath) { + !isEmpty(copyCommand):copyCommand += && + copyCommand += $(MKDIR) \"$$target\" + copyCommand += && $(COPY_DIR) \"$$source\" \"$$target\" + } + } + !isEmpty(copyCommand) { + copyCommand = @echo Copying application data... && $$copyCommand + copydeploymentfolders.commands = $$copyCommand + first.depends = $(first) copydeploymentfolders + export(first.depends) + export(copydeploymentfolders.commands) + QMAKE_EXTRA_TARGETS += first copydeploymentfolders + } + } + !isEmpty(target.path) { + installPrefix = $${target.path} + } else { + installPrefix = /opt/$${TARGET} + } + for(deploymentfolder, DEPLOYMENTFOLDERS) { + item = item$${deploymentfolder} + itemfiles = $${item}.files + $$itemfiles = $$eval($${deploymentfolder}.source) + itempath = $${item}.path + $$itempath = $${installPrefix}/$$eval($${deploymentfolder}.target) + export($$itemfiles) + export($$itempath) + INSTALLS += $$item + } + + !isEmpty(desktopfile.path) { + export(icon.files) + export(icon.path) + export(desktopfile.files) + export(desktopfile.path) + INSTALLS += icon desktopfile + } + + isEmpty(target.path) { + target.path = $${installPrefix}/bin + export(target.path) + } + INSTALLS += target +} + +export (ICON) +export (INSTALLS) +export (DEPLOYMENT) +export (LIBS) +export (QMAKE_EXTRA_TARGETS) +} + diff --git a/bootloader/disk.c b/bootloader/disk.c new file mode 100644 index 0000000..646448e --- /dev/null +++ b/bootloader/disk.c @@ -0,0 +1,98 @@ +#include <efi.h> +#include <efilib.h> + +#include "disk.h" +#include "memory.h" + +UINTN EFIAPI ceil2(float x) +{ + UINTN ret = x; + if (x - (int)x > 0) { + x += 1; + ret = (int)x; + } + + return ret; +} + +void * EFIAPI LoadFile(CHAR16 * name, UINTN memtype, int32_t* filesize) +{ + // ask for the protocol to handle the filesystem + EFI_GUID EfiSimpleFileSystemGuid = SIMPLE_FILE_SYSTEM_PROTOCOL; + EFI_FILE_IO_INTERFACE * FSInterface = NULL; + struct _EFI_FILE_HANDLE * fsroot = NULL; + + EFI_STATUS localteprotocolstat = uefi_call_wrapper(BS->LocateProtocol, 3, &EfiSimpleFileSystemGuid, NULL, &FSInterface); + + if(localteprotocolstat != EFI_SUCCESS) + { + Print(L"Failed to locate protocol\n"); + } + + EFI_STATUS openvolumestat = uefi_call_wrapper(FSInterface->OpenVolume, 2, FSInterface, &fsroot); + + if(openvolumestat != EFI_SUCCESS) + { + Print(L"FAiled to open the volume\n"); + } + + struct _EFI_FILE_HANDLE * fp = NULL; + + EFI_STATUS openstat = uefi_call_wrapper(fsroot->Open, 5, fsroot, &fp, name, (UINT64)1, (UINT64)1); + + + + if(openstat != EFI_SUCCESS) + { + Print(L"Failed opening the file\n"); + } + + + // even if the specification says that asking to open the file with insuficient memory + // reports the full file size, qemu and virtualbox implementations don't do that + // as such we need to get manually the file info + UINTN infosize = 1024; + EFI_FILE_INFO * info = AllocatePool(infosize); + EFI_GUID infoguid = EFI_FILE_INFO_ID; + + EFI_STATUS infostatus = uefi_call_wrapper(fp->GetInfo, 4, fp, &infoguid, &infosize, info); + + if(infostatus != EFI_SUCCESS) + { + Print(L"Failed to get FileInfo\n"); + } + + *filesize = info->FileSize; + + UINTN size = info->FileSize; + void * data = NULL; + + //data = AllocatePool(size); + //EFI_STATUS allocstatus = uefi_call_wrapper(BS->AllocatePool, 3, EfiLoaderData, size, (void**)&data); + float pages = (size/1024)/4; + + UINTN ipages = ceil2(pages); + EFI_PHYSICAL_ADDRESS tmp; + + EFI_STATUS allocstatus = uefi_call_wrapper(BS->AllocatePages, 4, AllocateAnyPages, memtype, ipages, &tmp); + + data = (void*)tmp; + + //data = AllocatePages2(size); + + //if(data == NULL) + if(allocstatus != EFI_SUCCESS) + { + Print(L"Failed to get Kernel memory\n"); + } + + // phoenix lies, must specify the size myself + uefi_call_wrapper(fp->Read, 3, fp, &size, data); + + // Print(L"Read Size: %d\n", size); + + uefi_call_wrapper(fp->Close, 1, fp); + + return data; +} + diff --git a/bootloader/disk.h b/bootloader/disk.h new file mode 100644 index 0000000..e291861 --- /dev/null +++ b/bootloader/disk.h @@ -0,0 +1,9 @@ +#ifndef DISK_H +#define DISK_H + +#include <efidef.h> +#include <stdint.h> + +void * EFIAPI LoadFile(CHAR16 * name, UINTN memtype, int32_t* filesize); + +#endif // DISK_H 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) +} diff --git a/bootloader/memory.c b/bootloader/memory.c new file mode 100644 index 0000000..1e310ae --- /dev/null +++ b/bootloader/memory.c @@ -0,0 +1,29 @@ +#include "memory.h" + + +void * EFIAPI AllocatePagesType(IN UINTN size, IN UINTN type) +{ + + void * ret = NULL; + + Print(L"About to allocate\n"); + EFI_STATUS status = uefi_call_wrapper(BS->AllocatePool, 3, type, size, &ret); + + if(status == EFI_SUCCESS) + { + Print(L"Pool Allocated\n"); + return ret; + } + + Print(L"Allocation Failed\n"); + return NULL; +} + +void bootloader_memset(void * in, uint64_t size, uint8_t value) +{ + uint8_t * tmpin = in; + for(int i = 0; i < size; i++) + { + tmpin[i] = value; + } +} diff --git a/bootloader/memory.h b/bootloader/memory.h new file mode 100644 index 0000000..1d42960 --- /dev/null +++ b/bootloader/memory.h @@ -0,0 +1,14 @@ +#ifndef MEMORY_H +#define MEMORY_H + +#include <efi.h> +#include <efilib.h> + +#include <stdint.h> + +#include "memorytypes.h" + +void * EFIAPI AllocatePagesType(IN UINTN size, IN UINTN type); +void bootloader_memset(void *, uint64_t size, uint8_t value); + +#endif diff --git a/bootloader/memorytypes.h b/bootloader/memorytypes.h new file mode 100644 index 0000000..53ba8fb --- /dev/null +++ b/bootloader/memorytypes.h @@ -0,0 +1,12 @@ +#ifndef MEMORYTYPES_H +#define MEMORYTYPES_H + +// memory types to mark the pages as of specific types +// the specification allows custom types that are bigger than 0x80000000 + +#define MEM_KERNEL 0x80000010 +#define MEM_RAMDISK 0x80000020 +#define MEM_ARGS 0x80000030 +#define MEM_PAGING 0x80000040 + +#endif // MEMORYTYPES_H diff --git a/bootloader/misc.s b/bootloader/misc.s new file mode 100644 index 0000000..c228607 --- /dev/null +++ b/bootloader/misc.s @@ -0,0 +1,10 @@ +.text +.global BootDisableInterrupts + +BootDisableInterrupts: + pushq %rbp + movq %rsp, %rbp + cli + popq %rbp + ret + diff --git a/bootloader/other.c b/bootloader/other.c new file mode 100644 index 0000000..9286dac --- /dev/null +++ b/bootloader/other.c @@ -0,0 +1,42 @@ +#include <efi.h> +#include <efilib.h> +#include <efidef.h> + +#include "other.h" + +void PrintImageAddr(EFI_HANDLE image) +{ + EFI_LOADED_IMAGE *loaded_image = NULL; + EFI_STATUS status; + + status = uefi_call_wrapper(BS->HandleProtocol, + 3, + image, + &LoadedImageProtocol, + (void **)&loaded_image); + + if (EFI_ERROR(status)) + { + Print(L"handleprotocol: %r\n", status); + } + + Print(L"Image base: 0x%lx\n", loaded_image->ImageBase); +} + +bool AreEqual(void* lhs, void* rhs, uint64_t size) +{ + char* clhs = (char*)lhs; + char* crhs = (char*)rhs; + + bool equal = true; + + for(int i = 0; i < size; i++) + { + if(clhs[i] != crhs[i]) + { + equal = false; + } + } + + return equal; +} diff --git a/bootloader/other.h b/bootloader/other.h new file mode 100644 index 0000000..a602956 --- /dev/null +++ b/bootloader/other.h @@ -0,0 +1,12 @@ +#ifndef OTHER_H +#define OTHER_H + +#include <efi.h> +#include <efilib.h> +#include <efidef.h> + +void PrintImageAddr(EFI_HANDLE image); +bool AreEqual(void* lhs, void* rhs, uint64_t size); + +#endif // OTHER_H + diff --git a/bootloader/paging.c b/bootloader/paging.c new file mode 100644 index 0000000..d3d6dba --- /dev/null +++ b/bootloader/paging.c @@ -0,0 +1,295 @@ +#include <efi.h> +#include <efilib.h> +#include <stdint.h> + +#include "memorytypes.h" +#include "paging_struct.h" +#include "memory.h" + +uint64_t size; +uint64_t baseaddr; +uint64_t current; + +uint64_t count; + +EFI_PHYSICAL_ADDRESS pages; +uint64_t * CR3; + +uint64_t virtualmemory; +uint64_t maxneg; +//uint64_t base_memory; + +uint64_t GetNextEntry() +{ + uint64_t ret = current + 0x1000;//1024*4; + + count++; + + if(count > 1023) + { + // need to allocate new page + // 1024 pages for 4MB + EFI_STATUS allocstatus = uefi_call_wrapper(BS->AllocatePages, 4, AllocateAnyPages, MEM_PAGING, size, &pages); + if(allocstatus != EFI_SUCCESS) + { + Print(L"Paging space allocation failed\n"); + Print(L"Current: 0x%llX \n", current); + return -1; + } + bootloader_memset((void*)pages, size*0x1000, 0x0); + baseaddr = (uint64_t)pages; + ret = baseaddr; + + //Print(L"New Chunk: 0x%llX\n", baseaddr); + count = 0; + + current = ret; + + if(ret % 0x1000 != 0) + { + Print(L"WARNING Memory not aligned\n"); + } + + return ret; + } + + //Print(L"New Entry: 0x%llX\n", ret); + current = ret; + + if(ret % 0x1000 != 0) + { + Print(L"WARNING Memory not aligned\n"); + } + + return ret; +} + +uint8_t NeedAllocation(uint64_t in) +{ + if(in == -1) + { + return 1; + } + + return 0; +} + +UINT64 EFIAPI GetVMCPUID() +{ + long out = 0; + long id = 0x80000008; + + __asm__ __volatile__ ("movq %1, %%rax;" + "cpuid;" + "movq %%rax, %0;" + :"=r"(out) + :"r"(id) + ); + + return out; +} + +uint64_t powerTwo(uint64_t power) +{ + uint64_t ret = 1; + + while(power > 0) + { + ret *= 2; + + power--; + } + + return ret; +} + +void initCR3() +{ + UINT64 cpu = GetVMCPUID(); + + CPUIDsizes * sizes = (CPUIDsizes*)&cpu; + + // Print(L"raw: %x\n", cpu); + // Print(L"Physical: %d\n", sizes->PhysicalAddress); + // Print(L"Virtual: %d\n", sizes->VirtualAddress); + virtualmemory = sizes->PhysicalAddress; + + maxneg = powerTwo(virtualmemory) - 1; + + size = 1024; + + Print(L"Started CR3\n"); + + // 1024 pages for 4MB + EFI_STATUS allocstatus = uefi_call_wrapper(BS->AllocatePages, 4, AllocateAnyPages, MEM_PAGING, size, &pages); + if(allocstatus != EFI_SUCCESS) + { + Print(L"Paging space allocation failed\n"); + return; + } + + count = 1; + + // 1024 pages at 4kb each + bootloader_memset((void*)pages, size*4*1024, 0x0); + + baseaddr = (uint64_t)pages; + current = baseaddr; + + CR3 = (uint64_t*)current; + *CR3 = 0; + + *CR3 |= CR3_PCD; + *CR3 |= CR3_PWT; + //*CR3 |=(maxneg << CR3_ADDR_SHIFT); + + //((s_CR3*)CR3)->PCD = 1; + //((s_CR3*)CR3)->PWT = 1; + //((s_CR3*)CR3)->base_addr = GetNextEntry(); + + + //int32_t pml4es = sizeof(s_PML4E); + + + //((s_CR3*)CR3)->base_addr = maxneg; + +} + +void printCR3() +{ + Print(L"CR3 value: 0x%llX\n", *((uint64_t*)CR3)); +} + +void writeCR3() +{ + __asm__ __volatile__("movq %0, %%cr3;" + : + :"r"(*CR3)); +} + +void SetVirtualAddress(uint64_t phy, uint64_t virt) +{ + uint64_t* pml4 = (uint64_t*)MaskPhyAddr(*CR3); + + // Get the offsets to each page table + uint64_t pml4offset = GetPML4Offset(virt); + uint64_t pdpoffset = GetPDPOffset(virt); + uint64_t pdoffset = GetPDOffset(virt); + uint64_t ptoffset = GetPTOffset(virt); + + + uint64_t pml4e = pml4[pml4offset]; + + // if not present, allocate the page + if((pml4e & PE_P) == 0x0ull) + { + //assign the physical addr, and clear all to zero + uint64_t tmpaddr = GetNextEntry(); + pml4e |= MaskPhyAddr(tmpaddr); + + // initialize the page + pml4e |= PE_P; + pml4e |= PE_RW; + pml4e |= PE_US; + pml4e |= PE_PWT; + pml4e |= PE_PCD; + } + // assign the values to the array + pml4[pml4offset] = pml4e; + + + uint64_t pdpe = ((uint64_t*)MaskPhyAddr(pml4e))[pdpoffset]; + if((pdpe & PE_P) == 0x0ull) + { + // page not present + uint64_t tmpaddr = GetNextEntry(); + pdpe |= MaskPhyAddr(tmpaddr); + + pdpe |= PE_P; + pdpe |= PE_RW; + pdpe |= PE_US; + pdpe |= PE_PWT; + pdpe |= PE_PCD; + } + ((uint64_t*)MaskPhyAddr(pml4e))[pdpoffset] = pdpe; + + uint64_t pde = ((uint64_t*)MaskPhyAddr(pdpe))[pdoffset]; + + if((pde & PE_P) == 0x0ull) + { + uint64_t tmpaddr = GetNextEntry(); + + pde |= MaskPhyAddr(tmpaddr); + + pde |= PE_P; + pde |= PE_RW; + pde |= PE_US; + pde |= PE_PWT; + pde |= PE_PCD; + } + ((uint64_t*)MaskPhyAddr(pdpe))[pdoffset] = pde; + + uint64_t pte = ((uint64_t*)MaskPhyAddr(pde))[ptoffset]; + + // need to make the pt entry + + if((pte & PE_P) == 0x0ull) + { + pte |= PE_P; + pte |= PE_RW; + pte |= PE_US; + pte |= PE_PWT; + pte |= PE_PCD; + pte |= MaskPhyAddr(phy); + } + ((uint64_t*)MaskPhyAddr(pde))[ptoffset] = pte; +} + +uint8_t checkIdentity(uint64_t phy) +{ + //uint8_t phyvalue = (uint8_t)(*(uint64_t*)phy); + uint8_t phyvalue = *(uint64_t*)phy; + uint8_t virtvalue; + uint64_t pml4e = CR3GetAddr(*CR3);// + GetPML4Offset(phy); + pml4e = *(((uint64_t*)pml4e) + GetPML4Offset(phy)); + uint64_t pdpe = *(((uint64_t*)GetAddr(pml4e)) + GetPDPOffset(phy)); + uint64_t pde = *(((uint64_t*)GetAddr(pdpe)) + GetPDOffset(phy)); + uint64_t pte = *(((uint64_t*)GetAddr(pde)) + GetPTOffset(phy)); + uint64_t pteptr = ((GetAddr(pte)) + GetPhyOffset(phy)); + virtvalue = *(uint64_t*)((GetAddr(pte)) + GetPhyOffset(phy)); + + //s_PDPE * pdpe = ((s_PDPE*)(pml4e->PDPBA + 8*virt->PDP)); + //s_PDE * pde = ((s_PDE*)(pdpe->PDBA + 8*virt->PD)); + //s_PTE * pte = ((s_PTE*)(pde->PTBA + 8*virt->PT)); + //virtvalue = *(uint8_t*)(pte->PPBA + virt->offset); + + // get the correct virtual value + + Print(L"ADDR: 0x%llx\n", phy); + + Print(L"PML4E 0x%llx\n", pml4e); + Print(L"PDPE 0x%llx\n", pdpe); + Print(L"PDE 0x%llx\n", pde); + Print(L"PTE 0x%llx\n", pte); + Print(L"pageentry: 0x%llx\n", pteptr); + Print(L"PPBA 0x%llx\n", GetAddr(pte)); + + Print(L"PML4 %d\n", GetPML4Offset(phy)); + Print(L"PDP %d\n", GetPDPOffset(phy)); + Print(L"PD %d\n", GetPDOffset(phy)); + Print(L"PT %d\n", GetPTOffset(phy)); + Print(L"PHY 0x%llx\n", GetPhyOffset(phy)); + + + Print(L"PHYSICAL: 0x%x\n", phyvalue); + Print(L"VIRTUAL: 0x%x\n", virtvalue); + + if(phyvalue != virtvalue) + { + Print(L"Incorrect physical virtual value\n"); + return 0; + } + + Print(L"Correct physical virtual value\n"); + return 1; +} diff --git a/bootloader/paging.h b/bootloader/paging.h new file mode 100644 index 0000000..59eef1e --- /dev/null +++ b/bootloader/paging.h @@ -0,0 +1,17 @@ +#ifndef PAGING_H +#define PAGING_H + +#include <stdint.h> + +uint64_t GetNextEntry(); +void initCR3(); +void printCR3(); +void writeCR3(); +void SetVirtualAddress(uint64_t phy, uint64_t virt); +uint8_t checkIdentity(uint64_t phy); + + +//void * SetPagingStructs(); + +#endif // PAGING_H + diff --git a/bootloader/paging_struct.h b/bootloader/paging_struct.h new file mode 100644 index 0000000..2c3781f --- /dev/null +++ b/bootloader/paging_struct.h @@ -0,0 +1,189 @@ +#ifndef PAGING_STRUCT_H +#define PAGING_STRUCT_H + +#include <efi.h> +#include <efilib.h> +#include <stdint.h> + +typedef UINT64 uchar; // need to replace this for other more sensible thing or location + +UINT64 GetVMCPUID(); // implemented in misc.s + +extern uint64_t maxneg; + +typedef struct _CPUIDsizes +{ + UINT64 PhysicalAddress:8; + UINT64 VirtualAddress:8; + UINT64 Padding:48; +} CPUIDsizes; + +// these entries are for 4KB pages + + +// Virtual pointer bits breakdown (4KB pages) +// +---------------+-------------+------------+-----------+-----------+-----------------------+ +// | 63 - 48 | 47 - 39 | 38 - 30 | 29 - 21 | 20 - 12 | 11 - 0 | +// +---------------+-------------+------------+-----------+-----------+-----------------------+ +// | sign extend | PML4 offset | PDP offset | PD offset | PT offset | physical page offset | +// +---------------+-------------+------------+-----------+-----------+-----------------------+ + +// Virtual pointer bits breakdown (2MB pages) +// +---------------+-------------+------------+-----------+-----------------------------------+ +// | 63 - 48 | 47 - 39 | 38 - 30 | 29 - 21 | 20 - 0 | +// +---------------+-------------+------------+-----------+-----------------------------------+ +// | sign extend | PML4 offset | PDP offset | PD offset | physical page offset | +// +---------------+-------------+------------+-----------+-----------------------------------+ + + +// paging structure: + +// CR3 +// the contents of this struct go into CR3 +typedef struct __attribute__((packed)) +{ + uint64_t reserved1:3; + uint64_t PWT:1; // page level writethough + uint64_t PCD:1; // page level cache disable + uint64_t reserved2:7; + uint64_t base_addr:40; // base address to the table of PML4 entries + uint64_t reserved3:13; +} s_CR3; + +// Virtual Pointer +#define VP_OFF_PHY 0ull +#define VP_OFF_PT 12ull +#define VP_OFF_PD 21ull +#define VP_OFF_PDP 30ull +#define VP_OFF_PML4 39ull +#define VP_OFF_SIGN 48ull + +#define GetPhyOffset(x) (x & 0xFFFull) +#define GetPTOffset(x) ((x >> VP_OFF_PT) & 0x1FFull) +#define GetPDOffset(x) ((x >> VP_OFF_PD) & 0x1FFull) +#define GetPDPOffset(x) ((x >> VP_OFF_PDP) & 0x1FFull) +#define GetPML4Offset(x) ((x >> VP_OFF_PML4) & 0x1FFull) +#define GetSignOffset(x) ((x >> VP_OFF_SIGN) & 0xFFFFull) + + +// CR3 +#define CR3_PWT (1ull << 3ull) +#define CR3_PCD (1ull << 4ull) +#define CR3_ADDR_SHIFT 12ull +#define CR3_ERASE (~(maxneg << CR3_ADDR_SHIFT)) + +#define CR3GetAddr(x) ((x >> CR3_ADDR_SHIFT) & maxneg) +#define CR3SetAddr(x) ((x & maxneg) << CR3_ADDR_SHIFT) + +// Page Entry +#define PE_P (1ull << 0ull) +#define PE_RW (1ull << 1ull) +#define PE_US (1ull << 2ull) +#define PE_PWT (1ull << 3ull) +#define PE_PCD (1ull << 4ull) +#define PE_A (1ull << 5ull) +#define PE_D (1ull << 6ull) +#define PE_PS (1ull << 7ull) +#define PE_G (1ull << 8ull) +#define PE_BA (1ull << 12ull) +#define PE_NX (1ull << 63ull) +#define PE_ADDR_SHIFT 12ull +#define PE_ERASE (~(maxneg << PE_ADDR_SHIFT)) + +#define MaskTable(x) (x & maxneg) +#define MaskPhyAddr(x) (x & 0xFFFFFFF000ull) +#define SetAddr(x) (x << PE_ADDR_SHIFT) +#define GetAddr(x) (x >> PE_ADDR_SHIFT) +//#define GetAddr(x) (x & ~0xFFFull) + + + +// PML4E + +typedef struct __attribute__((packed)) +{ + uint64_t P:1; // present bit + uint64_t RW:1; // read write (if 0 write protected) + uint64_t US:1; // user/supervisor if 0 no user mode access + uint64_t PWT:1; // page level write though + uint64_t PCD:1; // page level cache disable + uint64_t A:1; // accesed + uint64_t PS:1; // value must be 1 for 1GB pages + uint64_t MBZ:2; + uint64_t AVL:3; + uint64_t PDPBA:40; // physical address of the table pointed by this entry + uint64_t available:11; // need to look into what values go here + uint64_t NX:1; // execute disable +} s_PML4E; + + + +// PDPE + +typedef struct __attribute__((packed)) +{ + uint64_t P:1; + uint64_t RW:1; + uint64_t US:1; + uint64_t PWT:1; + uint64_t PCD:1; + uint64_t A:1; + uint64_t PS:1; // value must be 1 for 2MB pages + uint64_t zero:1; // zero + uint64_t MBZ:1; + uint64_t AVL:3; + uint64_t PDBA:40; + uint64_t available:11; + uint64_t NX:1; +} s_PDPE; + +// PDE + +typedef struct __attribute__((packed)) +{ + uint64_t P:1; + uint64_t RW:1; + uint64_t US:1; + uint64_t PWT:1; + uint64_t PCD:1; + uint64_t A:1; + uint64_t ignored1:1; + uint64_t zero:1; + uint64_t ignored2:1; + uint64_t AVL:3; + uint64_t PTBA:40; + uint64_t available:11; + uint64_t NX:1; +} s_PDE; + +// PTE + +typedef struct __attribute__((packed)) +{ + uint64_t P:1; + uint64_t RW:1; + uint64_t US:1; + uint64_t PWT:1; + uint64_t PCD:1; + uint64_t A:1; + uint64_t D:1; + uint64_t PAT:1; + uint64_t G:1; + uint64_t AVL:3; + uint64_t PPBA:40; + uint64_t available:11; + uint64_t NX:1; +} s_PTE; + +typedef struct __attribute__((packed)) +{ + uint64_t offset:12; + uint64_t PT:9; + uint64_t PD:9; + uint64_t PDP:9; + uint64_t PML4:9; + uint64_t sign:16; +} s_VPTR; + +#endif // PAGING_STRUCT_H + diff --git a/bootloader/vga.c b/bootloader/vga.c new file mode 100644 index 0000000..355c17f --- /dev/null +++ b/bootloader/vga.c @@ -0,0 +1,108 @@ +#include <efi.h> +#include <efilib.h> + +#include "vga.h" + +void * EFIAPI SetVideoMode(int width, int height, int bitdepth) +{ + // find the location of the Graphics Output protocol to aquire a linear framebuffer + EFI_GUID EfiGOPGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; + + struct _EFI_GRAPHICS_OUTPUT_PROTOCOL * Graphics = NULL; + + Print(L"Searching for GOP\n"); + + EFI_STATUS localteprotocolstat = uefi_call_wrapper(BS->LocateProtocol, 3, &EfiGOPGuid, NULL, &Graphics); + + if(localteprotocolstat != EFI_SUCCESS) + { + Print(L"Failed to locate GOP\n"); + } + + // we now search for a 1024x768 mode with a bit depth of 32bits + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE * GOPMode; + + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION * GOPInfo = NULL; + + GOPMode = Graphics->Mode; + + UINT32 MaxModes = GOPMode->MaxMode; + + UINTN infosize = 0; + + uefi_call_wrapper(Graphics->QueryMode, 4, Graphics, 0, &infosize, &GOPMode); + + Print(L"Size of GOP Info: %d\n", infosize); + + // print information about the available modes + UINT32 i; + uint64_t foundmode = 0; + + for(i = 0; i < MaxModes; ++i) + { + uefi_call_wrapper(Graphics->QueryMode, 4, Graphics, i, &infosize, &GOPInfo); + + /* + switch(GOPInfo->PixelFormat) + { + case PixelRedGreenBlueReserved8BitPerColor: + Print(L"RGBZ\n"); + break; + case PixelBlueGreenRedReserved8BitPerColor: + Print(L"BGRZ\n"); + break; + case PixelBitMask: + Print(L"By Mask\n"); + break; + case PixelBltOnly: + Print(L"Only Blt\n"); // this mode doesn't expose a linear framebuffer + default: + Print(L"Unknown\n"); + break; + } + */ + if(GOPInfo->HorizontalResolution == width && GOPInfo->VerticalResolution == height) + { + foundmode = i; + } + + // Print(L"Mode %d: Width: %d Height: %d\n", i, GOPInfo->HorizontalResolution, GOPInfo->VerticalResolution); + } + + uefi_call_wrapper(Graphics->SetMode, 2, Graphics, foundmode); // hardcoded to mode 2(1024x768), this is only tue for the cirrus vga that qemu exposes + uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); // clear the screen + //uefi_call_wrapper(Graphics->QueryMode, 4, Graphics, i, &infosize, &GOPInfo); + Print(L"Width: %d Height: %d Format: ", Graphics->Mode->Info->HorizontalResolution, Graphics->Mode->Info->VerticalResolution); + switch(Graphics->Mode->Info->PixelFormat) + { + case PixelRedGreenBlueReserved8BitPerColor: + Print(L"RGBZ\n"); + break; + case PixelBlueGreenRedReserved8BitPerColor: + Print(L"BGRZ\n"); + break; + case PixelBitMask: + Print(L"By Mask\n"); + break; + case PixelBltOnly: + Print(L"Only Blt\n"); + default: + Print(L"Unknown\n"); + break; + } + + Print(L"RedBitmask: %d\n", Graphics->Mode->Info->PixelInformation.RedMask); + Print(L"GreenBitmask: %d\n", Graphics->Mode->Info->PixelInformation.GreenMask); + Print(L"BlueBitmask: %d\n", Graphics->Mode->Info->PixelInformation.BlueMask); + Print(L"ReservedBitmask: %d\n", Graphics->Mode->Info->PixelInformation.ReservedMask); + Print(L"Pixels Per ScanLine: %d\n", Graphics->Mode->Info->PixelsPerScanLine); + + // pixels seem to be 4 bytes wide(32bits) + // format seems to be RGB Reserved + + //Print(L"FrameBuffer Size: %d\n", Graphics->Mode->FrameBufferSize); + //Print(L"FrameBuffer Addr: %d\n", Graphics->Mode->FrameBufferBase); + + return (void*)Graphics->Mode->FrameBufferBase; +} + diff --git a/bootloader/vga.h b/bootloader/vga.h new file mode 100644 index 0000000..ba0843c --- /dev/null +++ b/bootloader/vga.h @@ -0,0 +1,16 @@ +#ifndef VGA_H +#define VGA_H + +#include <efi.h> +#include <efilib.h> + +typedef struct _FBinfo +{ + int width; + int height; + +} FBinfo; + +void * EFIAPI SetVideoMode(int width, int height, int bitdepth); + +#endif // VGA_H diff --git a/bootloader/vmmem.c b/bootloader/vmmem.c new file mode 100644 index 0000000..f15c9ac --- /dev/null +++ b/bootloader/vmmem.c @@ -0,0 +1,25 @@ +#include "vmmem.h" + +//#include "paging_struct.h" + + +EFI_STATUS EFIAPI SetVM(IN UINTN size, IN UINTN descriptorsize, IN UINTN descriptorversion, EFI_MEMORY_DESCRIPTOR * map, void * kernel) +{ + + // the code for setting up paging should go here + + // edit the memory mapping so that the uefi runtime knows about it + + EFI_MEMORY_DESCRIPTOR * tmp = map; + + UINTN elements = size/descriptorsize; + UINTN i; + for(i = 0; i < elements; ++i) + { + tmp = (EFI_MEMORY_DESCRIPTOR*)(((EFI_PHYSICAL_ADDRESS)tmp + descriptorsize)); + tmp->VirtualStart = tmp->PhysicalStart; + } + + return uefi_call_wrapper(RT->SetVirtualAddressMap, 4, size, descriptorsize, descriptorversion, map); +} + diff --git a/bootloader/vmmem.h b/bootloader/vmmem.h new file mode 100644 index 0000000..97252ed --- /dev/null +++ b/bootloader/vmmem.h @@ -0,0 +1,9 @@ +#ifndef VMMEM_H +#define VMMEM_H + +#include <efi.h> +#include <efilib.h> + +EFI_STATUS EFIAPI SetVM(IN UINTN size, IN UINTN descriptorsize, IN UINTN descriptorversion, EFI_MEMORY_DESCRIPTOR * map, void * kernel); + +#endif // VMMEM_H |
