VirtualBox

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

最後變更 在這個檔案從3542是 2913,由 vboxsync 提交於 18 年 前

#1647: Immediately stop if F12 was pressed during boot; don't accept any other keys during boot menu

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

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