On Tue, Sep 05, 2017 at 12:47:15AM +0000, Klemens Nanni wrote:
> I also have a working and tested diff for `machine fb [n]' analog to
> `machine video [n]' that enables listing/and setting the GOP mode just
> like FreeBSD does it with `gop list | get | set <mode>'. I'd also like to
> get this in together with some other minor clean ups in case this is
> the way to go.
Here's the diff. I went for gop instead of fb since the frame buffer
can also be handled via UGA (which we're not doing), hence gop being
more correct and descriptive.
efi_gop_setmode() was introduced in my very last commit and is being
reused here.
This has been working fine so far on three different machines, I can list
and set modes properly prior to booting:
boot> machine gop
Mode 0: 1920 x 1080 (stride = 1920)
Mode 1: 640 x 480 (stride = 640)
Mode 2: 800 x 600 (stride = 800)
Mode 3: 1024 x 768 (stride = 1024)
Mode 4: 1280 x 1024 (stride = 1280)
Current Mode = 2
boot> machine gop 0
[frame buffer gets reset, resolution is now 1920x1080]
Current Mode = 0
boot> boot
In case of a broken or non-existent mode, the current mode stays the
same:
boot> machine gop
[...]
Current Mode = 2
boot> machine gop 0
[setting mode failed]
Current Mode = 2
boot> machine gop 42
[mode 42 doesn't exist]
Current Mode = 2
boot>
Comments, Feedback? More testing is very welcome of course.
diff --git a/sys/arch/amd64/stand/efiboot/efiboot.c
b/sys/arch/amd64/stand/efiboot/efiboot.c
index f8196b2cbcb..42e79fbea6b 100644
--- a/sys/arch/amd64/stand/efiboot/efiboot.c
+++ b/sys/arch/amd64/stand/efiboot/efiboot.c
@@ -888,3 +888,44 @@ Xpoweroff_efi(void)
EFI_CALL(RS->ResetSystem, EfiResetShutdown, EFI_SUCCESS, 0, NULL);
return (0);
}
+
+int
+Xgop_efi(void)
+{
+ EFI_STATUS status;
+ EFI_GRAPHICS_OUTPUT *gop;
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
+ *info;
+ int i, mode = -1;
+ UINTN sz;
+
+ status = EFI_CALL(BS->LocateProtocol, &gop_guid, NULL,
+ (void **)&gop);
+ if (EFI_ERROR(status))
+ return (0);
+
+ if (cmd.argc >= 2) {
+ mode = strtol(cmd.argv[1], NULL, 10);
+ if (0 <= mode && mode < gop->Mode->MaxMode) {
+ status = EFI_CALL(gop->QueryMode, gop, mode,
+ &sz, &info);
+ if (!EFI_ERROR(status))
+ (void)efi_gop_setmode(gop, mode);
+ }
+ } else {
+ for (i = 0; i < gop->Mode->MaxMode; i++) {
+ status = EFI_CALL(gop->QueryMode, gop, i, &sz,
+ &info);
+ if (EFI_ERROR(status))
+ continue;
+ printf("Mode %d: %d x %d (stride = %d)\n", i,
+ info->HorizontalResolution,
+ info->VerticalResolution,
+ info->PixelsPerScanLine);
+ }
+ printf("\n");
+ }
+ printf("Current Mode = %d\n", gop->Mode->Mode);
+
+ return (0);
+}
diff --git a/sys/arch/amd64/stand/efiboot/efiboot.h
b/sys/arch/amd64/stand/efiboot/efiboot.h
index 8a07d5b46b3..3f5f5b3352c 100644
--- a/sys/arch/amd64/stand/efiboot/efiboot.h
+++ b/sys/arch/amd64/stand/efiboot/efiboot.h
@@ -30,6 +30,7 @@ void efi_com_init(struct consdev *);
int efi_com_getc(dev_t);
void efi_com_putc(dev_t, int);
int Xvideo_efi(void);
+int Xgop_efi(void);
int Xexit_efi(void);
void efi_makebootargs(void);
diff --git a/sys/arch/amd64/stand/libsa/cmd_i386.c
b/sys/arch/amd64/stand/libsa/cmd_i386.c
index 592cca49547..ee3b7f3cd63 100644
--- a/sys/arch/amd64/stand/libsa/cmd_i386.c
+++ b/sys/arch/amd64/stand/libsa/cmd_i386.c
@@ -62,6 +62,7 @@ const struct cmd_table cmd_machine[] = {
{ "memory", CMDT_CMD, Xmemory },
#ifdef EFIBOOT
{ "video", CMDT_CMD, Xvideo_efi },
+ { "gop", CMDT_CMD, Xgop_efi },
{ "exit", CMDT_CMD, Xexit_efi },
{ "poweroff", CMDT_CMD, Xpoweroff_efi },
#endif