/* Allocate pages. Return the pointer to the first of allocated pages. */ void * grub_efi_allocate_pages_real (grub_efi_physical_address_t address, grub_efi_uintn_t pages, grub_efi_allocate_type_t alloctype, grub_efi_memory_type_t memtype) { grub_efi_status_t status; grub_efi_boot_services_t *b; /* Limit the memory access to less than 4GB for 32-bit platforms. */ if (address > GRUB_EFI_MAX_USABLE_ADDRESS) return 0; b = grub_efi_system_table->boot_services; status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &address); if (status != GRUB_EFI_SUCCESS) return 0; if (address == 0) { /* Uggh, the address 0 was allocated... This is too annoying, so reallocate another one. */ address = GRUB_EFI_MAX_USABLE_ADDRESS; status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &address); grub_efi_free_pages (0, pages); if (status != GRUB_EFI_SUCCESS) return 0; } return (void *) ((grub_addr_t) address); }
/* Allocate pages below a specified address */ void * grub_efi_allocate_pages_max (grub_efi_physical_address_t max, grub_efi_uintn_t pages) { grub_efi_status_t status; grub_efi_boot_services_t *b; grub_efi_physical_address_t address = max; if (max > 0xffffffff) return 0; b = grub_efi_system_table->boot_services; status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA, pages, &address); if (status != GRUB_EFI_SUCCESS) return 0; if (address == 0) { /* Uggh, the address 0 was allocated... This is too annoying, so reallocate another one. */ address = max; status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA, pages, &address); grub_efi_free_pages (0, pages); if (status != GRUB_EFI_SUCCESS) return 0; } return (void *) ((grub_addr_t) address); }
static int grub_video_gop_iterate (int (*hook) (const struct grub_video_mode_info *info)) { unsigned mode; for (mode = 0; mode < gop->mode->max_mode; mode++) { grub_efi_uintn_t size; grub_efi_status_t status; struct grub_efi_gop_mode_info *info = NULL; grub_err_t err; struct grub_video_mode_info mode_info; status = efi_call_4 (gop->query_mode, gop, mode, &size, &info); if (status) { info = 0; continue; } err = grub_video_gop_fill_mode_info (mode, info, &mode_info); if (err) { grub_errno = GRUB_ERR_NONE; continue; } if (hook (&mode_info)) return 1; } return 0; }
void grub_halt (void) { grub_efi_fini (); efi_call_4 (grub_efi_system_table->runtime_services->reset_system, GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_SUCCESS, 0, NULL); }
void grub_reboot (void) { grub_efi_fini (); efi_call_4 (grub_efi_system_table->runtime_services->reset_system, GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL); }
/* Allocate pages. Return the pointer to the first of allocated pages. */ void * grub_efi_allocate_pages (grub_efi_physical_address_t address, grub_efi_uintn_t pages) { grub_efi_allocate_type_t type; grub_efi_status_t status; grub_efi_boot_services_t *b; #if 1 /* Limit the memory access to less than 4GB for 32-bit platforms. */ if (address > GRUB_EFI_MAX_USABLE_ADDRESS) return 0; #endif #if 1 if (address == 0) { type = GRUB_EFI_ALLOCATE_MAX_ADDRESS; address = GRUB_EFI_MAX_USABLE_ADDRESS; } else type = GRUB_EFI_ALLOCATE_ADDRESS; #else if (address == 0) type = GRUB_EFI_ALLOCATE_ANY_PAGES; else type = GRUB_EFI_ALLOCATE_ADDRESS; #endif b = grub_efi_system_table->boot_services; status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_LOADER_DATA, pages, &address); if (status != GRUB_EFI_SUCCESS) return 0; if (address == 0) { /* Uggh, the address 0 was allocated... This is too annoying, so reallocate another one. */ address = GRUB_EFI_MAX_USABLE_ADDRESS; status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_LOADER_DATA, pages, &address); grub_efi_free_pages (0, pages); if (status != GRUB_EFI_SUCCESS) return 0; } return (void *) ((grub_addr_t) address); }
void grub_exit (void) { grub_efi_fini (); efi_call_4 (grub_efi_system_table->boot_services->exit, grub_efi_image_handle, GRUB_EFI_SUCCESS, 0, 0); for (;;) ; }
void grub_reboot (void) { grub_machine_fini (GRUB_LOADER_FLAG_NORETURN); efi_call_4 (grub_efi_system_table->runtime_services->reset_system, GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL); for (;;) ; }
void grub_halt (void) { grub_machine_fini (GRUB_LOADER_FLAG_NORETURN); #if !defined(__ia64__) && !defined(__arm__) && !defined(__aarch64__) grub_acpi_halt (); #endif efi_call_4 (grub_efi_system_table->runtime_services->reset_system, GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_SUCCESS, 0, NULL); while (1); }
void grub_efi_init (void) { /* First of all, initialize the console so that GRUB can display messages. */ grub_console_init (); /* Initialize the memory management system. */ grub_efi_mm_init (); efi_call_4 (grub_efi_system_table->boot_services->set_watchdog_timer, 0, 0, 0, NULL); grub_efidisk_init (); }
grub_err_t grub_efi_set_virtual_address_map (grub_efi_uintn_t memory_map_size, grub_efi_uintn_t descriptor_size, grub_efi_uint32_t descriptor_version, grub_efi_memory_descriptor_t *virtual_map) { grub_efi_runtime_services_t *r; grub_efi_status_t status; r = grub_efi_system_table->runtime_services; status = efi_call_4 (r->set_virtual_address_map, memory_map_size, descriptor_size, descriptor_version, virtual_map); if (status == GRUB_EFI_SUCCESS) return GRUB_ERR_NONE; return grub_error (GRUB_ERR_IO, "set_virtual_address_map failed"); }
int grub_efi_set_text_mode (int on) { grub_efi_console_control_protocol_t *c; grub_efi_screen_mode_t mode, new_mode; c = grub_efi_locate_protocol (&console_control_guid, 0); if (! c) /* No console control protocol instance available, assume it is already in text mode. */ return 1; if (efi_call_4 (c->get_mode, c, &mode, 0, 0) != GRUB_EFI_SUCCESS) return 0; new_mode = on ? GRUB_EFI_SCREEN_TEXT : GRUB_EFI_SCREEN_GRAPHICS; if (mode != new_mode) if (efi_call_2 (c->set_mode, c, new_mode) != GRUB_EFI_SUCCESS) return 0; return 1; }
static grub_err_t grub_video_gop_setup (unsigned int width, unsigned int height, unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused))) { unsigned int depth; struct grub_efi_gop_mode_info *info = NULL; unsigned best_mode = 0; grub_err_t err; unsigned bpp; int found = 0; unsigned long long best_volume = 0; depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS; /* Keep current mode if possible. */ if (gop->mode->info) { bpp = grub_video_gop_get_bpp (gop->mode->info); if (bpp && ((width == gop->mode->info->width && height == gop->mode->info->height) || (width == 0 && height == 0)) && (depth == bpp || depth == 0)) { grub_dprintf ("video", "GOP: keeping mode %d\n", gop->mode->mode); best_mode = gop->mode->mode; found = 1; } } if (!found) { unsigned mode; grub_dprintf ("video", "GOP: %d modes detected\n", gop->mode->max_mode); for (mode = 0; mode < gop->mode->max_mode; mode++) { grub_efi_uintn_t size; grub_efi_status_t status; status = efi_call_4 (gop->query_mode, gop, mode, &size, &info); if (status) { info = 0; continue; } grub_dprintf ("video", "GOP: mode %d: %dx%d\n", mode, info->width, info->height); bpp = grub_video_gop_get_bpp (info); if (!bpp) { grub_dprintf ("video", "GOP: mode %d: incompatible pixel mode\n", mode); continue; } grub_dprintf ("video", "GOP: mode %d: depth %d\n", mode, bpp); if (!(((info->width == width && info->height == height) || (width == 0 && height == 0)) && (bpp == depth || depth == 0))) { grub_dprintf ("video", "GOP: mode %d: rejected\n", mode); continue; } if (best_volume < ((unsigned long long) info->width) * ((unsigned long long) info->height) * ((unsigned long long) bpp)) { best_volume = ((unsigned long long) info->width) * ((unsigned long long) info->height) * ((unsigned long long) bpp); best_mode = mode; } found = 1; } } if (!found) { grub_dprintf ("video", "GOP: no mode found\n"); return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching mode found"); } if (best_mode != gop->mode->mode) { if (!restore_needed) { old_mode = gop->mode->mode; restore_needed = 1; } efi_call_2 (gop->set_mode, gop, best_mode); } info = gop->mode->info; err = grub_video_gop_fill_mode_info (gop->mode->mode, info, &framebuffer.mode_info); if (err) { grub_dprintf ("video", "GOP: couldn't fill mode info\n"); return err; } framebuffer.ptr = (void *) (grub_addr_t) gop->mode->fb_base; grub_dprintf ("video", "GOP: initialising FB @ %p %dx%dx%d\n", framebuffer.ptr, framebuffer.mode_info.width, framebuffer.mode_info.height, framebuffer.mode_info.bpp); err = grub_video_fb_create_render_target_from_pointer (&framebuffer.render_target, &framebuffer.mode_info, framebuffer.ptr); if (err) { grub_dprintf ("video", "GOP: Couldn't create FB target\n"); return err; } err = grub_video_fb_set_active_render_target (framebuffer.render_target); if (err) { grub_dprintf ("video", "GOP: Couldn't set FB target\n"); return err; } err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, grub_video_fbstd_colors); if (err) grub_dprintf ("video", "GOP: Couldn't set palette\n"); else grub_dprintf ("video", "GOP: Success\n"); return err; }