Пример #1
0
/*
 * 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);
}
Пример #2
0
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);
}
Пример #3
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);
}