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

« back to all changes in this revision

Viewing changes to grub-core/kern/i386/pc/startup.S

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Robert Millan, Updated translations
  • Date: 2010-11-22 12:24:56 UTC
  • mfrom: (1.26.4 upstream) (17.3.36 sid)
  • mto: (17.3.43 sid)
  • mto: This revision was merged to the branch mainline in revision 89.
  • Revision ID: james.westby@ubuntu.com-20101122122456-y82z3sfb7k4zfdcc
Tags: 1.99~20101122-1
[ Colin Watson ]
* New Bazaar snapshot.  Too many changes to list in full, but some of the
  more user-visible ones are as follows:
  - GRUB script:
    + Function parameters, "break", "continue", "shift", "setparams",
      "return", and "!".
    + "export" command supports multiple variable names.
    + Multi-line quoted strings support.
    + Wildcard expansion.
  - sendkey support.
  - USB hotunplugging and USB serial support.
  - Rename CD-ROM to cd on BIOS.
  - Add new --boot-directory option to grub-install, grub-reboot, and
    grub-set-default; the old --root-directory option is still accepted
    but was often confusing.
  - Basic btrfs detection/UUID support (but no file reading yet).
  - bash-completion for utilities.
  - If a device is listed in device.map, always assume that it is
    BIOS-visible rather than using extra layers such as LVM or RAID.
  - Add grub-mknetdir script (closes: #550658).
  - Remove deprecated "root" command.
  - Handle RAID devices containing virtio components.
  - GRUB Legacy configuration file support (via grub-menulst2cfg).
  - Keyboard layout support (via grub-mklayout and grub-kbdcomp).
  - Check generated grub.cfg for syntax errors before saving.
  - Pause execution for at most ten seconds if any errors are displayed,
    so that the user has a chance to see them.
  - Support submenus.
  - Write embedding zone using Reed-Solomon, so that it's robust against
    being partially overwritten (closes: #550702, #591416, #593347).
  - GRUB_DISABLE_LINUX_RECOVERY and GRUB_DISABLE_NETBSD_RECOVERY merged
    into a single GRUB_DISABLE_RECOVERY variable.
  - Fix loader memory allocation failure (closes: #551627).
  - Don't call savedefault on recovery entries (closes: #589325).
  - Support triple-indirect blocks on ext2 (closes: #543924).
  - Recognise DDF1 fake RAID (closes: #603354).

[ Robert Millan ]
* Use dpkg architecture wildcards.

[ Updated translations ]
* Slovenian (Vanja Cvelbar).  Closes: #604003
* Dzongkha (dawa pemo via Tenzin Dendup).  Closes: #604102

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
reed_solomon_redundancy:
 
104
        .long   0
 
105
 
 
106
#ifdef APPLE_CC
 
107
bss_start:
 
108
        .long 0
 
109
bss_end:
 
110
        .long 0
 
111
#endif
 
112
/*
 
113
 *  This is the area for all of the special variables.
 
114
 */
 
115
 
 
116
VARIABLE(grub_boot_drive)
 
117
        .byte   0
 
118
 
 
119
/* the real mode code continues... */
 
120
LOCAL (codestart):
 
121
        cli             /* we're not safe here! */
 
122
 
 
123
        /* set up %ds, %ss, and %es */
 
124
        xorw    %ax, %ax
 
125
        movw    %ax, %ds
 
126
        movw    %ax, %ss
 
127
        movw    %ax, %es
 
128
 
 
129
        /* set up the real mode/BIOS stack */
 
130
        movl    $GRUB_MEMORY_MACHINE_REAL_STACK, %ebp
 
131
        movl    %ebp, %esp
 
132
 
 
133
        sti             /* we're safe again */
 
134
 
 
135
        /* save the boot drive */
 
136
        ADDR32  movb    %dl, EXT_C(grub_boot_drive)
 
137
 
 
138
        /* reset disk system (%ah = 0) */
 
139
        int     $0x13
 
140
 
 
141
        /* transition to protected mode */
 
142
        DATA32  call real_to_prot
 
143
 
 
144
        /* The ".code32" directive takes GAS out of 16-bit mode. */
 
145
        .code32
 
146
 
 
147
        incl    %eax
 
148
        call    grub_gate_a20
 
149
 
 
150
        movl    EXT_C(grub_compressed_size), %edx
 
151
        addl    $(GRUB_KERNEL_MACHINE_RAW_SIZE - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART), %edx
 
152
        movl    reed_solomon_redundancy, %ecx
 
153
        leal    _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART, %eax
 
154
        testl   %edx, %edx
 
155
        jz post_reed_solomon
 
156
        call    EXT_C (grub_reed_solomon_recover)
 
157
        jmp post_reed_solomon
 
158
 
 
159
#include <rs_decoder.S>
 
160
 
 
161
        .text
 
162
 
 
163
        . = _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART
 
164
/*
 
165
 * Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself).
 
166
 * This uses the a.out kludge to load raw binary to the area starting at 1MB,
 
167
 * and relocates itself after loaded.
 
168
 */
 
169
        .p2align        2       /* force 4-byte alignment */
 
170
multiboot_header:
 
171
        /* magic */
 
172
        .long   0x1BADB002
 
173
        /* flags */
 
174
        .long   (1 << 16)
 
175
        /* checksum */
 
176
        .long   -0x1BADB002 - (1 << 16)
 
177
        /* header addr */
 
178
        .long   multiboot_header - _start + 0x100000 + 0x200
 
179
        /* load addr */
 
180
        .long   0x100000
 
181
        /* load end addr */
 
182
        .long   0
 
183
        /* bss end addr */
 
184
        .long   0
 
185
        /* entry addr */
 
186
        .long   multiboot_entry - _start + 0x100000 + 0x200
 
187
 
 
188
multiboot_entry:
 
189
        .code32
 
190
        /* obtain the boot device */
 
191
        movl    12(%ebx), %edx
 
192
 
 
193
        movl    $GRUB_MEMORY_MACHINE_PROT_STACK, %ebp
 
194
        movl    %ebp, %esp
 
195
 
 
196
        /* relocate the code */
 
197
        movl    $(GRUB_KERNEL_MACHINE_RAW_SIZE + 0x200), %ecx
 
198
        addl    EXT_C(grub_compressed_size) - _start + 0x100000 + 0x200, %ecx
 
199
        movl    $0x100000, %esi
 
200
        movl    $GRUB_BOOT_MACHINE_KERNEL_ADDR, %edi
 
201
        cld
 
202
        rep
 
203
        movsb
 
204
        /* jump to the real address */
 
205
        movl    $multiboot_trampoline, %eax
 
206
        jmp     *%eax
 
207
 
 
208
multiboot_trampoline:
 
209
        /* fill the boot information */
 
210
        movl    %edx, %eax
 
211
        shrl    $8, %eax
 
212
        xorl    %ebx, %ebx
 
213
        cmpb    $0xFF, %ah
 
214
        je      1f
 
215
        movb    %ah, %bl
 
216
        movl    %ebx, EXT_C(grub_install_dos_part)
 
217
1:
 
218
        cmpb    $0xFF, %al
 
219
        je      2f
 
220
        movb    %al, %bl
 
221
        movl    %ebx, EXT_C(grub_install_bsd_part)
 
222
2:
 
223
        shrl    $24, %edx
 
224
        movb    $0xFF, %dh
 
225
        /* enter the usual booting */
 
226
        call    prot_to_real
 
227
        jmp     LOCAL (codestart)
 
228
 
 
229
post_reed_solomon:
 
230
 
 
231
#ifdef ENABLE_LZMA
 
232
        movl    $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi
 
233
        movl    $(_start + GRUB_KERNEL_MACHINE_RAW_SIZE), %esi
 
234
        pushl   %edi
 
235
        pushl   %esi
 
236
        movl    EXT_C(grub_kernel_image_size), %ecx
 
237
        addl    EXT_C(grub_total_module_size), %ecx
 
238
        subl    $GRUB_KERNEL_MACHINE_RAW_SIZE, %ecx
 
239
        pushl   %ecx
 
240
        leal    (%edi, %ecx), %ebx
 
241
        call    _LzmaDecodeA
 
242
        /* _LzmaDecodeA clears DF, so no need to run cld */
 
243
        popl    %ecx
 
244
        popl    %edi
 
245
        popl    %esi
 
246
#endif
 
247
 
 
248
        /* copy back the decompressed part (except the modules) */
 
249
        subl    EXT_C(grub_total_module_size), %ecx
 
250
        rep
 
251
        movsb
 
252
 
 
253
#if 0
 
254
        /* copy modules before cleaning out the bss */
 
255
        movl    EXT_C(grub_total_module_size), %ecx
 
256
        movl    EXT_C(grub_kernel_image_size), %esi
 
257
        addl    %ecx, %esi
 
258
        addl    $_start, %esi
 
259
        decl    %esi
 
260
        movl    $END_SYMBOL, %edi
 
261
        addl    %ecx, %edi
 
262
        decl    %edi
 
263
        std
 
264
        rep
 
265
        movsb
 
266
#endif
 
267
 
 
268
#ifdef APPLE_CC
 
269
        /* clean out the bss */
 
270
        bss_start_abs = ABS (bss_start)
 
271
        bss_end_abs = ABS (bss_end)
 
272
 
 
273
        movl    bss_start_abs, %edi
 
274
 
 
275
        /* compute the bss length */
 
276
        movl    bss_end_abs, %ecx
 
277
        subl    %edi, %ecx
 
278
#else
 
279
        /* clean out the bss */
 
280
        movl    $BSS_START_SYMBOL, %edi
 
281
 
 
282
        /* compute the bss length */
 
283
        movl    $END_SYMBOL, %ecx
 
284
        subl    %edi, %ecx
 
285
#endif
 
286
 
 
287
        /* clean out */
 
288
        xorl    %eax, %eax
 
289
        cld
 
290
        rep
 
291
        stosb
 
292
 
 
293
        /*
 
294
         *  Call the start of main body of C code.
 
295
         */
 
296
        call EXT_C(grub_main)
 
297
 
 
298
#include "../realmode.S"
 
299
 
 
300
/*
 
301
 * grub_gate_a20(int on)
 
302
 *
 
303
 * Gate address-line 20 for high memory.
 
304
 *
 
305
 * This routine is probably overconservative in what it does, but so what?
 
306
 *
 
307
 * It also eats any keystrokes in the keyboard buffer.  :-(
 
308
 */
 
309
 
 
310
grub_gate_a20:  
 
311
        movl    %eax, %edx
 
312
 
 
313
gate_a20_test_current_state:
 
314
        /* first of all, test if already in a good state */
 
315
        call    gate_a20_check_state
 
316
        cmpb    %al, %dl
 
317
        jnz     gate_a20_try_bios
 
318
        ret
 
319
 
 
320
gate_a20_try_bios:
 
321
        /* second, try a BIOS call */
 
322
        pushl   %ebp
 
323
        call    prot_to_real
 
324
 
 
325
        .code16
 
326
        movw    $0x2400, %ax
 
327
        testb   %dl, %dl
 
328
        jz      1f
 
329
        incw    %ax
 
330
1:      int     $0x15
 
331
 
 
332
        DATA32  call    real_to_prot
 
333
        .code32
 
334
 
 
335
        popl    %ebp
 
336
        call    gate_a20_check_state
 
337
        cmpb    %al, %dl
 
338
        jnz     gate_a20_try_system_control_port_a
 
339
        ret
 
340
 
 
341
gate_a20_try_system_control_port_a:
 
342
        /*
 
343
         * In macbook, the keyboard test would hang the machine, so we move
 
344
         * this forward.
 
345
         */
 
346
        /* fourth, try the system control port A */
 
347
        inb     $0x92
 
348
        andb    $(~0x03), %al
 
349
        testb   %dl, %dl
 
350
        jz      6f
 
351
        orb     $0x02, %al
 
352
6:      outb    $0x92
 
353
 
 
354
        /* When turning off Gate A20, do not check the state strictly,
 
355
           because a failure is not fatal usually, and Gate A20 is always
 
356
           on some modern machines.  */
 
357
        testb   %dl, %dl
 
358
        jz      7f
 
359
        call    gate_a20_check_state
 
360
        cmpb    %al, %dl
 
361
        jnz     gate_a20_try_keyboard_controller
 
362
7:      ret
 
363
 
 
364
gate_a20_flush_keyboard_buffer:
 
365
        inb     $0x64
 
366
        andb    $0x02, %al
 
367
        jnz     gate_a20_flush_keyboard_buffer
 
368
2:
 
369
        inb     $0x64
 
370
        andb    $0x01, %al
 
371
        jz      3f
 
372
        inb     $0x60
 
373
        jmp     2b
 
374
3:
 
375
        ret
 
376
 
 
377
gate_a20_try_keyboard_controller:
 
378
        /* third, try the keyboard controller */
 
379
        call    gate_a20_flush_keyboard_buffer
 
380
 
 
381
        movb    $0xd1, %al
 
382
        outb    $0x64
 
383
4:
 
384
        inb     $0x64
 
385
        andb    $0x02, %al
 
386
        jnz     4b
 
387
 
 
388
        movb    $0xdd, %al
 
389
        testb   %dl, %dl
 
390
        jz      5f
 
391
        orb     $0x02, %al
 
392
5:      outb    $0x60
 
393
        call    gate_a20_flush_keyboard_buffer
 
394
 
 
395
        /* output a dummy command (USB keyboard hack) */
 
396
        movb    $0xff, %al
 
397
        outb    $0x64
 
398
        call    gate_a20_flush_keyboard_buffer
 
399
 
 
400
        call    gate_a20_check_state
 
401
        cmpb    %al, %dl
 
402
        /* everything failed, so restart from the beginning */
 
403
        jnz     gate_a20_try_bios
 
404
        ret
 
405
 
 
406
gate_a20_check_state:
 
407
        /* iterate the checking for a while */
 
408
        movl    $100, %ecx
 
409
1:
 
410
        call    3f
 
411
        cmpb    %al, %dl
 
412
        jz      2f
 
413
        loop    1b
 
414
2:
 
415
        ret
 
416
3:
 
417
        pushl   %ebx
 
418
        pushl   %ecx
 
419
        xorl    %eax, %eax
 
420
        /* compare the byte at 0x8000 with that at 0x108000 */
 
421
        movl    $GRUB_BOOT_MACHINE_KERNEL_ADDR, %ebx
 
422
        pushl   %ebx
 
423
        /* save the original byte in CL */
 
424
        movb    (%ebx), %cl
 
425
        /* store the value at 0x108000 in AL */
 
426
        addl    $0x100000, %ebx
 
427
        movb    (%ebx), %al
 
428
        /* try to set one less value at 0x8000 */
 
429
        popl    %ebx
 
430
        movb    %al, %ch
 
431
        decb    %ch
 
432
        movb    %ch, (%ebx)
 
433
        /* serialize */
 
434
        outb    %al, $0x80
 
435
        outb    %al, $0x80
 
436
        /* obtain the value at 0x108000 in CH */
 
437
        pushl   %ebx
 
438
        addl    $0x100000, %ebx
 
439
        movb    (%ebx), %ch
 
440
        /* this result is 1 if A20 is on or 0 if it is off */
 
441
        subb    %ch, %al
 
442
        xorb    $1, %al
 
443
        /* restore the original */
 
444
        popl    %ebx
 
445
        movb    %cl, (%ebx)
 
446
        popl    %ecx
 
447
        popl    %ebx
 
448
        ret
 
449
 
 
450
#ifdef ENABLE_LZMA
 
451
#include "lzma_decode.S"
 
452
#endif
 
453
 
 
454
/*
 
455
 * The code beyond this point is compressed.  Assert that the uncompressed
 
456
 * code fits GRUB_KERNEL_MACHINE_RAW_SIZE.
 
457
 */
 
458
        . = _start + GRUB_KERNEL_MACHINE_RAW_SIZE
 
459
 
 
460
        . = _start + GRUB_KERNEL_MACHINE_PREFIX
 
461
VARIABLE(grub_prefix)
 
462
        /* to be filled by grub-mkimage */
 
463
 
 
464
        /*
 
465
         *  Leave some breathing room for the prefix.
 
466
         */
 
467
        . = _start + GRUB_KERNEL_MACHINE_PREFIX_END
 
468
 
 
469
 
 
470
 
 
471
/*
 
472
 * grub_exit()
 
473
 *
 
474
 * Exit the system.
 
475
 */
 
476
FUNCTION(grub_exit)
 
477
        call    prot_to_real
 
478
        .code16
 
479
        /* Tell the BIOS a boot failure. If this does not work, reboot.  */
 
480
        int     $0x18
 
481
        jmp     cold_reboot
 
482
        .code32
 
483
 
 
484
/*
 
485
 *  void grub_chainloader_real_boot (int drive, void *part_addr)
 
486
 *
 
487
 *  This starts another boot loader.
 
488
 */
 
489
 
 
490
FUNCTION(grub_chainloader_real_boot)
 
491
        pushl   %edx
 
492
        pushl   %eax
 
493
 
 
494
        /* Turn off Gate A20 */
 
495
        xorl    %eax, %eax
 
496
        call    grub_gate_a20
 
497
 
 
498
        /* set up to pass boot drive */
 
499
        popl    %edx
 
500
 
 
501
        /* ESI must point to a partition table entry */
 
502
        popl    %esi
 
503
 
 
504
        call    prot_to_real
 
505
        .code16
 
506
        ljmp    $0, $GRUB_MEMORY_MACHINE_BOOT_LOADER_ADDR
 
507
        .code32
 
508
 
 
509
/*
 
510
 * void grub_console_putchar (int c)
 
511
 *
 
512
 * Put the character C on the console. Because GRUB wants to write a
 
513
 * character with an attribute, this implementation is a bit tricky.
 
514
 * If C is a control character (CR, LF, BEL, BS), use INT 10, AH = 0Eh
 
515
 * (TELETYPE OUTPUT). Otherwise, save the original position, put a space,
 
516
 * save the current position, restore the original position, write the
 
517
 * character and the attribute, and restore the current position.
 
518
 *
 
519
 * The reason why this is so complicated is that there is no easy way to
 
520
 * get the height of the screen, and the TELETYPE OUTPUT BIOS call doesn't
 
521
 * support setting a background attribute.
 
522
 */
 
523
FUNCTION(grub_console_putchar)
 
524
        /* Retrieve the base character.  */
 
525
        movl    0(%edx), %edx
 
526
        pusha
 
527
        movb    EXT_C(grub_console_cur_color), %bl
 
528
 
 
529
        call    prot_to_real
 
530
        .code16
 
531
        movb    %dl, %al
 
532
        xorb    %bh, %bh
 
533
 
 
534
        /* use teletype output if control character */
 
535
        cmpb    $0x7, %al
 
536
        je      1f
 
537
        cmpb    $0x8, %al
 
538
        je      1f
 
539
        cmpb    $0xa, %al
 
540
        je      1f
 
541
        cmpb    $0xd, %al
 
542
        je      1f
 
543
 
 
544
        /* save the character and the attribute on the stack */
 
545
        pushw   %ax
 
546
        pushw   %bx
 
547
 
 
548
        /* get the current position */
 
549
        movb    $0x3, %ah
 
550
        int     $0x10
 
551
 
 
552
        /* check the column with the width */
 
553
        cmpb    $79, %dl
 
554
        jl      2f
 
555
 
 
556
        /* print CR and LF, if next write will exceed the width */
 
557
        movw    $0x0e0d, %ax
 
558
        int     $0x10
 
559
        movb    $0x0a, %al
 
560
        int     $0x10
 
561
 
 
562
        /* get the current position */
 
563
        movb    $0x3, %ah
 
564
        int     $0x10
 
565
 
 
566
2:
 
567
        /* restore the character and the attribute */
 
568
        popw    %bx
 
569
        popw    %ax
 
570
 
 
571
        /* write the character with the attribute */
 
572
        movb    $0x9, %ah
 
573
        movw    $1, %cx
 
574
        int     $0x10
 
575
 
 
576
        /* move the cursor forward */
 
577
        incb    %dl
 
578
        movb    $0x2, %ah
 
579
        int     $0x10
 
580
 
 
581
        jmp     3f
 
582
 
 
583
1:      movw    $1, %bx
 
584
        movb    $0xe, %ah
 
585
        int     $0x10
 
586
 
 
587
3:      DATA32  call    real_to_prot
 
588
        .code32
 
589
 
 
590
        popa
 
591
        ret
 
592
 
 
593
 
 
594
LOCAL(bypass_table):
 
595
        .word 0x011b, 0x0f00 | '\t', 0x0e00 | '\b', 0x1c00 | '\r'
 
596
        .word 0x1c00 | '\n'
 
597
LOCAL(bypass_table_end):
 
598
 
 
599
/*
 
600
 * int grub_console_getkey (void)
 
601
 *      if there is a character pending, return it; otherwise return -1
 
602
 * BIOS call "INT 16H Function 01H" to check whether a character is pending
 
603
 *      Call with       %ah = 0x1
 
604
 *      Return:
 
605
 *              If key waiting to be input:
 
606
 *                      %ah = keyboard scan code
 
607
 *                      %al = ASCII character
 
608
 *                      Zero flag = clear
 
609
 *              else
 
610
 *                      Zero flag = set
 
611
 * BIOS call "INT 16H Function 00H" to read character from keyboard
 
612
 *      Call with       %ah = 0x0
 
613
 *      Return:         %ah = keyboard scan code
 
614
 *                      %al = ASCII character
 
615
 */
 
616
 
 
617
FUNCTION(grub_console_getkey)
 
618
        pushl   %ebp
 
619
        pushl   %edi
 
620
 
 
621
        call    prot_to_real
 
622
        .code16
 
623
 
 
624
        /*
 
625
         * Due to a bug in apple's bootcamp implementation, INT 16/AH = 0 would
 
626
         * cause the machine to hang at the second keystroke. However, we can
 
627
         * work around this problem by ensuring the presence of keystroke with
 
628
         * INT 16/AH = 1 before calling INT 16/AH = 0.
 
629
         */
 
630
 
 
631
        movb    $1, %ah
 
632
        int     $0x16
 
633
        jz      notpending
 
634
 
 
635
        movb    $0, %ah
 
636
        int     $0x16
 
637
 
 
638
        xorl    %edx, %edx
 
639
        movw    %ax, %dx                /* real_to_prot uses %eax */
 
640
 
 
641
        DATA32  call    real_to_prot
 
642
        .code32
 
643
 
 
644
        movl    $0xff, %eax
 
645
        testl   %eax, %edx
 
646
        jz      1f
 
647
 
 
648
        andl    %edx, %eax
 
649
        cmpl    $0x20, %eax
 
650
        jae     2f
 
651
        movl    %edx, %eax
 
652
        leal    LOCAL(bypass_table), %edi
 
653
        movl    $((LOCAL(bypass_table_end) - LOCAL(bypass_table)) / 2), %ecx
 
654
        repne scasw 
 
655
        jz      3f
 
656
 
 
657
        andl    $0xff, %eax
 
658
        addl    $(('a' - 1) | GRUB_TERM_CTRL), %eax
 
659
        jmp     2f
 
660
3:
 
661
        andl    $0xff, %eax
 
662
        jmp 2f
 
663
 
 
664
1:      movl    %edx, %eax
 
665
        shrl    $8, %eax
 
666
        orl     $GRUB_TERM_EXTENDED, %eax
 
667
2:
 
668
        popl    %edi
 
669
        popl    %ebp
 
670
        ret
 
671
 
 
672
notpending:     
 
673
        .code16
 
674
        DATA32  call    real_to_prot
 
675
        .code32
 
676
#if GRUB_TERM_NO_KEY != 0
 
677
#error Fix this asm code
 
678
#endif
 
679
        jmp 2b
 
680
 
 
681
 
 
682
/*
 
683
 * grub_uint16_t grub_console_getxy (void)
 
684
 * BIOS call "INT 10H Function 03h" to get cursor position
 
685
 *      Call with       %ah = 0x03
 
686
 *                      %bh = page
 
687
 *      Returns         %ch = starting scan line
 
688
 *                      %cl = ending scan line
 
689
 *                      %dh = row (0 is top)
 
690
 *                      %dl = column (0 is left)
 
691
 */
 
692
 
 
693
 
 
694
FUNCTION(grub_console_getxy)
 
695
        pushl   %ebp
 
696
        pushl   %ebx                    /* save EBX */
 
697
 
 
698
        call    prot_to_real
 
699
        .code16
 
700
 
 
701
        xorb    %bh, %bh                /* set page to 0 */
 
702
        movb    $0x3, %ah
 
703
        int     $0x10                   /* get cursor position */
 
704
 
 
705
        DATA32  call    real_to_prot
 
706
        .code32
 
707
 
 
708
        movb    %dl, %ah
 
709
        movb    %dh, %al
 
710
 
 
711
        popl    %ebx
 
712
        popl    %ebp
 
713
        ret
 
714
 
 
715
 
 
716
/*
 
717
 * void grub_console_gotoxy(grub_uint8_t x, grub_uint8_t y)
 
718
 * BIOS call "INT 10H Function 02h" to set cursor position
 
719
 *      Call with       %ah = 0x02
 
720
 *                      %bh = page
 
721
 *                      %dh = row (0 is top)
 
722
 *                      %dl = column (0 is left)
 
723
 */
 
724
 
 
725
 
 
726
FUNCTION(grub_console_gotoxy)
 
727
        pushl   %ebp
 
728
        pushl   %ebx                    /* save EBX */
 
729
 
 
730
        movb    %cl, %dh        /* %dh = y */
 
731
        /* %dl = x */
 
732
 
 
733
        call    prot_to_real
 
734
        .code16
 
735
 
 
736
        xorb    %bh, %bh                /* set page to 0 */
 
737
        movb    $0x2, %ah
 
738
        int     $0x10                   /* set cursor position */
 
739
 
 
740
        DATA32  call    real_to_prot
 
741
        .code32
 
742
 
 
743
        popl    %ebx
 
744
        popl    %ebp
 
745
        ret
 
746
 
 
747
 
 
748
/*
 
749
 * void grub_console_cls (void)
 
750
 * BIOS call "INT 10H Function 09h" to write character and attribute
 
751
 *      Call with       %ah = 0x09
 
752
 *                      %al = (character)
 
753
 *                      %bh = (page number)
 
754
 *                      %bl = (attribute)
 
755
 *                      %cx = (number of times)
 
756
 */
 
757
 
 
758
FUNCTION(grub_console_cls)
 
759
        pushl   %ebp
 
760
        pushl   %ebx                    /* save EBX */
 
761
 
 
762
        call    prot_to_real
 
763
        .code16
 
764
 
 
765
        /* move the cursor to the beginning */
 
766
        movb    $0x02, %ah
 
767
        xorb    %bh, %bh
 
768
        xorw    %dx, %dx
 
769
        int     $0x10
 
770
 
 
771
        /* write spaces to the entire screen */
 
772
        movw    $0x0920, %ax
 
773
        movw    $0x07, %bx
 
774
        movw    $(80 * 25), %cx
 
775
        int     $0x10
 
776
 
 
777
        /* move back the cursor */
 
778
        movb    $0x02, %ah
 
779
        int     $0x10
 
780
 
 
781
        DATA32  call    real_to_prot
 
782
        .code32
 
783
 
 
784
        popl    %ebx
 
785
        popl    %ebp
 
786
        ret
 
787
 
 
788
 
 
789
/*
 
790
 * void grub_console_setcursor (int on)
 
791
 * BIOS call "INT 10H Function 01h" to set cursor type
 
792
 *      Call with       %ah = 0x01
 
793
 *                      %ch = cursor starting scanline
 
794
 *                      %cl = cursor ending scanline
 
795
 */
 
796
 
 
797
console_cursor_state:
 
798
        .byte   1
 
799
console_cursor_shape:
 
800
        .word   0
 
801
 
 
802
FUNCTION(grub_console_setcursor)
 
803
        pushl   %ebp
 
804
        pushl   %ebx
 
805
 
 
806
        /* push ON */
 
807
        pushl   %edx
 
808
 
 
809
        /* check if the standard cursor shape has already been saved */
 
810
        movw    console_cursor_shape, %ax
 
811
        testw   %ax, %ax
 
812
        jne     1f
 
813
 
 
814
        call    prot_to_real
 
815
        .code16
 
816
 
 
817
        movb    $0x03, %ah
 
818
        xorb    %bh, %bh
 
819
        int     $0x10
 
820
 
 
821
        DATA32  call    real_to_prot
 
822
        .code32
 
823
 
 
824
        cmp     %cl, %ch
 
825
        jb      3f
 
826
        movw    $0x0d0e, %cx
 
827
3:      
 
828
        movw    %cx, console_cursor_shape
 
829
1:
 
830
        /* set %cx to the designated cursor shape */
 
831
        movw    $0x2000, %cx
 
832
        popl    %eax
 
833
        testl   %eax, %eax
 
834
        jz      2f
 
835
        movw    console_cursor_shape, %cx
 
836
2:
 
837
        call    prot_to_real
 
838
        .code16
 
839
 
 
840
        movb    $0x1, %ah
 
841
        int     $0x10
 
842
 
 
843
        DATA32  call    real_to_prot
 
844
        .code32
 
845
 
 
846
        popl    %ebx
 
847
        popl    %ebp
 
848
        ret
 
849
 
 
850
/*
 
851
 * grub_get_rtc()
 
852
 *      return the real time in ticks, of which there are about
 
853
 *      18-20 per second
 
854
 */
 
855
FUNCTION(grub_get_rtc)
 
856
        pushl   %ebp
 
857
 
 
858
        call    prot_to_real    /* enter real mode */
 
859
        .code16
 
860
 
 
861
        /* %ax is already zero */
 
862
        int     $0x1a
 
863
 
 
864
        DATA32  call    real_to_prot
 
865
        .code32
 
866
 
 
867
        movl    %ecx, %eax
 
868
        shll    $16, %eax
 
869
        movw    %dx, %ax
 
870
 
 
871
        popl    %ebp
 
872
        ret
 
873
 
 
874
/*
 
875
 * int grub_pxe_call (int func, void* data, grub_uint32_t pxe_rm_entry);
 
876
 */
 
877
FUNCTION(grub_pxe_call)
 
878
        pushl   %ebp
 
879
        movl    %esp, %ebp
 
880
        pushl   %esi
 
881
        pushl   %edi
 
882
        pushl   %ebx
 
883
 
 
884
        movl    %ecx, %ebx
 
885
        movl    %eax, %ecx
 
886
        movl    %edx, %eax
 
887
        andl    $0xF, %eax
 
888
        shrl    $4, %edx
 
889
        shll    $16, %edx
 
890
        addl    %eax, %edx
 
891
 
 
892
        call    prot_to_real
 
893
        .code16
 
894
 
 
895
        pushl   %ebx
 
896
        pushl   %edx
 
897
        pushw   %cx
 
898
        movw    %sp, %bx
 
899
        lcall   *%ss:6(%bx)
 
900
        cld
 
901
        addw    $10, %sp
 
902
        movw    %ax, %cx
 
903
 
 
904
        DATA32  call    real_to_prot
 
905
        .code32
 
906
 
 
907
        movzwl  %cx, %eax
 
908
 
 
909
        popl    %ebx
 
910
        popl    %edi
 
911
        popl    %esi
 
912
        popl    %ebp
 
913
        ret
 
914
 
 
915
FUNCTION(grub_bios_interrupt)
 
916
        pushl    %ebp
 
917
        pushl    %ecx
 
918
        pushl    %eax
 
919
        pushl    %ebx
 
920
        pushl    %esi
 
921
        pushl    %edi   
 
922
        pushl    %edx
 
923
        
 
924
        movb     %al, intno
 
925
        movl     (%edx), %eax
 
926
        movl     %eax, LOCAL(bios_register_eax)
 
927
        movw     4(%edx), %ax
 
928
        movw     %ax, LOCAL(bios_register_es)
 
929
        movw     6(%edx), %ax
 
930
        movw     %ax, LOCAL(bios_register_ds)
 
931
        movw     8(%edx), %ax
 
932
        movw     %ax, LOCAL(bios_register_flags)
 
933
 
 
934
        movl    12(%edx), %ebx
 
935
        movl    16(%edx), %ecx
 
936
        movl    20(%edx), %edi
 
937
        movl    24(%edx), %esi
 
938
        movl    28(%edx), %edx
 
939
 
 
940
        call    prot_to_real
 
941
        .code16
 
942
 
 
943
        mov     %ds, %ax
 
944
        push    %ax
 
945
 
 
946
        /* movw imm16, %ax*/
 
947
        .byte   0xb8
 
948
LOCAL(bios_register_es):
 
949
        .short  0
 
950
        movw    %ax, %es
 
951
        /* movw imm16, %ax*/
 
952
        .byte   0xb8
 
953
LOCAL(bios_register_ds):
 
954
        .short  0
 
955
        movw    %ax, %ds
 
956
 
 
957
        /* movw imm16, %ax*/
 
958
        .byte   0xb8
 
959
LOCAL(bios_register_flags):
 
960
        .short  0
 
961
        push    %ax
 
962
        popf
 
963
 
 
964
        /* movl imm32, %eax*/
 
965
        .byte   0x66, 0xb8
 
966
LOCAL(bios_register_eax):
 
967
        .long   0
 
968
        
 
969
        /* int imm8.  */
 
970
        .byte   0xcd
 
971
intno:  
 
972
        .byte   0
 
973
 
 
974
        movl    %eax, %cs:LOCAL(bios_register_eax)
 
975
        movw    %ds, %ax
 
976
        movw    %ax, %cs:LOCAL(bios_register_ds)
 
977
        pop     %ax
 
978
        mov     %ax, %ds
 
979
        pushf
 
980
        pop     %ax
 
981
        movw    %ax, LOCAL(bios_register_flags)
 
982
        mov     %es, %ax
 
983
        movw    %ax, LOCAL(bios_register_es)
 
984
 
 
985
        DATA32  call    real_to_prot
 
986
        .code32
 
987
 
 
988
        popl    %eax
 
989
 
 
990
        movl    %ebx, 12(%eax)
 
991
        movl    %ecx, 16(%eax)
 
992
        movl    %edi, 20(%eax)
 
993
        movl    %esi, 24(%eax)
 
994
        movl    %edx, 28(%eax)
 
995
 
 
996
        movl     %eax, %edx
 
997
 
 
998
        movl     LOCAL(bios_register_eax), %eax
 
999
        movl     %eax, (%edx)
 
1000
        movw     LOCAL(bios_register_es), %ax
 
1001
        movw     %ax, 4(%edx)
 
1002
        movw     LOCAL(bios_register_ds), %ax
 
1003
        movw     %ax, 6(%edx)
 
1004
        movw     LOCAL(bios_register_flags), %ax
 
1005
        movw     %ax, 8(%edx)
 
1006
 
 
1007
        popl    %edi
 
1008
        popl    %esi
 
1009
        popl    %ebx
 
1010
        popl    %eax
 
1011
        popl    %ecx
 
1012
        popl    %ebp
 
1013
        ret