VirtualBox

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

最後變更 在這個檔案從6875是 6870,由 vboxsync 提交於 17 年 前

Make the BIOS booting from any attached disk.

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

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