VirtualBox

source: vbox/trunk/src/VBox/Devices/PC/BIOS/logo.c@ 5574

Last change on this file since 5574 was 4525, checked in by vboxsync, 17 years ago

F12 boot menu Floppy selection fixed.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.9 KB
Line 
1#define COMPRESS_NONE 0
2#define COMPRESS_RLE8 1
3#define COMPRESS_RLE4 2
4
5#define BMP_HEADER_OS21 12
6#define BMP_HEADER_OS22 64
7#define BMP_HEADER_WIN3 40
8
9#define WAIT_HZ 64
10#define WAIT_MS 16
11
12#define F12_SCAN_CODE 0x86
13#define F12_WAIT_TIME (3 * WAIT_HZ) /* 3 seconds. Used only if logo disabled. */
14
15#define LOGO_IO_PORT 0x506
16
17typedef struct
18{
19 Bit8u Blue;
20 Bit8u Green;
21 Bit8u Red;
22} RGBPAL;
23
24/* BMP File Format Bitmap Header. */
25typedef struct
26{
27 Bit16u Type; /* File Type Identifier */
28 Bit32u FileSize; /* Size of File */
29 Bit16u Reserved1; /* Reserved (should be 0) */
30 Bit16u Reserved2; /* Reserved (should be 0) */
31 Bit32u Offset; /* Offset to bitmap data */
32} BMPINFO;
33
34/* OS/2 1.x Information Header Format. */
35typedef struct
36{
37 Bit32u Size; /* Size of Remianing Header */
38 Bit16u Width; /* Width of Bitmap in Pixels */
39 Bit16u Height; /* Height of Bitmap in Pixels */
40 Bit16u Planes; /* Number of Planes */
41 Bit16u BitCount; /* Color Bits Per Pixel */
42} OS2HDR;
43
44/* OS/2 2.0 Information Header Format. */
45typedef struct
46{
47 Bit32u Size; /* Size of Remianing Header */
48 Bit32u Width; /* Width of Bitmap in Pixels */
49 Bit32u Height; /* Height of Bitmap in Pixels */
50 Bit16u Planes; /* Number of Planes */
51 Bit16u BitCount; /* Color Bits Per Pixel */
52 Bit32u Compression; /* Compression Scheme (0=none) */
53 Bit32u SizeImage; /* Size of bitmap in bytes */
54 Bit32u XPelsPerMeter; /* Horz. Resolution in Pixels/Meter */
55 Bit32u YPelsPerMeter; /* Vert. Resolution in Pixels/Meter */
56 Bit32u ClrUsed; /* Number of Colors in Color Table */
57 Bit32u ClrImportant; /* Number of Important Colors */
58 Bit16u Units; /* Resolution Mesaurement Used */
59 Bit16u Reserved; /* Reserved FIelds (always 0) */
60 Bit16u Recording; /* Orientation of Bitmap */
61 Bit16u Rendering; /* Halftone Algorithm Used on Image */
62 Bit32u Size1; /* Halftone Algorithm Data */
63 Bit32u Size2; /* Halftone Algorithm Data */
64 Bit32u ColorEncoding; /* Color Table Format (always 0) */
65 Bit32u Identifier; /* Misc. Field for Application Use */
66} OS22HDR;
67
68/* Windows 3.x Information Header Format. */
69typedef struct
70{
71 Bit32u Size; /* Size of Remianing Header */
72 Bit32u Width; /* Width of Bitmap in Pixels */
73 Bit32u Height; /* Height of Bitmap in Pixels */
74 Bit16u Planes; /* Number of Planes */
75 Bit16u BitCount; /* Bits Per Pixel */
76 Bit32u Compression; /* Compression Scheme (0=none) */
77 Bit32u SizeImage; /* Size of bitmap in bytes */
78 Bit32u XPelsPerMeter; /* Horz. Resolution in Pixels/Meter */
79 Bit32u YPelsPerMeter; /* Vert. Resolution in Pixels/Meter */
80 Bit32u ClrUsed; /* Number of Colors in Color Table */
81 Bit32u ClrImportant; /* Number of Important Colors */
82} WINHDR;
83
84// Logo settings header
85typedef struct
86{
87 Bit16u Signature;
88 Bit8u FadeIn;
89 Bit8u FadeOut;
90 Bit16u LogoTime;
91 Bit8u ShowBootMenu;
92 Bit32u LogoSize;
93
94} LOGOHDR;
95
96// Width and height of the "Press F12 to select boot device." bitmap. Anything
97// that exceeds the limit of F12BootText below is filled with background.
98#define F12BOOTTEXTWIDTH 284
99#define F12BOOTTEXTHEIGHT 13
100// "Press F12 to select boot device." bitmap.
101Bit8u F12BootText[] = {
102 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0x0C, 0x3E, 0x00, 0x20, 0x00,
103 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x20, 0x00, 0x70, 0x00, 0x00, 0x00,
104 0x04, 0x00, 0x70, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00,
105 0x00, 0x00, 0x00, 0x98, 0xE1, 0x30, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
106 0xC0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x60, 0x00, 0x00, 0x06,
107 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
108 0x11, 0x0F, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00,
109 0x30, 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00,
110 0x00, 0x00, 0x60, 0x66, 0x87, 0x0F, 0x1F, 0x3E, 0x00, 0x58, 0xC0, 0x00, 0x03,
111 0xC0, 0x0F, 0x1F, 0x00, 0x7C, 0xF8, 0xC0, 0xE0, 0xC3, 0xC7, 0x0F, 0x00, 0x1E,
112 0x7C, 0xF8, 0xF8, 0x01, 0x80, 0x87, 0x8F, 0x61, 0x1C, 0x7C, 0xF8, 0x00, 0x3E,
113 0xDC, 0x8C, 0x19, 0x33, 0x06, 0x80, 0x07, 0x0C, 0x18, 0x00, 0x30, 0x18, 0x03,
114 0x60, 0xCC, 0x18, 0x0C, 0x63, 0xC6, 0x30, 0x00, 0x60, 0x63, 0xCC, 0x18, 0x06,
115 0x00, 0x6C, 0x8C, 0x19, 0x86, 0x61, 0xCC, 0x18, 0x60, 0xC0, 0xCC, 0x1F, 0x03,
116 0x06, 0x00, 0x58, 0xC0, 0xC0, 0x00, 0x00, 0x83, 0x31, 0x00, 0x0C, 0xFC, 0xC1,
117 0xF0, 0x67, 0x00, 0x03, 0x00, 0x66, 0xC6, 0x8C, 0x61, 0x00, 0x60, 0xC6, 0x9F,
118 0x61, 0x18, 0x06, 0xFC, 0x01, 0x06, 0x0C, 0x0C, 0xE0, 0xC0, 0x01, 0x80, 0x01,
119 0x0C, 0x06, 0x00, 0x30, 0x18, 0x03, 0x80, 0xC3, 0x00, 0x0C, 0x03, 0x06, 0x30,
120 0x00, 0x60, 0x66, 0xCC, 0x18, 0x06, 0x00, 0x66, 0x0C, 0x18, 0x86, 0x61, 0xC0,
121 0x00, 0x60, 0xC0, 0xC0, 0x00, 0x18, 0x30, 0x00, 0x18, 0xC0, 0x30, 0x00, 0x00,
122 0x83, 0x31, 0x00, 0x60, 0x0C, 0xC0, 0x30, 0x60, 0x00, 0x03, 0x00, 0x66, 0xC6,
123 0x8C, 0x61, 0x00, 0x60, 0xC6, 0x00, 0x33, 0x18, 0x06, 0x0C, 0x00, 0x06, 0x0C,
124 0x8C, 0x19, 0x33, 0x06, 0x80, 0x01, 0x0C, 0x63, 0x00, 0xB0, 0x19, 0x03, 0x60,
125 0xCC, 0x18, 0x0C, 0x63, 0xC6, 0xB0, 0x01, 0x60, 0x66, 0xCC, 0x18, 0x36, 0x00,
126 0x66, 0x8C, 0xE1, 0x81, 0x61, 0xCC, 0x18, 0xFC, 0xE0, 0x81, 0x0F, 0x1F, 0x3E,
127 0x00, 0x3C, 0xF0, 0xF3, 0x07, 0x00, 0x0E, 0x1F, 0x00, 0x7C, 0xF8, 0xE0, 0xE1,
128 0xC3, 0x07, 0x0E, 0x00, 0x3E, 0x7C, 0xF8, 0xC0, 0x01, 0xC0, 0x8D, 0x0F, 0x0C,
129 0x3C, 0x7C, 0xF8, 0xC0
130};
131
132static unsigned char get_mode();
133static void set_mode();
134static Bit8u wait(ticks, stop_on_key);
135static void write_pixel();
136static Bit8u read_logo_byte();
137static Bit16u read_logo_word();
138
139/**
140 * Get current video mode (VGA).
141 * @returns Video mode.
142 */
143unsigned char get_mode()
144 {
145 ASM_START
146 push bp
147 mov bp, sp
148
149 push bx
150
151 mov ax, #0x0F00
152 int #0x10
153
154 pop bx
155
156 pop bp
157 ASM_END
158 }
159
160/**
161 * Set video mode (VGA).
162 * @params New video mode.
163 */
164void set_mode(mode)
165 Bit8u mode;
166 {
167 ASM_START
168 push bp
169 mov bp, sp
170
171 push ax
172
173 mov ah, #0
174 mov al, 4[bp] ; mode
175 int #0x10
176
177 pop ax
178
179 pop bp
180 ASM_END
181 }
182
183/**
184 * Set VESA video mode.
185 * @params New video mode.
186 */
187Bit16u vesa_set_mode(mode)
188 Bit16u mode;
189 {
190 ASM_START
191 push bp
192 mov bp, sp
193
194 push bx
195
196 mov ax, #0x4f02
197 mov bx, 4[bp] ; mode
198 int #0x10
199
200 pop bx
201
202 pop bp
203 ASM_END
204}
205
206/**
207 * Check for keystroke.
208 * @returns True if keystroke available, False if not.
209 */
210Bit8u check_for_keystroke()
211 {
212 ASM_START
213 mov ax, #0x100
214 int #0x16
215 jz no_key
216 mov al, #1
217 jmp done
218no_key:
219 xor al, al
220done:
221 ASM_END
222}
223
224/**
225 * Get keystroke.
226 * @returns BIOS scan code.
227 */
228Bit8u get_keystroke()
229 {
230 ASM_START
231 mov ax, #0x0
232 int #0x16
233 xchg ah, al
234 ASM_END
235}
236
237void wait_init()
238{
239 // The default is 18.2 ticks per second (~55ms tick interval).
240 // Set the timer to 16ms ticks (64K / (Hz / (PIT_HZ / 64K)) = count).
241 // 0x10000 / (1000 / (1193182 / 0x10000)) = 1193 (0x04a9)
242 // 0x10000 / ( 128 / (1193182 / 0x10000)) = 9321 (0x2469)
243 // 0x10000 / ( 64 / (1193182 / 0x10000)) = 18643 (0x48d3)
244ASM_START
245 mov al, #0x34 ; timer0: binary count, 16bit count, mode 2
246 out 0x43, al
247 mov al, #0xd3 ; Low byte - 64Hz
248 out 0x40, al
249 mov al, #0x48 ; High byte - 64Hz
250 out 0x40, al
251ASM_END
252}
253
254void wait_uninit()
255{
256ASM_START
257 pushf
258 cli
259
260 /* Restore the timer to the default 18.2Hz. */
261 mov al, #0x34 ; timer0: binary count, 16bit count, mode 2
262 out 0x43, al
263 xor ax, ax ; maximum count of 0000H = 18.2Hz
264 out 0x40, al
265 out 0x40, al
266
267 /*
268 * Reinitialize the tick and rollover counts since we've
269 * screwed them up by running the timer at WAIT_HZ for a while.
270 */
271 pushad
272 push ds
273 mov ds, ax ; already 0
274 call timer_tick_post
275 pop ds
276 popad
277
278 popf
279ASM_END
280}
281
282/**
283 * Waits (sleeps) for the given number of ticks.
284 * Checks for keystroke.
285 *
286 * @returns BIOS scan code if available, 0 if not.
287 * @param ticks Number of ticks to sleep.
288 * @param stop_on_key Whether to stop immediately upon keypress.
289 */
290Bit8u wait(ticks, stop_on_key)
291 Bit16u ticks;
292 Bit8u stop_on_key;
293{
294 long ticks_to_wait, delta;
295 Bit32u prev_ticks, t;
296 Bit8u scan_code = 0;
297
298 /*
299 * The 0:046c wraps around at 'midnight' according to a 18.2Hz clock.
300 * We also have to be careful about interrupt storms.
301 */
302ASM_START
303 pushf
304 sti
305ASM_END
306 ticks_to_wait = ticks;
307 prev_ticks = read_dword(0x0, 0x46c);
308 do
309 {
310ASM_START
311 hlt
312ASM_END
313 t = read_dword(0x0, 0x46c);
314 if (t > prev_ticks)
315 {
316 delta = t - prev_ticks; /* The temp var is required or bcc screws up. */
317 ticks_to_wait -= delta;
318 }
319 else if (t < prev_ticks)
320 ticks_to_wait -= t; /* wrapped */
321 prev_ticks = t;
322
323 if (check_for_keystroke())
324 {
325 scan_code = get_keystroke();
326 bios_printf(BIOS_PRINTF_INFO, "Key pressed: %x\n", scan_code);
327 if (stop_on_key)
328 return scan_code;
329 }
330 } while (ticks_to_wait > 0);
331ASM_START
332 popf
333ASM_END
334 return scan_code;
335}
336
337void read_palette(pal_seg, bmp_off, size, type)
338 Bit16u pal_seg;
339 Bit16u bmp_off;
340 Bit16u size;
341 Bit16u type;
342 {
343 Bit16u i;
344 RGBPAL *palette;
345
346 palette = 0;
347
348 for (i = 0; i < size; i++)
349 {
350 Bit8u pal;
351
352 pal = read_logo_byte(bmp_off);
353 write_byte(pal_seg, &palette->Blue, pal);
354 bmp_off++;
355
356 pal = read_logo_byte(bmp_off);
357 write_byte(pal_seg, &palette->Green, pal);
358 bmp_off++;
359
360 pal = read_logo_byte(bmp_off);
361 write_byte(pal_seg, &palette->Red, pal);
362 bmp_off++;
363
364 if (type != BMP_HEADER_OS21)
365 {
366 // Skip 4th byte
367 bmp_off++;
368 }
369
370 *palette++;
371 }
372}
373
374void set_dark_palette(palette_size)
375 Bit16u palette_size;
376 {
377 Bit16u i;
378
379 // Set bitmap palette (dark)
380 outb(0x03c8, palette_size);
381
382 for (i = 0; i < palette_size; i++)
383 {
384 outb(0x03c8, i);
385 outb(0x03c9, 0);
386 outb(0x03c9, 0);
387 outb(0x03c9, 0);
388 }
389}
390
391void set_bitmap_palette(palette_seg, palette_size)
392 Bit16u palette_seg;
393 Bit16u palette_size;
394 {
395 RGBPAL *palette;
396 Bit16u i;
397
398 palette = 0;
399
400 outb(0x03c6, palette_size);
401
402 for (i = 0; i < palette_size; i++)
403 {
404 Bit8u b;
405
406 outb(0x03c8, i);
407
408 b = read_byte(palette_seg, &palette->Red);
409 outb(0x03c9, b >> 2);
410 b = read_byte(palette_seg, &palette->Green);
411 outb(0x03c9, b >> 2);
412 b = read_byte(palette_seg, &palette->Blue);
413 outb(0x03c9, b >> 2);
414
415 *palette++;
416 }
417}
418
419/**
420 * Fade in and check for keystroke.
421 * @returns 1 if F12 was pressed, 0 if not.
422 */
423Bit8u fade_in(palette_seg, palette_size)
424 Bit16u palette_seg;
425 Bit16u palette_size;
426 {
427 RGBPAL *palette;
428 Bit16u i, j;
429 Bit8u scode;
430
431 // Fade in
432 for (i = 0; i < 0x3F; i++)
433 {
434 outb(0x03c6, palette_size);
435 palette = 0;
436
437 for (j = 0; j < palette_size; j++)
438 {
439 Bit8u r, g, b;
440
441 r = read_byte(palette_seg, &palette->Red) >> 2;
442 g = read_byte(palette_seg, &palette->Green) >> 2;
443 b = read_byte(palette_seg, &palette->Blue) >> 2;
444
445 if (r > 0 && r >= i) r = i;
446 if (g > 0 && g >= i) g = i;
447 if (b > 0 && b >= i) b = i;
448
449 outb(0x03c8, j);
450 outb(0x03c9, r);
451 outb(0x03c9, g);
452 outb(0x03c9, b);
453
454 *palette++;
455 }
456 scode = wait(16 / WAIT_MS, 0);
457 if (scode == F12_SCAN_CODE)
458 return 1;
459 }
460
461 return 0; // F12 not pressed
462}
463
464/**
465 * Fade out and check for keystroke.
466 * @returns 1 if F12 was pressed, 0 if not.
467 */
468Bit8u fade_out(palette_seg, palette_size)
469 Bit16u palette_seg;
470 Bit16u palette_size;
471 {
472 RGBPAL *palette;
473 Bit16u i, j;
474 Bit8u scode;
475
476 // Fade out
477 for (i = 0x3F; i > 0; i--)
478 {
479 outb(0x03c6, palette_size);
480 palette = 0;
481
482 for (j = 0; j < palette_size; j++)
483 {
484 Bit8u r, g, b;
485
486 r = read_byte(palette_seg, &palette->Red) >> 2;
487 g = read_byte(palette_seg, &palette->Green) >> 2;
488 b = read_byte(palette_seg, &palette->Blue) >> 2;
489
490 if (r > 0 && r >= i) r = i;
491 if (g > 0 && g >= i) g = i;
492 if (b > 0 && b >= i) b = i;
493
494 outb(0x03c8, j);
495 outb(0x03c9, r);
496 outb(0x03c9, g);
497 outb(0x03c9, b);
498
499 *palette++;
500 }
501 scode = wait(16 / WAIT_MS, 0);
502 if (scode == F12_SCAN_CODE)
503 return 1;
504 }
505
506 return 0; // F12 not pressed
507}
508
509void vesa_set_bank(bank)
510 Bit16u bank;
511 {
512 ASM_START
513 push bp
514 mov bp, sp
515
516 push bx
517 push dx
518
519 mov ax, #0x4f05
520 xor bx, bx
521 mov dx, 4[bp] ; bank
522 int #0x10
523
524 pop dx
525 pop bx
526
527 pop bp
528 ASM_END
529}
530
531Bit8u read_logo_byte(offset)
532 Bit16u offset;
533{
534 if (offset)
535 {
536 outw(LOGO_IO_PORT, offset);
537 }
538
539 return inb(LOGO_IO_PORT);
540}
541
542Bit16u read_logo_word(offset)
543 Bit16u offset;
544{
545 if (offset)
546 {
547 outw(LOGO_IO_PORT, offset);
548 }
549
550 return inw(LOGO_IO_PORT);
551}
552
553#define VID_SEG 0xA000
554#define TMP_SEG 0x1000
555
556void show_logo()
557{
558 Bit16u ebda_seg=read_word(0x0040,0x000E);
559
560 LOGOHDR *logo_hdr;
561 BMPINFO *bmp_info;
562 OS2HDR *os2_head;
563 OS22HDR *os22_head;
564 WINHDR *win_head;
565 Bit16u rom_seg, pal_seg, logo_hdr_size, tmp, i;
566 Bit32u hdr_size;
567 Bit8u vid_mode;
568
569 Bit8u is_fade_in, is_fade_out, is_logo_failed, uBootMenu;
570 Bit16u logo_time;
571
572 Bit32u offset;
573 Bit16u bank = 0;
574 Bit8u logo_bank = 0;
575 Bit16u address;
576
577 Bit8u scode, f12_pressed = 0;
578 Bit8u c;
579
580 // Set PIT to 1ms ticks
581 wait_init();
582
583 is_logo_failed = 0;
584
585 logo_hdr = 0;
586 logo_hdr_size = sizeof(LOGOHDR);
587
588 // Get main signature
589 tmp = read_logo_word(&logo_hdr->Signature);
590 if (tmp != 0x66BB)
591 goto done;
592
593 // Get options
594 is_fade_in = read_logo_byte(&logo_hdr->FadeIn);
595 is_fade_out = read_logo_byte(&logo_hdr->FadeOut);
596 logo_time = read_logo_word(&logo_hdr->LogoTime);
597 uBootMenu = read_logo_byte(&logo_hdr->ShowBootMenu);
598
599 // Is Logo disabled?
600 if (!is_fade_in && !is_fade_out && !logo_time)
601 goto done;
602
603show_bmp:
604
605 // Set offset of bitmap header
606 bmp_info = logo_hdr_size;
607 os2_head = os22_head = win_head = logo_hdr_size + sizeof(BMPINFO);
608
609 // Check bitmap ID
610 tmp = read_logo_word(&bmp_info->Type);
611 if (tmp != 0x4D42) // 'BM'
612 {
613 goto error;
614 }
615 else
616 {
617 Bit16u scr_width, scr_height, start_x, start_y, bmp_data, j;
618 Bit16u width, height, compr, clr_used;
619 Bit16u pad_bytes, depth, planes, palette_size, palette_data;
620 Bit16u bidx, didx;
621 int x, y;
622
623 // Check the size of the information header that indicates
624 // the structure type
625 hdr_size = read_logo_word(&win_head->Size);
626 hdr_size |= read_logo_word(0) << 16;
627
628 if (hdr_size == BMP_HEADER_OS21) // OS2 1.x header
629 {
630 width = read_logo_word(&os2_head->Width);
631 height = read_logo_word(&os2_head->Height);
632 planes = read_logo_word(&os2_head->Planes);
633 depth = read_logo_word(&os2_head->BitCount);
634 compr = COMPRESS_NONE;
635 clr_used = 0;
636 }
637 else
638 if (hdr_size == BMP_HEADER_OS22) // OS2 2.0 header
639 {
640 width = read_logo_word(&os22_head->Width);
641 height = read_logo_word(&os22_head->Height);
642 planes = read_logo_word(&os22_head->Planes);
643 depth = read_logo_word(&os22_head->BitCount);
644 compr = read_logo_word(&os22_head->Compression);
645 clr_used = read_logo_word(&os22_head->ClrUsed);
646 }
647 else
648 if (hdr_size == BMP_HEADER_WIN3) // Windows 3.x header
649 {
650 width = read_logo_word(&win_head->Width);
651 height = read_logo_word(&win_head->Height);
652 planes = read_logo_word(&win_head->Planes);
653 depth = read_logo_word(&win_head->BitCount);
654 compr = read_logo_word(&win_head->Compression);
655 clr_used = read_logo_word(&win_head->ClrUsed);
656 }
657 else
658 goto error;
659
660 // Test some bitmap fields
661 if (width > 640 || height > 480)
662 goto error;
663
664 if (planes != 1)
665 goto error;
666
667 if (depth < 4 || depth > 8)
668 goto error;
669
670 if (clr_used > 256)
671 goto error;
672
673 // Bitmap processing
674 if (compr != COMPRESS_NONE)
675 goto error;
676
677 // Screen size
678 scr_width = 640;
679 scr_height = 480;
680
681 // Center of screen
682 start_x = (scr_width - width) / 2;
683 start_y = (scr_height - height) / 2;
684
685 // Read palette
686 if (hdr_size == BMP_HEADER_OS21)
687 {
688 palette_size = (Bit16u) (1 << (planes * depth));
689 }
690 else
691 if (hdr_size == BMP_HEADER_WIN3 || hdr_size == BMP_HEADER_OS22)
692 {
693 if (clr_used)
694 palette_size = clr_used;
695 else
696 palette_size = (Bit16u) (1 << (planes * depth));
697 }
698
699 pal_seg = TMP_SEG;
700 palette_data = logo_hdr_size + sizeof(BMPINFO) + hdr_size;
701
702 read_palette(pal_seg, palette_data, palette_size, hdr_size);
703
704 // Get current video mode
705 vid_mode = get_mode();
706
707 // Set video mode #0x101 640x480x8bpp
708 vesa_set_mode(0x101);
709
710 // Set dark/bitmap palette
711 if (is_fade_in)
712 set_dark_palette(palette_size);
713 else
714 set_bitmap_palette(pal_seg, palette_size);
715
716 // 0 bank
717 vesa_set_bank(0);
718
719 // Show bitmap
720 tmp = read_logo_word(&bmp_info->Offset);
721 outw(LOGO_IO_PORT, logo_hdr_size + tmp);
722
723 switch(depth)
724 {
725 case 4:
726 // Compute padding bytes
727 if (((width % 8) == 0) || ((width % 8) > 6))
728 pad_bytes = 0;
729 else if ((width % 8) <= 2)
730 pad_bytes = 3;
731 else if ((width % 8) <= 4)
732 pad_bytes = 2;
733 else
734 pad_bytes = 1;
735
736 // For 4 bits per pixel, each byte is two pixels.
737 // The upper half go to the first pixel,
738 // and the lower half to the second.
739 for (y = height; y > 0; y--)
740 {
741 Bit8u z;
742
743 for (x = 0; x < width; x += 2)
744 {
745 Bit8u c;
746
747 c = read_logo_byte(0);
748
749 for (z = 0; z < 2; z++)
750 {
751 Bit8u color;
752 Bit16u new_bank;
753
754 offset = (((Bit32u)start_y + (Bit32u)y) * (Bit32u)scr_width) + ((Bit32u)start_x + (Bit32u)x + (Bit32u)z);
755 new_bank = (offset >> 16);
756 address = (Bit16u)(offset & 0xffffL);
757
758 if (bank != new_bank)
759 {
760 bank = new_bank;
761 vesa_set_bank(bank);
762 }
763
764 if (z & 1)
765 color = c & 0xF;
766 else
767 color = (c >> 4) & 0xF;
768
769 write_byte(VID_SEG, address, color);
770 }
771 }
772
773 for (z = 0; z < pad_bytes; z++)
774 {
775 c = read_logo_byte(0);
776 }
777 }
778 break;
779
780 case 8:
781 // Compute padding bytes
782 pad_bytes = ((width % 4) == 0) ? 0 : (4 - (width % 4));
783
784 // For 8 bits per pixel, each byte is one pixel.
785 for (y = height; y > 0; y--)
786 {
787 Bit8u z;
788
789 for (x = 0; x < width; x++)
790 {
791 Bit8u c, z;
792 Bit16u new_bank;
793
794 c = read_logo_byte(0);
795
796 offset = (((Bit32u)start_y + (Bit32u)y) * (Bit32u)scr_width) + ((Bit32u)start_x + (Bit32u)x);
797 new_bank = (offset >> 16);
798 address = (Bit16u)(offset & 0xffffL);
799
800 if (bank != new_bank)
801 {
802 bank = new_bank;
803 vesa_set_bank(bank);
804 }
805
806 write_byte(VID_SEG, address, c);
807 }
808
809 for (z = 0; z < pad_bytes; z++)
810 {
811 c = read_logo_byte(0);
812 }
813 }
814 break;
815
816#if 0 // 24bpp bitmaps are unsupported
817 case 24:
818 // Compute padding bytes
819 pad_bytes = width % 4;
820
821 // For 24 bits per pixel it's RGB structure.
822 for (y = height; y > 0; y--)
823 {
824 Bit8u z;
825 for (x = 0; x < width; x++)
826 {
827 for (z = 0; z < 3; z++)
828 {
829 Bit8u color;
830 Bit16u new_bank;
831
832 color = read_logo_byte(0);
833
834 offset = (((Bit32u)start_y + (Bit32u)y) * (Bit32u)scr_width*3) + (((Bit32u)start_x + (Bit32u)x) * (Bit32u)3 + z);
835 new_bank = (offset >> 16);
836 address = (Bit16u)(offset & 0xffffL);
837
838 if (bank != new_bank)
839 {
840 bank = new_bank;
841 vesa_set_bank(bank);
842 }
843
844 write_byte(VID_SEG, address, color);
845 }
846 }
847
848 for (z = 0; z < pad_bytes; z++)
849 {
850 c = read_logo_byte(0);
851 }
852 }
853 break;
854#endif
855 }
856
857 // If Setup menu enabled
858 if (uBootMenu == 2 && (is_fade_in || is_fade_out || logo_time))
859 {
860 RGBPAL *palette = 0;
861 Bit16u blum, dlum;
862
863 // Get the brightest and the darkest palette indexes
864 bidx = didx = blum = 0;
865 dlum = 3 * 0xff;
866
867 for (i = 0; i < palette_size; i++)
868 {
869 Bit8u r, g, b;
870 Bit16u lum;
871
872 r = read_byte(pal_seg, &palette->Red) >> 2;
873 g = read_byte(pal_seg, &palette->Green) >> 2;
874 b = read_byte(pal_seg, &palette->Blue) >> 2;
875 lum = (Bit16u)r + (Bit16u)g + (Bit16u)b;
876
877 if (lum > blum) { blum = lum; bidx = i; }
878
879 if (lum < dlum) { dlum = lum; didx = i; }
880
881 *palette++;
882 }
883
884 // 0 bank
885 vesa_set_bank(0);
886
887 // Top-left corner of screen
888 start_x = 340;
889 start_y = 450;
890
891 // Image size
892 width = (start_x + F12BOOTTEXTWIDTH <= scr_width) ? F12BOOTTEXTWIDTH : scr_width - start_x;
893 height = (start_y + F12BOOTTEXTHEIGHT <= scr_height) ? F12BOOTTEXTHEIGHT : scr_height - start_y;
894 bmp_data = j = 0;
895
896 for (y = 0; y < height; y++)
897 {
898 for (x = 0; x < width; x++)
899 {
900 Bit16u new_bank;
901 Bit8u pix_idx;
902
903 if (!j)
904 {
905 if (bmp_data < sizeof(F12BootText))
906 c = read_byte(0xf000, F12BootText + bmp_data++);
907 else
908 c = 0;
909 }
910
911 offset = (((Bit32u)start_y + (Bit32u)y) * (Bit32u)scr_width) + ((Bit32u)start_x + (Bit32u)x);
912 new_bank = (offset >> 16);
913 address = (Bit16u)(offset & 0xffffL);
914
915 if (bank != new_bank)
916 {
917 bank = new_bank;
918 vesa_set_bank(bank);
919 }
920
921 pix_idx = c & 1;
922 c >>= 1;
923
924 if (pix_idx)
925 pix_idx = bidx;
926 else
927 pix_idx = didx;
928
929 write_byte(VID_SEG, address, pix_idx);
930
931 if (j++ >= 7) j = 0;
932 }
933 }
934 }
935
936 // Fade in
937 if (is_fade_in)
938 {
939 if (fade_in(pal_seg, palette_size))
940 f12_pressed = 1;
941 }
942
943 // Wait (interval in milliseconds)
944 if (!f12_pressed)
945 {
946 scode = wait(logo_time / WAIT_MS, 0);
947 if (scode == F12_SCAN_CODE)
948 f12_pressed = 1;
949 }
950
951 // Fade out (only if F12 was not pressed)
952 if (is_fade_out && !f12_pressed)
953 {
954 if (fade_out(pal_seg, palette_size))
955 f12_pressed = 1;
956 }
957 }
958
959 goto done;
960
961error:
962 if (!is_logo_failed)
963 {
964 is_logo_failed = 1;
965
966 logo_hdr_size = 0;
967
968 // Switch to defaul logo
969 outw(LOGO_IO_PORT, 0xFFFF);
970
971 goto show_bmp;
972 }
973done:
974
975 // Clear forced boot drive setting.
976 write_byte(ebda_seg,&EbdaData->uForceBootDrive, 0);
977
978 // Don't restore previous video mode
979 // The default text mode should be set up. (defect #1235)
980 set_mode(0x0003);
981
982 // If Setup menu enabled
983 if (uBootMenu)
984 {
985 // If the graphics logo disabled
986 if (!is_fade_in && !is_fade_out && !logo_time)
987 {
988 int i;
989
990 if (uBootMenu == 2)
991 printf("Press F12 to select boot device.");
992
993 // if the user has pressed F12 don't wait here
994 if (!f12_pressed)
995 {
996 // Wait for timeout or keystroke
997 scode = wait(F12_WAIT_TIME, 1);
998 if (scode == F12_SCAN_CODE)
999 f12_pressed = 1;
1000 }
1001 }
1002
1003 // If F12 pressed, show boot menu
1004 if (f12_pressed)
1005 {
1006 // Hide cursor, clear screen and move cursor to starting position
1007 ASM_START
1008 push bx
1009 push cx
1010 push dx
1011
1012 mov ax, #0x100
1013 mov cx, #0x1000
1014 int #0x10
1015
1016 mov ax, #0x700
1017 mov bh, #7
1018 xor cx, cx
1019 mov dx, #0x184f
1020 int #0x10
1021
1022 mov ax, #0x200
1023 xor bx, bx
1024 xor dx, dx
1025 int #0x10
1026
1027 pop dx
1028 pop cx
1029 pop bx
1030 ASM_END
1031
1032 // Show menu
1033 printf("\n"
1034 "VirtualBox temporary boot device selection\n"
1035 "\n"
1036 " 1) Floppy\n"
1037 " 2) Hard Disk\n"
1038 " 3) CD-ROM\n"
1039 " 4) LAN\n"
1040 "\n"
1041 " 0) Continue booting\n");
1042
1043 // Wait for keystroke
1044 for (;;)
1045 {
1046 do
1047 {
1048 scode = wait(WAIT_HZ, 1);
1049 } while (scode == 0);
1050
1051 // Change first boot device code to selected one
1052 if (scode >= 0x02 && scode <= 0x05)
1053 {
1054 write_byte(ebda_seg,&EbdaData->uForceBootDrive, scode-1);
1055 break;
1056 }
1057
1058 // '0' ... continue
1059 if (scode == 0x0b)
1060 break;
1061 }
1062
1063 // Switch to text mode. Clears screen and enables cursor again.
1064 set_mode(0x0003);
1065 }
1066 }
1067
1068 // Restore PIT ticks
1069 wait_uninit();
1070
1071 return;
1072}
1073
1074
1075void delay_boot(secs)
1076 Bit16u secs;
1077{
1078 Bit16u i;
1079
1080 if (!secs)
1081 return;
1082
1083 // Set PIT to 1ms ticks
1084 wait_init();
1085
1086 printf("Delaying boot for %d seconds:", secs);
1087 for (i = secs; i > 0; i--)
1088 {
1089 printf(" %d", i);
1090 wait(WAIT_HZ, 0);
1091 }
1092 printf("\n");
1093 // Restore PIT ticks
1094 wait_uninit();
1095}
1096
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette