text mode

This commit is contained in:
a1ive 2025-02-18 21:24:11 +09:00
parent 46d376c250
commit 74b421ba89
No known key found for this signature in database
GPG Key ID: DA9BACF4F462B55D
9 changed files with 104 additions and 22 deletions

View File

@ -426,7 +426,7 @@ efidisk_read (void *disk, uint64_t sector, size_t len, void *buf)
EFI_BLOCK_IO_PROTOCOL *bio; EFI_BLOCK_IO_PROTOCOL *bio;
EFI_STATUS status; EFI_STATUS status;
UINTN pages = BYTES_TO_PAGES (len); UINTN pages = BYTES_TO_PAGES (len);
void *mem = efi_allocate_pages (pages); void *mem = efi_allocate_pages (pages, EfiLoaderData);
bio = d->bio; bio = d->bio;

View File

@ -43,6 +43,12 @@ file=/path/to/xxx.vhd
``` ```
The path to the WIM/VHD/VHDX file. Bootloader will automatically detect the file type. The path to the WIM/VHD/VHDX file. Bootloader will automatically detect the file type.
### text
```
text
```
Force the Windows boot manager to display error messages in text mode.
### testmode ### testmode
``` ```
testmode=yes|no testmode=yes|no

View File

@ -40,6 +40,7 @@
struct nt_args struct nt_args
{ {
uint8_t textmode;
uint8_t testmode; uint8_t testmode;
uint8_t hires; uint8_t hires;
uint8_t hal; uint8_t hal;

View File

@ -74,10 +74,11 @@ extern EFI_GUID efi_device_path_protocol_guid;
extern EFI_GUID efi_loaded_image_protocol_guid; extern EFI_GUID efi_loaded_image_protocol_guid;
extern EFI_GUID efi_simple_file_system_protocol_guid; extern EFI_GUID efi_simple_file_system_protocol_guid;
extern EFI_GUID efi_load_file2_protocol_guid; extern EFI_GUID efi_load_file2_protocol_guid;
extern EFI_GUID efi_gop_guid;
extern void *efi_malloc (size_t size); extern void *efi_malloc (size_t size);
extern void efi_free (void *ptr); extern void efi_free (void *ptr);
extern void efi_free_pages (void *ptr, UINTN pages); extern void efi_free_pages (void *ptr, UINTN pages);
extern void *efi_allocate_pages (UINTN pages); extern void *efi_allocate_pages (UINTN pages, EFI_MEMORY_TYPE type);
#endif /* _EFI_H */ #endif /* _EFI_H */

View File

@ -29,6 +29,7 @@
static struct nt_args args = static struct nt_args args =
{ {
.textmode = NTARG_BOOL_FALSE,
.testmode = NTARG_BOOL_FALSE, .testmode = NTARG_BOOL_FALSE,
.hires = NTARG_BOOL_UNSET, // wim = yes .hires = NTARG_BOOL_UNSET, // wim = yes
.hal = NTARG_BOOL_TRUE, .hal = NTARG_BOOL_TRUE,
@ -185,6 +186,10 @@ void process_cmdline (char *cmdline)
else else
args.boottype = NTBOOT_VHD; args.boottype = NTBOOT_VHD;
} }
else if (strcmp (key, "text") == 0)
{
args.textmode = NTARG_BOOL_TRUE;
}
else if (strcmp (key, "testmode") == 0) else if (strcmp (key, "testmode") == 0)
{ {
args.testmode = convert_bool (value); args.testmode = convert_bool (value);

View File

@ -23,6 +23,7 @@
#include "efi/Protocol/SimpleFileSystem.h" #include "efi/Protocol/SimpleFileSystem.h"
#include "efi/Protocol/LoadFile2.h" #include "efi/Protocol/LoadFile2.h"
#include "efi/Protocol/LoadedImage.h" #include "efi/Protocol/LoadedImage.h"
#include "efi/Protocol/GraphicsOutput.h"
/** EFI system table */ /** EFI system table */
EFI_SYSTEM_TABLE *efi_systab; EFI_SYSTEM_TABLE *efi_systab;
@ -50,6 +51,10 @@ EFI_GUID efi_simple_file_system_protocol_guid
EFI_GUID efi_load_file2_protocol_guid EFI_GUID efi_load_file2_protocol_guid
= EFI_LOAD_FILE2_PROTOCOL_GUID; = EFI_LOAD_FILE2_PROTOCOL_GUID;
/** Graphics output protocol GUID */
EFI_GUID efi_gop_guid
= EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
void *efi_malloc (size_t size) void *efi_malloc (size_t size)
{ {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
@ -73,13 +78,13 @@ void efi_free_pages (void *ptr, UINTN pages)
efi_systab->BootServices->FreePages (addr, pages); efi_systab->BootServices->FreePages (addr, pages);
} }
void *efi_allocate_pages (UINTN pages) void *efi_allocate_pages (UINTN pages, EFI_MEMORY_TYPE type)
{ {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_STATUS efirc; EFI_STATUS efirc;
EFI_PHYSICAL_ADDRESS addr = 0; EFI_PHYSICAL_ADDRESS addr = 0;
efirc = bs->AllocatePages (AllocateAnyPages, efirc = bs->AllocatePages (AllocateAnyPages,
EfiLoaderData, pages, &addr); type, pages, &addr);
if (efirc != EFI_SUCCESS) if (efirc != EFI_SUCCESS)
die ("Could not allocate memory.\n"); die ("Could not allocate memory.\n");
return (void *) (intptr_t) addr; return (void *) (intptr_t) addr;

View File

@ -31,6 +31,68 @@
#include "vdisk.h" #include "vdisk.h"
#include "efi.h" #include "efi.h"
#include "efiboot.h" #include "efiboot.h"
#include "efi/Protocol/GraphicsOutput.h"
/** Original OpenProtocol() method */
static EFI_OPEN_PROTOCOL orig_open_protocol;
/** Dummy "opening gop blocked once" protocol GUID */
static EFI_GUID efi_gop_blocked_guid =
{
0xbd1598bf, 0x8e65, 0x47e0,
{ 0x80, 0x01, 0xe4, 0x62, 0x4c, 0xab, 0xa4, 0x7f }
};
/** Dummy "opening gop blocked once" protocol instance */
static uint8_t efi_gop_blocked;
/**
* Intercept OpenProtocol()
*
* @v handle EFI handle
* @v protocol Protocol GUID
* @v interface Opened interface
* @v agent_handle Agent handle
* @v controller_handle Controller handle
* @v attributes Attributes
* @ret efirc EFI status code
*/
static EFI_STATUS EFIAPI
efi_open_protocol_wrapper (EFI_HANDLE handle, EFI_GUID *protocol,
VOID **interface, EFI_HANDLE agent_handle,
EFI_HANDLE controller_handle,
UINT32 attributes)
{
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_STATUS efirc;
/* Open the protocol */
efirc = orig_open_protocol (handle, protocol, interface,
agent_handle, controller_handle,
attributes);
if (efirc != 0)
return efirc;
/* Block first attempt by bootmgfw.efi to open each
* EFI_GRAPHICS_OUTPUT_PROTOCOL. This forces error messages
* to be displayed in text mode (thereby avoiding the totally
* blank error screen if the fonts are missing). We must
* allow subsequent attempts to succeed, otherwise the OS will
* fail to boot.
*/
if ((memcmp (protocol, &efi_gop_guid, sizeof (*protocol)) == 0) &&
(bs->InstallMultipleProtocolInterfaces (&handle,
&efi_gop_blocked_guid,
&efi_gop_blocked,
NULL) == 0) &&
(nt_cmdline->textmode))
{
DBG ("Forcing text mode output\n");
return EFI_INVALID_PARAMETER;
}
return 0;
}
/** /**
* Boot from EFI device * Boot from EFI device
@ -47,24 +109,13 @@ void efi_boot (EFI_DEVICE_PATH_PROTOCOL *path,
EFI_LOADED_IMAGE_PROTOCOL *image; EFI_LOADED_IMAGE_PROTOCOL *image;
void *intf; void *intf;
} loaded; } loaded;
EFI_PHYSICAL_ADDRESS phys;
void *data; void *data;
unsigned int pages;
EFI_HANDLE handle; EFI_HANDLE handle;
EFI_STATUS efirc; EFI_STATUS efirc;
/* Allocate memory */ /* Allocate memory */
pages = ((nt_cmdline->bootmgr_length + PAGE_SIZE - 1) / PAGE_SIZE); data = efi_allocate_pages (
efirc = bs->AllocatePages (AllocateAnyPages, BYTES_TO_PAGES (nt_cmdline->bootmgr_length), EfiLoaderCode);
EfiBootServicesData, pages,
&phys);
if (efirc != 0)
{
die ("Could not allocate %d pages: %#lx\n",
pages, ((unsigned long) efirc));
}
data = ((void *) (intptr_t) phys);
/* Copy image */ /* Copy image */
memcpy (data, nt_cmdline->bootmgr, nt_cmdline->bootmgr_length); memcpy (data, nt_cmdline->bootmgr, nt_cmdline->bootmgr_length);
@ -98,6 +149,12 @@ void efi_boot (EFI_DEVICE_PATH_PROTOCOL *path,
loaded.image->DeviceHandle = device; loaded.image->DeviceHandle = device;
} }
/* Intercept calls to OpenProtocol() */
orig_open_protocol =
loaded.image->SystemTable->BootServices->OpenProtocol;
loaded.image->SystemTable->BootServices->OpenProtocol =
efi_open_protocol_wrapper;
/* Start image */ /* Start image */
if ((efirc = bs->StartImage (handle, NULL, NULL)) != 0) if ((efirc = bs->StartImage (handle, NULL, NULL)) != 0)
{ {

View File

@ -95,7 +95,7 @@ efi_load_sfs_initrd (UINTN *len, EFI_HANDLE handle)
die ("Could not get file size\n"); die ("Could not get file size\n");
DBG ("...found %ls size 0x%llx\n", wpath, size); DBG ("...found %ls size 0x%llx\n", wpath, size);
*len = size; *len = size;
initrd = efi_allocate_pages (BYTES_TO_PAGES (*len)); initrd = efi_allocate_pages (BYTES_TO_PAGES (*len), EfiLoaderData);
efirc = file->Read (file, len, initrd); efirc = file->Read (file, len, initrd);
if (efirc != EFI_SUCCESS) if (efirc != EFI_SUCCESS)
die ("Could not read from file.\n"); die ("Could not read from file.\n");
@ -140,7 +140,7 @@ efi_load_lf2_initrd (UINTN *len)
die ("Could not get initrd size\n"); die ("Could not get initrd size\n");
/* Allocate memory */ /* Allocate memory */
initrd = efi_allocate_pages (BYTES_TO_PAGES (*len)); initrd = efi_allocate_pages (BYTES_TO_PAGES (*len), EfiLoaderData);
/* Read initrd */ /* Read initrd */
efirc = lf2->LoadFile (lf2, dp, FALSE, len, initrd); efirc = lf2->LoadFile (lf2, dp, FALSE, len, initrd);

View File

@ -73,11 +73,11 @@ enum
static void call_interrupt_wrapper (struct bootapp_callback_params *params) static void call_interrupt_wrapper (struct bootapp_callback_params *params)
{ {
struct paging_state state; struct paging_state state;
uint16_t *attributes;
/* Handle/modify/pass-through interrupt as required */ /* Handle/modify/pass-through interrupt as required */
if (params->vector.interrupt == 0x13) if (params->vector.interrupt == 0x13)
{ {
/* Enable paging */ /* Enable paging */
enable_paging (&state); enable_paging (&state);
@ -86,11 +86,18 @@ static void call_interrupt_wrapper (struct bootapp_callback_params *params)
/* Disable paging */ /* Disable paging */
disable_paging (&state); disable_paging (&state);
}
else if ((params->vector.interrupt == 0x10) &&
(params->ax == 0x4f01) &&
(nt_cmdline->textmode))
{
/* Mark all VESA video modes as unsupported */
attributes = REAL_PTR ( params->es, params->di );
call_interrupt ( params );
*attributes &= ~0x0001;
} }
else else
{ {
/* Pass through interrupt */ /* Pass through interrupt */
call_interrupt (params); call_interrupt (params);
} }