static grub_err_t retrieve_video_parameters (grub_properly_aligned_t **ptrorig) { grub_err_t err; struct grub_video_mode_info mode_info; void *framebuffer; grub_video_driver_id_t driv_id; struct grub_video_palette_data palette[256]; struct multiboot_tag_framebuffer *tag = (struct multiboot_tag_framebuffer *) *ptrorig; err = grub_multiboot_set_video_mode (); if (err) { grub_print_error (); grub_errno = GRUB_ERR_NONE; } grub_video_get_palette (0, ARRAY_SIZE (palette), palette); driv_id = grub_video_get_driver_id (); #if HAS_VGA_TEXT if (driv_id == GRUB_VIDEO_DRIVER_NONE) { struct grub_vbe_mode_info_block vbe_mode_info; grub_uint32_t vbe_mode; #if defined (GRUB_MACHINE_PCBIOS) { grub_vbe_status_t status; void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; status = grub_vbe_bios_get_mode (scratch); vbe_mode = *(grub_uint32_t *) scratch; if (status != GRUB_VBE_STATUS_OK) return GRUB_ERR_NONE; } #else vbe_mode = 3; #endif /* get_mode_info isn't available for mode 3. */ if (vbe_mode == 3) { grub_memset (&vbe_mode_info, 0, sizeof (struct grub_vbe_mode_info_block)); vbe_mode_info.memory_model = GRUB_VBE_MEMORY_MODEL_TEXT; vbe_mode_info.x_resolution = 80; vbe_mode_info.y_resolution = 25; } #if defined (GRUB_MACHINE_PCBIOS) else { grub_vbe_status_t status; void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; status = grub_vbe_bios_get_mode_info (vbe_mode, scratch); if (status != GRUB_VBE_STATUS_OK) return GRUB_ERR_NONE; grub_memcpy (&vbe_mode_info, scratch, sizeof (struct grub_vbe_mode_info_block)); } #endif if (vbe_mode_info.memory_model == GRUB_VBE_MEMORY_MODEL_TEXT) { tag = (struct multiboot_tag_framebuffer *) *ptrorig; tag->common.type = MULTIBOOT_TAG_TYPE_FRAMEBUFFER; tag->common.size = 0; tag->common.framebuffer_addr = 0xb8000; tag->common.framebuffer_pitch = 2 * vbe_mode_info.x_resolution; tag->common.framebuffer_width = vbe_mode_info.x_resolution; tag->common.framebuffer_height = vbe_mode_info.y_resolution; tag->common.framebuffer_bpp = 16; tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT; tag->common.size = sizeof (tag->common); tag->common.reserved = 0; *ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN) / sizeof (grub_properly_aligned_t); } return GRUB_ERR_NONE; } #else if (driv_id == GRUB_VIDEO_DRIVER_NONE) return GRUB_ERR_NONE; #endif #if GRUB_MACHINE_HAS_VBE { struct multiboot_tag_vbe *tag_vbe = (struct multiboot_tag_vbe *) *ptrorig; fill_vbe_tag (tag_vbe); *ptrorig += ALIGN_UP (tag_vbe->size, MULTIBOOT_TAG_ALIGN) / sizeof (grub_properly_aligned_t); } #endif err = grub_video_get_info_and_fini (&mode_info, &framebuffer); if (err) return err; tag = (struct multiboot_tag_framebuffer *) *ptrorig; tag->common.type = MULTIBOOT_TAG_TYPE_FRAMEBUFFER; tag->common.size = 0; tag->common.framebuffer_addr = (grub_addr_t) framebuffer; tag->common.framebuffer_pitch = mode_info.pitch; tag->common.framebuffer_width = mode_info.width; tag->common.framebuffer_height = mode_info.height; tag->common.framebuffer_bpp = mode_info.bpp; tag->common.reserved = 0; if (mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) { unsigned i; tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED; tag->framebuffer_palette_num_colors = mode_info.number_of_colors; if (tag->framebuffer_palette_num_colors > ARRAY_SIZE (palette)) tag->framebuffer_palette_num_colors = ARRAY_SIZE (palette); tag->common.size = sizeof (struct multiboot_tag_framebuffer_common) + sizeof (multiboot_uint16_t) + tag->framebuffer_palette_num_colors * sizeof (struct multiboot_color); for (i = 0; i < tag->framebuffer_palette_num_colors; i++) { tag->framebuffer_palette[i].red = palette[i].r; tag->framebuffer_palette[i].green = palette[i].g; tag->framebuffer_palette[i].blue = palette[i].b; } } else { tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB; tag->framebuffer_red_field_position = mode_info.red_field_pos; tag->framebuffer_red_mask_size = mode_info.red_mask_size; tag->framebuffer_green_field_position = mode_info.green_field_pos; tag->framebuffer_green_mask_size = mode_info.green_mask_size; tag->framebuffer_blue_field_position = mode_info.blue_field_pos; tag->framebuffer_blue_mask_size = mode_info.blue_mask_size; tag->common.size = sizeof (struct multiboot_tag_framebuffer_common) + 6; } *ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN) / sizeof (grub_properly_aligned_t); return GRUB_ERR_NONE; }
static grub_err_t retrieve_video_parameters (struct multiboot_info *mbi, grub_uint8_t *ptrorig, grub_uint32_t ptrdest) { grub_err_t err; struct grub_video_mode_info mode_info; void *framebuffer; grub_video_driver_id_t driv_id; struct grub_video_palette_data palette[256]; err = grub_multiboot_set_video_mode (); if (err) { grub_print_error (); grub_errno = GRUB_ERR_NONE; } grub_video_get_palette (0, ARRAY_SIZE (palette), palette); driv_id = grub_video_get_driver_id (); if (driv_id == GRUB_VIDEO_DRIVER_NONE) return GRUB_ERR_NONE; err = grub_video_get_info_and_fini (&mode_info, &framebuffer); if (err) return err; mbi->framebuffer_addr = (grub_addr_t) framebuffer; mbi->framebuffer_pitch = mode_info.pitch; mbi->framebuffer_width = mode_info.width; mbi->framebuffer_height = mode_info.height; mbi->framebuffer_bpp = mode_info.bpp; if (mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) { struct multiboot_color *mb_palette; unsigned i; mbi->framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED; mbi->framebuffer_palette_addr = ptrdest; mbi->framebuffer_palette_num_colors = mode_info.number_of_colors; if (mbi->framebuffer_palette_num_colors > ARRAY_SIZE (palette)) mbi->framebuffer_palette_num_colors = ARRAY_SIZE (palette); mb_palette = (struct multiboot_color *) ptrorig; for (i = 0; i < mbi->framebuffer_palette_num_colors; i++) { mb_palette[i].red = palette[i].r; mb_palette[i].green = palette[i].g; mb_palette[i].blue = palette[i].b; } ptrorig += mbi->framebuffer_palette_num_colors * sizeof (struct multiboot_color); ptrdest += mbi->framebuffer_palette_num_colors * sizeof (struct multiboot_color); } else { mbi->framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB; mbi->framebuffer_red_field_position = mode_info.green_field_pos; mbi->framebuffer_red_mask_size = mode_info.green_mask_size; mbi->framebuffer_green_field_position = mode_info.green_field_pos; mbi->framebuffer_green_mask_size = mode_info.green_mask_size; mbi->framebuffer_blue_field_position = mode_info.blue_field_pos; mbi->framebuffer_blue_mask_size = mode_info.blue_mask_size; } mbi->flags |= MULTIBOOT_INFO_FRAMEBUFFER_INFO; return GRUB_ERR_NONE; }
static grub_err_t grub_linux_setup_video (struct linux_kernel_params *params) { struct grub_video_mode_info mode_info; void *framebuffer; grub_err_t err; grub_video_driver_id_t driver_id; const char *gfxlfbvar = grub_env_get ("gfxpayloadforcelfb"); driver_id = grub_video_get_driver_id (); if (driver_id == GRUB_VIDEO_DRIVER_NONE) return 1; err = grub_video_get_info_and_fini (&mode_info, &framebuffer); if (err) { grub_errno = GRUB_ERR_NONE; return 1; } params->lfb_width = mode_info.width; params->lfb_height = mode_info.height; params->lfb_depth = mode_info.bpp; params->lfb_line_len = mode_info.pitch; params->lfb_base = (grub_size_t) framebuffer; params->lfb_size = ALIGN_UP (params->lfb_line_len * params->lfb_height, 65536); params->red_mask_size = mode_info.red_mask_size; params->red_field_pos = mode_info.red_field_pos; params->green_mask_size = mode_info.green_mask_size; params->green_field_pos = mode_info.green_field_pos; params->blue_mask_size = mode_info.blue_mask_size; params->blue_field_pos = mode_info.blue_field_pos; params->reserved_mask_size = mode_info.reserved_mask_size; params->reserved_field_pos = mode_info.reserved_field_pos; if (gfxlfbvar && (gfxlfbvar[0] == '1' || gfxlfbvar[0] == 'y')) params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE; else { switch (driver_id) { case GRUB_VIDEO_DRIVER_VBE: params->lfb_size >>= 16; params->have_vga = GRUB_VIDEO_LINUX_TYPE_VESA; break; case GRUB_VIDEO_DRIVER_EFI_UGA: case GRUB_VIDEO_DRIVER_EFI_GOP: params->have_vga = GRUB_VIDEO_LINUX_TYPE_EFIFB; break; /* FIXME: check if better id is available. */ case GRUB_VIDEO_DRIVER_SM712: case GRUB_VIDEO_DRIVER_SIS315PRO: case GRUB_VIDEO_DRIVER_VGA: case GRUB_VIDEO_DRIVER_CIRRUS: case GRUB_VIDEO_DRIVER_BOCHS: case GRUB_VIDEO_DRIVER_RADEON_FULOONG2E: case GRUB_VIDEO_DRIVER_RADEON_YEELOONG3A: case GRUB_VIDEO_DRIVER_IEEE1275: case GRUB_VIDEO_DRIVER_COREBOOT: /* Make gcc happy. */ case GRUB_VIDEO_DRIVER_XEN: case GRUB_VIDEO_DRIVER_SDL: case GRUB_VIDEO_DRIVER_NONE: case GRUB_VIDEO_ADAPTER_CAPTURE: params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE; break; } } #ifdef GRUB_MACHINE_PCBIOS /* VESA packed modes may come with zeroed mask sizes, which need to be set here according to DAC Palette width. If we don't, this results in Linux displaying a black screen. */ if (driver_id == GRUB_VIDEO_DRIVER_VBE && mode_info.bpp <= 8) { struct grub_vbe_info_block controller_info; int status; int width = 8; status = grub_vbe_bios_get_controller_info (&controller_info); if (status == GRUB_VBE_STATUS_OK && (controller_info.capabilities & GRUB_VBE_CAPABILITY_DACWIDTH)) status = grub_vbe_bios_set_dac_palette_width (&width); if (status != GRUB_VBE_STATUS_OK) /* 6 is default after mode reset. */ width = 6; params->red_mask_size = params->green_mask_size = params->blue_mask_size = width; params->reserved_mask_size = 0; } #endif return GRUB_ERR_NONE; }