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_STATUS status;
UINTN pages = BYTES_TO_PAGES (len);
void *mem = efi_allocate_pages (pages);
void *mem = efi_allocate_pages (pages, EfiLoaderData);
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.
### text
```
text
```
Force the Windows boot manager to display error messages in text mode.
### testmode
```
testmode=yes|no

View File

@ -40,6 +40,7 @@
struct nt_args
{
uint8_t textmode;
uint8_t testmode;
uint8_t hires;
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_simple_file_system_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_free (void *ptr);
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 */

View File

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

View File

@ -23,6 +23,7 @@
#include "efi/Protocol/SimpleFileSystem.h"
#include "efi/Protocol/LoadFile2.h"
#include "efi/Protocol/LoadedImage.h"
#include "efi/Protocol/GraphicsOutput.h"
/** EFI system table */
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_LOAD_FILE2_PROTOCOL_GUID;
/** Graphics output protocol GUID */
EFI_GUID efi_gop_guid
= EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
void *efi_malloc (size_t size)
{
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);
}
void *efi_allocate_pages (UINTN pages)
void *efi_allocate_pages (UINTN pages, EFI_MEMORY_TYPE type)
{
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_STATUS efirc;
EFI_PHYSICAL_ADDRESS addr = 0;
efirc = bs->AllocatePages (AllocateAnyPages,
EfiLoaderData, pages, &addr);
type, pages, &addr);
if (efirc != EFI_SUCCESS)
die ("Could not allocate memory.\n");
return (void *) (intptr_t) addr;

View File

@ -31,6 +31,68 @@
#include "vdisk.h"
#include "efi.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
@ -47,24 +109,13 @@ void efi_boot (EFI_DEVICE_PATH_PROTOCOL *path,
EFI_LOADED_IMAGE_PROTOCOL *image;
void *intf;
} loaded;
EFI_PHYSICAL_ADDRESS phys;
void *data;
unsigned int pages;
EFI_HANDLE handle;
EFI_STATUS efirc;
/* Allocate memory */
pages = ((nt_cmdline->bootmgr_length + PAGE_SIZE - 1) / PAGE_SIZE);
efirc = bs->AllocatePages (AllocateAnyPages,
EfiBootServicesData, pages,
&phys);
if (efirc != 0)
{
die ("Could not allocate %d pages: %#lx\n",
pages, ((unsigned long) efirc));
}
data = ((void *) (intptr_t) phys);
data = efi_allocate_pages (
BYTES_TO_PAGES (nt_cmdline->bootmgr_length), EfiLoaderCode);
/* Copy image */
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;
}
/* Intercept calls to OpenProtocol() */
orig_open_protocol =
loaded.image->SystemTable->BootServices->OpenProtocol;
loaded.image->SystemTable->BootServices->OpenProtocol =
efi_open_protocol_wrapper;
/* Start image */
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");
DBG ("...found %ls size 0x%llx\n", wpath, 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);
if (efirc != EFI_SUCCESS)
die ("Could not read from file.\n");
@ -140,7 +140,7 @@ efi_load_lf2_initrd (UINTN *len)
die ("Could not get initrd size\n");
/* Allocate memory */
initrd = efi_allocate_pages (BYTES_TO_PAGES (*len));
initrd = efi_allocate_pages (BYTES_TO_PAGES (*len), EfiLoaderData);
/* Read 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)
{
struct paging_state state;
uint16_t *attributes;
/* Handle/modify/pass-through interrupt as required */
if (params->vector.interrupt == 0x13)
{
/* Enable paging */
enable_paging (&state);
@ -86,11 +86,18 @@ static void call_interrupt_wrapper (struct bootapp_callback_params *params)
/* Disable paging */
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
{
/* Pass through interrupt */
call_interrupt (params);
}