boot/uefi: choose a resolution with R, the same as the BIOS path
GOP instead of VBE, and the same reasoning. There are no mode numbers worth hardcoding here: the firmware publishes however many modes the hardware can do and which index means what varies by machine, so the menu is built by walking them. Press R within four seconds for a list, then either a mode number or Enter to type a size. 800x600 stays the floor. Fixes a header bug this is the first code to notice. The spec's order in EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE is MaxMode then Mode; efi.h had them swapped. Info, SizeOfInfo and FrameBufferBase sit at the same offsets either way because both fields are UINT32, so the framebuffer worked perfectly and nothing was wrong until something asked how many modes existed -- and was told the current mode number instead. Zero, on a machine reporting thirty. QueryMode and SetMode were void* padding and now have real prototypes; ConIn likewise, so the loader can read a key. Under OVMF the console includes the serial line, which is where `make qemu-uefi` puts it and where the person actually is -- the same mistake the BIOS menu made first time round. Verified over serial against OVMF: 30 modes enumerated; picking listed mode 14 gives 1280x1024; typing 1024x768 gives 1024x768; no key keeps the firmware's mode and boots. All reach schinit. bootcheck 108 [ok]. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
03a867f43e
commit
0362427e80
2 changed files with 210 additions and 4 deletions
|
|
@ -97,6 +97,27 @@ typedef struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {
|
|||
void *Mode;
|
||||
} EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
|
||||
|
||||
// --- console input ---------------------------------------------------------
|
||||
|
||||
typedef struct {
|
||||
UINT16 ScanCode;
|
||||
UINT16 UnicodeChar;
|
||||
} EFI_INPUT_KEY;
|
||||
|
||||
struct EFI_SIMPLE_TEXT_INPUT_PROTOCOL;
|
||||
typedef EFI_STATUS (*EFI_INPUT_RESET)(
|
||||
struct EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, unsigned char ExtendedVerification);
|
||||
// Returns EFI_NOT_READY when nothing has been typed, which is what makes a
|
||||
// timed prompt possible without blocking the boot.
|
||||
typedef EFI_STATUS (*EFI_INPUT_READ_KEY)(
|
||||
struct EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, EFI_INPUT_KEY *Key);
|
||||
|
||||
typedef struct EFI_SIMPLE_TEXT_INPUT_PROTOCOL {
|
||||
EFI_INPUT_RESET Reset;
|
||||
EFI_INPUT_READ_KEY ReadKeyStroke;
|
||||
void *WaitForKey;
|
||||
} EFI_SIMPLE_TEXT_INPUT_PROTOCOL;
|
||||
|
||||
// --- boot services --------------------------------------------------------
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -160,7 +181,7 @@ typedef struct {
|
|||
CHAR16 *FirmwareVendor;
|
||||
UINT32 FirmwareRevision;
|
||||
EFI_HANDLE ConsoleInHandle;
|
||||
void *ConIn;
|
||||
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn;
|
||||
EFI_HANDLE ConsoleOutHandle;
|
||||
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
|
||||
EFI_HANDLE StandardErrorHandle;
|
||||
|
|
@ -259,17 +280,36 @@ typedef struct {
|
|||
} EFI_GRAPHICS_OUTPUT_MODE_INFORMATION;
|
||||
|
||||
typedef struct {
|
||||
UINT32 Mode;
|
||||
// MaxMode first, then Mode. That is the specification's order and getting
|
||||
// it backwards is invisible until something reads them: Info,
|
||||
// SizeOfInfo and FrameBufferBase all sit at the same offsets either way,
|
||||
// because both fields are UINT32. It was backwards here, so the first code
|
||||
// to ask how many modes existed was told the current mode number instead --
|
||||
// zero, on a machine with plenty of them.
|
||||
UINT32 MaxMode;
|
||||
UINT32 Mode;
|
||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
|
||||
UINTN SizeOfInfo;
|
||||
EFI_PHYSICAL_ADDRESS FrameBufferBase;
|
||||
UINTN FrameBufferSize;
|
||||
} EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE;
|
||||
|
||||
struct EFI_GRAPHICS_OUTPUT_PROTOCOL;
|
||||
|
||||
// Ask what a mode is, and switch to one. Declared properly rather than as
|
||||
// void*, because choosing a resolution means walking every mode the firmware
|
||||
// offers and asking each one its size -- the same shape as the BIOS path's
|
||||
// VBE enumeration, and for the same reason: a table of numbers can only
|
||||
// describe hardware somebody already tested.
|
||||
typedef EFI_STATUS (*EFI_GOP_QUERY_MODE)(
|
||||
struct EFI_GRAPHICS_OUTPUT_PROTOCOL *This, UINT32 ModeNumber,
|
||||
UINTN *SizeOfInfo, EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info);
|
||||
typedef EFI_STATUS (*EFI_GOP_SET_MODE)(
|
||||
struct EFI_GRAPHICS_OUTPUT_PROTOCOL *This, UINT32 ModeNumber);
|
||||
|
||||
typedef struct EFI_GRAPHICS_OUTPUT_PROTOCOL {
|
||||
void *QueryMode;
|
||||
void *SetMode;
|
||||
EFI_GOP_QUERY_MODE QueryMode;
|
||||
EFI_GOP_SET_MODE SetMode;
|
||||
void *Blt;
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode;
|
||||
} EFI_GRAPHICS_OUTPUT_PROTOCOL;
|
||||
|
|
|
|||
Loading…
Reference in a new issue