Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


imported SEABIOS source tree
[palacios.git] / bios / seabios / src / bootsplash.c
1 // Option rom scanning code.
2 //
3 // Copyright (C) 2009-2010  coresystems GmbH
4 // Copyright (C) 2010  Kevin O'Connor <kevin@koconnor.net>
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
13 #include "biosvar.h" // SET_EBDA
14 #include "paravirt.h" // romfile_find
15 #include "bmp.h"
16
17 /****************************************************************
18  * VESA structures
19  ****************************************************************/
20
21 struct vesa_info {
22     u32 vesa_signature;
23     u16 vesa_version;
24     struct segoff_s oem_string_ptr;
25     u8 capabilities[4];
26     struct segoff_s video_mode_ptr;
27     u16 total_memory;
28     u16 oem_software_rev;
29     struct segoff_s oem_vendor_name_ptr;
30     struct segoff_s oem_product_name_ptr;
31     struct segoff_s oem_product_rev_ptr;
32     u8 reserved[222];
33     u8 oem_data[256];
34 } PACKED;
35
36 #define VESA_SIGNATURE 0x41534556 // VESA
37 #define VBE2_SIGNATURE 0x32454256 // VBE2
38
39 struct vesa_mode_info {
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;
69     void *phys_base_ptr;
70     u32 offscreen_mem_offset;
71     u16 offscreen_mem_size;
72     u8 reserved[206];
73 } PACKED;
74
75
76 /****************************************************************
77  * Helper functions
78  ****************************************************************/
79
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
91 /****************************************************************
92  * VGA text / graphics console
93  ****************************************************************/
94
95 void
96 enable_vga_console(void)
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;
104     call16_int10(&br);
105
106     // Write to screen.
107     printf("SeaBIOS (version %s)\n\n", VERSION);
108 }
109
110 static int
111 find_videomode(struct vesa_info *vesa_info, struct vesa_mode_info *mode_info
112                , int width, int height, int bpp_req)
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;
124         memset(&br, 0, sizeof(br));
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 (bpp_req == 0) {
139             if (depth != 16 && depth != 24 && depth != 32)
140                 continue;
141         } else {
142             if (depth != bpp_req)
143                 continue;
144         }
145         return videomode;
146     }
147 }
148
149 static int BootsplashActive;
150
151 void
152 enable_bootsplash(void)
153 {
154     if (!CONFIG_BOOTSPLASH)
155         return;
156     /* splash picture can be bmp or jpeg file */
157     dprintf(3, "Checking for bootsplash\n");
158     u8 type = 0; /* 0 means jpg, 1 means bmp, default is 0=jpg */
159     int filesize;
160     u8 *filedata = romfile_loadfile("bootsplash.jpg", &filesize);
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");
168
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;
172     struct vesa_info *vesa_info = malloc_tmplow(sizeof(*vesa_info));
173     struct vesa_mode_info *mode_info = malloc_tmplow(sizeof(*mode_info));
174     if (!vesa_info || !mode_info) {
175         warn_noalloc();
176         goto done;
177     }
178
179     /* Check whether we have a VESA 2.0 compliant BIOS */
180     memset(vesa_info, 0, sizeof(struct vesa_info));
181     vesa_info->vesa_signature = VBE2_SIGNATURE;
182     struct bregs br;
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);
187     call16_int10(&br);
188     if (vesa_info->vesa_signature != VESA_SIGNATURE) {
189         dprintf(1,"No VBE2 found.\n");
190         goto done;
191     }
192
193     /* Print some debugging information about our card. */
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
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;
231     }
232     /* jpeg would use 16 or 24 bpp video mode, BMP use 24bpp mode only */
233
234     // Try to find a graphics mode with the corresponding dimensions.
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);
240         goto done;
241     }
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.
250     int imagesize = height * mode_info->bytes_per_scanline;
251     picture = malloc_tmphigh(imagesize);
252     if (!picture) {
253         warn_noalloc();
254         goto done;
255     }
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         }
273     }
274
275     /* Switch to graphics mode */
276     dprintf(5, "Switching to graphics mode\n");
277     memset(&br, 0, sizeof(br));
278     br.ax = 0x4f02;
279     br.bx = (1 << 14) | videomode;
280     call16_int10(&br);
281     if (br.ax != 0x4f) {
282         dprintf(1, "set_mode failed.\n");
283         goto done;
284     }
285
286     /* Show the picture */
287     dprintf(5, "Showing bootsplash picture\n");
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);
298     free(bmp);
299     return;
300 }
301
302 void
303 disable_bootsplash(void)
304 {
305     if (!CONFIG_BOOTSPLASH || !BootsplashActive)
306         return;
307     BootsplashActive = 0;
308     enable_vga_console();
309 }