bios_emulator: Add some VESA interface debugging
authorSimon Glass <sjg@chromium.org>
Tue, 30 Dec 2014 02:32:26 +0000 (19:32 -0700)
committerSimon Glass <sjg@chromium.org>
Sat, 24 Jan 2015 00:24:16 +0000 (17:24 -0700)
Allow the supported modes to be listed when in debug mode.

Signed-off-by: Simon Glass <sjg@chromium.org>
drivers/bios_emulator/atibios.c
include/vbe.h

index 93b815ccb497d7c81eb0491a441fa082e3c703f6..7ea5fa622472ca38a8256e97cc82c6a2cf883d93 100644 (file)
@@ -62,40 +62,158 @@ static u32 saveBaseAddress14;
 static u32 saveBaseAddress18;
 static u32 saveBaseAddress20;
 
-static void atibios_set_vesa_mode(RMREGS *regs, int vesa_mode,
-                                 struct vbe_mode_info *mode_info)
+/* Addres im memory of VBE region */
+const int vbe_offset = 0x2000;
+
+static const void *bios_ptr(const void *buf, BE_VGAInfo *vga_info,
+                           u32 x86_dword_ptr)
+{
+       u32 seg_ofs, flat;
+
+       seg_ofs = le32_to_cpu(x86_dword_ptr);
+       flat = ((seg_ofs & 0xffff0000) >> 12) | (seg_ofs & 0xffff);
+       if (flat >= 0xc0000)
+               return vga_info->BIOSImage + flat - 0xc0000;
+       else
+               return buf + (flat - vbe_offset);
+}
+
+static int atibios_debug_mode(BE_VGAInfo *vga_info, RMREGS *regs,
+                             int vesa_mode, struct vbe_mode_info *mode_info)
+{
+       void *buffer = (void *)(M.mem_base + vbe_offset);
+       u16 buffer_seg = (((unsigned long)vbe_offset) >> 4) & 0xff00;
+       u16 buffer_adr = ((unsigned long)vbe_offset) & 0xffff;
+       struct vesa_mode_info *vm;
+       struct vbe_info *info;
+       const u16 *modes_bios, *ptr;
+       u16 *modes;
+       int size;
+
+       debug("VBE: Getting information\n");
+       regs->e.eax = VESA_GET_INFO;
+       regs->e.esi = buffer_seg;
+       regs->e.edi = buffer_adr;
+       info = buffer;
+       memset(info, '\0', sizeof(*info));
+       strcpy(info->signature, "VBE2");
+       BE_int86(0x10, regs, regs);
+       if (regs->e.eax != 0x4f) {
+               debug("VESA_GET_INFO: error %x\n", regs->e.eax);
+               return -ENOSYS;
+       }
+       debug("version %x\n", le16_to_cpu(info->version));
+       debug("oem '%s'\n", (char *)bios_ptr(buffer, vga_info,
+                                            info->oem_string_ptr));
+       debug("vendor '%s'\n", (char *)bios_ptr(buffer, vga_info,
+                                               info->vendor_name_ptr));
+       debug("product '%s'\n", (char *)bios_ptr(buffer, vga_info,
+                                                info->product_name_ptr));
+       debug("rev '%s'\n", (char *)bios_ptr(buffer, vga_info,
+                                            info->product_rev_ptr));
+       modes_bios = bios_ptr(buffer, vga_info, info->modes_ptr);
+       debug("Modes: ");
+       for (ptr = modes_bios; *ptr != 0xffff; ptr++)
+               debug("%x ", le16_to_cpu(*ptr));
+       debug("\nmemory %dMB\n", le16_to_cpu(info->total_memory) >> 4);
+       size = (ptr - modes_bios) * sizeof(u16) + 2;
+       modes = malloc(size);
+       if (!modes)
+               return -ENOMEM;
+       memcpy(modes, modes_bios, size);
+
+       regs->e.eax = VESA_GET_CUR_MODE;
+       BE_int86(0x10, regs, regs);
+       if (regs->e.eax != 0x4f) {
+               debug("VESA_GET_CUR_MODE: error %x\n", regs->e.eax);
+               return -ENOSYS;
+       }
+       debug("Current mode %x\n", regs->e.ebx);
+
+       for (ptr = modes; *ptr != 0xffff; ptr++) {
+               int mode = le16_to_cpu(*ptr);
+               bool linear_ok;
+               int attr;
+
+               break;
+               debug("Mode %x: ", mode);
+               memset(buffer, '\0', sizeof(struct vbe_mode_info));
+               regs->e.eax = VESA_GET_MODE_INFO;
+               regs->e.ebx = 0;
+               regs->e.ecx = mode;
+               regs->e.edx = 0;
+               regs->e.esi = buffer_seg;
+               regs->e.edi = buffer_adr;
+               BE_int86(0x10, regs, regs);
+               if (regs->e.eax != 0x4f) {
+                       debug("VESA_GET_MODE_INFO: error %x\n", regs->e.eax);
+                       continue;
+               }
+               memcpy(mode_info->mode_info_block, buffer,
+                      sizeof(struct vesa_mode_info));
+               mode_info->valid = true;
+               vm = &mode_info->vesa;
+               attr = le16_to_cpu(vm->mode_attributes);
+               linear_ok = attr & 0x80;
+               debug("res %d x %d, %d bpp, mm %d, (Linear %s, attr %02x)\n",
+                     le16_to_cpu(vm->x_resolution),
+                     le16_to_cpu(vm->y_resolution),
+                     vm->bits_per_pixel, vm->memory_model,
+                     linear_ok ? "OK" : "not available",
+                     attr);
+               debug("\tRGB pos=%d,%d,%d, size=%d,%d,%d\n",
+                     vm->red_mask_pos, vm->green_mask_pos, vm->blue_mask_pos,
+                     vm->red_mask_size, vm->green_mask_size,
+                     vm->blue_mask_size);
+       }
+
+       return 0;
+}
+
+static int atibios_set_vesa_mode(RMREGS *regs, int vesa_mode,
+                                struct vbe_mode_info *mode_info)
 {
+       void *buffer = (void *)(M.mem_base + vbe_offset);
+       u16 buffer_seg = (((unsigned long)vbe_offset) >> 4) & 0xff00;
+       u16 buffer_adr = ((unsigned long)vbe_offset) & 0xffff;
+       struct vesa_mode_info *vm;
+
        debug("VBE: Setting VESA mode %#04x\n", vesa_mode);
-       /* request linear framebuffer mode */
-       vesa_mode |= (1 << 14);
-       /* request clearing of framebuffer */
-       vesa_mode &= ~(1 << 15);
        regs->e.eax = VESA_SET_MODE;
        regs->e.ebx = vesa_mode;
+       /* request linear framebuffer mode and don't clear display */
+       regs->e.ebx |= (1 << 14) | (1 << 15);
        BE_int86(0x10, regs, regs);
+       if (regs->e.eax != 0x4f) {
+               debug("VESA_SET_MODE: error %x\n", regs->e.eax);
+               return -ENOSYS;
+       }
 
-       int offset = 0x2000;
-       void *buffer = (void *)(M.mem_base + offset);
-
-       u16 buffer_seg = (((unsigned long)offset) >> 4) & 0xff00;
-       u16 buffer_adr = ((unsigned long)offset) & 0xffff;
+       memset(buffer, '\0', sizeof(struct vbe_mode_info));
+       debug("VBE: Geting info for VESA mode %#04x\n", vesa_mode);
        regs->e.eax = VESA_GET_MODE_INFO;
-       regs->e.ebx = 0;
        regs->e.ecx = vesa_mode;
-       regs->e.edx = 0;
        regs->e.esi = buffer_seg;
        regs->e.edi = buffer_adr;
        BE_int86(0x10, regs, regs);
+       if (regs->e.eax != 0x4f) {
+               debug("VESA_GET_MODE_INFO: error %x\n", regs->e.eax);
+               return -ENOSYS;
+       }
+
        memcpy(mode_info->mode_info_block, buffer,
-              sizeof(struct vbe_mode_info));
+               sizeof(struct vesa_mode_info));
        mode_info->valid = true;
