1 /** @file 2 3 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR> 4 This program and the accompanying materials 5 are licensed and made available under the terms and conditions of the BSD License 6 which accompanies this distribution. The full text of the license may be found at 7 http://opensource.org/licenses/bsd-license.php 8 9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 12 **/ 13 14 #include <Uefi.h> 15 16 #include <Library/BaseLib.h> 17 #include <Library/DebugLib.h> 18 #include <Library/LoadLinuxLib.h> 19 #include <Library/MemoryAllocationLib.h> 20 #include <Library/QemuFwCfgLib.h> 21 #include <Library/UefiBootServicesTableLib.h> 22 #include <Library/UefiLib.h> 23 24 25 EFI_STATUS 26 TryRunningQemuKernel ( 27 VOID 28 ) 29 { 30 EFI_STATUS Status; 31 UINTN KernelSize; 32 UINTN KernelInitialSize; 33 VOID *KernelBuf; 34 UINTN SetupSize; 35 VOID *SetupBuf; 36 UINTN CommandLineSize; 37 CHAR8 *CommandLine; 38 UINTN InitrdSize; 39 VOID* InitrdData; 40 41 SetupBuf = NULL; 42 SetupSize = 0; 43 KernelBuf = NULL; 44 KernelInitialSize = 0; 45 CommandLine = NULL; 46 CommandLineSize = 0; 47 InitrdData = NULL; 48 InitrdSize = 0; 49 50 if (!QemuFwCfgIsAvailable ()) { 51 return EFI_NOT_FOUND; 52 } 53 54 QemuFwCfgSelectItem (QemuFwCfgItemKernelSize); 55 KernelSize = (UINTN) QemuFwCfgRead64 (); 56 57 QemuFwCfgSelectItem (QemuFwCfgItemKernelSetupSize); 58 SetupSize = (UINTN) QemuFwCfgRead64 (); 59 60 if (KernelSize == 0 || SetupSize == 0) { 61 DEBUG ((EFI_D_INFO, "qemu -kernel was not used.\n")); 62 return EFI_NOT_FOUND; 63 } 64 65 SetupBuf = LoadLinuxAllocateKernelSetupPages (EFI_SIZE_TO_PAGES (SetupSize)); 66 if (SetupBuf == NULL) { 67 DEBUG ((EFI_D_ERROR, "Unable to allocate memory for kernel setup!\n")); 68 return EFI_OUT_OF_RESOURCES; 69 } 70 71 DEBUG ((EFI_D_INFO, "Setup size: 0x%x\n", (UINT32) SetupSize)); 72 DEBUG ((EFI_D_INFO, "Reading kernel setup image ...")); 73 QemuFwCfgSelectItem (QemuFwCfgItemKernelSetupData); 74 QemuFwCfgReadBytes (SetupSize, SetupBuf); 75 DEBUG ((EFI_D_INFO, " [done]\n")); 76 77 Status = LoadLinuxCheckKernelSetup (SetupBuf, SetupSize); 78 if (EFI_ERROR (Status)) { 79 goto FreeAndReturn; 80 } 81 82 Status = LoadLinuxInitializeKernelSetup (SetupBuf); 83 if (EFI_ERROR (Status)) { 84 goto FreeAndReturn; 85 } 86 87 KernelInitialSize = LoadLinuxGetKernelSize (SetupBuf, KernelSize); 88 if (KernelInitialSize == 0) { 89 Status = EFI_UNSUPPORTED; 90 goto FreeAndReturn; 91 } 92 93 KernelBuf = LoadLinuxAllocateKernelPages ( 94 SetupBuf, 95 EFI_SIZE_TO_PAGES (KernelInitialSize)); 96 if (KernelBuf == NULL) { 97 DEBUG ((EFI_D_ERROR, "Unable to allocate memory for kernel!\n")); 98 Status = EFI_OUT_OF_RESOURCES; 99 goto FreeAndReturn; 100 } 101 102 DEBUG ((EFI_D_INFO, "Kernel size: 0x%x\n", (UINT32) KernelSize)); 103 DEBUG ((EFI_D_INFO, "Reading kernel image ...")); 104 QemuFwCfgSelectItem (QemuFwCfgItemKernelData); 105 QemuFwCfgReadBytes (KernelSize, KernelBuf); 106 DEBUG ((EFI_D_INFO, " [done]\n")); 107 108 QemuFwCfgSelectItem (QemuFwCfgItemCommandLineSize); 109 CommandLineSize = (UINTN) QemuFwCfgRead64 (); 110 111 if (CommandLineSize > 0) { 112 CommandLine = LoadLinuxAllocateCommandLinePages ( 113 EFI_SIZE_TO_PAGES (CommandLineSize)); 114 QemuFwCfgSelectItem (QemuFwCfgItemCommandLineData); 115 QemuFwCfgReadBytes (CommandLineSize, CommandLine); 116 } else { 117 CommandLine = NULL; 118 } 119 120 Status = LoadLinuxSetCommandLine (SetupBuf, CommandLine); 121 if (EFI_ERROR (Status)) { 122 goto FreeAndReturn; 123 } 124 125 QemuFwCfgSelectItem (QemuFwCfgItemInitrdSize); 126 InitrdSize = (UINTN) QemuFwCfgRead64 (); 127 128 if (InitrdSize > 0) { 129 InitrdData = LoadLinuxAllocateInitrdPages ( 130 SetupBuf, 131 EFI_SIZE_TO_PAGES (InitrdSize) 132 ); 133 DEBUG ((EFI_D_INFO, "Initrd size: 0x%x\n", (UINT32) InitrdSize)); 134 DEBUG ((EFI_D_INFO, "Reading initrd image ...")); 135 QemuFwCfgSelectItem (QemuFwCfgItemInitrdData); 136 QemuFwCfgReadBytes (InitrdSize, InitrdData); 137 DEBUG ((EFI_D_INFO, " [done]\n")); 138 } else { 139 InitrdData = NULL; 140 } 141 142 Status = LoadLinuxSetInitrd (SetupBuf, InitrdData, InitrdSize); 143 if (EFI_ERROR (Status)) { 144 goto FreeAndReturn; 145 } 146 147 // 148 // Signal the EVT_SIGNAL_READY_TO_BOOT event 149 // 150 EfiSignalEventReadyToBoot(); 151 152 Status = LoadLinux (KernelBuf, SetupBuf); 153 154 FreeAndReturn: 155 if (SetupBuf != NULL) { 156 FreePages (SetupBuf, EFI_SIZE_TO_PAGES (SetupSize)); 157 } 158 if (KernelBuf != NULL) { 159 FreePages (KernelBuf, EFI_SIZE_TO_PAGES (KernelInitialSize)); 160 } 161 if (CommandLine != NULL) { 162 FreePages (CommandLine, EFI_SIZE_TO_PAGES (CommandLineSize)); 163 } 164 if (InitrdData != NULL) { 165 FreePages (InitrdData, EFI_SIZE_TO_PAGES (InitrdSize)); 166 } 167 168 return Status; 169 } 170 171