|
|
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.1.4 ! root 15: #include "bmp.h"
1.1 root 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
1.1.1.4 ! root 112: , int width, int height, int bpp_req)
1.1.1.2 root 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;
1.1.1.4 ! root 138: if (bpp_req == 0) {
! 139: if (depth != 16 && depth != 24 && depth != 32)
! 140: continue;
! 141: } else {
! 142: if (depth != bpp_req)
! 143: continue;
! 144: }
1.1.1.2 root 145: return videomode;
1.1 root 146: }
147: }
148:
1.1.1.2 root 149: static int BootsplashActive;
150:
151: void
152: enable_bootsplash(void)
1.1 root 153: {
1.1.1.2 root 154: if (!CONFIG_BOOTSPLASH)
1.1 root 155: return;
1.1.1.4 ! root 156: /* splash picture can be bmp or jpeg file */
1.1.1.2 root 157: dprintf(3, "Checking for bootsplash\n");
1.1.1.4 ! root 158: u8 type = 0; /* 0 means jpg, 1 means bmp, default is 0=jpg */
1.1.1.3 root 159: int filesize;
160: u8 *filedata = romfile_loadfile("bootsplash.jpg", &filesize);
1.1.1.4 ! root 161: if (!filedata) {
! 162: filedata = romfile_loadfile("bootsplash.bmp", &filesize);
! 163: if (!filedata)
! 164: return;
! 165: type = 1;
! 166: }
! 167: dprintf(3, "start showing bootsplash\n");
1.1 root 168:
1.1.1.4 ! root 169: u8 *picture = NULL; /* data buff used to be flushed to the video buf */
! 170: struct jpeg_decdata *jpeg = NULL;
! 171: struct bmp_decdata *bmp = NULL;
1.1.1.2 root 172: struct vesa_info *vesa_info = malloc_tmplow(sizeof(*vesa_info));
173: struct vesa_mode_info *mode_info = malloc_tmplow(sizeof(*mode_info));
1.1.1.4 ! root 174: if (!vesa_info || !mode_info) {
1.1.1.2 root 175: warn_noalloc();
176: goto done;
177: }
1.1 root 178:
179: /* Check whether we have a VESA 2.0 compliant BIOS */
180: memset(vesa_info, 0, sizeof(struct vesa_info));
1.1.1.2 root 181: vesa_info->vesa_signature = VBE2_SIGNATURE;
182: struct bregs br;
1.1 root 183: memset(&br, 0, sizeof(br));
184: br.ax = 0x4f00;
185: br.di = FLATPTR_TO_OFFSET(vesa_info);
186: br.es = FLATPTR_TO_SEG(vesa_info);
1.1.1.2 root 187: call16_int10(&br);
188: if (vesa_info->vesa_signature != VESA_SIGNATURE) {
1.1 root 189: dprintf(1,"No VBE2 found.\n");
1.1.1.2 root 190: goto done;
1.1 root 191: }
192:
193: /* Print some debugging information about our card. */
1.1.1.2 root 194: char *vendor = SEGOFF_TO_FLATPTR(vesa_info->oem_vendor_name_ptr);
195: char *product = SEGOFF_TO_FLATPTR(vesa_info->oem_product_name_ptr);
196: dprintf(3, "VESA %d.%d\nVENDOR: %s\nPRODUCT: %s\n",
197: vesa_info->vesa_version>>8, vesa_info->vesa_version&0xff,
198: vendor, product);
199:
1.1.1.4 ! root 200: int ret, width, height;
! 201: int bpp_require = 0;
! 202: if (type == 0) {
! 203: jpeg = jpeg_alloc();
! 204: if (!jpeg) {
! 205: warn_noalloc();
! 206: goto done;
! 207: }
! 208: /* Parse jpeg and get image size. */
! 209: dprintf(5, "Decoding bootsplash.jpg\n");
! 210: ret = jpeg_decode(jpeg, filedata);
! 211: if (ret) {
! 212: dprintf(1, "jpeg_decode failed with return code %d...\n", ret);
! 213: goto done;
! 214: }
! 215: jpeg_get_size(jpeg, &width, &height);
! 216: } else {
! 217: bmp = bmp_alloc();
! 218: if (!bmp) {
! 219: warn_noalloc();
! 220: goto done;
! 221: }
! 222: /* Parse bmp and get image size. */
! 223: dprintf(5, "Decoding bootsplash.bmp\n");
! 224: ret = bmp_decode(bmp, filedata, filesize);
! 225: if (ret) {
! 226: dprintf(1, "bmp_decode failed with return code %d...\n", ret);
! 227: goto done;
! 228: }
! 229: bmp_get_size(bmp, &width, &height);
! 230: bpp_require = 24;
1.1 root 231: }
1.1.1.4 ! root 232: /* jpeg would use 16 or 24 bpp video mode, BMP use 24bpp mode only */
1.1 root 233:
1.1.1.2 root 234: // Try to find a graphics mode with the corresponding dimensions.
1.1.1.4 ! root 235: int videomode = find_videomode(vesa_info, mode_info, width, height,
! 236: bpp_require);
! 237: if (videomode < 0) {
! 238: dprintf(1, "failed to find a videomode with %dx%d %dbpp (0=any).\n",
! 239: width, height, bpp_require);
1.1.1.2 root 240: goto done;
1.1.1.4 ! root 241: }
1.1.1.2 root 242: void *framebuffer = mode_info->phys_base_ptr;
243: int depth = mode_info->bits_per_pixel;
244: dprintf(3, "mode: %04x\n", videomode);
245: dprintf(3, "framebuffer: %p\n", framebuffer);
246: dprintf(3, "bytes per scanline: %d\n", mode_info->bytes_per_scanline);
247: dprintf(3, "bits per pixel: %d\n", depth);
248:
249: // Allocate space for image and decompress it.
1.1.1.4 ! root 250: int imagesize = height * mode_info->bytes_per_scanline;
1.1.1.2 root 251: picture = malloc_tmphigh(imagesize);
252: if (!picture) {
253: warn_noalloc();
254: goto done;
1.1 root 255: }
1.1.1.4 ! root 256:
! 257: if (type == 0) {
! 258: dprintf(5, "Decompressing bootsplash.jpg\n");
! 259: ret = jpeg_show(jpeg, picture, width, height, depth,
! 260: mode_info->bytes_per_scanline);
! 261: if (ret) {
! 262: dprintf(1, "jpeg_show failed with return code %d...\n", ret);
! 263: goto done;
! 264: }
! 265: } else {
! 266: dprintf(5, "Decompressing bootsplash.bmp\n");
! 267: ret = bmp_show(bmp, picture, width, height, depth,
! 268: mode_info->bytes_per_scanline);
! 269: if (ret) {
! 270: dprintf(1, "bmp_show failed with return code %d...\n", ret);
! 271: goto done;
! 272: }
1.1 root 273: }
274:
1.1.1.2 root 275: /* Switch to graphics mode */
276: dprintf(5, "Switching to graphics mode\n");
1.1 root 277: memset(&br, 0, sizeof(br));
1.1.1.2 root 278: br.ax = 0x4f02;
279: br.bx = (1 << 14) | videomode;
280: call16_int10(&br);
1.1 root 281: if (br.ax != 0x4f) {
1.1.1.2 root 282: dprintf(1, "set_mode failed.\n");
283: goto done;
1.1 root 284: }
285:
1.1.1.2 root 286: /* Show the picture */
1.1.1.4 ! root 287: dprintf(5, "Showing bootsplash picture\n");
1.1.1.2 root 288: iomemcpy(framebuffer, picture, imagesize);
289: dprintf(5, "Bootsplash copy complete\n");
290: BootsplashActive = 1;
291:
292: done:
293: free(filedata);
294: free(picture);
295: free(vesa_info);
296: free(mode_info);
297: free(jpeg);
1.1.1.4 ! root 298: free(bmp);
1.1.1.2 root 299: return;
1.1 root 300: }
301:
302: void
303: disable_bootsplash(void)
304: {
1.1.1.2 root 305: if (!CONFIG_BOOTSPLASH || !BootsplashActive)
1.1 root 306: return;
1.1.1.2 root 307: BootsplashActive = 0;
308: enable_vga_console();
1.1 root 309: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.