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