VirtualBox

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

Last change on this file since 450 was 155, checked in by vboxsync, 18 years ago

Hack to allow configurable boot delay (up to 15 seconds).

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