~hamo/ubuntu/precise/grub2/grub2.hi_res

« back to all changes in this revision

Viewing changes to kern/i386/pc/startup.S

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Evan Broder, Mario Limonciello
  • Date: 2010-11-24 13:59:55 UTC
  • mfrom: (1.17.6 upstream) (17.6.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20101124135955-r6ii5sepayr7jt53
Tags: 1.99~20101124-1ubuntu1
[ Colin Watson ]
* Resynchronise with Debian experimental.  Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed.  If it is, show the
    menu, otherwise boot immediately.  If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt.  Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - Suppress progress messages as the kernel and initrd load for
    non-recovery kernel menu entries.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Don't generate /boot/grub/device.map during grub-install or
    grub-mkconfig by default.
  - Adjust upgrade version checks for Ubuntu.
  - Don't display "GRUB loading" unless Shift is held down.
  - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
    our backport of the grub-doc split.
  - Fix LVM/RAID probing in the absence of /boot/grub/device.map.
  - Look for .mo files in /usr/share/locale-langpack as well, in
    preference.
  - Make sure GRUB_TIMEOUT isn't quoted unnecessarily.
  - Probe all devices in 'grub-probe --target=drive' if
    /boot/grub/device.map is missing.
  - Build-depend on qemu-kvm rather than qemu-system for grub-pc tests.
  - Use qemu rather than qemu-system-i386.
  - Program vesafb on BIOS systems rather than efifb.
  - Add a grub-rescue-efi-amd64 package containing a rescue CD-ROM image
    for EFI-AMD64.
  - On Wubi, don't ask for an install device, but just update wubildr
    using the diverted grub-install.
  - When embedding the core image in a post-MBR gap, check for and avoid
    sectors matching any of a list of known signatures.
  - Disable video_bochs and video_cirrus on PC BIOS systems, as probing
    PCI space seems to break on some systems.
* Downgrade "ACPI shutdown failed" error to a debug message, since it can
  cause spurious test failures.

[ Evan Broder ]
* Enable lua from grub-extras.
* Incorporate the bitop library into lua.
* Add enum_pci function to grub module in lua.
* Switch back to gfxpayload=keep by default, unless the video hardware
  is known to not support it.

[ Mario Limonciello ]
* Built part_msdos and vfat into bootx64.efi (LP: #677758)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  GRUB  --  GRand Unified Bootloader
3
 
 *  Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
4
 
 *
5
 
 *  GRUB is free software: you can redistribute it and/or modify
6
 
 *  it under the terms of the GNU General Public License as published by
7
 
 *  the Free Software Foundation, either version 3 of the License, or
8
 
 *  (at your option) any later version.
9
 
 *
10
 
 *  GRUB is distributed in the hope that it will be useful,
11
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
17
 
 */
18
 
 
19
 
 
20
 
/*
21
 
 * Note: These functions defined in this file may be called from C.
22
 
 *       Be careful of that you must not modify some registers. Quote
23
 
 *       from gcc-2.95.2/gcc/config/i386/i386.h:
24
 
 
25
 
   1 for registers not available across function calls.
26
 
   These must include the FIXED_REGISTERS and also any
27
 
   registers that can be used without being saved.
28
 
   The latter must include the registers where values are returned
29
 
   and the register where structure-value addresses are passed.
30
 
   Aside from that, you can include as many other registers as you like.
31
 
 
32
 
  ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg
33
 
{  1, 1, 1, 0, 0, 0, 0, 1, 1,  1,  1,  1,  1,  1,  1,  1,  1 }
34
 
 */
35
 
 
36
 
/*
37
 
 * Note: GRUB is compiled with the options -mrtd and -mregparm=3.
38
 
 *       So the first three arguments are passed in %eax, %edx, and %ecx,
39
 
 *       respectively, and if a function has a fixed number of arguments
40
 
 *       and the number is greater than three, the function must return
41
 
 *       with "ret $N" where N is ((the number of arguments) - 3) * 4.
42
 
 */
43
 
 
44
 
#include <config.h>
45
 
#include <grub/symbol.h>
46
 
#include <grub/boot.h>
47
 
#include <grub/machine/boot.h>
48
 
#include <grub/machine/memory.h>
49
 
#include <grub/machine/console.h>
50
 
#include <grub/cpu/linux.h>
51
 
#include <grub/machine/kernel.h>
52
 
#include <grub/term.h>
53
 
#include <multiboot.h>
54
 
#include <multiboot2.h>
55
 
 
56
 
#define ABS(x)  ((x) - LOCAL (base) + GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200)
57
 
 
58
 
        .file   "startup.S"
59
 
 
60
 
        .text
61
 
 
62
 
        /* Tell GAS to generate 16-bit instructions so that this code works
63
 
           in real mode. */
64
 
        .code16
65
 
 
66
 
        .globl  start, _start
67
 
start:
68
 
_start:
69
 
LOCAL (base):
70
 
        /*
71
 
         *  Guarantee that "main" is loaded at 0x0:0x8200.
72
 
         */
73
 
#ifdef __APPLE__
74
 
        ljmp $0, $(ABS(LOCAL (codestart)) - 0x10000)
75
 
#else
76
 
        ljmp $0, $ABS(LOCAL (codestart))
77
 
#endif
78
 
        /*
79
 
         *  Compatibility version number
80
 
         *
81
 
         *  These MUST be at byte offset 6 and 7 of the executable
82
 
         *  DO NOT MOVE !!!
83
 
         */
84
 
        . = _start + 0x6
85
 
        .byte   GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
86
 
 
87
 
        /*
88
 
         *  This is a special data area 8 bytes from the beginning.
89
 
         */
90
 
 
91
 
        . = _start + 0x8
92
 
 
93
 
VARIABLE(grub_total_module_size)
94
 
        .long   0
95
 
VARIABLE(grub_kernel_image_size)
96
 
        .long   0
97
 
VARIABLE(grub_compressed_size)
98
 
        .long   0
99
 
VARIABLE(grub_install_dos_part)
100
 
        .long   0xFFFFFFFF
101
 
VARIABLE(grub_install_bsd_part)
102
 
        .long   0xFFFFFFFF
103
 
VARIABLE(grub_prefix)
104
 
        /* to be filled by grub-mkimage */
105
 
 
106
 
        /*
107
 
         *  Leave some breathing room for the prefix.
108
 
         */
109
 
 
110
 
        . = _start + GRUB_KERNEL_MACHINE_DATA_END
111
 
 
112
 
#ifdef APPLE_CC
113
 
bss_start:
114
 
        .long 0
115
 
bss_end:
116
 
        .long 0
117
 
#endif
118
 
 
119
 
/*
120
 
 * Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself).
121
 
 * This uses the a.out kludge to load raw binary to the area starting at 1MB,
122
 
 * and relocates itself after loaded.
123
 
 */
124
 
        .p2align        2       /* force 4-byte alignment */
125
 
multiboot_header:
126
 
        /* magic */
127
 
        .long   0x1BADB002
128
 
        /* flags */
129
 
        .long   (1 << 16)
130
 
        /* checksum */
131
 
        .long   -0x1BADB002 - (1 << 16)
132
 
        /* header addr */
133
 
        .long   multiboot_header - _start + 0x100000 + 0x200
134
 
        /* load addr */
135
 
        .long   0x100000
136
 
        /* load end addr */
137
 
        .long   0
138
 
        /* bss end addr */
139
 
        .long   0
140
 
        /* entry addr */
141
 
        .long   multiboot_entry - _start + 0x100000 + 0x200
142
 
 
143
 
multiboot_entry:
144
 
        .code32
145
 
        /* obtain the boot device */
146
 
        movl    12(%ebx), %edx
147
 
 
148
 
        movl    $GRUB_MEMORY_MACHINE_PROT_STACK, %ebp
149
 
        movl    %ebp, %esp
150
 
 
151
 
        /* relocate the code */
152
 
        movl    $(GRUB_KERNEL_MACHINE_RAW_SIZE + 0x200), %ecx
153
 
        addl    EXT_C(grub_compressed_size) - _start + 0x100000 + 0x200, %ecx
154
 
        movl    $0x100000, %esi
155
 
        movl    $GRUB_BOOT_MACHINE_KERNEL_ADDR, %edi
156
 
        cld
157
 
        rep
158
 
        movsb
159
 
        /* jump to the real address */
160
 
        movl    $multiboot_trampoline, %eax
161
 
        jmp     *%eax
162
 
 
163
 
multiboot_trampoline:
164
 
        /* fill the boot information */
165
 
        movl    %edx, %eax
166
 
        shrl    $8, %eax
167
 
        xorl    %ebx, %ebx
168
 
        cmpb    $0xFF, %ah
169
 
        je      1f
170
 
        movb    %ah, %bl
171
 
        movl    %ebx, EXT_C(grub_install_dos_part)
172
 
1:
173
 
        cmpb    $0xFF, %al
174
 
        je      2f
175
 
        movb    %al, %bl
176
 
        movl    %ebx, EXT_C(grub_install_bsd_part)
177
 
2:
178
 
        shrl    $24, %edx
179
 
        movb    $0xFF, %dh
180
 
        /* enter the usual booting */
181
 
        call    prot_to_real
182
 
        .code16
183
 
 
184
 
/* the real mode code continues... */
185
 
LOCAL (codestart):
186
 
        cli             /* we're not safe here! */
187
 
 
188
 
        /* set up %ds, %ss, and %es */
189
 
        xorw    %ax, %ax
190
 
        movw    %ax, %ds
191
 
        movw    %ax, %ss
192
 
        movw    %ax, %es
193
 
 
194
 
        /* set up the real mode/BIOS stack */
195
 
        movl    $GRUB_MEMORY_MACHINE_REAL_STACK, %ebp
196
 
        movl    %ebp, %esp
197
 
 
198
 
        sti             /* we're safe again */
199
 
 
200
 
        /* save the boot drive */
201
 
        ADDR32  movb    %dl, EXT_C(grub_boot_drive)
202
 
 
203
 
        /* reset disk system (%ah = 0) */
204
 
        int     $0x13
205
 
 
206
 
        /* transition to protected mode */
207
 
        DATA32  call real_to_prot
208
 
 
209
 
        /* The ".code32" directive takes GAS out of 16-bit mode. */
210
 
        .code32
211
 
 
212
 
        incl    %eax
213
 
        call    EXT_C(grub_gate_a20)
214
 
 
215
 
#ifdef ENABLE_LZMA
216
 
        movl    $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi
217
 
        movl    $(_start + GRUB_KERNEL_MACHINE_RAW_SIZE), %esi
218
 
        pushl   %edi
219
 
        pushl   %esi
220
 
        movl    EXT_C(grub_kernel_image_size), %ecx
221
 
        addl    EXT_C(grub_total_module_size), %ecx
222
 
        subl    $GRUB_KERNEL_MACHINE_RAW_SIZE, %ecx
223
 
        pushl   %ecx
224
 
        leal    (%edi, %ecx), %ebx
225
 
        call    _LzmaDecodeA
226
 
        /* _LzmaDecodeA clears DF, so no need to run cld */
227
 
        popl    %ecx
228
 
        popl    %edi
229
 
        popl    %esi
230
 
#endif
231
 
 
232
 
        /* copy back the decompressed part (except the modules) */
233
 
        subl    EXT_C(grub_total_module_size), %ecx
234
 
        rep
235
 
        movsb
236
 
 
237
 
#if 0
238
 
        /* copy modules before cleaning out the bss */
239
 
        movl    EXT_C(grub_total_module_size), %ecx
240
 
        movl    EXT_C(grub_kernel_image_size), %esi
241
 
        addl    %ecx, %esi
242
 
        addl    $_start, %esi
243
 
        decl    %esi
244
 
        movl    $END_SYMBOL, %edi
245
 
        addl    %ecx, %edi
246
 
        decl    %edi
247
 
        std
248
 
        rep
249
 
        movsb
250
 
#endif
251
 
 
252
 
#ifdef APPLE_CC
253
 
        /* clean out the bss */
254
 
        bss_start_abs = ABS (bss_start)
255
 
        bss_end_abs = ABS (bss_end)
256
 
 
257
 
        movl    bss_start_abs, %edi
258
 
 
259
 
        /* compute the bss length */
260
 
        movl    bss_end_abs, %ecx
261
 
        subl    %edi, %ecx
262
 
#else
263
 
        /* clean out the bss */
264
 
        movl    $BSS_START_SYMBOL, %edi
265
 
 
266
 
        /* compute the bss length */
267
 
        movl    $END_SYMBOL, %ecx
268
 
        subl    %edi, %ecx
269
 
#endif
270
 
 
271
 
        /* clean out */
272
 
        xorl    %eax, %eax
273
 
        cld
274
 
        rep
275
 
        stosb
276
 
 
277
 
        /*
278
 
         *  Call the start of main body of C code.
279
 
         */
280
 
        call EXT_C(grub_main)
281
 
 
282
 
/*
283
 
 *  This is the area for all of the special variables.
284
 
 */
285
 
 
286
 
VARIABLE(grub_boot_drive)
287
 
        .byte   0
288
 
 
289
 
        .p2align        2       /* force 4-byte alignment */
290
 
 
291
 
#include "../realmode.S"
292
 
 
293
 
/*
294
 
 * grub_gate_a20(int on)
295
 
 *
296
 
 * Gate address-line 20 for high memory.
297
 
 *
298
 
 * This routine is probably overconservative in what it does, but so what?
299
 
 *
300
 
 * It also eats any keystrokes in the keyboard buffer.  :-(
301
 
 */
302
 
 
303
 
FUNCTION(grub_gate_a20)
304
 
        movl    %eax, %edx
305
 
 
306
 
gate_a20_test_current_state:
307
 
        /* first of all, test if already in a good state */
308
 
        call    gate_a20_check_state
309
 
        cmpb    %al, %dl
310
 
        jnz     gate_a20_try_bios
311
 
        ret
312
 
 
313
 
gate_a20_try_bios:
314
 
        /* second, try a BIOS call */
315
 
        pushl   %ebp
316
 
        call    prot_to_real
317
 
 
318
 
        .code16
319
 
        movw    $0x2400, %ax
320
 
        testb   %dl, %dl
321
 
        jz      1f
322
 
        incw    %ax
323
 
1:      int     $0x15
324
 
 
325
 
        DATA32  call    real_to_prot
326
 
        .code32
327
 
 
328
 
        popl    %ebp
329
 
        call    gate_a20_check_state
330
 
        cmpb    %al, %dl
331
 
        jnz     gate_a20_try_system_control_port_a
332
 
        ret
333
 
 
334
 
gate_a20_try_system_control_port_a:
335
 
        /*
336
 
         * In macbook, the keyboard test would hang the machine, so we move
337
 
         * this forward.
338
 
         */
339
 
        /* fourth, try the system control port A */
340
 
        inb     $0x92
341
 
        andb    $(~0x03), %al
342
 
        testb   %dl, %dl
343
 
        jz      6f
344
 
        orb     $0x02, %al
345
 
6:      outb    $0x92
346
 
 
347
 
        /* When turning off Gate A20, do not check the state strictly,
348
 
           because a failure is not fatal usually, and Gate A20 is always
349
 
           on some modern machines.  */
350
 
        testb   %dl, %dl
351
 
        jz      7f
352
 
        call    gate_a20_check_state
353
 
        cmpb    %al, %dl
354
 
        jnz     gate_a20_try_keyboard_controller
355
 
7:      ret
356
 
 
357
 
gate_a20_flush_keyboard_buffer:
358
 
        inb     $0x64
359
 
        andb    $0x02, %al
360
 
        jnz     gate_a20_flush_keyboard_buffer
361
 
2:
362
 
        inb     $0x64
363
 
        andb    $0x01, %al
364
 
        jz      3f
365
 
        inb     $0x60
366
 
        jmp     2b
367
 
3:
368
 
        ret
369
 
 
370
 
gate_a20_try_keyboard_controller:
371
 
        /* third, try the keyboard controller */
372
 
        call    gate_a20_flush_keyboard_buffer
373
 
 
374
 
        movb    $0xd1, %al
375
 
        outb    $0x64
376
 
4:
377
 
        inb     $0x64
378
 
        andb    $0x02, %al
379
 
        jnz     4b
380
 
 
381
 
        movb    $0xdd, %al
382
 
        testb   %dl, %dl
383
 
        jz      5f
384
 
        orb     $0x02, %al
385
 
5:      outb    $0x60
386
 
        call    gate_a20_flush_keyboard_buffer
387
 
 
388
 
        /* output a dummy command (USB keyboard hack) */
389
 
        movb    $0xff, %al
390
 
        outb    $0x64
391
 
        call    gate_a20_flush_keyboard_buffer
392
 
 
393
 
        call    gate_a20_check_state
394
 
        cmpb    %al, %dl
395
 
        /* everything failed, so restart from the beginning */
396
 
        jnz     gate_a20_try_bios
397
 
        ret
398
 
 
399
 
gate_a20_check_state:
400
 
        /* iterate the checking for a while */
401
 
        movl    $100, %ecx
402
 
1:
403
 
        call    3f
404
 
        cmpb    %al, %dl
405
 
        jz      2f
406
 
        loop    1b
407
 
2:
408
 
        ret
409
 
3:
410
 
        pushl   %ebx
411
 
        pushl   %ecx
412
 
        xorl    %eax, %eax
413
 
        /* compare the byte at 0x8000 with that at 0x108000 */
414
 
        movl    $GRUB_BOOT_MACHINE_KERNEL_ADDR, %ebx
415
 
        pushl   %ebx
416
 
        /* save the original byte in CL */
417
 
        movb    (%ebx), %cl
418
 
        /* store the value at 0x108000 in AL */
419
 
        addl    $0x100000, %ebx
420
 
        movb    (%ebx), %al
421
 
        /* try to set one less value at 0x8000 */
422
 
        popl    %ebx
423
 
        movb    %al, %ch
424
 
        decb    %ch
425
 
        movb    %ch, (%ebx)
426
 
        /* serialize */
427
 
        outb    %al, $0x80
428
 
        outb    %al, $0x80
429
 
        /* obtain the value at 0x108000 in CH */
430
 
        pushl   %ebx
431
 
        addl    $0x100000, %ebx
432
 
        movb    (%ebx), %ch
433
 
        /* this result is 1 if A20 is on or 0 if it is off */
434
 
        subb    %ch, %al
435
 
        xorb    $1, %al
436
 
        /* restore the original */
437
 
        popl    %ebx
438
 
        movb    %cl, (%ebx)
439
 
        popl    %ecx
440
 
        popl    %ebx
441
 
        ret
442
 
 
443
 
#ifdef ENABLE_LZMA
444
 
#include "lzma_decode.S"
445
 
#endif
446
 
 
447
 
/*
448
 
 * The code beyond this point is compressed.  Assert that the uncompressed
449
 
 * code fits GRUB_KERNEL_MACHINE_RAW_SIZE.
450
 
 */
451
 
        . = _start + GRUB_KERNEL_MACHINE_RAW_SIZE
452
 
 
453
 
        /*
454
 
         * This next part is sort of evil.  It takes advantage of the
455
 
         * byte ordering on the x86 to work in either 16-bit or 32-bit
456
 
         * mode, so think about it before changing it.
457
 
         */
458
 
 
459
 
FUNCTION(grub_hard_stop)
460
 
        hlt
461
 
        jmp EXT_C(grub_hard_stop)
462
 
 
463
 
 
464
 
/*
465
 
 * grub_stop_floppy()
466
 
 *
467
 
 * Stop the floppy drive from spinning, so that other software is
468
 
 * jumped to with a known state.
469
 
 */
470
 
FUNCTION(grub_stop_floppy)
471
 
        movw    $0x3F2, %dx
472
 
        xorb    %al, %al
473
 
        outb    %al, %dx
474
 
        ret
475
 
 
476
 
/*
477
 
 * grub_exit()
478
 
 *
479
 
 * Exit the system.
480
 
 */
481
 
FUNCTION(grub_exit)
482
 
        call    prot_to_real
483
 
        .code16
484
 
        /* Tell the BIOS a boot failure. If this does not work, reboot.  */
485
 
        int     $0x18
486
 
        jmp     cold_reboot
487
 
        .code32
488
 
 
489
 
/*
490
 
 * grub_halt(int no_apm)
491
 
 *
492
 
 * Halt the system, using APM if possible. If NO_APM is true, don't use
493
 
 * APM even if it is available.
494
 
 */
495
 
FUNCTION(grub_halt)
496
 
        /* see if zero */
497
 
        testl   %eax, %eax
498
 
        jnz     EXT_C(grub_stop)
499
 
 
500
 
        call    prot_to_real
501
 
        .code16
502
 
 
503
 
        /* detect APM */
504
 
        movw    $0x5300, %ax
505
 
        xorw    %bx, %bx
506
 
        int     $0x15
507
 
        jc      EXT_C(grub_hard_stop)
508
 
        /* don't check %bx for buggy BIOSes... */
509
 
 
510
 
        /* disconnect APM first */
511
 
        movw    $0x5304, %ax
512
 
        xorw    %bx, %bx
513
 
        int     $0x15
514
 
 
515
 
        /* connect APM */
516
 
        movw    $0x5301, %ax
517
 
        xorw    %bx, %bx
518
 
        int     $0x15
519
 
        jc      EXT_C(grub_hard_stop)
520
 
 
521
 
        /* set APM protocol level - 1.1 or bust. (this covers APM 1.2 also) */
522
 
        movw    $0x530E, %ax
523
 
        xorw    %bx, %bx
524
 
        movw    $0x0101, %cx
525
 
        int     $0x15
526
 
        jc      EXT_C(grub_hard_stop)
527
 
 
528
 
        /* set the power state to off */
529
 
        movw    $0x5307, %ax
530
 
        movw    $1, %bx
531
 
        movw    $3, %cx
532
 
        int     $0x15
533
 
 
534
 
        /* shouldn't reach here */
535
 
        jmp     EXT_C(grub_hard_stop)
536
 
        .code32
537
 
 
538
 
 
539
 
/*
540
 
 *  void grub_chainloader_real_boot (int drive, void *part_addr)
541
 
 *
542
 
 *  This starts another boot loader.
543
 
 */
544
 
 
545
 
FUNCTION(grub_chainloader_real_boot)
546
 
        pushl   %edx
547
 
        pushl   %eax
548
 
 
549
 
        call    EXT_C(grub_dl_unload_all)
550
 
 
551
 
        /* Turn off Gate A20 */
552
 
        xorl    %eax, %eax
553
 
        call    EXT_C(grub_gate_a20)
554
 
 
555
 
        /* set up to pass boot drive */
556
 
        popl    %edx
557
 
 
558
 
        /* ESI must point to a partition table entry */
559
 
        popl    %esi
560
 
 
561
 
        call    prot_to_real
562
 
        .code16
563
 
        ljmp    $0, $GRUB_MEMORY_MACHINE_BOOT_LOADER_ADDR
564
 
        .code32
565
 
 
566
 
#include "../loader.S"
567
 
 
568
 
/*
569
 
 *   int grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap)
570
 
 *
571
 
 *   Call IBM/MS INT13 Extensions (int 13 %ah=AH) for DRIVE. DAP
572
 
 *   is passed for disk address packet. If an error occurs, return
573
 
 *   non-zero, otherwise zero.
574
 
 */
575
 
 
576
 
FUNCTION(grub_biosdisk_rw_int13_extensions)
577
 
        pushl   %ebp
578
 
        pushl   %esi
579
 
 
580
 
        /* compute the address of disk_address_packet */
581
 
        movw    %cx, %si
582
 
        xorw    %cx, %cx
583
 
        shrl    $4, %ecx        /* save the segment to cx */
584
 
 
585
 
        /* ah */
586
 
        movb    %al, %dh
587
 
        /* enter real mode */
588
 
        call    prot_to_real
589
 
 
590
 
        .code16
591
 
        movb    %dh, %ah
592
 
        movw    %cx, %ds
593
 
        int     $0x13           /* do the operation */
594
 
        movb    %ah, %dl        /* save return value */
595
 
        /* back to protected mode */
596
 
        DATA32  call    real_to_prot
597
 
        .code32
598
 
 
599
 
        movb    %dl, %al        /* return value in %eax */
600
 
 
601
 
        popl    %esi
602
 
        popl    %ebp
603
 
 
604
 
        ret
605
 
 
606
 
/*
607
 
 *   int grub_biosdisk_rw_standard (int ah, int drive, int coff, int hoff,
608
 
 *                                  int soff, int nsec, int segment)
609
 
 *
610
 
 *   Call standard and old INT13 (int 13 %ah=AH) for DRIVE. Read/write
611
 
 *   NSEC sectors from COFF/HOFF/SOFF into SEGMENT. If an error occurs,
612
 
 *   return non-zero, otherwise zero.
613
 
 */
614
 
 
615
 
FUNCTION(grub_biosdisk_rw_standard)
616
 
        pushl   %ebp
617
 
        movl    %esp, %ebp
618
 
 
619
 
        pushl   %ebx
620
 
        pushl   %edi
621
 
        pushl   %esi
622
 
 
623
 
        /* set up CHS information */
624
 
 
625
 
        /* set %ch to low eight bits of cylinder */
626
 
        xchgb   %cl, %ch
627
 
        /* set bits 6-7 of %cl to high two bits of cylinder */
628
 
        shlb    $6, %cl
629
 
        /* set bits 0-5 of %cl to sector */
630
 
        addb    0xc(%ebp), %cl
631
 
        /* set %dh to head */
632
 
        movb    0x8(%ebp), %dh
633
 
        /* set %ah to AH */
634
 
        movb    %al, %ah
635
 
        /* set %al to NSEC */
636
 
        movb    0x10(%ebp), %al
637
 
        /* save %ax in %di */
638
 
        movw    %ax, %di
639
 
        /* save SEGMENT in %bx */
640
 
        movw    0x14(%ebp), %bx
641
 
 
642
 
        /* enter real mode */
643
 
        call    prot_to_real
644
 
 
645
 
        .code16
646
 
        movw    %bx, %es
647
 
        xorw    %bx, %bx
648
 
        movw    $3, %si         /* attempt at least three times */
649
 
 
650
 
1:
651
 
        movw    %di, %ax
652
 
        int     $0x13           /* do the operation */
653
 
        jnc     2f              /* check if successful */
654
 
 
655
 
        movb    %ah, %bl        /* save return value */
656
 
        /* if fail, reset the disk system */
657
 
        xorw    %ax, %ax
658
 
        int     $0x13
659
 
 
660
 
        decw    %si
661
 
        cmpw    $0, %si
662
 
        je      2f
663
 
        xorb    %bl, %bl
664
 
        jmp     1b              /* retry */
665
 
2:
666
 
        /* back to protected mode */
667
 
        DATA32  call    real_to_prot
668
 
        .code32
669
 
 
670
 
        movb    %bl, %al        /* return value in %eax */
671
 
 
672
 
        popl    %esi
673
 
        popl    %edi
674
 
        popl    %ebx
675
 
        popl    %ebp
676
 
 
677
 
        ret     $(4 * 4)
678
 
 
679
 
 
680
 
/*
681
 
 *   int grub_biosdisk_check_int13_extensions (int drive)
682
 
 *
683
 
 *   Check if LBA is supported for DRIVE. If it is supported, then return
684
 
 *   the major version of extensions, otherwise zero.
685
 
 */
686
 
 
687
 
FUNCTION(grub_biosdisk_check_int13_extensions)
688
 
        pushl   %ebp
689
 
        pushl   %ebx
690
 
 
691
 
        /* drive */
692
 
        movb    %al, %dl
693
 
        /* enter real mode */
694
 
        call    prot_to_real
695
 
 
696
 
        .code16
697
 
        movb    $0x41, %ah
698
 
        movw    $0x55aa, %bx
699
 
        int     $0x13           /* do the operation */
700
 
 
701
 
        /* check the result */
702
 
        jc      1f
703
 
        cmpw    $0xaa55, %bx
704
 
        jne     1f
705
 
 
706
 
        movb    %ah, %bl        /* save the major version into %bl */
707
 
 
708
 
        /* check if AH=0x42 is supported */
709
 
        andw    $1, %cx
710
 
        jnz     2f
711
 
 
712
 
1:
713
 
        xorb    %bl, %bl
714
 
2:
715
 
        /* back to protected mode */
716
 
        DATA32  call    real_to_prot
717
 
        .code32
718
 
 
719
 
        movb    %bl, %al        /* return value in %eax */
720
 
 
721
 
        popl    %ebx
722
 
        popl    %ebp
723
 
 
724
 
        ret
725
 
 
726
 
 
727
 
/*
728
 
 *   int grub_biosdisk_get_cdinfo_int13_extensions (int drive, void *cdrp)
729
 
 *
730
 
 *   Return the cdrom information of DRIVE in CDRP. If an error occurs,
731
 
 *   then return non-zero, otherwise zero.
732
 
 */
733
 
 
734
 
FUNCTION(grub_biosdisk_get_cdinfo_int13_extensions)
735
 
        movw    $0x4B01, %cx
736
 
        jmp     1f
737
 
 
738
 
/*
739
 
 *   int grub_biosdisk_get_diskinfo_int13_extensions (int drive, void *drp)
740
 
 *
741
 
 *   Return the geometry of DRIVE in a drive parameters, DRP. If an error
742
 
 *   occurs, then return non-zero, otherwise zero.
743
 
 */
744
 
 
745
 
FUNCTION(grub_biosdisk_get_diskinfo_int13_extensions)
746
 
        movb    $0x48, %ch
747
 
1:
748
 
        pushl   %ebp
749
 
        pushl   %ebx
750
 
        pushl   %esi
751
 
 
752
 
        /* compute the address of drive parameters */
753
 
        movw    %dx, %si
754
 
        andl    $0xf, %esi
755
 
        shrl    $4, %edx
756
 
        movw    %dx, %bx        /* save the segment into %bx */
757
 
        /* drive */
758
 
        movb    %al, %dl
759
 
        /* enter real mode */
760
 
        call    prot_to_real
761
 
 
762
 
        .code16
763
 
        movw    %cx, %ax
764
 
        movw    %bx, %ds
765
 
        int     $0x13           /* do the operation */
766
 
        jc      noclean
767
 
        /* Clean return value if carry isn't set to workaround
768
 
        some buggy BIOSes.  */
769
 
        xor     %ax, %ax
770
 
noclean:
771
 
        movb    %ah, %bl        /* save return value in %bl */
772
 
        /* back to protected mode */
773
 
        DATA32  call    real_to_prot
774
 
        .code32
775
 
 
776
 
        movb    %bl, %al        /* return value in %eax */
777
 
 
778
 
        popl    %esi
779
 
        popl    %ebx
780
 
        popl    %ebp
781
 
 
782
 
        ret
783
 
 
784
 
 
785
 
/*
786
 
 *   int grub_biosdisk_get_diskinfo_standard (int drive,
787
 
 *                                            unsigned long *cylinders,
788
 
 *                                            unsigned long *heads,
789
 
 *                                            unsigned long *sectors)
790
 
 *
791
 
 *   Return the geometry of DRIVE in CYLINDERS, HEADS and SECTORS. If an
792
 
 *   error occurs, then return non-zero, otherwise zero.
793
 
 */
794
 
 
795
 
FUNCTION(grub_biosdisk_get_diskinfo_standard)
796
 
        pushl   %ebp
797
 
        pushl   %ebx
798
 
        pushl   %edi
799
 
 
800
 
        /* push CYLINDERS */
801
 
        pushl   %edx
802
 
        /* push HEADS */
803
 
        pushl   %ecx
804
 
        /* SECTORS is on the stack */
805
 
 
806
 
        /* drive */
807
 
        movb    %al, %dl
808
 
        /* enter real mode */
809
 
        call    prot_to_real
810
 
 
811
 
        .code16
812
 
        movb    $0x8, %ah
813
 
        int     $0x13           /* do the operation */
814
 
        jc      noclean2
815
 
        /* Clean return value if carry isn't set to workaround
816
 
        some buggy BIOSes.  */
817
 
        xor     %ax, %ax
818
 
noclean2:
819
 
        /* check if successful */
820
 
        testb   %ah, %ah
821
 
        jnz     1f
822
 
        /* bogus BIOSes may not return an error number */
823
 
        testb   $0x3f, %cl      /* 0 sectors means no disk */
824
 
        jnz     1f              /* if non-zero, then succeed */
825
 
        /* XXX 0x60 is one of the unused error numbers */
826
 
        movb    $0x60, %ah
827
 
1:
828
 
        movb    %ah, %bl        /* save return value in %bl */
829
 
        /* back to protected mode */
830
 
        DATA32  call    real_to_prot
831
 
        .code32
832
 
 
833
 
        /* pop HEADS */
834
 
        popl    %edi
835
 
        movb    %dh, %al
836
 
        incl    %eax    /* the number of heads is counted from zero */
837
 
        movl    %eax, (%edi)
838
 
 
839
 
        /* pop CYLINDERS */
840
 
        popl    %edi
841
 
        movb    %ch, %al
842
 
        movb    %cl, %ah
843
 
        shrb    $6, %ah /* the number of cylinders is counted from zero */
844
 
        incl    %eax
845
 
        movl    %eax, (%edi)
846
 
 
847
 
        /* SECTORS */
848
 
        movl    0x10(%esp), %edi
849
 
        andb    $0x3f, %cl
850
 
        movzbl  %cl, %eax
851
 
        movl    %eax, (%edi)
852
 
 
853
 
        xorl    %eax, %eax
854
 
        movb    %bl, %al        /* return value in %eax */
855
 
 
856
 
        popl    %edi
857
 
        popl    %ebx
858
 
        popl    %ebp
859
 
 
860
 
        ret     $4
861
 
 
862
 
 
863
 
/*
864
 
 * int grub_biosdisk_get_num_floppies (void)
865
 
 */
866
 
FUNCTION(grub_biosdisk_get_num_floppies)
867
 
        pushl   %ebp
868
 
 
869
 
        xorl    %edx, %edx
870
 
        call    prot_to_real
871
 
 
872
 
        .code16
873
 
        /* reset the disk system first */
874
 
        int     $0x13
875
 
1:
876
 
        stc
877
 
 
878
 
        /* call GET DISK TYPE */
879
 
        movb    $0x15, %ah
880
 
        int     $0x13
881
 
 
882
 
        jc      2f
883
 
 
884
 
        /* check if this drive exists */
885
 
        testb   $0x3, %ah
886
 
        jz      2f
887
 
 
888
 
        incb    %dl
889
 
        cmpb    $2, %dl
890
 
        jne     1b
891
 
2:
892
 
        DATA32  call    real_to_prot
893
 
        .code32
894
 
 
895
 
        movl    %edx, %eax
896
 
        popl    %ebp
897
 
        ret
898
 
 
899
 
 
900
 
/*
901
 
 *
902
 
 * grub_get_memsize(i) :  return the memory size in KB. i == 0 for conventional
903
 
 *              memory, i == 1 for extended memory
904
 
 *      BIOS call "INT 12H" to get conventional memory size
905
 
 *      BIOS call "INT 15H, AH=88H" to get extended memory size
906
 
 *              Both have the return value in AX.
907
 
 *
908
 
 */
909
 
 
910
 
FUNCTION(grub_get_memsize)
911
 
        pushl   %ebp
912
 
 
913
 
        movl    %eax, %edx
914
 
 
915
 
        call    prot_to_real    /* enter real mode */
916
 
        .code16
917
 
 
918
 
        testl   %edx, %edx
919
 
        jnz     xext
920
 
 
921
 
        int     $0x12
922
 
        jmp     xdone
923
 
 
924
 
xext:
925
 
        movb    $0x88, %ah
926
 
        int     $0x15
927
 
 
928
 
xdone:
929
 
        movw    %ax, %dx
930
 
 
931
 
        DATA32  call    real_to_prot
932
 
        .code32
933
 
 
934
 
        movw    %dx, %ax
935
 
 
936
 
        popl    %ebp
937
 
        ret
938
 
 
939
 
 
940
 
/*
941
 
 *
942
 
 * grub_get_eisa_mmap() :  return packed EISA memory map, lower 16 bits is
943
 
 *              memory between 1M and 16M in 1K parts, upper 16 bits is
944
 
 *              memory above 16M in 64K parts.  If error, return zero.
945
 
 *      BIOS call "INT 15H, AH=E801H" to get EISA memory map,
946
 
 *              AX = memory between 1M and 16M in 1K parts.
947
 
 *              BX = memory above 16M in 64K parts.
948
 
 *
949
 
 */
950
 
 
951
 
FUNCTION(grub_get_eisa_mmap)
952
 
        pushl   %ebp
953
 
        pushl   %ebx
954
 
 
955
 
        call    prot_to_real    /* enter real mode */
956
 
        .code16
957
 
 
958
 
        movw    $0xe801, %ax
959
 
        int     $0x15
960
 
 
961
 
        shll    $16, %ebx
962
 
        movw    %ax, %bx
963
 
 
964
 
        DATA32  call    real_to_prot
965
 
        .code32
966
 
 
967
 
        cmpb    $0x86, %bh
968
 
        je      xnoteisa
969
 
 
970
 
        movl    %ebx, %eax
971
 
 
972
 
xnoteisa:
973
 
        popl    %ebx
974
 
        popl    %ebp
975
 
        ret
976
 
 
977
 
/*
978
 
 *
979
 
 * grub_get_mmap_entry(addr, cont) : address and old continuation value (zero to
980
 
 *              start), for the Query System Address Map BIOS call.
981
 
 *
982
 
 *  Sets the first 4-byte int value of "addr" to the size returned by
983
 
 *  the call.  If the call fails, sets it to zero.
984
 
 *
985
 
 *      Returns:  new (non-zero) continuation value, 0 if done.
986
 
 */
987
 
 
988
 
FUNCTION(grub_get_mmap_entry)
989
 
        pushl   %ebp
990
 
        pushl   %ebx
991
 
        pushl   %edi
992
 
        pushl   %esi
993
 
 
994
 
        /* push ADDR */
995
 
        pushl   %eax
996
 
 
997
 
        /* place address (+4) in ES:DI */
998
 
        addl    $4, %eax
999
 
        movl    %eax, %edi
1000
 
        andl    $0xf, %edi
1001
 
        shrl    $4, %eax
1002
 
        movl    %eax, %esi
1003
 
 
1004
 
        /* set continuation value */
1005
 
        movl    %edx, %ebx
1006
 
 
1007
 
        /* set default maximum buffer size */
1008
 
        movl    $0x14, %ecx
1009
 
 
1010
 
        /* set EDX to 'SMAP' */
1011
 
        movl    $0x534d4150, %edx
1012
 
 
1013
 
        call    prot_to_real    /* enter real mode */
1014
 
        .code16
1015
 
 
1016
 
        movw    %si, %es
1017
 
        movl    $0xe820, %eax
1018
 
        int     $0x15
1019
 
 
1020
 
        DATA32  jc      xnosmap
1021
 
 
1022
 
        cmpl    $0x534d4150, %eax
1023
 
        jne     xnosmap
1024
 
 
1025
 
        cmpl    $0x14, %ecx
1026
 
        jl      xnosmap
1027
 
 
1028
 
        cmpl    $0x400, %ecx
1029
 
        jg      xnosmap
1030
 
 
1031
 
        jmp     xsmap
1032
 
 
1033
 
xnosmap:
1034
 
        xorl    %ecx, %ecx
1035
 
 
1036
 
/*      Apple's cc jumps few bytes before the correct
1037
 
        label in this context. Hence nops. */
1038
 
#ifdef APPLE_CC
1039
 
        nop
1040
 
        nop
1041
 
        nop
1042
 
        nop
1043
 
        nop
1044
 
        nop
1045
 
#endif
1046
 
 
1047
 
xsmap:
1048
 
        DATA32  call    real_to_prot
1049
 
        .code32
1050
 
 
1051
 
        /* write length of buffer (zero if error) into ADDR */
1052
 
        popl    %eax
1053
 
        movl    %ecx, (%eax)
1054
 
 
1055
 
        /* set return value to continuation */
1056
 
        movl    %ebx, %eax
1057
 
 
1058
 
        popl    %esi
1059
 
        popl    %edi
1060
 
        popl    %ebx
1061
 
        popl    %ebp
1062
 
        ret
1063
 
 
1064
 
 
1065
 
/*
1066
 
 * void grub_console_putchar (const struct grub_unicode_glyph *c)
1067
 
 *
1068
 
 * Put the character C on the console. Because GRUB wants to write a
1069
 
 * character with an attribute, this implementation is a bit tricky.
1070
 
 * If C is a control character (CR, LF, BEL, BS), use INT 10, AH = 0Eh
1071
 
 * (TELETYPE OUTPUT). Otherwise, save the original position, put a space,
1072
 
 * save the current position, restore the original position, write the
1073
 
 * character and the attribute, and restore the current position.
1074
 
 *
1075
 
 * The reason why this is so complicated is that there is no easy way to
1076
 
 * get the height of the screen, and the TELETYPE OUTPUT BIOS call doesn't
1077
 
 * support setting a background attribute.
1078
 
 */
1079
 
FUNCTION(grub_console_putchar)
1080
 
        /* Retrieve the base character.  */
1081
 
        movl    0(%edx), %edx
1082
 
        pusha
1083
 
        movb    EXT_C(grub_console_cur_color), %bl
1084
 
 
1085
 
        call    prot_to_real
1086
 
        .code16
1087
 
        movb    %dl, %al
1088
 
        xorb    %bh, %bh
1089
 
 
1090
 
        /* use teletype output if control character */
1091
 
        cmpb    $0x7, %al
1092
 
        je      1f
1093
 
        cmpb    $0x8, %al
1094
 
        je      1f
1095
 
        cmpb    $0xa, %al
1096
 
        je      1f
1097
 
        cmpb    $0xd, %al
1098
 
        je      1f
1099
 
 
1100
 
        /* save the character and the attribute on the stack */
1101
 
        pushw   %ax
1102
 
        pushw   %bx
1103
 
 
1104
 
        /* get the current position */
1105
 
        movb    $0x3, %ah
1106
 
        int     $0x10
1107
 
 
1108
 
        /* check the column with the width */
1109
 
        cmpb    $79, %dl
1110
 
        jl      2f
1111
 
 
1112
 
        /* print CR and LF, if next write will exceed the width */
1113
 
        movw    $0x0e0d, %ax
1114
 
        int     $0x10
1115
 
        movb    $0x0a, %al
1116
 
        int     $0x10
1117
 
 
1118
 
        /* get the current position */
1119
 
        movb    $0x3, %ah
1120
 
        int     $0x10
1121
 
 
1122
 
2:
1123
 
        /* restore the character and the attribute */
1124
 
        popw    %bx
1125
 
        popw    %ax
1126
 
 
1127
 
        /* write the character with the attribute */
1128
 
        movb    $0x9, %ah
1129
 
        movw    $1, %cx
1130
 
        int     $0x10
1131
 
 
1132
 
        /* move the cursor forward */
1133
 
        incb    %dl
1134
 
        movb    $0x2, %ah
1135
 
        int     $0x10
1136
 
 
1137
 
        jmp     3f
1138
 
 
1139
 
1:      movw    $1, %bx
1140
 
        movb    $0xe, %ah
1141
 
        int     $0x10
1142
 
 
1143
 
3:      DATA32  call    real_to_prot
1144
 
        .code32
1145
 
 
1146
 
        popa
1147
 
        ret
1148
 
 
1149
 
 
1150
 
/*
1151
 
 * int grub_console_getkey (void)
1152
 
 * BIOS call "INT 16H Function 00H" to read character from keyboard
1153
 
 *      Call with       %ah = 0x0
1154
 
 *      Return:         %ah = keyboard scan code
1155
 
 *                      %al = ASCII character
1156
 
 */
1157
 
 
1158
 
/* this table is used in translate_keycode below */
1159
 
LOCAL (translation_table):
1160
 
        .word   GRUB_CONSOLE_KEY_LEFT, GRUB_TERM_LEFT
1161
 
        .word   GRUB_CONSOLE_KEY_RIGHT, GRUB_TERM_RIGHT
1162
 
        .word   GRUB_CONSOLE_KEY_UP, GRUB_TERM_UP
1163
 
        .word   GRUB_CONSOLE_KEY_DOWN, GRUB_TERM_DOWN
1164
 
        .word   GRUB_CONSOLE_KEY_HOME, GRUB_TERM_HOME
1165
 
        .word   GRUB_CONSOLE_KEY_END, GRUB_TERM_END
1166
 
        .word   GRUB_CONSOLE_KEY_DC, GRUB_TERM_DC
1167
 
        .word   GRUB_CONSOLE_KEY_BACKSPACE, GRUB_TERM_BACKSPACE
1168
 
        .word   GRUB_CONSOLE_KEY_PPAGE, GRUB_TERM_PPAGE
1169
 
        .word   GRUB_CONSOLE_KEY_NPAGE, GRUB_TERM_NPAGE
1170
 
        .word   0
1171
 
 
1172
 
/*
1173
 
 * translate_keycode translates the key code %dx to an ascii code.
1174
 
 */
1175
 
        .code16
1176
 
 
1177
 
translate_keycode:
1178
 
        pushw   %bx
1179
 
        pushw   %si
1180
 
 
1181
 
#ifdef __APPLE__
1182
 
        movw    $(ABS(LOCAL (translation_table)) - 0x10000), %si
1183
 
#else
1184
 
        movw    $ABS(LOCAL (translation_table)), %si
1185
 
#endif
1186
 
 
1187
 
1:      lodsw
1188
 
        /* check if this is the end */
1189
 
        testw   %ax, %ax
1190
 
        jz      2f
1191
 
        /* load the ascii code into %ax */
1192
 
        movw    %ax, %bx
1193
 
        lodsw
1194
 
        /* check if this matches the key code */
1195
 
        cmpw    %bx, %dx
1196
 
        jne     1b
1197
 
        /* translate %dx, if successful */
1198
 
        movw    %ax, %dx
1199
 
 
1200
 
2:      popw    %si
1201
 
        popw    %bx
1202
 
        ret
1203
 
 
1204
 
        .code32
1205
 
 
1206
 
FUNCTION(grub_console_getkey)
1207
 
        pushl   %ebp
1208
 
 
1209
 
        call    prot_to_real
1210
 
        .code16
1211
 
 
1212
 
        /*
1213
 
         * Due to a bug in apple's bootcamp implementation, INT 16/AH = 0 would
1214
 
         * cause the machine to hang at the second keystroke. However, we can
1215
 
         * work around this problem by ensuring the presence of keystroke with
1216
 
         * INT 16/AH = 1 before calling INT 16/AH = 0.
1217
 
         */
1218
 
 
1219
 
1:
1220
 
        movb    $1, %ah
1221
 
        int     $0x16
1222
 
        jnz     2f
1223
 
        hlt
1224
 
        jmp     1b
1225
 
 
1226
 
2:
1227
 
 
1228
 
        movb    $0, %ah
1229
 
        int     $0x16
1230
 
 
1231
 
        movw    %ax, %dx                /* real_to_prot uses %eax */
1232
 
        call    translate_keycode
1233
 
 
1234
 
        DATA32  call    real_to_prot
1235
 
        .code32
1236
 
 
1237
 
        movw    %dx, %ax
1238
 
 
1239
 
        popl    %ebp
1240
 
        ret
1241
 
 
1242
 
 
1243
 
/*
1244
 
 * int grub_console_checkkey (void)
1245
 
 *      if there is a character pending, return it; otherwise return -1
1246
 
 * BIOS call "INT 16H Function 01H" to check whether a character is pending
1247
 
 *      Call with       %ah = 0x1
1248
 
 *      Return:
1249
 
 *              If key waiting to be input:
1250
 
 *                      %ah = keyboard scan code
1251
 
 *                      %al = ASCII character
1252
 
 *                      Zero flag = clear
1253
 
 *              else
1254
 
 *                      Zero flag = set
1255
 
 */
1256
 
FUNCTION(grub_console_checkkey)
1257
 
        pushl   %ebp
1258
 
        xorl    %edx, %edx
1259
 
 
1260
 
        call    prot_to_real    /* enter real mode */
1261
 
        .code16
1262
 
 
1263
 
        movb    $0x1, %ah
1264
 
        int     $0x16
1265
 
 
1266
 
        jz      notpending
1267
 
 
1268
 
        movw    %ax, %dx
1269
 
        DATA32  jmp     pending
1270
 
 
1271
 
notpending:
1272
 
        decl    %edx
1273
 
 
1274
 
pending:
1275
 
        DATA32  call    real_to_prot
1276
 
        .code32
1277
 
 
1278
 
        movl    %edx, %eax
1279
 
 
1280
 
        popl    %ebp
1281
 
        ret
1282
 
 
1283
 
 
1284
 
/*
1285
 
 * grub_uint16_t grub_console_getxy (void)
1286
 
 * BIOS call "INT 10H Function 03h" to get cursor position
1287
 
 *      Call with       %ah = 0x03
1288
 
 *                      %bh = page
1289
 
 *      Returns         %ch = starting scan line
1290
 
 *                      %cl = ending scan line
1291
 
 *                      %dh = row (0 is top)
1292
 
 *                      %dl = column (0 is left)
1293
 
 */
1294
 
 
1295
 
 
1296
 
FUNCTION(grub_console_getxy)
1297
 
        pushl   %ebp
1298
 
        pushl   %ebx                    /* save EBX */
1299
 
 
1300
 
        call    prot_to_real
1301
 
        .code16
1302
 
 
1303
 
        xorb    %bh, %bh                /* set page to 0 */
1304
 
        movb    $0x3, %ah
1305
 
        int     $0x10                   /* get cursor position */
1306
 
 
1307
 
        DATA32  call    real_to_prot
1308
 
        .code32
1309
 
 
1310
 
        movb    %dl, %ah
1311
 
        movb    %dh, %al
1312
 
 
1313
 
        popl    %ebx
1314
 
        popl    %ebp
1315
 
        ret
1316
 
 
1317
 
 
1318
 
/*
1319
 
 * void grub_console_gotoxy(grub_uint8_t x, grub_uint8_t y)
1320
 
 * BIOS call "INT 10H Function 02h" to set cursor position
1321
 
 *      Call with       %ah = 0x02
1322
 
 *                      %bh = page
1323
 
 *                      %dh = row (0 is top)
1324
 
 *                      %dl = column (0 is left)
1325
 
 */
1326
 
 
1327
 
 
1328
 
FUNCTION(grub_console_gotoxy)
1329
 
        pushl   %ebp
1330
 
        pushl   %ebx                    /* save EBX */
1331
 
 
1332
 
        movb    %cl, %dh        /* %dh = y */
1333
 
        /* %dl = x */
1334
 
 
1335
 
        call    prot_to_real
1336
 
        .code16
1337
 
 
1338
 
        xorb    %bh, %bh                /* set page to 0 */
1339
 
        movb    $0x2, %ah
1340
 
        int     $0x10                   /* set cursor position */
1341
 
 
1342
 
        DATA32  call    real_to_prot
1343
 
        .code32
1344
 
 
1345
 
        popl    %ebx
1346
 
        popl    %ebp
1347
 
        ret
1348
 
 
1349
 
 
1350
 
/*
1351
 
 * void grub_console_cls (void)
1352
 
 * BIOS call "INT 10H Function 09h" to write character and attribute
1353
 
 *      Call with       %ah = 0x09
1354
 
 *                      %al = (character)
1355
 
 *                      %bh = (page number)
1356
 
 *                      %bl = (attribute)
1357
 
 *                      %cx = (number of times)
1358
 
 */
1359
 
 
1360
 
FUNCTION(grub_console_cls)
1361
 
        pushl   %ebp
1362
 
        pushl   %ebx                    /* save EBX */
1363
 
 
1364
 
        call    prot_to_real
1365
 
        .code16
1366
 
 
1367
 
        /* move the cursor to the beginning */
1368
 
        movb    $0x02, %ah
1369
 
        xorb    %bh, %bh
1370
 
        xorw    %dx, %dx
1371
 
        int     $0x10
1372
 
 
1373
 
        /* write spaces to the entire screen */
1374
 
        movw    $0x0920, %ax
1375
 
        movw    $0x07, %bx
1376
 
        movw    $(80 * 25), %cx
1377
 
        int     $0x10
1378
 
 
1379
 
        /* move back the cursor */
1380
 
        movb    $0x02, %ah
1381
 
        int     $0x10
1382
 
 
1383
 
        DATA32  call    real_to_prot
1384
 
        .code32
1385
 
 
1386
 
        popl    %ebx
1387
 
        popl    %ebp
1388
 
        ret
1389
 
 
1390
 
 
1391
 
/*
1392
 
 * void grub_console_setcursor (int on)
1393
 
 * BIOS call "INT 10H Function 01h" to set cursor type
1394
 
 *      Call with       %ah = 0x01
1395
 
 *                      %ch = cursor starting scanline
1396
 
 *                      %cl = cursor ending scanline
1397
 
 */
1398
 
 
1399
 
console_cursor_state:
1400
 
        .byte   1
1401
 
console_cursor_shape:
1402
 
        .word   0
1403
 
 
1404
 
FUNCTION(grub_console_setcursor)
1405
 
        pushl   %ebp
1406
 
        pushl   %ebx
1407
 
 
1408
 
        /* push ON */
1409
 
        pushl   %edx
1410
 
 
1411
 
        /* check if the standard cursor shape has already been saved */
1412
 
        movw    console_cursor_shape, %ax
1413
 
        testw   %ax, %ax
1414
 
        jne     1f
1415
 
 
1416
 
        call    prot_to_real
1417
 
        .code16
1418
 
 
1419
 
        movb    $0x03, %ah
1420
 
        xorb    %bh, %bh
1421
 
        int     $0x10
1422
 
 
1423
 
        DATA32  call    real_to_prot
1424
 
        .code32
1425
 
 
1426
 
        movw    %cx, console_cursor_shape
1427
 
1:
1428
 
        /* set %cx to the designated cursor shape */
1429
 
        movw    $0x2000, %cx
1430
 
        popl    %eax
1431
 
        testl   %eax, %eax
1432
 
        jz      2f
1433
 
        movw    console_cursor_shape, %cx
1434
 
2:
1435
 
        call    prot_to_real
1436
 
        .code16
1437
 
 
1438
 
        movb    $0x1, %ah
1439
 
        int     $0x10
1440
 
 
1441
 
        DATA32  call    real_to_prot
1442
 
        .code32
1443
 
 
1444
 
        popl    %ebx
1445
 
        popl    %ebp
1446
 
        ret
1447
 
 
1448
 
/*
1449
 
 * grub_get_rtc()
1450
 
 *      return the real time in ticks, of which there are about
1451
 
 *      18-20 per second
1452
 
 */
1453
 
FUNCTION(grub_get_rtc)
1454
 
        pushl   %ebp
1455
 
 
1456
 
        call    prot_to_real    /* enter real mode */
1457
 
        .code16
1458
 
 
1459
 
        /* %ax is already zero */
1460
 
        int     $0x1a
1461
 
 
1462
 
        DATA32  call    real_to_prot
1463
 
        .code32
1464
 
 
1465
 
        movl    %ecx, %eax
1466
 
        shll    $16, %eax
1467
 
        movw    %dx, %ax
1468
 
 
1469
 
        popl    %ebp
1470
 
        ret
1471
 
 
1472
 
 
1473
 
/*
1474
 
 * unsigned char grub_vga_set_mode (unsigned char mode)
1475
 
 */
1476
 
FUNCTION(grub_vga_set_mode)
1477
 
        pushl   %ebp
1478
 
        pushl   %ebx
1479
 
        movl    %eax, %ecx
1480
 
 
1481
 
        call    prot_to_real
1482
 
        .code16
1483
 
        /* get current mode */
1484
 
        xorw    %bx, %bx
1485
 
        movb    $0x0f, %ah
1486
 
        int     $0x10
1487
 
        movb    %al, %dl
1488
 
 
1489
 
        /* set the new mode */
1490
 
        movb    %cl, %al
1491
 
        xorb    %ah, %ah
1492
 
        int     $0x10
1493
 
 
1494
 
        DATA32  call    real_to_prot
1495
 
        .code32
1496
 
 
1497
 
        movb    %dl, %al
1498
 
        popl    %ebx
1499
 
        popl    %ebp
1500
 
        ret
1501
 
 
1502
 
/*
1503
 
 * grub_vbe_bios_status_t grub_vbe_get_controller_info (struct grub_vbe_info_block *controller_info)
1504
 
 *
1505
 
 * Register allocations for parameters:
1506
 
 * %eax         *controller_info
1507
 
 */
1508
 
FUNCTION(grub_vbe_bios_get_controller_info)
1509
 
        pushl   %ebp
1510
 
        pushl   %edi
1511
 
        pushl   %edx
1512
 
 
1513
 
        movw    %ax, %di        /* Store *controller_info to %edx:%di.  */
1514
 
        xorw    %ax, %ax
1515
 
        shrl    $4, %eax
1516
 
        mov     %eax, %edx      /* prot_to_real destroys %eax.  */
1517
 
 
1518
 
        call    prot_to_real
1519
 
        .code16
1520
 
 
1521
 
        pushw   %es
1522
 
 
1523
 
        movw    %dx, %es        /* *controller_info is now on %es:%di.  */
1524
 
        movw    $0x4f00, %ax
1525
 
        int     $0x10
1526
 
 
1527
 
        movw    %ax, %dx        /* real_to_prot destroys %eax.  */
1528
 
 
1529
 
        popw    %es
1530
 
 
1531
 
        DATA32 call     real_to_prot
1532
 
        .code32
1533
 
 
1534
 
        movl    %edx, %eax
1535
 
        andl    $0x0FFFF, %eax  /* Return value in %eax.  */
1536
 
 
1537
 
        pop     %edx
1538
 
        popl    %edi
1539
 
        popl    %ebp
1540
 
        ret
1541
 
 
1542
 
/*
1543
 
 * grub_vbe_status_t grub_vbe_bios_get_mode_info (grub_uint32_t mode,
1544
 
 *                                                struct grub_vbe_mode_info_block *mode_info)
1545
 
 *
1546
 
 * Register allocations for parameters:
1547
 
 * %eax         mode
1548
 
 * %edx         *mode_info
1549
 
 */
1550
 
FUNCTION(grub_vbe_bios_get_mode_info)
1551
 
        pushl   %ebp
1552
 
        pushl   %edi
1553
 
 
1554
 
        movl    %eax, %ecx      /* Store mode number to %ecx.  */
1555
 
 
1556
 
        movw    %dx, %di        /* Store *mode_info to %edx:%di.  */
1557
 
        xorw    %dx, %dx
1558
 
        shrl    $4, %edx
1559
 
 
1560
 
        call    prot_to_real
1561
 
        .code16
1562
 
 
1563
 
        pushw   %es
1564
 
 
1565
 
        movw    %dx, %es        /* *mode_info is now on %es:%di.  */
1566
 
        movw    $0x4f01, %ax
1567
 
        int     $0x10
1568
 
 
1569
 
        movw    %ax, %dx        /* real_to_prot destroys %eax.  */
1570
 
 
1571
 
        popw    %es
1572
 
 
1573
 
        DATA32 call     real_to_prot
1574
 
        .code32
1575
 
 
1576
 
        movl    %edx, %eax
1577
 
        andl    $0x0FFFF, %eax  /* Return value in %eax.  */
1578
 
 
1579
 
        popl    %edi
1580
 
        popl    %ebp
1581
 
        ret
1582
 
 
1583
 
/*
1584
 
 * grub_vbe_status_t grub_vbe_bios_set_mode (grub_uint32_t mode,
1585
 
 *                                           struct grub_vbe_crtc_info_block *crtc_info)
1586
 
 *
1587
 
 * Register allocations for parameters:
1588
 
 * %eax         mode
1589
 
 * %edx         *crtc_info
1590
 
 */
1591
 
FUNCTION(grub_vbe_bios_set_mode)
1592
 
        pushl   %ebp
1593
 
        pushl   %ebx
1594
 
        pushl   %edi
1595
 
 
1596
 
        movl    %eax, %ebx      /* Store mode in %ebx.  */
1597
 
 
1598
 
        movw    %dx, %di        /* Store *crtc_info to %edx:%di.  */
1599
 
        xorw    %dx, %dx
1600
 
        shrl    $4, %edx
1601
 
 
1602
 
        call    prot_to_real
1603
 
        .code16
1604
 
 
1605
 
        pushw   %es
1606
 
 
1607
 
        movw    %dx, %es        /* *crtc_info is now on %es:%di.  */
1608
 
 
1609
 
        movw    $0x4f02, %ax
1610
 
        int     $0x10
1611
 
 
1612
 
        movw    %ax, %dx        /* real_to_prot destroys %eax.  */
1613
 
 
1614
 
        popw    %es
1615
 
 
1616
 
        DATA32 call     real_to_prot
1617
 
        .code32
1618
 
 
1619
 
        movw    %dx, %ax
1620
 
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
1621
 
 
1622
 
        popl    %edi
1623
 
        popl    %ebx
1624
 
        popl    %ebp
1625
 
        ret
1626
 
 
1627
 
/*
1628
 
 * grub_vbe_status_t grub_vbe_bios_get_mode (grub_uint32_t *mode)
1629
 
 *
1630
 
 * Register allocations for parameters:
1631
 
 * %eax         *mode
1632
 
 */
1633
 
FUNCTION(grub_vbe_bios_get_mode)
1634
 
        pushl   %ebp
1635
 
        pushl   %ebx
1636
 
        pushl   %edi
1637
 
        pushl   %edx
1638
 
        pushl   %eax            /* Push *mode to stack.  */
1639
 
 
1640
 
        call    prot_to_real
1641
 
        .code16
1642
 
 
1643
 
        movw    $0x4f03, %ax
1644
 
        int     $0x10
1645
 
 
1646
 
        movw    %ax, %dx        /* real_to_prot destroys %eax.  */
1647
 
 
1648
 
        DATA32 call     real_to_prot
1649
 
        .code32
1650
 
 
1651
 
        popl    %edi            /* Pops *mode from stack to %edi.  */
1652
 
        andl    $0xFFFF, %ebx
1653
 
        movl    %ebx, (%edi)
1654
 
 
1655
 
        movw    %dx, %ax
1656
 
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
1657
 
 
1658
 
        popl    %edx
1659
 
        popl    %edi
1660
 
        popl    %ebx
1661
 
        popl    %ebp
1662
 
        ret
1663
 
 
1664
 
/*
1665
 
 * grub_vbe_status_t grub_vbe_bios_getset_dac_palette_width (int set, int *dac_mask_size)
1666
 
 *
1667
 
 * Register allocations for parameters:
1668
 
 * %eax         set
1669
 
 * %edx         *dac_mask_size
1670
 
 */
1671
 
FUNCTION(grub_vbe_bios_getset_dac_palette_width)
1672
 
        pushl   %ebp
1673
 
        pushl   %ebx
1674
 
 
1675
 
        xorl    %ebx, %ebx
1676
 
 
1677
 
        /* If we only want to fetch the value, set %bl to 1.  */
1678
 
        testl   %eax, %eax
1679
 
        jne     1f
1680
 
        incb    %bl
1681
 
1:
1682
 
 
1683
 
        /* Put desired width in %bh.  */
1684
 
        movl    (%edx), %eax
1685
 
        movb    %al, %bh
1686
 
 
1687
 
        call    prot_to_real
1688
 
        .code16
1689
 
 
1690
 
        movw    $0x4f08, %ax
1691
 
        int     $0x10
1692
 
 
1693
 
        movw    %ax, %cx        /* real_to_prot destroys %eax.  */
1694
 
 
1695
 
        DATA32 call     real_to_prot
1696
 
        .code32
1697
 
 
1698
 
        /* Move result back to *dac_mask_size.  */
1699
 
        xorl    %eax, %eax
1700
 
        movb    %bh, %al
1701
 
        movl    %eax, (%edx)
1702
 
 
1703
 
        /* Return value in %eax.  */
1704
 
        movw    %cx, %ax
1705
 
 
1706
 
        popl    %ebx
1707
 
        popl    %ebp
1708
 
        ret
1709
 
 
1710
 
/*
1711
 
 * grub_vbe_status_t grub_vbe_bios_set_memory_window (grub_uint32_t window,
1712
 
 *                                                    grub_uint32_t position);
1713
 
 *
1714
 
 * Register allocations for parameters:
1715
 
 * %eax         window
1716
 
 * %edx         position
1717
 
 */
1718
 
FUNCTION(grub_vbe_bios_set_memory_window)
1719
 
        pushl   %ebp
1720
 
        pushl   %ebx
1721
 
 
1722
 
        movl    %eax, %ebx
1723
 
 
1724
 
        call    prot_to_real
1725
 
        .code16
1726
 
 
1727
 
        movw    $0x4f05, %ax
1728
 
        andw    $0x00ff, %bx    /* BL = window, BH = 0, Set memory window.  */
1729
 
        int     $0x10
1730
 
 
1731
 
        movw    %ax, %dx        /* real_to_prot destroys %eax.  */
1732
 
 
1733
 
        DATA32 call     real_to_prot
1734
 
        .code32
1735
 
 
1736
 
        movw    %dx, %ax
1737
 
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
1738
 
 
1739
 
        popl    %ebx
1740
 
        popl    %ebp
1741
 
        ret
1742
 
 
1743
 
/*
1744
 
 * grub_vbe_status_t grub_vbe_bios_get_memory_window (grub_uint32_t window,
1745
 
 *                                                    grub_uint32_t *position);
1746
 
 *
1747
 
 * Register allocations for parameters:
1748
 
 * %eax         window
1749
 
 * %edx         *position
1750
 
 */
1751
 
FUNCTION(grub_vbe_bios_get_memory_window)
1752
 
        pushl   %ebp
1753
 
        pushl   %ebx
1754
 
        pushl   %edi
1755
 
        pushl   %edx            /* Push *position to stack.  */
1756
 
 
1757
 
        movl    %eax, %ebx      /* Store window in %ebx.  */
1758
 
 
1759
 
        call    prot_to_real
1760
 
        .code16
1761
 
 
1762
 
        movw    $0x4f05, %ax
1763
 
        andw    $0x00ff, %bx    /* BL = window.  */
1764
 
        orw     $0x0100, %bx    /* BH = 1, Get memory window.  */
1765
 
        int     $0x10
1766
 
 
1767
 
        movw    %ax, %bx        /* real_to_prot destroys %eax.  */
1768
 
 
1769
 
        DATA32 call     real_to_prot
1770
 
        .code32
1771
 
 
1772
 
        popl    %edi            /* pops *position from stack to %edi.  */
1773
 
        andl    $0xFFFF, %edx
1774
 
        movl    %edx, (%edi)    /* Return position to caller.  */
1775
 
 
1776
 
        movw    %bx, %ax
1777
 
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
1778
 
 
1779
 
        popl    %edi
1780
 
        popl    %ebx
1781
 
        popl    %ebp
1782
 
        ret
1783
 
 
1784
 
/*
1785
 
 * grub_vbe_status_t grub_vbe_bios_set_scanline_length (grub_uint32_t length)
1786
 
 *
1787
 
 * Register allocations for parameters:
1788
 
 * %eax         length
1789
 
 */
1790
 
FUNCTION(grub_vbe_bios_set_scanline_length)
1791
 
        pushl   %ebp
1792
 
        pushl   %ebx
1793
 
        pushl   %edx
1794
 
 
1795
 
        movl    %eax, %ecx      /* Store length in %ecx.  */
1796
 
 
1797
 
        call    prot_to_real
1798
 
        .code16
1799
 
 
1800
 
        movw    $0x4f06, %ax
1801
 
        movw    $0x0002, %bx    /* BL = 2, Set Scan Line in Bytes.  */
1802
 
        int     $0x10
1803
 
 
1804
 
        movw    %ax, %dx        /* real_to_prot destroys %eax.  */
1805
 
 
1806
 
        DATA32 call     real_to_prot
1807
 
        .code32
1808
 
 
1809
 
        movw    %dx, %ax
1810
 
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
1811
 
 
1812
 
        popl    %edx
1813
 
        popl    %ebx
1814
 
        popl    %ebp
1815
 
        ret
1816
 
 
1817
 
/*
1818
 
 * grub_vbe_status_t grub_vbe_bios_get_scanline_length (grub_uint32_t *length)
1819
 
 *
1820
 
 * Register allocations for parameters:
1821
 
 * %eax         *length
1822
 
 */
1823
 
FUNCTION(grub_vbe_bios_get_scanline_length)
1824
 
        pushl   %ebp
1825
 
        pushl   %ebx
1826
 
        pushl   %edi
1827
 
        pushl   %edx            /* Push *length to stack.  */
1828
 
 
1829
 
        call    prot_to_real
1830
 
        .code16
1831
 
 
1832
 
        movw    $0x4f06, %ax
1833
 
        movw    $0x0001, %bx    /* BL = 1, Get Scan Line Length (in bytes).  */
1834
 
        int     $0x10
1835
 
 
1836
 
        movw    %ax, %dx        /* real_to_prot destroys %eax.  */
1837
 
 
1838
 
        DATA32 call     real_to_prot
1839
 
        .code32
1840
 
 
1841
 
        popl    %edi            /* Pops *length from stack to %edi.  */
1842
 
        andl    $0xFFFF, %ebx
1843
 
        movl    %ebx, (%edi)    /* Return length to caller.  */
1844
 
 
1845
 
        movw    %dx, %ax
1846
 
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
1847
 
 
1848
 
        popl    %edi
1849
 
        popl    %ebx
1850
 
        popl    %ebp
1851
 
        ret
1852
 
 
1853
 
/*
1854
 
 * grub_vbe_status_t grub_vbe_bios_set_display_start (grub_uint32_t x,
1855
 
 *                                                    grub_uint32_t y)
1856
 
 *
1857
 
 * Register allocations for parameters:
1858
 
 * %eax         x
1859
 
 * %edx         y
1860
 
 */
1861
 
FUNCTION(grub_vbe_bios_set_display_start)
1862
 
        pushl   %ebp
1863
 
        pushl   %ebx
1864
 
 
1865
 
        movl    %eax, %ecx      /* Store x in %ecx.  */
1866
 
 
1867
 
        call    prot_to_real
1868
 
        .code16
1869
 
 
1870
 
        movw    $0x4f07, %ax
1871
 
        movw    $0x0080, %bx    /* BL = 80h, Set Display Start
1872
 
                                   during Vertical Retrace.  */
1873
 
        int     $0x10
1874
 
 
1875
 
        movw    %ax, %dx        /* real_to_prot destroys %eax.  */
1876
 
 
1877
 
        DATA32 call     real_to_prot
1878
 
        .code32
1879
 
 
1880
 
        movw    %dx, %ax
1881
 
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
1882
 
 
1883
 
        popl    %ebx
1884
 
        popl    %ebp
1885
 
        ret
1886
 
 
1887
 
/*
1888
 
 * grub_vbe_status_t grub_vbe_bios_get_display_start (grub_uint32_t *x,
1889
 
 *                                                    grub_uint32_t *y)
1890
 
 *
1891
 
 * Register allocations for parameters:
1892
 
 * %eax         *x
1893
 
 * %edx         *y
1894
 
 */
1895
 
FUNCTION(grub_vbe_bios_get_display_start)
1896
 
        pushl   %ebp
1897
 
        pushl   %ebx
1898
 
        pushl   %edi
1899
 
        pushl   %eax            /* Push *x to stack.  */
1900
 
        pushl   %edx            /* Push *y to stack.  */
1901
 
 
1902
 
        call    prot_to_real
1903
 
        .code16
1904
 
 
1905
 
        movw    $0x4f07, %ax
1906
 
        movw    $0x0001, %bx    /* BL = 1, Get Display Start.  */
1907
 
        int     $0x10
1908
 
 
1909
 
        movw    %ax, %bx        /* real_to_prot destroys %eax.  */
1910
 
 
1911
 
        DATA32 call     real_to_prot
1912
 
        .code32
1913
 
 
1914
 
        popl    %edi            /* Pops *y from stack to %edi.  */
1915
 
        andl    $0xFFFF, %edx
1916
 
        movl    %edx, (%edi)    /* Return y-position to caller.  */
1917
 
 
1918
 
        popl    %edi            /* Pops *x from stack to %edi.  */
1919
 
        andl    $0xFFFF, %ecx
1920
 
        movl    %ecx, (%edi)    /* Return x-position to caller.  */
1921
 
 
1922
 
        movw    %bx, %ax
1923
 
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
1924
 
 
1925
 
        popl    %edi
1926
 
        popl    %ebx
1927
 
        popl    %ebp
1928
 
        ret
1929
 
 
1930
 
/*
1931
 
 * grub_vbe_status_t grub_vbe_bios_set_palette_data (grub_uint32_t color_count,
1932
 
 *                                                   grub_uint32_t start_index,
1933
 
 *                                                   struct grub_vbe_palette_data *palette_data)
1934
 
 *
1935
 
 * Register allocations for parameters:
1936
 
 * %eax         color_count
1937
 
 * %edx         start_index
1938
 
 * %ecx         *palette_data
1939
 
 */
1940
 
FUNCTION(grub_vbe_bios_set_palette_data)
1941
 
        pushl   %ebp
1942
 
        pushl   %ebx
1943
 
        pushl   %edi
1944
 
 
1945
 
        movl    %eax, %ebx      /* Store color_count in %ebx.  */
1946
 
 
1947
 
        movw    %cx, %di        /* Store *palette_data to %ecx:%di.  */
1948
 
        xorw    %cx, %cx
1949
 
        shrl    $4, %ecx
1950
 
 
1951
 
        call    prot_to_real
1952
 
        .code16
1953
 
 
1954
 
        pushw   %es
1955
 
 
1956
 
        movw    %cx, %es        /* *palette_data is now on %es:%di.  */
1957
 
        movw    %bx, %cx        /* color_count is now on %cx.  */
1958
 
 
1959
 
        movw    $0x4f09, %ax
1960
 
        xorw    %bx, %bx        /* BL = 0, Set Palette Data.  */
1961
 
        int     $0x10
1962
 
 
1963
 
        movw    %ax, %dx        /* real_to_prot destroys %eax.  */
1964
 
 
1965
 
        popw    %es
1966
 
 
1967
 
        DATA32 call     real_to_prot
1968
 
        .code32
1969
 
 
1970
 
        movw    %dx, %ax
1971
 
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
1972
 
 
1973
 
        popl    %edi
1974
 
        popl    %ebx
1975
 
        popl    %ebp
1976
 
        ret
1977
 
 
1978
 
 
1979
 
pxe_rm_entry:
1980
 
        .long   0
1981
 
 
1982
 
/*
1983
 
 * struct grub_pxenv *grub_pxe_scan (void);
1984
 
 */
1985
 
FUNCTION(grub_pxe_scan)
1986
 
        pushl   %ebp
1987
 
        pushl   %ebx
1988
 
 
1989
 
        xorl    %ebx, %ebx
1990
 
        xorl    %ecx, %ecx
1991
 
 
1992
 
        call    prot_to_real
1993
 
        .code16
1994
 
 
1995
 
        pushw   %es
1996
 
 
1997
 
        movw    $0x5650, %ax
1998
 
        int     $0x1A
1999
 
        cmpw    $0x564E, %ax
2000
 
        jnz     1f
2001
 
        cmpl    $0x4E455850, %es:(%bx)          /* PXEN(V+)  */
2002
 
        jnz     1f
2003
 
        cmpw    $0x201, %es:6(%bx)              /* API version  */
2004
 
        jb      1f
2005
 
        lesw    %es:0x28(%bx), %bx              /* !PXE structure  */
2006
 
        cmpl    $0x45585021, %es:(%bx)          /* !PXE  */
2007
 
        jnz     1f
2008
 
        movw    %es, %cx
2009
 
        jmp     2f
2010
 
1:
2011
 
        xorw    %bx, %bx
2012
 
        xorw    %cx, %cx
2013
 
2:
2014
 
 
2015
 
        popw    %es
2016
 
 
2017
 
        DATA32 call     real_to_prot
2018
 
        .code32
2019
 
 
2020
 
        xorl    %eax, %eax
2021
 
        leal    (%eax, %ecx, 4), %ecx
2022
 
        leal    (%ebx, %ecx, 4), %eax           /* eax = ecx * 16 + ebx  */
2023
 
 
2024
 
        orl     %eax, %eax
2025
 
        jz      1f
2026
 
 
2027
 
        movl    0x10(%eax), %ecx
2028
 
        movl    %ecx, pxe_rm_entry
2029
 
 
2030
 
1:
2031
 
 
2032
 
        popl    %ebx
2033
 
        popl    %ebp
2034
 
        ret
2035
 
 
2036
 
/*
2037
 
 * int grub_pxe_call (int func, void* data);
2038
 
 */
2039
 
FUNCTION(grub_pxe_call)
2040
 
        pushl   %ebp
2041
 
        movl    %esp, %ebp
2042
 
        pushl   %esi
2043
 
        pushl   %edi
2044
 
        pushl   %ebx
2045
 
 
2046
 
        movl    %eax, %ecx
2047
 
        movl    %edx, %eax
2048
 
        andl    $0xF, %eax
2049
 
        shrl    $4, %edx
2050
 
        shll    $16, %edx
2051
 
        addl    %eax, %edx
2052
 
        movl    pxe_rm_entry, %ebx
2053
 
 
2054
 
        call    prot_to_real
2055
 
        .code16
2056
 
 
2057
 
        pushl   %ebx
2058
 
        pushl   %edx
2059
 
        pushw   %cx
2060
 
        movw    %sp, %bx
2061
 
        lcall   *%ss:6(%bx)
2062
 
        cld
2063
 
        addw    $10, %sp
2064
 
        movw    %ax, %cx
2065
 
 
2066
 
        DATA32  call    real_to_prot
2067
 
        .code32
2068
 
 
2069
 
        movzwl  %cx, %eax
2070
 
 
2071
 
        popl    %ebx
2072
 
        popl    %edi
2073
 
        popl    %esi
2074
 
        popl    %ebp
2075
 
        ret