mirror of
https://github.com/grub4dos/ntloader.git
synced 2025-05-08 19:51:14 +08:00
text mode
This commit is contained in:
parent
46d376c250
commit
74b421ba89
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -40,6 +40,7 @@
|
||||
|
||||
struct nt_args
|
||||
{
|
||||
uint8_t textmode;
|
||||
uint8_t testmode;
|
||||
uint8_t hires;
|
||||
uint8_t hal;
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
13
kern/main.c
13
kern/main.c
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user