+       mode_info->video_mode = vesa_mode;
+       vm = &mode_info->vesa;
+       vm->x_resolution = le16_to_cpu(vm->x_resolution);
+       vm->y_resolution = le16_to_cpu(vm->y_resolution);
+       vm->bytes_per_scanline = le16_to_cpu(vm->bytes_per_scanline);
+       vm->phys_base_ptr = le32_to_cpu(vm->phys_base_ptr);
+       vm->mode_attributes = le16_to_cpu(vm->mode_attributes);
+       debug("VBE: Init complete\n");
 
-       vesa_mode |= (1 << 14);
-       /* request clearing of framebuffer */
-       vesa_mode &= ~(1 << 15);
-       regs->e.eax = VESA_SET_MODE;
-       regs->e.ebx = vesa_mode;
-       BE_int86(0x10, regs, regs);
+       return 0;
 }
 
 /****************************************************************************
@@ -132,6 +250,9 @@ static void PCI_doBIOSPOST(pci_dev_t pcidev, BE_VGAInfo *vga_info,
        /*Cleanup and exit*/
        BE_getVGA(vga_info);
 
+       /* Useful for debugging */
+       if (0)
+               atibios_debug_mode(vga_info, &regs, vesa_mode, mode_info);
        if (vesa_mode != -1)
                atibios_set_vesa_mode(&regs, vesa_mode, mode_info);
 }
index d4056914c4eb106b431be60828b311846c4aded6..c5deee9eca9d6e4c6997e6422c6d8cff802a3033 100644 (file)
@@ -35,10 +35,14 @@ struct __packed screen_info_input {
 struct __packed vbe_info {
        char signature[4];
        u16 version;
-       u8 *oem_string_ptr;
+       u32 oem_string_ptr;
        u32 capabilities;
-       u16 video_mode_list[256];
+       u32 modes_ptr;
        u16 total_memory;
+       u16 oem_version;
+       u32 vendor_name_ptr;
+       u32 product_name_ptr;
+       u32 product_rev_ptr;
 };
 
 struct __packed vesa_mode_info {
@@ -96,6 +100,7 @@ struct vbe_ddc_info {
 #define VESA_GET_INFO          0x4f00
 #define VESA_GET_MODE_INFO     0x4f01
 #define VESA_SET_MODE          0x4f02
+#define VESA_GET_CUR_MODE      0x4f03
 
 struct graphic_device;
 int vbe_get_video_info(struct graphic_device *gdev);