1 /* 2 * Copyright 2019-2020 Haiku, Inc. All rights reserved. 3 * Released under the terms of the MIT License. 4 */ 5 6 7 #include <boot/platform.h> 8 #include <boot/stage2.h> 9 #include <boot/stdio.h> 10 11 #include "efi_platform.h" 12 13 14 extern "C" void arch_enter_kernel(struct kernel_args *kernelArgs, 15 addr_t kernelEntry, addr_t kernelStackTop); 16 17 18 void 19 arch_start_kernel(addr_t kernelEntry) 20 { 21 // Prepare to exit EFI boot services. 22 // Read the memory map. 23 // First call is to determine the buffer size. 24 size_t memory_map_size = 0; 25 efi_memory_descriptor dummy; 26 efi_memory_descriptor *memory_map; 27 size_t map_key; 28 size_t descriptor_size; 29 uint32_t descriptor_version; 30 if (kBootServices->GetMemoryMap(&memory_map_size, &dummy, &map_key, 31 &descriptor_size, &descriptor_version) != EFI_BUFFER_TOO_SMALL) { 32 panic("Unable to determine size of system memory map"); 33 } 34 35 // Allocate a buffer twice as large as needed just in case it gets bigger 36 // between calls to ExitBootServices. 37 size_t actual_memory_map_size = memory_map_size * 2; 38 memory_map 39 = (efi_memory_descriptor *)kernel_args_malloc(actual_memory_map_size); 40 41 if (memory_map == NULL) 42 panic("Unable to allocate memory map."); 43 44 // Read (and print) the memory map. 45 memory_map_size = actual_memory_map_size; 46 if (kBootServices->GetMemoryMap(&memory_map_size, memory_map, &map_key, 47 &descriptor_size, &descriptor_version) != EFI_SUCCESS) { 48 panic("Unable to fetch system memory map."); 49 } 50 51 addr_t addr = (addr_t)memory_map; 52 dprintf("System provided memory map:\n"); 53 for (size_t i = 0; i < memory_map_size / descriptor_size; ++i) { 54 efi_memory_descriptor *entry 55 = (efi_memory_descriptor *)(addr + i * descriptor_size); 56 dprintf(" %#lx-%#lx %#lx %#x %#lx\n", entry->PhysicalStart, 57 entry->PhysicalStart + entry->NumberOfPages * B_PAGE_SIZE, 58 entry->VirtualStart, entry->Type, entry->Attribute); 59 } 60 61 // Attempt to fetch the memory map and exit boot services. 62 // This needs to be done in a loop, as ExitBootServices can change the 63 // memory map. 64 // Even better: Only GetMemoryMap and ExitBootServices can be called after 65 // the first call to ExitBootServices, as the firmware is permitted to 66 // partially exit. This is why twice as much space was allocated for the 67 // memory map, as it's impossible to allocate more now. 68 // A changing memory map shouldn't affect the generated page tables, as 69 // they only needed to know about the maximum address, not any specific 70 // entry. 71 dprintf("Calling ExitBootServices. So long, EFI!\n"); 72 while (true) { 73 if (kBootServices->ExitBootServices(kImage, map_key) == EFI_SUCCESS) { 74 // The console was provided by boot services, disable it. 75 stdout = NULL; 76 stderr = NULL; 77 // Can we adjust gKernelArgs.platform_args.serial_base_ports[0] 78 // to something fixed in qemu for debugging? 79 break; 80 } 81 82 memory_map_size = actual_memory_map_size; 83 if (kBootServices->GetMemoryMap(&memory_map_size, memory_map, &map_key, 84 &descriptor_size, &descriptor_version) != EFI_SUCCESS) { 85 panic("Unable to fetch system memory map."); 86 } 87 } 88 89 // Update EFI, generate final kernel physical memory map, etc. 90 //arch_mmu_post_efi_setup(memory_map_size, memory_map, 91 // descriptor_size, descriptor_version); 92 93 //smp_boot_other_cpus(final_pml4, kernelEntry); 94 95 // Enter the kernel! 96 arch_enter_kernel(&gKernelArgs, kernelEntry, 97 gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size); 98 } 99