ekern

ekern.git
git clone git://git.lenczewski.org/ekern.git
Log | Files | Refs | README | LICENSE

efistub.c (2479B)


      1 #include "efi.h"
      2 
      3 #include "kernel.h"
      4 
      5 void
      6 efi_die(struct efi_system_table *table, c16 *msg);
      7 
      8 EFI_IMAGE_ENTRY_POINT(__efi_entry)
      9 {
     10 	efi_status_t err;
     11 
     12 	struct efi_simple_text_output_protocol *stdout = system_table->con_out;
     13 	stdout->reset(stdout, false);
     14 	stdout->output_string(stdout, u"UEFI\r\n");
     15 
     16 	struct efi_boot_services *boot_services = system_table->boot_services;
     17 	struct efi_boot_info boot_info;
     18 
     19 	/* TODO: find acpi data */
     20 
     21 	/* TODO: setup framebuffer */
     22 
     23 	/* exit UEFI boot services
     24 	 * NOTE: exit_boot_services() can return EFI_INVALID_PARAMETER, in
     25 	 *       which case the process needs to be restarted with a new
     26 	 *       memory map key
     27 	 */
     28 	do {
     29 		umm mem_map_size = 0, mem_map_key, descriptor_size;
     30 		u32 descriptor_version;
     31 
     32 		err = boot_services->get_memory_map(&mem_map_size, NULL,
     33 						    &mem_map_key,
     34 						    &descriptor_size,
     35 						    &descriptor_version);
     36 
     37 		if (err != EFI_BUFFER_TOO_SMALL || mem_map_size == 0)
     38 			efi_die(system_table, u"ERROR: failed to get memory map size\r\n");
     39 
     40 		/* overallocate memory map buffer to avoid second get_memory_map() error */
     41 		umm buf_size = mem_map_size + (4 * descriptor_size);
     42 		boot_info.memory_map.map_size = boot_info.memory_map.buf_size = buf_size;
     43 
     44 		err = boot_services->allocate_pool(EFI_LOADER_DATA,
     45 						   boot_info.memory_map.buf_size,
     46 						   (void **) &boot_info.memory_map.map);
     47 
     48 		if (err)
     49 			efi_die(system_table, u"ERROR: failed to allocate memory map buffer\r\n");
     50 
     51 		err = boot_services->get_memory_map(&boot_info.memory_map.map_size,
     52 						    boot_info.memory_map.map,
     53 						    &boot_info.memory_map.key,
     54 						    &boot_info.memory_map.desc_size,
     55 						    &boot_info.memory_map.desc_ver);
     56 
     57 		if (err) {
     58 			boot_services->free_pool(boot_info.memory_map.map);
     59 			efi_die(system_table, u"ERROR: failed to get memory map\r\n");
     60 		}
     61 
     62 		err = boot_services->exit_boot_services(image_handle,
     63 							boot_info.memory_map.key);
     64 
     65 		if (err == EFI_INVALID_PARAMETER) {
     66 			boot_services->free_pool(boot_info.memory_map.map);
     67 		} else {
     68 			efi_die(system_table, u"ERROR: failed to exit boot services\r\n");
     69 		}
     70 	} while (err == EFI_INVALID_PARAMETER);
     71 
     72 	/* go into the kernel proper */
     73 	ksetup(&boot_info);
     74 	kmain(&boot_info);
     75 
     76 	for (;;);
     77 
     78 	return EFI_SUCCESS;
     79 }
     80 
     81 void
     82 efi_die(struct efi_system_table *system_table, c16 *msg)
     83 {
     84 	system_table->con_out->output_string(system_table->con_out, msg);
     85 	system_table->runtime_services->reset_system(EFI_RESET_SHUTDOWN, EFI_LOAD_ERROR, 0, NULL);
     86 }