5 #include <syslinux/memscan.h>
6 #include <syslinux/firmware.h>
7 #include <syslinux/linux.h>
13 __export
uint16_t PXERetry
;
14 __export
char copyright_str
[] = "Copyright (C) 2011\n";
15 uint8_t SerialNotice
= 1;
16 __export
char syslinux_banner
[] = "Syslinux 5.x (EFI)\n";
17 char CurrentDirName
[CURRENTDIR_MAX
];
18 struct com32_sys_args __com32
;
20 uint32_t _IdleTimer
= 0;
21 char __lowmem_heap
[32];
22 uint32_t BIOS_timer_next
;
24 __export
uint8_t KbdMap
[256];
27 static inline EFI_STATUS
28 efi_close_protocol(EFI_HANDLE handle
, EFI_GUID
*guid
, EFI_HANDLE agent
,
29 EFI_HANDLE controller
)
31 return uefi_call_wrapper(BS
->CloseProtocol
, 4, handle
,
32 guid
, agent
, controller
);
35 struct efi_binding
*efi_create_binding(EFI_GUID
*bguid
, EFI_GUID
*pguid
)
37 EFI_SERVICE_BINDING
*sbp
;
38 struct efi_binding
*b
;
40 EFI_HANDLE protocol
, child
, *handles
= NULL
;
41 UINTN i
, nr_handles
= 0;
43 b
= malloc(sizeof(*b
));
47 status
= LibLocateHandle(ByProtocol
, bguid
, NULL
, &nr_handles
, &handles
);
48 if (status
!= EFI_SUCCESS
)
51 for (i
= 0; i
< nr_handles
; i
++) {
52 status
= uefi_call_wrapper(BS
->OpenProtocol
, 6, handles
[i
],
54 image_handle
, handles
[i
],
55 EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
56 if (status
== EFI_SUCCESS
)
59 uefi_call_wrapper(BS
->CloseProtocol
, 4, handles
[i
], bguid
,
60 image_handle
, handles
[i
]);
68 status
= uefi_call_wrapper(sbp
->CreateChild
, 2, sbp
, (EFI_HANDLE
*)&child
);
69 if (status
!= EFI_SUCCESS
)
72 status
= uefi_call_wrapper(BS
->OpenProtocol
, 6, child
,
73 pguid
, (void **)&protocol
,
75 EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
76 if (status
!= EFI_SUCCESS
)
79 b
->parent
= handles
[i
];
87 uefi_call_wrapper(sbp
->DestroyChild
, 2, sbp
, child
);
90 uefi_call_wrapper(BS
->CloseProtocol
, 4, handles
[i
], bguid
,
91 image_handle
, handles
[i
]);
98 void efi_destroy_binding(struct efi_binding
*b
, EFI_GUID
*guid
)
100 efi_close_protocol(b
->child
, guid
, image_handle
, b
->binding
);
101 uefi_call_wrapper(b
->binding
->DestroyChild
, 2, b
->binding
, b
->child
);
102 efi_close_protocol(b
->parent
, guid
, image_handle
, b
->parent
);
112 void comboot_cleanup_api(void)
116 void printf_init(void)
120 __export
void local_boot(uint16_t ax
)
124 void bios_timer_cleanup(void)
130 void __cdecl
core_farcall(uint32_t c
, const com32sys_t
*a
, com32sys_t
*b
)
134 __export
struct firmware
*firmware
= NULL
;
135 void *__syslinux_adv_ptr
;
136 size_t __syslinux_adv_size
;
137 char core_xfer_buf
[65536];
138 struct iso_boot_info
{
139 uint32_t pvd
; /* LBA of primary volume descriptor */
140 uint32_t file
; /* LBA of boot file */
141 uint32_t length
; /* Length of boot file */
142 uint32_t csum
; /* Checksum of boot file */
143 uint32_t reserved
[10]; /* Currently unused */
153 uint16_t BIOS_fbm
= 1;
156 __export
unsigned int __bcopyxx_len
= 0;
158 void gpxe_unload(void)
173 mstime_t
sem_down(struct semaphore
*sem
, mstime_t time
)
175 /* EFI is single threaded */
179 void sem_up(struct semaphore
*sem
)
181 /* EFI is single threaded */
184 __export
volatile uint32_t __ms_timer
= 0;
185 volatile uint32_t __jiffies
= 0;
187 void efi_write_char(uint8_t ch
, uint8_t attribute
)
189 SIMPLE_TEXT_OUTPUT_INTERFACE
*out
= ST
->ConOut
;
192 uefi_call_wrapper(out
->SetAttribute
, 2, out
, attribute
);
194 /* Lookup primary Unicode encoding in the system codepage */
195 c
[0] = codepage
.uni
[0][ch
];
198 uefi_call_wrapper(out
->OutputString
, 2, out
, c
);
201 static void efi_showcursor(const struct term_state
*st
)
203 SIMPLE_TEXT_OUTPUT_INTERFACE
*out
= ST
->ConOut
;
204 bool cursor
= st
->cursor
? true : false;
206 uefi_call_wrapper(out
->EnableCursor
, 2, out
, cursor
);
209 static void efi_set_cursor(int x
, int y
, bool visible
)
211 SIMPLE_TEXT_OUTPUT_INTERFACE
*out
= ST
->ConOut
;
213 uefi_call_wrapper(out
->SetCursorPosition
, 3, out
, x
, y
);
216 static void efi_scroll_up(uint8_t cols
, uint8_t rows
, uint8_t attribute
)
218 efi_write_char('\n', 0);
219 efi_write_char('\r', 0);
222 static void efi_get_mode(int *cols
, int *rows
)
224 SIMPLE_TEXT_OUTPUT_INTERFACE
*out
= ST
->ConOut
;
227 uefi_call_wrapper(out
->QueryMode
, 4, out
, out
->Mode
->Mode
, &c
, &r
);
232 static void efi_erase(int x0
, int y0
, int x1
, int y1
, uint8_t attribute
)
234 SIMPLE_TEXT_OUTPUT_INTERFACE
*out
= ST
->ConOut
;
237 efi_get_mode(&cols
, &rows
);
240 * The BIOS version of this function has the ability to erase
241 * parts or all of the screen - the UEFI console doesn't
242 * support this so we just set the cursor position unless
243 * we're clearing the whole screen.
245 if (!x0
&& y0
== (cols
- 1)) {
246 /* Really clear the screen */
247 uefi_call_wrapper(out
->ClearScreen
, 1, out
);
249 uefi_call_wrapper(out
->SetCursorPosition
, 3, out
, y1
, x1
);
253 static void efi_set_mode(uint16_t mode
)
257 static void efi_get_cursor(uint8_t *x
, uint8_t *y
)
259 SIMPLE_TEXT_OUTPUT_INTERFACE
*out
= ST
->ConOut
;
260 *x
= out
->Mode
->CursorColumn
;
261 *y
= out
->Mode
->CursorRow
;
264 struct output_ops efi_ops
= {
266 .write_char
= efi_write_char
,
267 .showcursor
= efi_showcursor
,
268 .set_cursor
= efi_set_cursor
,
269 .scroll_up
= efi_scroll_up
,
270 .get_mode
= efi_get_mode
,
271 .set_mode
= efi_set_mode
,
272 .get_cursor
= efi_get_cursor
,
276 static inline EFI_MEMORY_DESCRIPTOR
*
277 get_memory_map(UINTN
*nr_entries
, UINTN
*key
, UINTN
*desc_sz
,
280 return LibMemoryMap(nr_entries
, key
, desc_sz
, desc_ver
);
284 int efi_scan_memory(scan_memory_callback_t callback
, void *data
)
286 UINTN i
, nr_entries
, key
, desc_sz
;
291 buf
= (UINTN
)get_memory_map(&nr_entries
, &key
, &desc_sz
, &desc_ver
);
296 for (i
= 0; i
< nr_entries
; bufpos
+= desc_sz
, i
++) {
297 EFI_MEMORY_DESCRIPTOR
*m
;
301 m
= (EFI_MEMORY_DESCRIPTOR
*)bufpos
;
302 region_sz
= m
->NumberOfPages
* EFI_PAGE_SIZE
;
305 case EfiConventionalMemory
:
313 rv
= callback(data
, m
->PhysicalStart
, region_sz
, valid
);
318 FreePool((void *)buf
);
322 extern uint16_t *bios_free_mem
;
330 char efi_getchar(char *hi
)
332 SIMPLE_INPUT_INTERFACE
*in
= ST
->ConIn
;
337 status
= uefi_call_wrapper(in
->ReadKeyStroke
, 2, in
, &key
);
338 } while (status
== EFI_NOT_READY
);
341 return (char)key
.UnicodeChar
;
344 * We currently only handle scan codes that fit in 8 bits.
346 *hi
= (char)key
.ScanCode
;
350 int efi_pollchar(void)
352 SIMPLE_INPUT_INTERFACE
*in
= ST
->ConIn
;
355 status
= WaitForSingleEvent(in
->WaitForKey
, 1);
356 return status
!= EFI_TIMEOUT
;
359 struct input_ops efi_iops
= {
360 .getchar
= efi_getchar
,
361 .pollchar
= efi_pollchar
,
364 extern void efi_adv_init(void);
365 extern int efi_adv_write(void);
367 struct adv_ops efi_adv_ops
= {
368 .init
= efi_adv_init
,
369 .write
= efi_adv_write
,
373 uint32_t load_signature
;
376 uint32_t desc_version
;
378 uint32_t memmap_size
;
385 #define E820_RESERVED 2
388 #define E820_UNUSABLE 5
390 #define BOOT_SIGNATURE 0xaa55
391 #define SYSLINUX_EFILDR 0x30 /* Is this published value? */
392 #define DEFAULT_TIMER_TICK_DURATION 500000 /* 500000 == 500000 * 100 * 10^-9 == 50 msec */
393 #define DEFAULT_MSTIMER_INC 0x32 /* 50 msec */
401 struct screen_info screen_info
;
402 uint8_t _pad
[0x1c0 - sizeof(struct screen_info
)];
405 uint8_t e820_entries
;
406 uint8_t _pad3
[0x2d0 - 0x1e8 - sizeof(uint8_t)];
407 struct e820_entry e820_map
[E820MAX
];
410 /* Allocate boot parameter block aligned to page */
411 #define BOOT_PARAM_BLKSIZE EFI_SIZE_TO_PAGES(sizeof(struct boot_params)) * EFI_PAGE_SIZE
413 /* Routines in support of efi boot loader were obtained from
414 * http://git.kernel.org/?p=boot/efilinux/efilinux.git:
415 * kernel_jump(), handover_jump(),
416 * emalloc()/efree, alloc_pages/free_pages
417 * allocate_pool()/free_pool()
420 #if __SIZEOF_POINTER__ == 4
421 #define EFI_LOAD_SIG "EL32"
422 static inline void kernel_jump(EFI_PHYSICAL_ADDRESS kernel_start
,
423 struct boot_params
*boot_params
)
425 asm volatile ("cli \n"
429 :: "m" (boot_params
), "m" (kernel_start
));
432 static inline void handover_jump(EFI_HANDLE image
, struct boot_params
*bp
,
433 EFI_PHYSICAL_ADDRESS kernel_start
)
435 /* handover protocol not implemented yet; the linux header needs to be updated */
437 kernel_start
+= hdr
->handover_offset
;
439 asm volatile ("cli \n"
445 :: "m" (bp
), "m" (ST
),
446 "m" (image
), "m" (kernel_start
));
449 #elif __SIZEOF_POINTER__ == 8
450 #define EFI_LOAD_SIG "EL64"
451 typedef void(*kernel_func
)(void *, struct boot_params
*);
452 typedef void(*handover_func
)(void *, EFI_SYSTEM_TABLE
*, struct boot_params
*);
453 static inline void kernel_jump(EFI_PHYSICAL_ADDRESS kernel_start
,
454 struct boot_params
*boot_params
)
458 asm volatile ("cli");
460 /* The 64-bit kernel entry is 512 bytes after the start. */
461 kf
= (kernel_func
)kernel_start
+ 512;
464 * The first parameter is a dummy because the kernel expects
465 * boot_params in %[re]si.
467 kf(NULL
, boot_params
);
470 static inline void handover_jump(EFI_HANDLE image
, struct boot_params
*bp
,
471 EFI_PHYSICAL_ADDRESS kernel_start
)
474 /* handover protocol not implemented yet the linux header needs to be updated */
476 UINT32 offset
= bp
->hdr
.handover_offset
;
479 asm volatile ("cli");
481 /* The 64-bit kernel entry is 512 bytes after the start. */
484 hf
= (handover_func
)(kernel_start
+ offset
);
489 #error "unsupported architecture"
497 struct dt_desc gdt
= { 0x800, (uint64_t *)0 };
498 struct dt_desc idt
= { 0, 0 };
500 static inline EFI_MEMORY_DESCRIPTOR
*
501 get_mem_desc(addr_t memmap
, UINTN desc_sz
, int i
)
503 return (EFI_MEMORY_DESCRIPTOR
*)(memmap
+ (i
* desc_sz
));
506 EFI_HANDLE image_handle
;
508 static inline UINT64
round_up(UINT64 x
, UINT64 y
)
510 return (((x
- 1) | (y
- 1)) + 1);
513 static inline UINT64
round_down(UINT64 x
, UINT64 y
)
515 return (x
& ~(y
- 1));
518 static void find_addr(EFI_PHYSICAL_ADDRESS
*first
,
519 EFI_PHYSICAL_ADDRESS
*last
,
520 EFI_PHYSICAL_ADDRESS min
,
521 EFI_PHYSICAL_ADDRESS max
,
522 size_t size
, size_t align
)
524 EFI_MEMORY_DESCRIPTOR
*map
;
526 UINTN i
, nr_entries
, key
, desc_sz
;
528 map
= get_memory_map(&nr_entries
, &key
, &desc_sz
, &desc_ver
);
532 for (i
= 0; i
< nr_entries
; i
++) {
533 EFI_MEMORY_DESCRIPTOR
*m
;
534 EFI_PHYSICAL_ADDRESS best
;
537 m
= get_mem_desc((addr_t
)map
, desc_sz
, i
);
538 if (m
->Type
!= EfiConventionalMemory
)
541 if (m
->NumberOfPages
< EFI_SIZE_TO_PAGES(size
))
544 start
= m
->PhysicalStart
;
545 end
= m
->PhysicalStart
+ (m
->NumberOfPages
<< EFI_PAGE_SHIFT
);
550 /* What's the best address? */
551 if (start
< min
&& min
< end
)
554 best
= m
->PhysicalStart
;
556 start
= round_up(best
, align
);
560 /* Have we run out of space in this region? */
561 if (end
< start
|| (start
+ size
) > end
)
572 /* What's the best address? */
573 if (start
< max
&& max
< end
)
578 start
= round_down(best
, align
);
579 if (start
< min
|| start
< m
->PhysicalStart
)
591 * allocate_pages - Allocate memory pages from the system
592 * @atype: type of allocation to perform
593 * @mtype: type of memory to allocate
594 * @num_pages: number of contiguous 4KB pages to allocate
595 * @memory: used to return the address of allocated pages
597 * Allocate @num_pages physically contiguous pages from the system
598 * memory and return a pointer to the base of the allocation in
599 * @memory if the allocation succeeds. On success, the firmware memory
600 * map is updated accordingly.
602 * If @atype is AllocateAddress then, on input, @memory specifies the
603 * address at which to attempt to allocate the memory pages.
605 static inline EFI_STATUS
606 allocate_pages(EFI_ALLOCATE_TYPE atype
, EFI_MEMORY_TYPE mtype
,
607 UINTN num_pages
, EFI_PHYSICAL_ADDRESS
*memory
)
609 return uefi_call_wrapper(BS
->AllocatePages
, 4, atype
,
610 mtype
, num_pages
, memory
);
613 * free_pages - Return memory allocated by allocate_pages() to the firmware
614 * @memory: physical base address of the page range to be freed
615 * @num_pages: number of contiguous 4KB pages to free
617 * On success, the firmware memory map is updated accordingly.
619 static inline EFI_STATUS
620 free_pages(EFI_PHYSICAL_ADDRESS memory
, UINTN num_pages
)
622 return uefi_call_wrapper(BS
->FreePages
, 2, memory
, num_pages
);
625 static EFI_STATUS
allocate_addr(EFI_PHYSICAL_ADDRESS
*addr
, size_t size
)
627 UINTN npages
= EFI_SIZE_TO_PAGES(size
);
629 return uefi_call_wrapper(BS
->AllocatePages
, 4,
631 EfiLoaderData
, npages
,
635 * allocate_pool - Allocate pool memory
636 * @type: the type of pool to allocate
637 * @size: number of bytes to allocate from pool of @type
638 * @buffer: used to return the address of allocated memory
640 * Allocate memory from pool of @type. If the pool needs more memory
641 * pages are allocated from EfiConventionalMemory in order to grow the
644 * All allocations are eight-byte aligned.
646 static inline EFI_STATUS
647 allocate_pool(EFI_MEMORY_TYPE type
, UINTN size
, void **buffer
)
649 return uefi_call_wrapper(BS
->AllocatePool
, 3, type
, size
, buffer
);
653 * free_pool - Return pool memory to the system
654 * @buffer: the buffer to free
656 * Return @buffer to the system. The returned memory is marked as
657 * EfiConventionalMemory.
659 static inline EFI_STATUS
free_pool(void *buffer
)
661 return uefi_call_wrapper(BS
->FreePool
, 1, buffer
);
664 static void free_addr(EFI_PHYSICAL_ADDRESS addr
, size_t size
)
666 UINTN npages
= EFI_SIZE_TO_PAGES(size
);
668 uefi_call_wrapper(BS
->FreePages
, 2, addr
, npages
);
671 /* cancel the established timer */
672 static EFI_STATUS
cancel_timer(EFI_EVENT ev
)
674 return uefi_call_wrapper(BS
->SetTimer
, 3, ev
, TimerCancel
, 0);
677 /* Check if timer went off and update default timer counter */
678 void timer_handler(EFI_EVENT ev
, VOID
*ctx
)
680 __ms_timer
+= DEFAULT_MSTIMER_INC
;
684 /* Setup a default periodic timer */
685 static EFI_STATUS
setup_default_timer(EFI_EVENT
*ev
)
687 EFI_STATUS efi_status
;
690 efi_status
= uefi_call_wrapper( BS
->CreateEvent
, 5, EVT_TIMER
|EVT_NOTIFY_SIGNAL
, TPL_NOTIFY
, (EFI_EVENT_NOTIFY
)timer_handler
, NULL
, ev
);
691 if (efi_status
== EFI_SUCCESS
) {
692 efi_status
= uefi_call_wrapper(BS
->SetTimer
, 3, *ev
, TimerPeriodic
, DEFAULT_TIMER_TICK_DURATION
);
698 * emalloc - Allocate memory with a strict alignment requirement
699 * @size: size in bytes of the requested allocation
700 * @align: the required alignment of the allocation
701 * @addr: a pointer to the allocated address on success
703 * If we cannot satisfy @align we return 0.
705 EFI_STATUS
emalloc(UINTN size
, UINTN align
, EFI_PHYSICAL_ADDRESS
*addr
)
707 UINTN i
, nr_entries
, map_key
, desc_size
;
708 EFI_MEMORY_DESCRIPTOR
*map_buf
;
712 UINTN nr_pages
= EFI_SIZE_TO_PAGES(size
);
714 map_buf
= get_memory_map(&nr_entries
, &map_key
,
715 &desc_size
, &desc_version
);
721 for (i
= 0; i
< nr_entries
; i
++, d
+= desc_size
) {
722 EFI_MEMORY_DESCRIPTOR
*desc
;
723 EFI_PHYSICAL_ADDRESS start
, end
, aligned
;
725 desc
= (EFI_MEMORY_DESCRIPTOR
*)d
;
726 if (desc
->Type
!= EfiConventionalMemory
)
729 if (desc
->NumberOfPages
< nr_pages
)
732 start
= desc
->PhysicalStart
;
733 end
= start
+ (desc
->NumberOfPages
<< EFI_PAGE_SHIFT
);
735 /* Low-memory is super-precious! */
738 if (start
< 1 << 20) {
739 size
-= (1 << 20) - start
;
743 aligned
= (start
+ align
-1) & ~(align
-1);
745 if ((aligned
+ size
) <= end
) {
746 err
= allocate_pages(AllocateAddress
, EfiLoaderData
,
748 if (err
== EFI_SUCCESS
) {
756 err
= EFI_OUT_OF_RESOURCES
;
763 * efree - Return memory allocated with emalloc
764 * @memory: the address of the emalloc() allocation
765 * @size: the size of the allocation
767 void efree(EFI_PHYSICAL_ADDRESS memory
, UINTN size
)
769 UINTN nr_pages
= EFI_SIZE_TO_PAGES(size
);
771 free_pages(memory
, nr_pages
);
775 * Boots the linux kernel using the image and parameters to boot with.
776 * The EFI boot loader is reworked taking the cue from
777 * http://git.kernel.org/?p=boot/efilinux/efilinux.git on the need to
778 * cap key kernel data structures at * 0x3FFFFFFF.
779 * The kernel image, kernel command line and boot parameter block are copied
780 * into allocated memory areas that honor the address capping requirement
781 * prior to kernel handoff.
784 * Can we move this allocation requirement to com32 linux loader in order
785 * to avoid double copying kernel image?
787 int efi_boot_linux(void *kernel_buf
, size_t kernel_size
,
788 struct initramfs
*initramfs
,
789 struct setup_data
*setup_data
,
792 EFI_MEMORY_DESCRIPTOR
*map
;
793 struct linux_header
*hdr
, *bhdr
;
794 struct boot_params
*bp
;
795 struct boot_params
*_bp
; /* internal, in efi_physical below 0x3FFFFFFF */
796 struct screen_info
*si
;
797 struct e820_entry
*e820buf
, *e
;
799 EFI_PHYSICAL_ADDRESS last
, addr
, pref_address
, kernel_start
= 0;
800 UINT64 setup_sz
, init_size
= 0;
801 UINTN i
, nr_entries
, key
, desc_sz
;
805 char *_cmdline
= NULL
; /* internal, in efi_physical below 0x3FFFFFFF */
807 hdr
= (struct linux_header
*)kernel_buf
;
808 bp
= (struct boot_params
*)hdr
;
810 * We require a relocatable kernel because we have no control
811 * over free memory in the memory map.
813 if (hdr
->version
< 0x20a || !hdr
->relocatable_kernel
) {
814 printf("bzImage version 0x%x unsupported\n", hdr
->version
);
818 /* FIXME: check boot sector signature */
819 if (hdr
->boot_flag
!= BOOT_SIGNATURE
) {
820 printf("Invalid Boot signature 0x%x, bailing out\n", hdr
->boot_flag
);
824 setup_sz
= (hdr
->setup_sects
+ 1) * 512;
825 if (hdr
->version
>= 0x20a) {
826 pref_address
= hdr
->pref_address
;
827 init_size
= hdr
->init_size
;
829 pref_address
= 0x100000;
832 * We need to account for the fact that the kernel
833 * needs room for decompression, otherwise we could
834 * end up trashing other chunks of allocated memory.
836 init_size
= (kernel_size
- setup_sz
) * 3;
838 hdr
->type_of_loader
= SYSLINUX_EFILDR
; /* SYSLINUX boot loader module */
840 * The kernel expects cmdline to be allocated pretty low,
841 * Documentation/x86/boot.txt says,
843 * "The kernel command line can be located anywhere
844 * between the end of the setup heap and 0xA0000"
847 status
= allocate_pages(AllocateMaxAddress
, EfiLoaderData
,
848 EFI_SIZE_TO_PAGES(strlen(cmdline
) + 1),
850 if (status
!= EFI_SUCCESS
) {
851 printf("Failed to allocate memory for kernel command line, bailing out\n");
854 _cmdline
= (char *)(UINTN
)addr
;
855 memcpy(_cmdline
, cmdline
, strlen(cmdline
) + 1);
856 hdr
->cmd_line_ptr
= (UINT32
)(UINTN
)_cmdline
;
857 memset((char *)&bp
->screen_info
, 0x0, sizeof(bp
->screen_info
));
860 status
= allocate_pages(AllocateAddress
, EfiLoaderData
,
861 EFI_SIZE_TO_PAGES(init_size
), &addr
);
862 if (status
!= EFI_SUCCESS
) {
864 * We failed to allocate the preferred address, so
865 * just allocate some memory and hope for the best.
867 status
= emalloc(init_size
, hdr
->kernel_alignment
, &addr
);
868 if (status
!= EFI_SUCCESS
) {
869 printf("Failed to allocate memory for kernel image, bailing out\n");
874 /* FIXME: we copy the kernel into the physical memory allocated here
875 * The syslinux kernel image load elsewhere could allocate the EFI memory from here
876 * prior to copying kernel and save an extra copy
878 memcpy((void *)(UINTN
)kernel_start
, kernel_buf
+setup_sz
, kernel_size
-setup_sz
);
880 /* allocate for boot parameter block */
882 status
= allocate_pages(AllocateMaxAddress
, EfiLoaderData
,
883 BOOT_PARAM_BLKSIZE
, &addr
);
884 if (status
!= EFI_SUCCESS
) {
885 printf("Failed to allocate memory for kernel boot parameter block, bailing out\n");
889 _bp
= (struct boot_params
*)(UINTN
)addr
;
891 memset((void *)_bp
, 0x0, BOOT_PARAM_BLKSIZE
);
892 /* Copy the first two sectors to boot_params */
893 memcpy((char *)_bp
, kernel_buf
, 2 * 512);
894 bhdr
= (struct linux_header
*)_bp
;
895 bhdr
->code32_start
= (UINT32
)((UINT64
)kernel_start
);
897 dprintf("efi_boot_linux: kernel_start 0x%x kernel_size 0x%x initramfs 0x%x setup_data 0x%x cmdline 0x%x\n",
898 kernel_start
, kernel_size
, initramfs
, setup_data
, _cmdline
);
899 si
= &_bp
->screen_info
;
900 memset(si
, 0, sizeof(*si
));
904 * FIXME: implement handover protocol
905 * Use the kernel's EFI boot stub by invoking the handover
908 /* Allocate gdt consistent with the alignment for architecture */
909 status
= emalloc(gdt
.limit
, __SIZEOF_POINTER__
, (EFI_PHYSICAL_ADDRESS
*)&gdt
.base
);
910 if (status
!= EFI_SUCCESS
) {
911 printf("Failed to allocate memory for GDT, bailing out\n");
914 memset(gdt
.base
, 0x0, gdt
.limit
);
917 * 4Gb - (0x100000*0x1000 = 4Gb)
920 * granularity=4096, 386 (+5th nibble of limit)
922 gdt
.base
[2] = 0x00cf9a000000ffff;
925 * 4Gb - (0x100000*0x1000 = 4Gb)
928 * granularity=4096, 386 (+5th nibble of limit)
930 gdt
.base
[3] = 0x00cf92000000ffff;
932 /* Task segment value */
933 gdt
.base
[4] = 0x0080890000000000;
935 dprintf("efi_boot_linux: setup_sects %d kernel_size %d\n", hdr
->setup_sects
, kernel_size
);
938 * Figure out the size of the initramfs, and where to put it.
939 * We should put it at the highest possible address which is
940 * <= hdr->initrd_addr_max, which fits the entire initramfs.
942 irf_size
= initramfs_size(initramfs
); /* Handles initramfs == NULL */
944 struct initramfs
*ip
;
945 addr_t next_addr
, len
, pad
;
948 find_addr(NULL
, &last
, 0x1000, hdr
->initrd_addr_max
,
949 irf_size
, INITRAMFS_MAX_ALIGN
);
951 status
= allocate_addr(&last
, irf_size
);
953 if (!last
|| status
!= EFI_SUCCESS
) {
954 printf("Failed to allocate initramfs memory, bailing out\n");
958 bhdr
->ramdisk_image
= (uint32_t)last
;
959 bhdr
->ramdisk_size
= irf_size
;
961 /* Copy initramfs into allocated memory */
962 for (ip
= initramfs
->next
; ip
->len
; ip
= ip
->next
) {
964 next_addr
= last
+ len
;
967 * If this isn't the last entry, extend the
968 * zero-pad region to enforce the alignment of
972 pad
= -next_addr
& (ip
->next
->align
- 1);
978 memcpy((void *)(UINTN
)last
, ip
->data
, ip
->data_len
);
980 if (len
> ip
->data_len
)
981 memset((void *)(UINTN
)(last
+ ip
->data_len
), 0,
988 /* Build efi memory map */
989 map
= get_memory_map(&nr_entries
, &key
, &desc_sz
, &desc_ver
);
993 _bp
->efi
.memmap
= (uint32_t)(unsigned long)map
;
994 _bp
->efi
.memmap_size
= nr_entries
* desc_sz
;
995 _bp
->efi
.systab
= (uint32_t)(unsigned long)ST
;
996 _bp
->efi
.desc_size
= desc_sz
;
997 _bp
->efi
.desc_version
= desc_ver
;
998 #if defined(__x86_64__)
999 _bp
->efi
.systab_hi
= ((unsigned long)ST
) >> 32;
1000 _bp
->efi
.memmap_hi
= ((unsigned long)map
) >> 32;
1005 * Even though 'memmap' contains the memory map we provided
1006 * previously in efi_scan_memory(), we should recalculate the
1007 * e820 map because it will most likely have changed in the
1010 e
= e820buf
= _bp
->e820_map
;
1011 for (i
= 0; i
< nr_entries
&& i
< E820MAX
; i
++) {
1012 struct e820_entry
*prev
= NULL
;
1017 map
= get_mem_desc(_bp
->efi
.memmap
, desc_sz
, i
);
1018 e
->start
= map
->PhysicalStart
;
1019 e
->len
= map
->NumberOfPages
<< EFI_PAGE_SHIFT
;
1021 switch (map
->Type
) {
1022 case EfiReservedMemoryType
:
1023 case EfiRuntimeServicesCode
:
1024 case EfiRuntimeServicesData
:
1025 case EfiMemoryMappedIO
:
1026 case EfiMemoryMappedIOPortSpace
:
1028 e820_type
= E820_RESERVED
;
1031 case EfiUnusableMemory
:
1032 e820_type
= E820_UNUSABLE
;
1035 case EfiACPIReclaimMemory
:
1036 e820_type
= E820_ACPI
;
1041 case EfiBootServicesCode
:
1042 case EfiBootServicesData
:
1043 case EfiConventionalMemory
:
1044 e820_type
= E820_RAM
;
1047 case EfiACPIMemoryNVS
:
1048 e820_type
= E820_NVS
;
1054 e
->type
= e820_type
;
1056 /* Check for adjacent entries we can merge. */
1057 if (prev
&& (prev
->start
+ prev
->len
) == e
->start
&&
1058 prev
->type
== e
->type
)
1059 prev
->len
+= e
->len
;
1064 _bp
->e820_entries
= e
- e820buf
;
1066 dprintf("efi_boot_linux: exit boot services\n");
1067 status
= uefi_call_wrapper(BS
->ExitBootServices
, 2, image_handle
, key
);
1068 if (status
!= EFI_SUCCESS
) {
1069 printf("Failed to exit boot services: 0x%016lx\n", status
);
1072 memcpy(&_bp
->efi
.load_signature
, EFI_LOAD_SIG
, sizeof(uint32_t));
1074 asm volatile ("lidt %0" :: "m" (idt
));
1075 asm volatile ("lgdt %0" :: "m" (gdt
));
1077 kernel_jump(kernel_start
, _bp
);
1083 efree((EFI_PHYSICAL_ADDRESS
)(unsigned long)_cmdline
,
1084 strlen(_cmdline
) + 1);
1087 efree((EFI_PHYSICAL_ADDRESS
)(unsigned long)_bp
,
1088 BOOT_PARAM_BLKSIZE
);
1089 if (kernel_start
) efree(kernel_start
, init_size
);
1092 free_addr(last
, irf_size
);
1097 extern struct disk
*efi_disk_init(EFI_HANDLE
);
1098 extern void serialcfg(uint16_t *, uint16_t *, uint16_t *);
1100 extern struct vesa_ops efi_vesa_ops
;
1102 struct mem_ops efi_mem_ops
= {
1103 .malloc
= efi_malloc
,
1104 .realloc
= efi_realloc
,
1106 .scan_memory
= efi_scan_memory
,
1109 struct firmware efi_fw
= {
1111 .disk_init
= efi_disk_init
,
1114 .get_serial_console_info
= serialcfg
,
1115 .adv_ops
= &efi_adv_ops
,
1116 .boot_linux
= efi_boot_linux
,
1117 .vesa
= &efi_vesa_ops
,
1118 .mem
= &efi_mem_ops
,
1121 static inline void syslinux_register_efi(void)
1126 extern void init(void);
1127 extern const struct fs_ops vfat_fs_ops
;
1128 extern const struct fs_ops pxe_fs_ops
;
1130 char free_high_memory
[4096];
1132 extern char __bss_start
[];
1133 extern char __bss_end
[];
1135 static void efi_setcwd(CHAR16
*dp
)
1141 /* Search for the start of the last path component */
1142 for (i
= StrLen(dp
) - 1; i
>= 0; i
--) {
1143 if (dp
[i
] == '\\' || dp
[i
] == '/')
1147 if (i
< 0 || i
> CURRENTDIR_MAX
) {
1152 c8
= CurrentDirName
;
1155 for (j
= 0; j
< i
; j
++) {
1166 EFI_STATUS
efi_main(EFI_HANDLE image
, EFI_SYSTEM_TABLE
*table
)
1168 EFI_PXE_BASE_CODE
*pxe
;
1169 EFI_LOADED_IMAGE
*info
;
1170 EFI_STATUS status
= EFI_SUCCESS
;
1171 const struct fs_ops
*ops
[] = { NULL
, NULL
};
1172 unsigned long len
= (unsigned long)__bss_end
- (unsigned long)__bss_start
;
1173 static struct efi_disk_private priv
;
1174 SIMPLE_INPUT_INTERFACE
*in
;
1178 memset(__bss_start
, 0, len
);
1179 InitializeLib(image
, table
);
1181 image_handle
= image
;
1182 syslinux_register_efi();
1185 status
= uefi_call_wrapper(BS
->HandleProtocol
, 3, image
,
1186 &LoadedImageProtocol
, (void **)&info
);
1187 if (status
!= EFI_SUCCESS
) {
1188 Print(L
"Failed to lookup LoadedImageProtocol\n");
1192 status
= uefi_call_wrapper(BS
->HandleProtocol
, 3, info
->DeviceHandle
,
1193 &PxeBaseCodeProtocol
, (void **)&pxe
);
1194 if (status
!= EFI_SUCCESS
) {
1196 * Use device handle to set up the volume root to
1197 * proceed with ADV init.
1199 if (EFI_ERROR(efi_set_volroot(info
->DeviceHandle
))) {
1200 Print(L
"Failed to locate root device to prep for ");
1201 Print(L
"file operations & ADV initialization\n");
1205 ops
[0] = &vfat_fs_ops
;
1207 ops
[0] = &pxe_fs_ops
;
1209 /* setup timer for boot menu system support */
1210 status
= setup_default_timer(&timer_ev
);
1211 if (status
!= EFI_SUCCESS
) {
1212 printf("Failed to set up EFI timer support, bailing out\n");
1216 /* TODO: once all errors are captured in efi_errno, bail out if necessary */
1218 priv
.dev_handle
= info
->DeviceHandle
;
1221 * Set the current working directory, which should be the
1222 * directory that syslinux.efi resides in.
1224 efi_setcwd(DevicePathToStr(info
->FilePath
));
1226 fs_init(ops
, (void *)&priv
);
1229 * There may be pending user input that wasn't processed by
1230 * whatever application invoked us. Consume and discard that
1235 status
= uefi_call_wrapper(in
->ReadKeyStroke
, 2, in
, &key
);
1236 } while (status
!= EFI_NOT_READY
);
1240 /* load_env32() failed.. cancel timer and bailout */
1241 status
= cancel_timer(timer_ev
);
1242 if (status
!= EFI_SUCCESS
)
1243 Print(L
"Failed to cancel EFI timer: %x\n", status
);
1246 * Tell the firmware that Syslinux failed to load.
1248 status
= EFI_LOAD_ERROR
;