blob: b96e0666df86bcf50274ba8dff48ecf479525c65 [file] [log] [blame]
Kevin O'Connorafbed1b2010-06-28 07:34:53 -04001// Option rom scanning code.
2//
3// Copyright (C) 2009-2010 coresystems GmbH
Kevin O'Connor6dc76f42010-07-26 23:16:12 -04004// Copyright (C) 2010 Kevin O'Connor <kevin@koconnor.net>
Kevin O'Connorafbed1b2010-06-28 07:34:53 -04005//
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
13
Kevin O'Connorafbed1b2010-06-28 07:34:53 -040014
15/****************************************************************
16 * VESA structures
17 ****************************************************************/
18
19struct vesa_info
20{
21 u8 vesa_signature[4];
22 u16 vesa_version;
Kevin O'Connora576c9c2010-07-26 22:43:18 -040023 struct segoff_s oem_string_ptr;
Kevin O'Connorafbed1b2010-06-28 07:34:53 -040024 u8 capabilities[4];
Kevin O'Connora576c9c2010-07-26 22:43:18 -040025 struct segoff_s video_mode_ptr;
Kevin O'Connorafbed1b2010-06-28 07:34:53 -040026 u16 total_memory;
27 u16 oem_software_rev;
Kevin O'Connora576c9c2010-07-26 22:43:18 -040028 struct segoff_s oem_vendor_name_ptr;
29 struct segoff_s oem_product_name_ptr;
30 struct segoff_s oem_product_rev_ptr;
Kevin O'Connorafbed1b2010-06-28 07:34:53 -040031 u8 reserved[222];
32 u8 oem_data[256];
33} PACKED;
34
35struct vesa_mode_info
36{
37 u16 mode_attributes;
38 u8 win_a_attributes;
39 u8 win_b_attributes;
40 u16 win_granularity;
41 u16 win_size;
42 u16 win_a_segment;
43 u16 win_b_segment;
44 u32 win_func_ptr;
45 u16 bytes_per_scanline;
46 u16 x_resolution;
47 u16 y_resolution;
48 u8 x_charsize;
49 u8 y_charsize;
50 u8 number_of_planes;
51 u8 bits_per_pixel;
52 u8 number_of_banks;
53 u8 memory_model;
54 u8 bank_size;
55 u8 number_of_image_pages;
56 u8 reserved_page;
57 u8 red_mask_size;
58 u8 red_mask_pos;
59 u8 green_mask_size;
60 u8 green_mask_pos;
61 u8 blue_mask_size;
62 u8 blue_mask_pos;
63 u8 reserved_mask_size;
64 u8 reserved_mask_pos;
65 u8 direct_color_mode_info;
66 u32 phys_base_ptr;
67 u32 offscreen_mem_offset;
68 u16 offscreen_mem_size;
69 u8 reserved[206];
70} PACKED;
71
72/****************************************************************
73 * Helper functions
74 ****************************************************************/
75
Kevin O'Connor26411862010-07-26 23:25:39 -040076// Call int10 vga handler.
77static void
78call16_int10(struct bregs *br)
79{
80 br->flags = F_IF;
81 start_preempt();
82 call16_int(0x10, br);
83 finish_preempt();
84}
85
86
Kevin O'Connorafbed1b2010-06-28 07:34:53 -040087/****************************************************************
88 * VGA text / graphics console
89 ****************************************************************/
Kevin O'Connor26411862010-07-26 23:25:39 -040090
Kevin O'Connorafbed1b2010-06-28 07:34:53 -040091static void enable_vga_text_console(void)
92{
93 dprintf(1, "Turning on vga text mode console\n");
94 struct bregs br;
95
96 /* Enable VGA text mode */
97 memset(&br, 0, sizeof(br));
Kevin O'Connorafbed1b2010-06-28 07:34:53 -040098 br.ax = 0x0003;
Kevin O'Connor26411862010-07-26 23:25:39 -040099 call16_int10(&br);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400100
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400101 // Write to screen.
102 printf("Starting SeaBIOS (version %s)\n\n", VERSION);
103}
104
105void enable_vga_console(void)
106{
Kevin O'Connor227dc3e2010-07-26 23:02:26 -0400107 struct vesa_info *vesa_info = NULL;
108 struct vesa_mode_info *mode_info = NULL;
109 struct jpeg_decdata *decdata = NULL;
Kevin O'Connor6dc76f42010-07-26 23:16:12 -0400110 u8 *jpeg = NULL, *picture = NULL;
Kevin O'Connor227dc3e2010-07-26 23:02:26 -0400111
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400112 /* Needs coreboot support for CBFS */
Kevin O'Connor227dc3e2010-07-26 23:02:26 -0400113 if (!CONFIG_BOOTSPLASH || !CONFIG_COREBOOT)
114 goto gotext;
115 struct cbfs_file *file = cbfs_finddatafile("bootsplash.jpg");
116 if (!file)
117 goto gotext;
118 int filesize = cbfs_datasize(file);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400119
Kevin O'Connor6dc76f42010-07-26 23:16:12 -0400120 int imagesize = (CONFIG_BOOTSPLASH_X * CONFIG_BOOTSPLASH_Y *
121 (CONFIG_BOOTSPLASH_DEPTH / 8));
Kevin O'Connor227dc3e2010-07-26 23:02:26 -0400122 jpeg = malloc_tmphigh(filesize);
Kevin O'Connor6dc76f42010-07-26 23:16:12 -0400123 picture = malloc_tmphigh(imagesize);
Kevin O'Connora576c9c2010-07-26 22:43:18 -0400124 vesa_info = malloc_tmplow(sizeof(*vesa_info));
125 mode_info = malloc_tmplow(sizeof(*mode_info));
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400126 decdata = malloc_tmphigh(sizeof(*decdata));
Kevin O'Connor6dc76f42010-07-26 23:16:12 -0400127 if (!jpeg || !picture || !vesa_info || !mode_info || !decdata) {
Kevin O'Connor227dc3e2010-07-26 23:02:26 -0400128 warn_noalloc();
129 goto gotext;
130 }
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400131
132 /* Check whether we have a VESA 2.0 compliant BIOS */
133 memset(vesa_info, 0, sizeof(struct vesa_info));
134 memcpy(vesa_info, "VBE2", 4);
135
Kevin O'Connor227dc3e2010-07-26 23:02:26 -0400136 struct bregs br;
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400137 memset(&br, 0, sizeof(br));
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400138 br.ax = 0x4f00;
139 br.di = FLATPTR_TO_OFFSET(vesa_info);
140 br.es = FLATPTR_TO_SEG(vesa_info);
Kevin O'Connor26411862010-07-26 23:25:39 -0400141 call16_int10(&br);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400142
Kevin O'Connor227dc3e2010-07-26 23:02:26 -0400143 if (strcmp("VESA", (char *)vesa_info) != 0) {
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400144 dprintf(1,"No VBE2 found.\n");
Kevin O'Connor227dc3e2010-07-26 23:02:26 -0400145 goto gotext;
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400146 }
147
148 /* Print some debugging information about our card. */
Kevin O'Connora576c9c2010-07-26 22:43:18 -0400149 char *vendor = SEGOFF_TO_FLATPTR(vesa_info->oem_vendor_name_ptr);
150 char *product = SEGOFF_TO_FLATPTR(vesa_info->oem_product_name_ptr);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400151 dprintf(8, "VESA %d.%d\nVENDOR: %s\nPRODUCT: %s\n",
Kevin O'Connora576c9c2010-07-26 22:43:18 -0400152 vesa_info->vesa_version>>8, vesa_info->vesa_version&0xff,
153 vendor, product);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400154
155 /* Get information about our graphics mode, like the
156 * framebuffer start address
157 */
158 memset(&br, 0, sizeof(br));
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400159 br.ax = 0x4f01;
160 br.cx = (1 << 14) | CONFIG_BOOTSPLASH_VESA_MODE;
161 br.di = FLATPTR_TO_OFFSET(mode_info);
162 br.es = FLATPTR_TO_SEG(mode_info);
Kevin O'Connor26411862010-07-26 23:25:39 -0400163 call16_int10(&br);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400164 if (br.ax != 0x4f) {
165 dprintf(1, "get_mode failed.\n");
Kevin O'Connor227dc3e2010-07-26 23:02:26 -0400166 goto gotext;
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400167 }
168 unsigned char *framebuffer = (unsigned char *) (mode_info->phys_base_ptr);
169
170 /* Switch to graphics mode */
171 memset(&br, 0, sizeof(br));
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400172 br.ax = 0x4f02;
173 br.bx = (1 << 14) | CONFIG_BOOTSPLASH_VESA_MODE;
Kevin O'Connor26411862010-07-26 23:25:39 -0400174 call16_int10(&br);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400175 if (br.ax != 0x4f) {
176 dprintf(1, "set_mode failed.\n");
Kevin O'Connor227dc3e2010-07-26 23:02:26 -0400177 goto gotext;
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400178 }
179
Kevin O'Connora576c9c2010-07-26 22:43:18 -0400180 dprintf(8, "framebuffer: %x\n", (u32)framebuffer);
181 dprintf(8, "bytes per scanline: %d\n", mode_info->bytes_per_scanline);
182 dprintf(8, "bits per pixel: %d\n", mode_info->bits_per_pixel);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400183
184 /* Look for bootsplash.jpg in CBFS and decompress it... */
Kevin O'Connor227dc3e2010-07-26 23:02:26 -0400185 dprintf(8, "Copying boot splash screen...\n");
186 cbfs_copyfile(file, jpeg, filesize);
187 dprintf(8, "Decompressing boot splash screen...\n");
Kevin O'Connor6dc76f42010-07-26 23:16:12 -0400188 int ret = jpeg_decode(jpeg, picture, CONFIG_BOOTSPLASH_X,
Kevin O'Connora576c9c2010-07-26 22:43:18 -0400189 CONFIG_BOOTSPLASH_Y, CONFIG_BOOTSPLASH_DEPTH, decdata);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400190 if (ret) {
Kevin O'Connor227dc3e2010-07-26 23:02:26 -0400191 dprintf(1, "jpeg_decode failed with return code %d...\n", ret);
192 goto gotext;
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400193 }
194
195 /* Show the picture */
Kevin O'Connor6dc76f42010-07-26 23:16:12 -0400196 iomemcpy(framebuffer, picture, imagesize);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400197
198cleanup:
Kevin O'Connor227dc3e2010-07-26 23:02:26 -0400199 free(jpeg);
Kevin O'Connor6dc76f42010-07-26 23:16:12 -0400200 free(picture);
Kevin O'Connor227dc3e2010-07-26 23:02:26 -0400201 free(vesa_info);
202 free(mode_info);
203 free(decdata);
204 return;
205gotext:
206 enable_vga_text_console();
207 goto cleanup;
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400208}
209
210void
211disable_bootsplash(void)
212{
213 if (! CONFIG_BOOTSPLASH)
214 return;
215 enable_vga_text_console();
216}