/* * Callback to notify about console mode change. * mode is value from enum EFI_CONSOLE_CONTROL_SCREEN_MODE. */ void plat_cons_update_mode(int mode) { UINTN cols, rows; struct vis_devinit devinit; struct efi_console_data *ecd = efi_console.c_private; /* Make sure we have usable console. */ if (efi_find_framebuffer(&efifb)) { console_mode = EfiConsoleControlScreenText; } else { efi_framebuffer_setup(); if (mode != -1 && console_mode != mode) console_mode = mode; } if (console_control != NULL) (void)console_control->SetMode(console_control, console_mode); /* some firmware enables the cursor when switching modes */ conout->EnableCursor(conout, FALSE); if (console_mode == EfiConsoleControlScreenText) { (void)conout->QueryMode(conout, conout->Mode->Mode, &cols, &rows); devinit.version = VIS_CONS_REV; devinit.width = cols; devinit.height = rows; devinit.depth = 4; devinit.linebytes = cols; devinit.color_map = NULL; devinit.mode = VIS_TEXT; ecd->ecd_visual_ops = &text_ops; } else { devinit.version = VIS_CONS_REV; devinit.width = gfx_fb.framebuffer_common.framebuffer_width; devinit.height = gfx_fb.framebuffer_common.framebuffer_height; devinit.depth = gfx_fb.framebuffer_common.framebuffer_bpp; devinit.linebytes = gfx_fb.framebuffer_common.framebuffer_pitch; devinit.color_map = gfx_fb_color_map; devinit.mode = VIS_PIXEL; ecd->ecd_visual_ops = &fb_ops; } modechg_cb(modechg_arg, &devinit); }
static int bi_load_efi_data(struct preloaded_file *kfp) { EFI_MEMORY_DESCRIPTOR *mm; EFI_PHYSICAL_ADDRESS addr; EFI_STATUS status; size_t efisz; UINTN mmsz, pages, sz; UINT32 mmver; struct efi_map_header *efihdr; struct efi_fb efifb; if (efi_find_framebuffer(&efifb) == 0) { printf("EFI framebuffer information:\n"); printf("addr, size 0x%lx, 0x%lx\n", efifb.fb_addr, efifb.fb_size); printf("dimensions %d x %d\n", efifb.fb_width, efifb.fb_height); printf("stride %d\n", efifb.fb_stride); printf("masks 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", efifb.fb_mask_red, efifb.fb_mask_green, efifb.fb_mask_blue, efifb.fb_mask_reserved); file_addmetadata(kfp, MODINFOMD_EFI_FB, sizeof(efifb), &efifb); } efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf; /* * Allocate enough pages to hold the bootinfo block and the memory * map EFI will return to us. The memory map has an unknown size, * so we have to determine that first. Note that the AllocatePages * call can itself modify the memory map, so we have to take that * into account as well. The changes to the memory map are caused * by splitting a range of free memory into two (AFAICT), so that * one is marked as being loader data. */ sz = 0; BS->GetMemoryMap(&sz, NULL, &x86_efi_mapkey, &mmsz, &mmver); sz += mmsz; sz = (sz + 0xf) & ~0xf; pages = EFI_SIZE_TO_PAGES(sz + efisz); status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, pages, &addr); if (EFI_ERROR(status)) { printf("%s: AllocatePages() returned 0x%lx\n", __func__, (long)status); return (ENOMEM); } /* * Read the memory map and stash it after bootinfo. Align the * memory map on a 16-byte boundary (the bootinfo block is page * aligned). */ efihdr = (struct efi_map_header *)addr; mm = (void *)((uint8_t *)efihdr + efisz); sz = (EFI_PAGE_SIZE * pages) - efisz; status = BS->GetMemoryMap(&sz, mm, &x86_efi_mapkey, &mmsz, &mmver); if (EFI_ERROR(status)) { printf("%s: GetMemoryMap() returned 0x%lx\n", __func__, (long)status); return (EINVAL); } efihdr->memory_size = sz; efihdr->descriptor_size = mmsz; efihdr->descriptor_version = mmver; file_addmetadata(kfp, MODINFOMD_EFI_MAP, efisz + sz, efihdr); return (0); }
static void efi_cons_probe(struct console *cp) { struct efi_console_data *ecd; EFI_STATUS status; UINTN i, max_dim, best_mode, cols, rows; ecd = calloc(1, sizeof (*ecd)); /* * As console probing is called very early, the only reason for * out of memory can be that we just do not have enough memory. */ if (ecd == NULL) panic("efi_cons_probe: This system has not enough memory\n"); cp->c_private = ecd; conout = ST->ConOut; ecd->ecd_conin = ST->ConIn; cp->c_flags |= C_PRESENTIN | C_PRESENTOUT; status = BS->LocateProtocol(&ccontrol_protocol_guid, NULL, (VOID **)&console_control); if (status == EFI_SUCCESS) { BOOLEAN GopUgaExists, StdInLocked; status = console_control->GetMode(console_control, &console_mode, &GopUgaExists, &StdInLocked); } else { console_mode = EfiConsoleControlScreenText; } max_dim = best_mode = 0; for (i = 0; i <= conout->Mode->MaxMode ; i++) { status = conout->QueryMode(conout, i, &cols, &rows); if (EFI_ERROR(status)) continue; if (cols * rows > max_dim) { max_dim = cols * rows; best_mode = i; } } if (max_dim > 0) conout->SetMode(conout, best_mode); status = conout->QueryMode(conout, best_mode, &cols, &rows); if (EFI_ERROR(status)) { setenv("screen-#rows", "24", 1); setenv("screen-#cols", "80", 1); } else { char env[8]; snprintf(env, sizeof (env), "%u", (unsigned)rows); setenv("screen-#rows", env, 1); snprintf(env, sizeof (env), "%u", (unsigned)cols); setenv("screen-#cols", env, 1); } if (efi_find_framebuffer(&efifb)) { console_mode = EfiConsoleControlScreenText; ecd->ecd_visual_ops = &text_ops; } else { efi_framebuffer_setup(); console_mode = EfiConsoleControlScreenGraphics; ecd->ecd_visual_ops = &fb_ops; } if (console_control != NULL) (void)console_control->SetMode(console_control, console_mode); /* some firmware enables the cursor when switching modes */ conout->EnableCursor(conout, FALSE); }