Linux.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. /** @file
  2. Copyright (c) 2011 - 2019 Intel Corporation. All rights reserved. <BR>
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. **/
  5. #include "LoadLinuxLib.h"
  6. /**
  7. A simple check of the kernel setup image
  8. An assumption is made that the size of the data is at least the
  9. size of struct boot_params.
  10. @param[in] KernelSetup - The kernel setup image
  11. @retval EFI_SUCCESS - The kernel setup looks valid and supported
  12. @retval EFI_INVALID_PARAMETER - KernelSetup was NULL
  13. @retval EFI_UNSUPPORTED - The kernel setup is not valid or supported
  14. **/
  15. STATIC
  16. EFI_STATUS
  17. EFIAPI
  18. BasicKernelSetupCheck (
  19. IN VOID *KernelSetup
  20. )
  21. {
  22. return LoadLinuxCheckKernelSetup(KernelSetup, sizeof (struct boot_params));
  23. }
  24. EFI_STATUS
  25. EFIAPI
  26. LoadLinuxCheckKernelSetup (
  27. IN VOID *KernelSetup,
  28. IN UINTN KernelSetupSize
  29. )
  30. {
  31. struct boot_params *Bp;
  32. if (KernelSetup == NULL) {
  33. return EFI_INVALID_PARAMETER;
  34. }
  35. if (KernelSetupSize < sizeof (*Bp)) {
  36. return EFI_UNSUPPORTED;
  37. }
  38. Bp = (struct boot_params*) KernelSetup;
  39. if ((Bp->hdr.signature != 0xAA55) || // Check boot sector signature
  40. (Bp->hdr.header != SETUP_HDR) ||
  41. (Bp->hdr.version < 0x205) || // We only support relocatable kernels
  42. (!Bp->hdr.relocatable_kernel)
  43. ) {
  44. return EFI_UNSUPPORTED;
  45. } else {
  46. return EFI_SUCCESS;
  47. }
  48. }
  49. UINTN
  50. EFIAPI
  51. LoadLinuxGetKernelSize (
  52. IN VOID *KernelSetup,
  53. IN UINTN KernelSize
  54. )
  55. {
  56. struct boot_params *Bp;
  57. if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup))) {
  58. return 0;
  59. }
  60. Bp = (struct boot_params*) KernelSetup;
  61. if (Bp->hdr.version > 0x20a) {
  62. return Bp->hdr.init_size;
  63. } else {
  64. //
  65. // Add extra size for kernel decompression
  66. //
  67. return 3 * KernelSize;
  68. }
  69. }
  70. VOID*
  71. EFIAPI
  72. LoadLinuxAllocateKernelSetupPages (
  73. IN UINTN Pages
  74. )
  75. {
  76. EFI_STATUS Status;
  77. EFI_PHYSICAL_ADDRESS Address;
  78. Address = BASE_1GB;
  79. Status = gBS->AllocatePages (
  80. AllocateMaxAddress,
  81. EfiLoaderData,
  82. Pages,
  83. &Address
  84. );
  85. if (!EFI_ERROR (Status)) {
  86. return (VOID*)(UINTN) Address;
  87. } else {
  88. return NULL;
  89. }
  90. }
  91. EFI_STATUS
  92. EFIAPI
  93. LoadLinuxInitializeKernelSetup (
  94. IN VOID *KernelSetup
  95. )
  96. {
  97. EFI_STATUS Status;
  98. UINTN SetupEnd;
  99. struct boot_params *Bp;
  100. Status = BasicKernelSetupCheck (KernelSetup);
  101. if (EFI_ERROR (Status)) {
  102. return Status;
  103. }
  104. Bp = (struct boot_params*) KernelSetup;
  105. SetupEnd = 0x202 + (Bp->hdr.jump & 0xff);
  106. //
  107. // Clear all but the setup_header
  108. //
  109. ZeroMem (KernelSetup, 0x1f1);
  110. ZeroMem (((UINT8 *)KernelSetup) + SetupEnd, 4096 - SetupEnd);
  111. DEBUG ((EFI_D_INFO, "Cleared kernel setup 0-0x1f1, 0x%Lx-0x1000\n",
  112. (UINT64)SetupEnd));
  113. return EFI_SUCCESS;
  114. }
  115. VOID*
  116. EFIAPI
  117. LoadLinuxAllocateKernelPages (
  118. IN VOID *KernelSetup,
  119. IN UINTN Pages
  120. )
  121. {
  122. EFI_STATUS Status;
  123. EFI_PHYSICAL_ADDRESS KernelAddress;
  124. UINT32 Loop;
  125. struct boot_params *Bp;
  126. if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup))) {
  127. return NULL;
  128. }
  129. Bp = (struct boot_params*) KernelSetup;
  130. for (Loop = 1; Loop < 512; Loop++) {
  131. KernelAddress = MultU64x32 (
  132. 2 * Bp->hdr.kernel_alignment,
  133. Loop
  134. );
  135. Status = gBS->AllocatePages (
  136. AllocateAddress,
  137. EfiLoaderData,
  138. Pages,
  139. &KernelAddress
  140. );
  141. if (!EFI_ERROR (Status)) {
  142. return (VOID*)(UINTN) KernelAddress;
  143. }
  144. }
  145. return NULL;
  146. }
  147. VOID*
  148. EFIAPI
  149. LoadLinuxAllocateCommandLinePages (
  150. IN UINTN Pages
  151. )
  152. {
  153. EFI_STATUS Status;
  154. EFI_PHYSICAL_ADDRESS Address;
  155. Address = 0xa0000;
  156. Status = gBS->AllocatePages (
  157. AllocateMaxAddress,
  158. EfiLoaderData,
  159. Pages,
  160. &Address
  161. );
  162. if (!EFI_ERROR (Status)) {
  163. return (VOID*)(UINTN) Address;
  164. } else {
  165. return NULL;
  166. }
  167. }
  168. VOID*
  169. EFIAPI
  170. LoadLinuxAllocateInitrdPages (
  171. IN VOID *KernelSetup,
  172. IN UINTN Pages
  173. )
  174. {
  175. EFI_STATUS Status;
  176. EFI_PHYSICAL_ADDRESS Address;
  177. struct boot_params *Bp;
  178. if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup))) {
  179. return NULL;
  180. }
  181. Bp = (struct boot_params*) KernelSetup;
  182. Address = (EFI_PHYSICAL_ADDRESS)(UINTN) Bp->hdr.ramdisk_max;
  183. Status = gBS->AllocatePages (
  184. AllocateMaxAddress,
  185. EfiLoaderData,
  186. Pages,
  187. &Address
  188. );
  189. if (!EFI_ERROR (Status)) {
  190. return (VOID*)(UINTN) Address;
  191. } else {
  192. return NULL;
  193. }
  194. }
  195. STATIC
  196. VOID
  197. SetupLinuxMemmap (
  198. IN OUT struct boot_params *Bp
  199. )
  200. {
  201. EFI_STATUS Status;
  202. UINT8 TmpMemoryMap[1];
  203. UINTN MapKey;
  204. UINTN DescriptorSize;
  205. UINT32 DescriptorVersion;
  206. UINTN MemoryMapSize;
  207. EFI_MEMORY_DESCRIPTOR *MemoryMap;
  208. EFI_MEMORY_DESCRIPTOR *MemoryMapPtr;
  209. UINTN Index;
  210. struct efi_info *Efi;
  211. struct e820_entry *LastE820;
  212. struct e820_entry *E820;
  213. UINTN E820EntryCount;
  214. EFI_PHYSICAL_ADDRESS LastEndAddr;
  215. //
  216. // Get System MemoryMapSize
  217. //
  218. MemoryMapSize = sizeof (TmpMemoryMap);
  219. Status = gBS->GetMemoryMap (
  220. &MemoryMapSize,
  221. (EFI_MEMORY_DESCRIPTOR *)TmpMemoryMap,
  222. &MapKey,
  223. &DescriptorSize,
  224. &DescriptorVersion
  225. );
  226. ASSERT (Status == EFI_BUFFER_TOO_SMALL);
  227. //
  228. // Enlarge space here, because we will allocate pool now.
  229. //
  230. MemoryMapSize += EFI_PAGE_SIZE;
  231. Status = gBS->AllocatePool (
  232. EfiLoaderData,
  233. MemoryMapSize,
  234. (VOID **) &MemoryMap
  235. );
  236. ASSERT_EFI_ERROR (Status);
  237. //
  238. // Get System MemoryMap
  239. //
  240. Status = gBS->GetMemoryMap (
  241. &MemoryMapSize,
  242. MemoryMap,
  243. &MapKey,
  244. &DescriptorSize,
  245. &DescriptorVersion
  246. );
  247. ASSERT_EFI_ERROR (Status);
  248. LastE820 = NULL;
  249. E820 = &Bp->e820_map[0];
  250. E820EntryCount = 0;
  251. LastEndAddr = 0;
  252. MemoryMapPtr = MemoryMap;
  253. for (Index = 0; Index < (MemoryMapSize / DescriptorSize); Index++) {
  254. UINTN E820Type = 0;
  255. if (MemoryMap->NumberOfPages == 0) {
  256. continue;
  257. }
  258. switch(MemoryMap->Type) {
  259. case EfiReservedMemoryType:
  260. case EfiRuntimeServicesCode:
  261. case EfiRuntimeServicesData:
  262. case EfiMemoryMappedIO:
  263. case EfiMemoryMappedIOPortSpace:
  264. case EfiPalCode:
  265. E820Type = E820_RESERVED;
  266. break;
  267. case EfiUnusableMemory:
  268. E820Type = E820_UNUSABLE;
  269. break;
  270. case EfiACPIReclaimMemory:
  271. E820Type = E820_ACPI;
  272. break;
  273. case EfiLoaderCode:
  274. case EfiLoaderData:
  275. case EfiBootServicesCode:
  276. case EfiBootServicesData:
  277. case EfiConventionalMemory:
  278. E820Type = E820_RAM;
  279. break;
  280. case EfiACPIMemoryNVS:
  281. E820Type = E820_NVS;
  282. break;
  283. default:
  284. DEBUG ((
  285. EFI_D_ERROR,
  286. "Invalid EFI memory descriptor type (0x%x)!\n",
  287. MemoryMap->Type
  288. ));
  289. continue;
  290. }
  291. if ((LastE820 != NULL) &&
  292. (LastE820->type == (UINT32) E820Type) &&
  293. (MemoryMap->PhysicalStart == LastEndAddr)) {
  294. LastE820->size += EFI_PAGES_TO_SIZE ((UINTN) MemoryMap->NumberOfPages);
  295. LastEndAddr += EFI_PAGES_TO_SIZE ((UINTN) MemoryMap->NumberOfPages);
  296. } else {
  297. if (E820EntryCount >= (sizeof (Bp->e820_map) / sizeof (Bp->e820_map[0]))) {
  298. break;
  299. }
  300. E820->type = (UINT32) E820Type;
  301. E820->addr = MemoryMap->PhysicalStart;
  302. E820->size = EFI_PAGES_TO_SIZE ((UINTN) MemoryMap->NumberOfPages);
  303. LastE820 = E820;
  304. LastEndAddr = E820->addr + E820->size;
  305. E820++;
  306. E820EntryCount++;
  307. }
  308. //
  309. // Get next item
  310. //
  311. MemoryMap = (EFI_MEMORY_DESCRIPTOR *)((UINTN)MemoryMap + DescriptorSize);
  312. }
  313. Bp->e820_entries = (UINT8) E820EntryCount;
  314. Efi = &Bp->efi_info;
  315. Efi->efi_systab = (UINT32)(UINTN) gST;
  316. Efi->efi_memdesc_size = (UINT32) DescriptorSize;
  317. Efi->efi_memdesc_version = DescriptorVersion;
  318. Efi->efi_memmap = (UINT32)(UINTN) MemoryMapPtr;
  319. Efi->efi_memmap_size = (UINT32) MemoryMapSize;
  320. #ifdef MDE_CPU_IA32
  321. Efi->efi_loader_signature = SIGNATURE_32 ('E', 'L', '3', '2');
  322. #else
  323. Efi->efi_systab_hi = (UINT32) (((UINT64)(UINTN) gST) >> 32);
  324. Efi->efi_memmap_hi = (UINT32) (((UINT64)(UINTN) MemoryMapPtr) >> 32);
  325. Efi->efi_loader_signature = SIGNATURE_32 ('E', 'L', '6', '4');
  326. #endif
  327. gBS->ExitBootServices (gImageHandle, MapKey);
  328. }
  329. EFI_STATUS
  330. EFIAPI
  331. LoadLinuxSetCommandLine (
  332. IN OUT VOID *KernelSetup,
  333. IN CHAR8 *CommandLine
  334. )
  335. {
  336. EFI_STATUS Status;
  337. struct boot_params *Bp;
  338. Status = BasicKernelSetupCheck (KernelSetup);
  339. if (EFI_ERROR (Status)) {
  340. return Status;
  341. }
  342. Bp = (struct boot_params*) KernelSetup;
  343. Bp->hdr.cmd_line_ptr = (UINT32)(UINTN) CommandLine;
  344. return EFI_SUCCESS;
  345. }
  346. EFI_STATUS
  347. EFIAPI
  348. LoadLinuxSetInitrd (
  349. IN OUT VOID *KernelSetup,
  350. IN VOID *Initrd,
  351. IN UINTN InitrdSize
  352. )
  353. {
  354. EFI_STATUS Status;
  355. struct boot_params *Bp;
  356. Status = BasicKernelSetupCheck (KernelSetup);
  357. if (EFI_ERROR (Status)) {
  358. return Status;
  359. }
  360. Bp = (struct boot_params*) KernelSetup;
  361. Bp->hdr.ramdisk_start = (UINT32)(UINTN) Initrd;
  362. Bp->hdr.ramdisk_len = (UINT32) InitrdSize;
  363. return EFI_SUCCESS;
  364. }
  365. STATIC VOID
  366. FindBits (
  367. unsigned long Mask,
  368. UINT8 *Pos,
  369. UINT8 *Size
  370. )
  371. {
  372. UINT8 First, Len;
  373. First = 0;
  374. Len = 0;
  375. if (Mask) {
  376. while (!(Mask & 0x1)) {
  377. Mask = Mask >> 1;
  378. First++;
  379. }
  380. while (Mask & 0x1) {
  381. Mask = Mask >> 1;
  382. Len++;
  383. }
  384. }
  385. *Pos = First;
  386. *Size = Len;
  387. }
  388. STATIC
  389. EFI_STATUS
  390. SetupGraphicsFromGop (
  391. struct screen_info *Si,
  392. EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop
  393. )
  394. {
  395. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
  396. EFI_STATUS Status;
  397. UINTN Size;
  398. Status = Gop->QueryMode(Gop, Gop->Mode->Mode, &Size, &Info);
  399. if (EFI_ERROR (Status)) {
  400. return Status;
  401. }
  402. /* We found a GOP */
  403. /* EFI framebuffer */
  404. Si->orig_video_isVGA = 0x70;
  405. Si->orig_x = 0;
  406. Si->orig_y = 0;
  407. Si->orig_video_page = 0;
  408. Si->orig_video_mode = 0;
  409. Si->orig_video_cols = 0;
  410. Si->orig_video_lines = 0;
  411. Si->orig_video_ega_bx = 0;
  412. Si->orig_video_points = 0;
  413. Si->lfb_base = (UINT32) Gop->Mode->FrameBufferBase;
  414. Si->lfb_size = (UINT32) Gop->Mode->FrameBufferSize;
  415. Si->lfb_width = (UINT16) Info->HorizontalResolution;
  416. Si->lfb_height = (UINT16) Info->VerticalResolution;
  417. Si->pages = 1;
  418. Si->vesapm_seg = 0;
  419. Si->vesapm_off = 0;
  420. if (Info->PixelFormat == PixelRedGreenBlueReserved8BitPerColor) {
  421. Si->lfb_depth = 32;
  422. Si->red_size = 8;
  423. Si->red_pos = 0;
  424. Si->green_size = 8;
  425. Si->green_pos = 8;
  426. Si->blue_size = 8;
  427. Si->blue_pos = 16;
  428. Si->rsvd_size = 8;
  429. Si->rsvd_pos = 24;
  430. Si->lfb_linelength = (UINT16) (Info->PixelsPerScanLine * 4);
  431. } else if (Info->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
  432. Si->lfb_depth = 32;
  433. Si->red_size = 8;
  434. Si->red_pos = 16;
  435. Si->green_size = 8;
  436. Si->green_pos = 8;
  437. Si->blue_size = 8;
  438. Si->blue_pos = 0;
  439. Si->rsvd_size = 8;
  440. Si->rsvd_pos = 24;
  441. Si->lfb_linelength = (UINT16) (Info->PixelsPerScanLine * 4);
  442. } else if (Info->PixelFormat == PixelBitMask) {
  443. FindBits(Info->PixelInformation.RedMask,
  444. &Si->red_pos, &Si->red_size);
  445. FindBits(Info->PixelInformation.GreenMask,
  446. &Si->green_pos, &Si->green_size);
  447. FindBits(Info->PixelInformation.BlueMask,
  448. &Si->blue_pos, &Si->blue_size);
  449. FindBits(Info->PixelInformation.ReservedMask,
  450. &Si->rsvd_pos, &Si->rsvd_size);
  451. Si->lfb_depth = Si->red_size + Si->green_size +
  452. Si->blue_size + Si->rsvd_size;
  453. Si->lfb_linelength = (UINT16) ((Info->PixelsPerScanLine * Si->lfb_depth) / 8);
  454. } else {
  455. Si->lfb_depth = 4;
  456. Si->red_size = 0;
  457. Si->red_pos = 0;
  458. Si->green_size = 0;
  459. Si->green_pos = 0;
  460. Si->blue_size = 0;
  461. Si->blue_pos = 0;
  462. Si->rsvd_size = 0;
  463. Si->rsvd_pos = 0;
  464. Si->lfb_linelength = Si->lfb_width / 2;
  465. }
  466. return Status;
  467. }
  468. STATIC
  469. EFI_STATUS
  470. SetupGraphics (
  471. IN OUT struct boot_params *Bp
  472. )
  473. {
  474. EFI_STATUS Status;
  475. EFI_HANDLE *HandleBuffer;
  476. UINTN HandleCount;
  477. UINTN Index;
  478. EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
  479. ZeroMem ((VOID*)&Bp->screen_info, sizeof(Bp->screen_info));
  480. Status = gBS->LocateHandleBuffer (
  481. ByProtocol,
  482. &gEfiGraphicsOutputProtocolGuid,
  483. NULL,
  484. &HandleCount,
  485. &HandleBuffer
  486. );
  487. if (!EFI_ERROR (Status)) {
  488. for (Index = 0; Index < HandleCount; Index++) {
  489. Status = gBS->HandleProtocol (
  490. HandleBuffer[Index],
  491. &gEfiGraphicsOutputProtocolGuid,
  492. (VOID*) &Gop
  493. );
  494. if (EFI_ERROR (Status)) {
  495. continue;
  496. }
  497. Status = SetupGraphicsFromGop (&Bp->screen_info, Gop);
  498. if (!EFI_ERROR (Status)) {
  499. FreePool (HandleBuffer);
  500. return EFI_SUCCESS;
  501. }
  502. }
  503. FreePool (HandleBuffer);
  504. }
  505. return EFI_NOT_FOUND;
  506. }
  507. STATIC
  508. EFI_STATUS
  509. SetupLinuxBootParams (
  510. IN OUT struct boot_params *Bp
  511. )
  512. {
  513. SetupGraphics (Bp);
  514. SetupLinuxMemmap (Bp);
  515. return EFI_SUCCESS;
  516. }
  517. EFI_STATUS
  518. EFIAPI
  519. LoadLinux (
  520. IN VOID *Kernel,
  521. IN OUT VOID *KernelSetup
  522. )
  523. {
  524. EFI_STATUS Status;
  525. struct boot_params *Bp;
  526. Status = BasicKernelSetupCheck (KernelSetup);
  527. if (EFI_ERROR (Status)) {
  528. return Status;
  529. }
  530. Bp = (struct boot_params *) KernelSetup;
  531. if (Bp->hdr.version < 0x205 || !Bp->hdr.relocatable_kernel) {
  532. //
  533. // We only support relocatable kernels
  534. //
  535. return EFI_UNSUPPORTED;
  536. }
  537. InitLinuxDescriptorTables ();
  538. Bp->hdr.code32_start = (UINT32)(UINTN) Kernel;
  539. if (Bp->hdr.version >= 0x20c && Bp->hdr.handover_offset &&
  540. (Bp->hdr.xloadflags & (sizeof (UINTN) == 4 ? BIT2 : BIT3))) {
  541. DEBUG ((EFI_D_INFO, "Jumping to kernel EFI handover point at ofs %x\n", Bp->hdr.handover_offset));
  542. DisableInterrupts ();
  543. JumpToUefiKernel ((VOID*) gImageHandle, (VOID*) gST, KernelSetup, Kernel);
  544. }
  545. //
  546. // Old kernels without EFI handover protocol
  547. //
  548. SetupLinuxBootParams (KernelSetup);
  549. DEBUG ((EFI_D_INFO, "Jumping to kernel\n"));
  550. DisableInterrupts ();
  551. SetLinuxDescriptorTables ();
  552. JumpToKernel (Kernel, (VOID*) KernelSetup);
  553. return EFI_SUCCESS;
  554. }