VirtualBox

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

Last change on this file since 7449 was 7099, checked in by vboxsync, 17 years ago

Use CMOS to store hard disk geometry for more than 4 disks

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 31.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 clear_screen()
557{
558// Hide cursor, clear screen and move cursor to starting position
559ASM_START
560 push bx
561 push cx
562 push dx
563
564 mov ax, #0x100
565 mov cx, #0x1000
566 int #0x10
567
568 mov ax, #0x700
569 mov bh, #7
570 xor cx, cx
571 mov dx, #0x184f
572 int #0x10
573
574 mov ax, #0x200
575 xor bx, bx
576 xor dx, dx
577 int #0x10
578
579 pop dx
580 pop cx
581 pop bx
582ASM_END
583}
584
585void print_detected_harddisks()
586{
587 Bit16u ebda_seg=read_word(0x0040,0x000E);
588 Bit8u actual_device = 0;
589 Bit8u first_ctrl_printed = 0;
590 Bit8u second_ctrl_printed = 0;
591 Bit8u device;
592
593 device = read_byte(ebda_seg, &EbdaData->ata.hdidmap[actual_device]);
594
595 while ((actual_device < BX_MAX_ATA_DEVICES) && (device < BX_MAX_ATA_DEVICES))
596 {
597 Bit8u device_position;
598
599 device_position = device;
600
601 if ((device_position < 4) && (first_ctrl_printed == 0))
602 {
603 printf("IDE controller:\n");
604 first_ctrl_printed = 1;
605 }
606 else if ((device_position >= 4) && (second_ctrl_printed == 0))
607 {
608 printf("\n\nAHCI controller:\n");
609 second_ctrl_printed = 1;
610 }
611
612 printf("\n %d) ", actual_device+1);
613
614 /*
615 * If actual_device is bigger than or equal 4
616 * this is the next controller and
617 * the positions start at the beginning.
618 */
619 if (device_position >= 4)
620 device_position -= 4;
621
622 if (device_position / 2)
623 printf("Secondary ");
624 else
625 printf("Primary ");
626
627 if (device_position % 2)
628 printf("Slave");
629 else
630 printf("Master");
631
632 actual_device++;
633 device = read_byte(ebda_seg, &EbdaData->ata.hdidmap[actual_device]);
634 }
635
636 printf("\n");
637}
638
639Bit8u get_boot_drive(scode)
640 Bit8u scode;
641{
642 Bit16u ebda_seg=read_word(0x0040,0x000E);
643 Bit8u actual_device;
644 Bit8u detected_devices = 0;
645
646 for (actual_device = 0; actual_device < BX_MAX_ATA_DEVICES; actual_device++)
647 {
648 Bit8u device = read_byte(ebda_seg, &EbdaData->ata.hdidmap[actual_device]);
649
650 if (device < BX_MAX_ATA_DEVICES)
651 {
652 scode--;
653 if (scode == 0x01)
654 return actual_device;
655 }
656 }
657
658 /* Scancode is higher than number of available devices */
659 return 0x08;
660}
661
662void show_logo()
663{
664 Bit16u ebda_seg=read_word(0x0040,0x000E);
665
666 LOGOHDR *logo_hdr;
667 BMPINFO *bmp_info;
668 OS2HDR *os2_head;
669 OS22HDR *os22_head;
670 WINHDR *win_head;
671 Bit16u rom_seg, pal_seg, logo_hdr_size, tmp, i;
672 Bit32u hdr_size;
673 Bit8u vid_mode;
674
675 Bit8u is_fade_in, is_fade_out, is_logo_failed, uBootMenu;
676 Bit16u logo_time;
677
678 Bit32u offset;
679 Bit16u bank = 0;
680 Bit8u logo_bank = 0;
681 Bit16u address;
682
683 Bit8u scode, f12_pressed = 0;
684 Bit8u c;
685
686 // Set PIT to 1ms ticks
687 wait_init();
688
689 is_logo_failed = 0;
690
691 logo_hdr = 0;
692 logo_hdr_size = sizeof(LOGOHDR);
693
694 // Get main signature
695 tmp = read_logo_word(&logo_hdr->Signature);
696 if (tmp != 0x66BB)
697 goto done;
698
699 // Get options
700 is_fade_in = read_logo_byte(&logo_hdr->FadeIn);
701 is_fade_out = read_logo_byte(&logo_hdr->FadeOut);
702 logo_time = read_logo_word(&logo_hdr->LogoTime);
703 uBootMenu = read_logo_byte(&logo_hdr->ShowBootMenu);
704
705 // Is Logo disabled?
706 if (!is_fade_in && !is_fade_out && !logo_time)
707 goto done;
708
709show_bmp:
710
711 // Set offset of bitmap header
712 bmp_info = logo_hdr_size;
713 os2_head = os22_head = win_head = logo_hdr_size + sizeof(BMPINFO);
714
715 // Check bitmap ID
716 tmp = read_logo_word(&bmp_info->Type);
717 if (tmp != 0x4D42) // 'BM'
718 {
719 goto error;
720 }
721 else
722 {
723 Bit16u scr_width, scr_height, start_x, start_y, bmp_data, j;
724 Bit16u width, height, compr, clr_used;
725 Bit16u pad_bytes, depth, planes, palette_size, palette_data;
726 Bit16u bidx, didx;
727 int x, y;
728
729 // Check the size of the information header that indicates
730 // the structure type
731 hdr_size = read_logo_word(&win_head->Size);
732 hdr_size |= read_logo_word(0) << 16;
733
734 if (hdr_size == BMP_HEADER_OS21) // OS2 1.x header
735 {
736 width = read_logo_word(&os2_head->Width);
737 height = read_logo_word(&os2_head->Height);
738 planes = read_logo_word(&os2_head->Planes);
739 depth = read_logo_word(&os2_head->BitCount);
740 compr = COMPRESS_NONE;
741 clr_used = 0;
742 }
743 else
744 if (hdr_size == BMP_HEADER_OS22) // OS2 2.0 header
745 {
746 width = read_logo_word(&os22_head->Width);
747 height = read_logo_word(&os22_head->Height);
748 planes = read_logo_word(&os22_head->Planes);
749 depth = read_logo_word(&os22_head->BitCount);
750 compr = read_logo_word(&os22_head->Compression);
751 clr_used = read_logo_word(&os22_head->ClrUsed);
752 }
753 else
754 if (hdr_size == BMP_HEADER_WIN3) // Windows 3.x header
755 {
756 width = read_logo_word(&win_head->Width);
757 height = read_logo_word(&win_head->Height);
758 planes = read_logo_word(&win_head->Planes);
759 depth = read_logo_word(&win_head->BitCount);
760 compr = read_logo_word(&win_head->Compression);
761 clr_used = read_logo_word(&win_head->ClrUsed);
762 }
763 else
764 goto error;
765
766 // Test some bitmap fields
767 if (width > 640 || height > 480)
768 goto error;
769
770 if (planes != 1)
771 goto error;
772
773 if (depth < 4 || depth > 8)
774 goto error;
775
776 if (clr_used > 256)
777 goto error;
778
779 // Bitmap processing
780 if (compr != COMPRESS_NONE)
781 goto error;
782
783 // Screen size
784 scr_width = 640;
785 scr_height = 480;
786
787 // Center of screen
788 start_x = (scr_width - width) / 2;
789 start_y = (scr_height - height) / 2;
790
791 // Read palette
792 if (hdr_size == BMP_HEADER_OS21)
793 {
794 palette_size = (Bit16u) (1 << (planes * depth));
795 }
796 else
797 if (hdr_size == BMP_HEADER_WIN3 || hdr_size == BMP_HEADER_OS22)
798 {
799 if (clr_used)
800 palette_size = clr_used;
801 else
802 palette_size = (Bit16u) (1 << (planes * depth));
803 }
804
805 pal_seg = TMP_SEG;
806 palette_data = logo_hdr_size + sizeof(BMPINFO) + hdr_size;
807
808 read_palette(pal_seg, palette_data, palette_size, hdr_size);
809
810 // Get current video mode
811 vid_mode = get_mode();
812
813 // Set video mode #0x101 640x480x8bpp
814 vesa_set_mode(0x101);
815
816 // Set dark/bitmap palette
817 if (is_fade_in)
818 set_dark_palette(palette_size);
819 else
820 set_bitmap_palette(pal_seg, palette_size);
821
822 // 0 bank
823 vesa_set_bank(0);
824
825 // Show bitmap
826 tmp = read_logo_word(&bmp_info->Offset);
827 outw(LOGO_IO_PORT, logo_hdr_size + tmp);
828
829 switch(depth)
830 {
831 case 4:
832 // Compute padding bytes
833 if (((width % 8) == 0) || ((width % 8) > 6))
834 pad_bytes = 0;
835 else if ((width % 8) <= 2)
836 pad_bytes = 3;
837 else if ((width % 8) <= 4)
838 pad_bytes = 2;
839 else
840 pad_bytes = 1;
841
842 // For 4 bits per pixel, each byte is two pixels.
843 // The upper half go to the first pixel,
844 // and the lower half to the second.
845 for (y = height; y > 0; y--)
846 {
847 Bit8u z;
848
849 for (x = 0; x < width; x += 2)
850 {
851 Bit8u c;
852
853 c = read_logo_byte(0);
854
855 for (z = 0; z < 2; z++)
856 {
857 Bit8u color;
858 Bit16u new_bank;
859
860 offset = (((Bit32u)start_y + (Bit32u)y) * (Bit32u)scr_width) + ((Bit32u)start_x + (Bit32u)x + (Bit32u)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 if (z & 1)
871 color = c & 0xF;
872 else
873 color = (c >> 4) & 0xF;
874
875 write_byte(VID_SEG, address, color);
876 }
877 }
878
879 for (z = 0; z < pad_bytes; z++)
880 {
881 c = read_logo_byte(0);
882 }
883 }
884 break;
885
886 case 8:
887 // Compute padding bytes
888 pad_bytes = ((width % 4) == 0) ? 0 : (4 - (width % 4));
889
890 // For 8 bits per pixel, each byte is one pixel.
891 for (y = height; y > 0; y--)
892 {
893 Bit8u z;
894
895 for (x = 0; x < width; x++)
896 {
897 Bit8u c, z;
898 Bit16u new_bank;
899
900 c = read_logo_byte(0);
901
902 offset = (((Bit32u)start_y + (Bit32u)y) * (Bit32u)scr_width) + ((Bit32u)start_x + (Bit32u)x);
903 new_bank = (offset >> 16);
904 address = (Bit16u)(offset & 0xffffL);
905
906 if (bank != new_bank)
907 {
908 bank = new_bank;
909 vesa_set_bank(bank);
910 }
911
912 write_byte(VID_SEG, address, c);
913 }
914
915 for (z = 0; z < pad_bytes; z++)
916 {
917 c = read_logo_byte(0);
918 }
919 }
920 break;
921
922#if 0 // 24bpp bitmaps are unsupported
923 case 24:
924 // Compute padding bytes
925 pad_bytes = width % 4;
926
927 // For 24 bits per pixel it's RGB structure.
928 for (y = height; y > 0; y--)
929 {
930 Bit8u z;
931 for (x = 0; x < width; x++)
932 {
933 for (z = 0; z < 3; z++)
934 {
935 Bit8u color;
936 Bit16u new_bank;
937
938 color = read_logo_byte(0);
939
940 offset = (((Bit32u)start_y + (Bit32u)y) * (Bit32u)scr_width*3) + (((Bit32u)start_x + (Bit32u)x) * (Bit32u)3 + z);
941 new_bank = (offset >> 16);
942 address = (Bit16u)(offset & 0xffffL);
943
944 if (bank != new_bank)
945 {
946 bank = new_bank;
947 vesa_set_bank(bank);
948 }
949
950 write_byte(VID_SEG, address, color);
951 }
952 }
953
954 for (z = 0; z < pad_bytes; z++)
955 {
956 c = read_logo_byte(0);
957 }
958 }
959 break;
960#endif
961 }
962
963 // If Setup menu enabled
964 if (uBootMenu == 2 && (is_fade_in || is_fade_out || logo_time))
965 {
966 RGBPAL *palette = 0;
967 Bit16u blum, dlum;
968
969 // Get the brightest and the darkest palette indexes
970 bidx = didx = blum = 0;
971 dlum = 3 * 0xff;
972
973 for (i = 0; i < palette_size; i++)
974 {
975 Bit8u r, g, b;
976 Bit16u lum;
977
978 r = read_byte(pal_seg, &palette->Red) >> 2;
979 g = read_byte(pal_seg, &palette->Green) >> 2;
980 b = read_byte(pal_seg, &palette->Blue) >> 2;
981 lum = (Bit16u)r + (Bit16u)g + (Bit16u)b;
982
983 if (lum > blum) { blum = lum; bidx = i; }
984
985 if (lum < dlum) { dlum = lum; didx = i; }
986
987 *palette++;
988 }
989
990 // 0 bank
991 vesa_set_bank(0);
992
993 // Top-left corner of screen
994 start_x = 340;
995 start_y = 450;
996
997 // Image size
998 width = (start_x + F12BOOTTEXTWIDTH <= scr_width) ? F12BOOTTEXTWIDTH : scr_width - start_x;
999 height = (start_y + F12BOOTTEXTHEIGHT <= scr_height) ? F12BOOTTEXTHEIGHT : scr_height - start_y;
1000 bmp_data = j = 0;
1001
1002 for (y = 0; y < height; y++)
1003 {
1004 for (x = 0; x < width; x++)
1005 {
1006 Bit16u new_bank;
1007 Bit8u pix_idx;
1008
1009 if (!j)
1010 {
1011 if (bmp_data < sizeof(F12BootText))
1012 c = read_byte(0xf000, F12BootText + bmp_data++);
1013 else
1014 c = 0;
1015 }
1016
1017 offset = (((Bit32u)start_y + (Bit32u)y) * (Bit32u)scr_width) + ((Bit32u)start_x + (Bit32u)x);
1018 new_bank = (offset >> 16);
1019 address = (Bit16u)(offset & 0xffffL);
1020
1021 if (bank != new_bank)
1022 {
1023 bank = new_bank;
1024 vesa_set_bank(bank);
1025 }
1026
1027 pix_idx = c & 1;
1028 c >>= 1;
1029
1030 if (pix_idx)
1031 pix_idx = bidx;
1032 else
1033 pix_idx = didx;
1034
1035 write_byte(VID_SEG, address, pix_idx);
1036
1037 if (j++ >= 7) j = 0;
1038 }
1039 }
1040 }
1041
1042 // Fade in
1043 if (is_fade_in)
1044 {
1045 if (fade_in(pal_seg, palette_size))
1046 f12_pressed = 1;
1047 }
1048
1049 // Wait (interval in milliseconds)
1050 if (!f12_pressed)
1051 {
1052 scode = wait(logo_time / WAIT_MS, 0);
1053 if (scode == F12_SCAN_CODE)
1054 f12_pressed = 1;
1055 }
1056
1057 // Fade out (only if F12 was not pressed)
1058 if (is_fade_out && !f12_pressed)
1059 {
1060 if (fade_out(pal_seg, palette_size))
1061 f12_pressed = 1;
1062 }
1063 }
1064
1065 goto done;
1066
1067error:
1068 if (!is_logo_failed)
1069 {
1070 is_logo_failed = 1;
1071
1072 logo_hdr_size = 0;
1073
1074 // Switch to defaul logo
1075 outw(LOGO_IO_PORT, 0xFFFF);
1076
1077 goto show_bmp;
1078 }
1079done:
1080
1081 // Clear forced boot drive setting.
1082 write_byte(ebda_seg,&EbdaData->uForceBootDevice, 0);
1083
1084 // Don't restore previous video mode
1085 // The default text mode should be set up. (defect #1235)
1086 set_mode(0x0003);
1087
1088 // If Setup menu enabled
1089 if (uBootMenu)
1090 {
1091 // If the graphics logo disabled
1092 if (!is_fade_in && !is_fade_out && !logo_time)
1093 {
1094 int i;
1095
1096 if (uBootMenu == 2)
1097 printf("Press F12 to select boot device.");
1098
1099 // if the user has pressed F12 don't wait here
1100 if (!f12_pressed)
1101 {
1102 // Wait for timeout or keystroke
1103 scode = wait(F12_WAIT_TIME, 1);
1104 if (scode == F12_SCAN_CODE)
1105 f12_pressed = 1;
1106 }
1107 }
1108
1109 // If F12 pressed, show boot menu
1110 if (f12_pressed)
1111 {
1112 Bit8u boot_device = 0;
1113 Bit8u boot_drive = 0;
1114
1115 clear_screen();
1116
1117 // Show menu
1118 printf("\n"
1119 "VirtualBox temporary boot device selection\n"
1120 "\n"
1121 "Detected Hard disks:\n"
1122 "\n");
1123 print_detected_harddisks();
1124 printf("\n"
1125 "Other boot devices:\n"
1126 " f) Floppy\n"
1127 " c) CD-ROM\n"
1128 " l) LAN\n"
1129 "\n"
1130 " b) Continue booting\n");
1131
1132
1133
1134 // Wait for keystroke
1135 for (;;)
1136 {
1137 do
1138 {
1139 scode = wait(WAIT_HZ, 1);
1140 } while (scode == 0);
1141
1142 if (scode == 0x30)
1143 {
1144 // 'b' ... continue
1145 break;
1146 }
1147
1148 // Check if hard disk was selected
1149 if ((scode >= 0x02) && (scode <= 0x09))
1150 {
1151 boot_drive = get_boot_drive(scode);
1152
1153 /*
1154 * We support a maximum of 8 boot drives.
1155 * If this value is bigger than 7 not all
1156 * values are used and the user pressed
1157 * and invalid key.
1158 * Wait for the next pressed key.
1159 */
1160 if (boot_drive > 7)
1161 continue;
1162
1163 write_byte(ebda_seg, &EbdaData->uForceBootDrive, boot_drive);
1164 boot_device = 0x02;
1165 break;
1166 }
1167
1168 switch (scode)
1169 {
1170 case 0x21:
1171 // Floppy
1172 boot_device = 0x01;
1173 break;
1174 case 0x2e:
1175 // CD-ROM
1176 boot_device = 0x03;
1177 break;
1178 case 0x26:
1179 // LAN
1180 boot_device = 0x04;
1181 break;
1182 }
1183
1184 if (boot_device != 0)
1185 break;
1186 }
1187
1188 write_byte(ebda_seg, &EbdaData->uForceBootDevice, boot_device);
1189
1190 // Switch to text mode. Clears screen and enables cursor again.
1191 set_mode(0x0003);
1192 }
1193 }
1194
1195 // Restore PIT ticks
1196 wait_uninit();
1197
1198 return;
1199}
1200
1201
1202void delay_boot(secs)
1203 Bit16u secs;
1204{
1205 Bit16u i;
1206
1207 if (!secs)
1208 return;
1209
1210 // Set PIT to 1ms ticks
1211 wait_init();
1212
1213 printf("Delaying boot for %d seconds:", secs);
1214 for (i = secs; i > 0; i--)
1215 {
1216 printf(" %d", i);
1217 wait(WAIT_HZ, 0);
1218 }
1219 printf("\n");
1220 // Restore PIT ticks
1221 wait_uninit();
1222}
1223
Note: See TracBrowser for help on using the repository browser.

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