diff --git a/src/system/boot/arch/arm/Jamfile b/src/system/boot/arch/arm/Jamfile index dd9c2608f1..01d8481c9a 100644 --- a/src/system/boot/arch/arm/Jamfile +++ b/src/system/boot/arch/arm/Jamfile @@ -39,7 +39,6 @@ for platform in [ MultiBootSubDirSetup u-boot efi ] { $(kernelArchSources) arch_cpu.cpp - arch_start_kernel.S # Reuse a subset of kernel debugging. kernel_stubs.cpp diff --git a/src/system/boot/platform/efi/arch/arm/Jamfile b/src/system/boot/platform/efi/arch/arm/Jamfile index 64563a985e..b3791a1a04 100644 --- a/src/system/boot/platform/efi/arch/arm/Jamfile +++ b/src/system/boot/platform/efi/arch/arm/Jamfile @@ -11,7 +11,7 @@ for platform in [ MultiBootSubDirSetup efi ] { local arch_src = crt0-efi-$(TARGET_ARCH).S - #entry.S + entry.S relocation_func.cpp arch_smp.cpp arch_start.cpp diff --git a/src/system/boot/platform/efi/arch/arm/arch_start.cpp b/src/system/boot/platform/efi/arch/arm/arch_start.cpp index 17ac58a838..17a25044f7 100644 --- a/src/system/boot/platform/efi/arch/arm/arch_start.cpp +++ b/src/system/boot/platform/efi/arch/arm/arch_start.cpp @@ -8,9 +8,90 @@ #include #include +#include "efi_platform.h" + + +extern "C" void arch_enter_kernel(struct kernel_args *kernelArgs, + addr_t kernelEntry, addr_t kernelStackTop); void arch_start_kernel(addr_t kernelEntry) { - // Kernel Entry! + // Prepare to exit EFI boot services. + // Read the memory map. + // First call is to determine the buffer size. + size_t memory_map_size = 0; + efi_memory_descriptor dummy; + efi_memory_descriptor *memory_map; + size_t map_key; + size_t descriptor_size; + uint32_t descriptor_version; + if (kBootServices->GetMemoryMap(&memory_map_size, &dummy, &map_key, + &descriptor_size, &descriptor_version) != EFI_BUFFER_TOO_SMALL) { + panic("Unable to determine size of system memory map"); + } + + // Allocate a buffer twice as large as needed just in case it gets bigger + // between calls to ExitBootServices. + size_t actual_memory_map_size = memory_map_size * 2; + memory_map + = (efi_memory_descriptor *)kernel_args_malloc(actual_memory_map_size); + + if (memory_map == NULL) + panic("Unable to allocate memory map."); + + // Read (and print) the memory map. + memory_map_size = actual_memory_map_size; + if (kBootServices->GetMemoryMap(&memory_map_size, memory_map, &map_key, + &descriptor_size, &descriptor_version) != EFI_SUCCESS) { + panic("Unable to fetch system memory map."); + } + + addr_t addr = (addr_t)memory_map; + dprintf("System provided memory map:\n"); + for (size_t i = 0; i < memory_map_size / descriptor_size; ++i) { + efi_memory_descriptor *entry + = (efi_memory_descriptor *)(addr + i * descriptor_size); + dprintf(" %#lx-%#lx %#lx %#x %#lx\n", entry->PhysicalStart, + entry->PhysicalStart + entry->NumberOfPages * B_PAGE_SIZE, + entry->VirtualStart, entry->Type, entry->Attribute); + } + + // Attempt to fetch the memory map and exit boot services. + // This needs to be done in a loop, as ExitBootServices can change the + // memory map. + // Even better: Only GetMemoryMap and ExitBootServices can be called after + // the first call to ExitBootServices, as the firmware is permitted to + // partially exit. This is why twice as much space was allocated for the + // memory map, as it's impossible to allocate more now. + // A changing memory map shouldn't affect the generated page tables, as + // they only needed to know about the maximum address, not any specific + // entry. + dprintf("Calling ExitBootServices. So long, EFI!\n"); + while (true) { + if (kBootServices->ExitBootServices(kImage, map_key) == EFI_SUCCESS) { + // The console was provided by boot services, disable it. + stdout = NULL; + stderr = NULL; + // Can we adjust gKernelArgs.platform_args.serial_base_ports[0] + // to something fixed in qemu for debugging? + break; + } + + memory_map_size = actual_memory_map_size; + if (kBootServices->GetMemoryMap(&memory_map_size, memory_map, &map_key, + &descriptor_size, &descriptor_version) != EFI_SUCCESS) { + panic("Unable to fetch system memory map."); + } + } + + // Update EFI, generate final kernel physical memory map, etc. + //arch_mmu_post_efi_setup(memory_map_size, memory_map, + // descriptor_size, descriptor_version); + + //smp_boot_other_cpus(final_pml4, kernelEntry); + + // Enter the kernel! + arch_enter_kernel(&gKernelArgs, kernelEntry, + gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size); } diff --git a/src/system/boot/platform/efi/arch/arm/entry.S b/src/system/boot/platform/efi/arch/arm/entry.S new file mode 100644 index 0000000000..d8ea332dcf --- /dev/null +++ b/src/system/boot/platform/efi/arch/arm/entry.S @@ -0,0 +1,36 @@ +/* + * Copyright 2011, François Revol . + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#include + + + .text + +/* status_t arch_enter_kernel(struct kernel_args *kernelArgs, + addr_t kernelEntry, addr_t kernelStackTop); + + r0 - kernelArgs + r1 - kernelEntry + r2 - kernelStackTop +*/ +FUNCTION(arch_enter_kernel): + + // set the kernel stack + mov sp,r2 + + // set up kernel _start args + //mov r0,r0 // kernelArgs + mov r4,r1 + mov r1,#0 // currentCPU=0 + + // call the kernel + mov pc,r4 + + // return + mov r0,#-1 // B_ERROR + mov pc,lr + +FUNCTION_END(arch_enter_kernel) + diff --git a/src/system/boot/platform/efi/arch/x86_64/arch_start.cpp b/src/system/boot/platform/efi/arch/x86_64/arch_start.cpp index 01388634d9..d67f735633 100644 --- a/src/system/boot/platform/efi/arch/x86_64/arch_start.cpp +++ b/src/system/boot/platform/efi/arch/x86_64/arch_start.cpp @@ -73,7 +73,7 @@ arch_start_kernel(addr_t kernelEntry) efi_memory_descriptor *entry = (efi_memory_descriptor *)(addr + i * descriptor_size); dprintf(" %#lx-%#lx %#lx %#x %#lx\n", entry->PhysicalStart, - entry->PhysicalStart + entry->NumberOfPages * 4096, + entry->PhysicalStart + entry->NumberOfPages * B_PAGE_SIZE, entry->VirtualStart, entry->Type, entry->Attribute); } diff --git a/src/system/boot/platform/u-boot/arch/arm/Jamfile b/src/system/boot/platform/u-boot/arch/arm/Jamfile index 787b84f9af..99eaf47687 100644 --- a/src/system/boot/platform/u-boot/arch/arm/Jamfile +++ b/src/system/boot/platform/u-boot/arch/arm/Jamfile @@ -17,6 +17,9 @@ BootMergeObject boot_platform_u-boot_arm.o : # must come first to have _start_* at correct locations shell.S + # Kernel entry calls + arch_start_kernel.S + # Framebuffer drivers arch_framebuffer_920.cpp arch_framebuffer_bcm2835.cpp diff --git a/src/system/boot/arch/arm/arch_start_kernel.S b/src/system/boot/platform/u-boot/arch/arm/arch_start_kernel.S similarity index 100% rename from src/system/boot/arch/arm/arch_start_kernel.S rename to src/system/boot/platform/u-boot/arch/arm/arch_start_kernel.S