blob: e2156f2bde10ff1c422a390c786b694719adddd7 [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
76/****************************************************************
77 * VGA text / graphics console
78 ****************************************************************/
79static void enable_vga_text_console(void)
80{
81 dprintf(1, "Turning on vga text mode console\n");
82 struct bregs br;
83
84 /* Enable VGA text mode */
85 memset(&br, 0, sizeof(br));
86 br.flags = F_IF;
87 br.ax = 0x0003;
88 start_preempt();
89 call16_int(0x10, &br);
90 finish_preempt();
91
Kevin O'Connorafbed1b2010-06-28 07:34:53 -040092 // Write to screen.
93 printf("Starting SeaBIOS (version %s)\n\n", VERSION);
94}
95
96void enable_vga_console(void)
97{
Kevin O'Connor227dc3e2010-07-26 23:02:26 -040098 struct vesa_info *vesa_info = NULL;
99 struct vesa_mode_info *mode_info = NULL;
100 struct jpeg_decdata *decdata = NULL;
Kevin O'Connor6dc76f42010-07-26 23:16:12 -0400101 u8 *jpeg = NULL, *picture = NULL;
Kevin O'Connor227dc3e2010-07-26 23:02:26 -0400102
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400103 /* Needs coreboot support for CBFS */
Kevin O'Connor227dc3e2010-07-26 23:02:26 -0400104 if (!CONFIG_BOOTSPLASH || !CONFIG_COREBOOT)
105 goto gotext;
106 struct cbfs_file *file = cbfs_finddatafile("bootsplash.jpg");
107 if (!file)
108 goto gotext;
109 int filesize = cbfs_datasize(file);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400110
Kevin O'Connor6dc76f42010-07-26 23:16:12 -0400111 int imagesize = (CONFIG_BOOTSPLASH_X * CONFIG_BOOTSPLASH_Y *
112 (CONFIG_BOOTSPLASH_DEPTH / 8));
Kevin O'Connor227dc3e2010-07-26 23:02:26 -0400113 jpeg = malloc_tmphigh(filesize);
Kevin O'Connor6dc76f42010-07-26 23:16:12 -0400114 picture = malloc_tmphigh(imagesize);
Kevin O'Connora576c9c2010-07-26 22:43:18 -0400115 vesa_info = malloc_tmplow(sizeof(*vesa_info));
116 mode_info = malloc_tmplow(sizeof(*mode_info));
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400117 decdata = malloc_tmphigh(sizeof(*decdata));
Kevin O'Connor6dc76f42010-07-26 23:16:12 -0400118 if (!jpeg || !picture || !vesa_info || !mode_info || !decdata) {
Kevin O'Connor227dc3e2010-07-26 23:02:26 -0400119 warn_noalloc();
120 goto gotext;
121 }
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400122
123 /* Check whether we have a VESA 2.0 compliant BIOS */
124 memset(vesa_info, 0, sizeof(struct vesa_info));
125 memcpy(vesa_info, "VBE2", 4);
126
Kevin O'Connor227dc3e2010-07-26 23:02:26 -0400127 struct bregs br;
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400128 memset(&br, 0, sizeof(br));
129 br.flags = F_IF;
130 br.ax = 0x4f00;
131 br.di = FLATPTR_TO_OFFSET(vesa_info);
132 br.es = FLATPTR_TO_SEG(vesa_info);
133 start_preempt();
134 call16_int(0x10, &br);
135 finish_preempt();
136
Kevin O'Connor227dc3e2010-07-26 23:02:26 -0400137 if (strcmp("VESA", (char *)vesa_info) != 0) {
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400138 dprintf(1,"No VBE2 found.\n");
Kevin O'Connor227dc3e2010-07-26 23:02:26 -0400139 goto gotext;
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400140 }
141
142 /* Print some debugging information about our card. */
Kevin O'Connora576c9c2010-07-26 22:43:18 -0400143 char *vendor = SEGOFF_TO_FLATPTR(vesa_info->oem_vendor_name_ptr);
144 char *product = SEGOFF_TO_FLATPTR(vesa_info->oem_product_name_ptr);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400145 dprintf(8, "VESA %d.%d\nVENDOR: %s\nPRODUCT: %s\n",
Kevin O'Connora576c9c2010-07-26 22:43:18 -0400146 vesa_info->vesa_version>>8, vesa_info->vesa_version&0xff,
147 vendor, product);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400148
149 /* Get information about our graphics mode, like the
150 * framebuffer start address
151 */
152 memset(&br, 0, sizeof(br));
153 br.flags = F_IF;
154 br.ax = 0x4f01;
155 br.cx = (1 << 14) | CONFIG_BOOTSPLASH_VESA_MODE;
156 br.di = FLATPTR_TO_OFFSET(mode_info);
157 br.es = FLATPTR_TO_SEG(mode_info);
158 start_preempt();
159 call16_int(0x10, &br);
160 finish_preempt();
161 if (br.ax != 0x4f) {
162 dprintf(1, "get_mode failed.\n");
Kevin O'Connor227dc3e2010-07-26 23:02:26 -0400163 goto gotext;
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400164 }
165 unsigned char *framebuffer = (unsigned char *) (mode_info->phys_base_ptr);
166
167 /* Switch to graphics mode */
168 memset(&br, 0, sizeof(br));
169 br.flags = F_IF;
170 br.ax = 0x4f02;
171 br.bx = (1 << 14) | CONFIG_BOOTSPLASH_VESA_MODE;
172 start_preempt();
173 call16_int(0x10, &br);
174 finish_preempt();
175 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}