|
|
1.1 root 1: // Option rom scanning code.
2: //
3: // Copyright (C) 2009-2010 coresystems GmbH
1.1.1.2 ! root 4: // Copyright (C) 2010 Kevin O'Connor <[email protected]>
1.1 root 5: //
6: // This file may be distributed under the terms of the GNU LGPLv3 license.
7:
8: #include "bregs.h" // struct bregs
9: #include "farptr.h" // FLATPTR_TO_SEG
10: #include "config.h" // CONFIG_*
11: #include "util.h" // dprintf
12: #include "jpeg.h" // splash
1.1.1.2 ! root 13: #include "biosvar.h" // SET_EBDA
! 14: #include "paravirt.h" // romfile_find
1.1 root 15:
16:
17: /****************************************************************
18: * VESA structures
19: ****************************************************************/
20:
1.1.1.2 ! root 21: struct vesa_info {
! 22: u32 vesa_signature;
1.1 root 23: u16 vesa_version;
1.1.1.2 ! root 24: struct segoff_s oem_string_ptr;
1.1 root 25: u8 capabilities[4];
1.1.1.2 ! root 26: struct segoff_s video_mode_ptr;
1.1 root 27: u16 total_memory;
28: u16 oem_software_rev;
1.1.1.2 ! root 29: struct segoff_s oem_vendor_name_ptr;
! 30: struct segoff_s oem_product_name_ptr;
! 31: struct segoff_s oem_product_rev_ptr;
1.1 root 32: u8 reserved[222];
33: u8 oem_data[256];
34: } PACKED;
35:
1.1.1.2 ! root 36: #define VESA_SIGNATURE 0x41534556 // VESA
! 37: #define VBE2_SIGNATURE 0x32454256 // VBE2
! 38:
! 39: struct vesa_mode_info {
1.1 root 40: u16 mode_attributes;
41: u8 win_a_attributes;
42: u8 win_b_attributes;
43: u16 win_granularity;
44: u16 win_size;
45: u16 win_a_segment;
46: u16 win_b_segment;
47: u32 win_func_ptr;
48: u16 bytes_per_scanline;
49: u16 x_resolution;
50: u16 y_resolution;
51: u8 x_charsize;
52: u8 y_charsize;
53: u8 number_of_planes;
54: u8 bits_per_pixel;
55: u8 number_of_banks;
56: u8 memory_model;
57: u8 bank_size;
58: u8 number_of_image_pages;
59: u8 reserved_page;
60: u8 red_mask_size;
61: u8 red_mask_pos;
62: u8 green_mask_size;
63: u8 green_mask_pos;
64: u8 blue_mask_size;
65: u8 blue_mask_pos;
66: u8 reserved_mask_size;
67: u8 reserved_mask_pos;
68: u8 direct_color_mode_info;
1.1.1.2 ! root 69: void *phys_base_ptr;
1.1 root 70: u32 offscreen_mem_offset;
71: u16 offscreen_mem_size;
72: u8 reserved[206];
73: } PACKED;
74:
1.1.1.2 ! root 75:
1.1 root 76: /****************************************************************
77: * Helper functions
78: ****************************************************************/
79:
1.1.1.2 ! root 80: // Call int10 vga handler.
! 81: static void
! 82: call16_int10(struct bregs *br)
! 83: {
! 84: br->flags = F_IF;
! 85: start_preempt();
! 86: call16_int(0x10, br);
! 87: finish_preempt();
! 88: }
! 89:
! 90:
1.1 root 91: /****************************************************************
92: * VGA text / graphics console
93: ****************************************************************/
1.1.1.2 ! root 94:
! 95: void
! 96: enable_vga_console(void)
1.1 root 97: {
98: dprintf(1, "Turning on vga text mode console\n");
99: struct bregs br;
100:
101: /* Enable VGA text mode */
102: memset(&br, 0, sizeof(br));
103: br.ax = 0x0003;
1.1.1.2 ! root 104: call16_int10(&br);
! 105:
! 106: // Write to screen.
! 107: printf("SeaBIOS (version %s)\n\n", VERSION);
! 108: }
1.1 root 109:
1.1.1.2 ! root 110: static int
! 111: find_videomode(struct vesa_info *vesa_info, struct vesa_mode_info *mode_info
! 112: , int width, int height)
! 113: {
! 114: dprintf(3, "Finding vesa mode with dimensions %d/%d\n", width, height);
! 115: u16 *videomodes = SEGOFF_TO_FLATPTR(vesa_info->video_mode_ptr);
! 116: for (;; videomodes++) {
! 117: u16 videomode = *videomodes;
! 118: if (videomode == 0xffff) {
! 119: dprintf(1, "Unable to find vesa video mode dimensions %d/%d\n"
! 120: , width, height);
! 121: return -1;
! 122: }
! 123: struct bregs br;
1.1 root 124: memset(&br, 0, sizeof(br));
1.1.1.2 ! root 125: br.ax = 0x4f01;
! 126: br.cx = (1 << 14) | videomode;
! 127: br.di = FLATPTR_TO_OFFSET(mode_info);
! 128: br.es = FLATPTR_TO_SEG(mode_info);
! 129: call16_int10(&br);
! 130: if (br.ax != 0x4f) {
! 131: dprintf(1, "get_mode failed.\n");
! 132: continue;
! 133: }
! 134: if (mode_info->x_resolution != width
! 135: || mode_info->y_resolution != height)
! 136: continue;
! 137: u8 depth = mode_info->bits_per_pixel;
! 138: if (depth != 16 && depth != 24 && depth != 32)
! 139: continue;
! 140: return videomode;
1.1 root 141: }
142: }
143:
1.1.1.2 ! root 144: static int BootsplashActive;
! 145:
! 146: void
! 147: enable_bootsplash(void)
1.1 root 148: {
1.1.1.2 ! root 149: if (!CONFIG_BOOTSPLASH)
1.1 root 150: return;
1.1.1.2 ! root 151: dprintf(3, "Checking for bootsplash\n");
! 152: u32 file = romfile_find("bootsplash.jpg");
! 153: if (!file)
! 154: return;
! 155: int filesize = romfile_size(file);
1.1 root 156:
1.1.1.2 ! root 157: u8 *picture = NULL;
! 158: u8 *filedata = malloc_tmphigh(filesize);
! 159: struct vesa_info *vesa_info = malloc_tmplow(sizeof(*vesa_info));
! 160: struct vesa_mode_info *mode_info = malloc_tmplow(sizeof(*mode_info));
! 161: struct jpeg_decdata *jpeg = jpeg_alloc();
! 162: if (!filedata || !jpeg || !vesa_info || !mode_info) {
! 163: warn_noalloc();
! 164: goto done;
! 165: }
1.1 root 166:
167: /* Check whether we have a VESA 2.0 compliant BIOS */
168: memset(vesa_info, 0, sizeof(struct vesa_info));
1.1.1.2 ! root 169: vesa_info->vesa_signature = VBE2_SIGNATURE;
! 170: struct bregs br;
1.1 root 171: memset(&br, 0, sizeof(br));
172: br.ax = 0x4f00;
173: br.di = FLATPTR_TO_OFFSET(vesa_info);
174: br.es = FLATPTR_TO_SEG(vesa_info);
1.1.1.2 ! root 175: call16_int10(&br);
! 176: if (vesa_info->vesa_signature != VESA_SIGNATURE) {
1.1 root 177: dprintf(1,"No VBE2 found.\n");
1.1.1.2 ! root 178: goto done;
1.1 root 179: }
180:
181: /* Print some debugging information about our card. */
1.1.1.2 ! root 182: char *vendor = SEGOFF_TO_FLATPTR(vesa_info->oem_vendor_name_ptr);
! 183: char *product = SEGOFF_TO_FLATPTR(vesa_info->oem_product_name_ptr);
! 184: dprintf(3, "VESA %d.%d\nVENDOR: %s\nPRODUCT: %s\n",
! 185: vesa_info->vesa_version>>8, vesa_info->vesa_version&0xff,
! 186: vendor, product);
! 187:
! 188: // Parse jpeg and get image size.
! 189: dprintf(5, "Copying bootsplash.jpg\n");
! 190: romfile_copy(file, filedata, filesize);
! 191: dprintf(5, "Decoding bootsplash.jpg\n");
! 192: int ret = jpeg_decode(jpeg, filedata);
! 193: if (ret) {
! 194: dprintf(1, "jpeg_decode failed with return code %d...\n", ret);
! 195: goto done;
1.1 root 196: }
1.1.1.2 ! root 197: int width, height;
! 198: jpeg_get_size(jpeg, &width, &height);
1.1 root 199:
1.1.1.2 ! root 200: // Try to find a graphics mode with the corresponding dimensions.
! 201: int videomode = find_videomode(vesa_info, mode_info, width, height);
! 202: if (videomode < 0)
! 203: goto done;
! 204: void *framebuffer = mode_info->phys_base_ptr;
! 205: int depth = mode_info->bits_per_pixel;
! 206: dprintf(3, "mode: %04x\n", videomode);
! 207: dprintf(3, "framebuffer: %p\n", framebuffer);
! 208: dprintf(3, "bytes per scanline: %d\n", mode_info->bytes_per_scanline);
! 209: dprintf(3, "bits per pixel: %d\n", depth);
! 210:
! 211: // Allocate space for image and decompress it.
! 212: int imagesize = width * height * (depth / 8);
! 213: picture = malloc_tmphigh(imagesize);
! 214: if (!picture) {
! 215: warn_noalloc();
! 216: goto done;
1.1 root 217: }
1.1.1.2 ! root 218: dprintf(5, "Decompressing bootsplash.jpg\n");
! 219: ret = jpeg_show(jpeg, picture, width, height, depth);
1.1 root 220: if (ret) {
1.1.1.2 ! root 221: dprintf(1, "jpeg_show failed with return code %d...\n", ret);
! 222: goto done;
1.1 root 223: }
224:
1.1.1.2 ! root 225: /* Switch to graphics mode */
! 226: dprintf(5, "Switching to graphics mode\n");
1.1 root 227: memset(&br, 0, sizeof(br));
1.1.1.2 ! root 228: br.ax = 0x4f02;
! 229: br.bx = (1 << 14) | videomode;
! 230: call16_int10(&br);
1.1 root 231: if (br.ax != 0x4f) {
1.1.1.2 ! root 232: dprintf(1, "set_mode failed.\n");
! 233: goto done;
1.1 root 234: }
235:
1.1.1.2 ! root 236: /* Show the picture */
! 237: dprintf(5, "Showing bootsplash.jpg\n");
! 238: iomemcpy(framebuffer, picture, imagesize);
! 239: dprintf(5, "Bootsplash copy complete\n");
! 240: BootsplashActive = 1;
! 241:
! 242: done:
! 243: free(filedata);
! 244: free(picture);
! 245: free(vesa_info);
! 246: free(mode_info);
! 247: free(jpeg);
! 248: return;
1.1 root 249: }
250:
251: void
252: disable_bootsplash(void)
253: {
1.1.1.2 ! root 254: if (!CONFIG_BOOTSPLASH || !BootsplashActive)
1.1 root 255: return;
1.1.1.2 ! root 256: BootsplashActive = 0;
! 257: enable_vga_console();
1.1 root 258: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.