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

Reply via email to