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

« back to all changes in this revision

Viewing changes to boot/i386/pc/boot.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
 
/* -*-Asm-*- */
2
 
/*
3
 
 *  GRUB  --  GRand Unified Bootloader
4
 
 *  Copyright (C) 1999,2000,2001,2002,2005,2006,2007,2008,2009  Free Software Foundation, Inc.
5
 
 *
6
 
 *  GRUB is free software: you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation, either version 3 of the License, or
9
 
 *  (at your option) any later version.
10
 
 *
11
 
 *  GRUB is distributed in the hope that it will be useful,
12
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 *  GNU General Public License for more details.
15
 
 *
16
 
 *  You should have received a copy of the GNU General Public License
17
 
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
18
 
 */
19
 
 
20
 
#include <grub/symbol.h>
21
 
#include <grub/boot.h>
22
 
#include <grub/machine/boot.h>
23
 
 
24
 
/*
25
 
 *  defines for the code go here
26
 
 */
27
 
 
28
 
        /* Print message string */
29
 
#define MSG(x)  movw $x, %si; call LOCAL(message)
30
 
 
31
 
        .file   "boot.S"
32
 
 
33
 
        .text
34
 
 
35
 
        /* Tell GAS to generate 16-bit instructions so that this code works
36
 
           in real mode. */
37
 
        .code16
38
 
 
39
 
.globl _start, start;
40
 
_start:
41
 
start:
42
 
        /*
43
 
         * _start is loaded at 0x7c00 and is jumped to with CS:IP 0:0x7c00
44
 
         */
45
 
 
46
 
        /*
47
 
         * Beginning of the sector is compatible with the FAT/HPFS BIOS
48
 
         * parameter block.
49
 
         */
50
 
 
51
 
        jmp     LOCAL(after_BPB)
52
 
        nop     /* do I care about this ??? */
53
 
 
54
 
        /*
55
 
         * This space is for the BIOS parameter block!!!!  Don't change
56
 
         * the first jump, nor start the code anywhere but right after
57
 
         * this area.
58
 
         */
59
 
 
60
 
        . = _start + GRUB_BOOT_MACHINE_BPB_START
61
 
        . = _start + 4
62
 
 
63
 
        /* scratch space */
64
 
mode:
65
 
        .byte   0
66
 
disk_address_packet:
67
 
sectors:
68
 
        .long   0
69
 
heads:
70
 
        .long   0
71
 
cylinders:
72
 
        .word   0
73
 
sector_start:
74
 
        .byte   0
75
 
head_start:
76
 
        .byte   0
77
 
cylinder_start:
78
 
        .word   0
79
 
        /* more space... */
80
 
 
81
 
        . = _start + GRUB_BOOT_MACHINE_BPB_END
82
 
 
83
 
        /*
84
 
         * End of BIOS parameter block.
85
 
         */
86
 
 
87
 
kernel_address:
88
 
        .word   GRUB_BOOT_MACHINE_KERNEL_ADDR
89
 
 
90
 
        . = _start + GRUB_BOOT_MACHINE_KERNEL_SECTOR
91
 
kernel_sector:
92
 
        .long   1, 0
93
 
 
94
 
        . = _start + GRUB_BOOT_MACHINE_BOOT_DRIVE
95
 
boot_drive:
96
 
        .byte 0xff      /* the disk to load kernel from */
97
 
                        /* 0xff means use the boot drive */
98
 
 
99
 
LOCAL(after_BPB):
100
 
 
101
 
/* general setup */
102
 
        cli             /* we're not safe here! */
103
 
 
104
 
        /*
105
 
         * This is a workaround for buggy BIOSes which don't pass boot
106
 
         * drive correctly. If GRUB is installed into a HDD, check if
107
 
         * DL is masked correctly. If not, assume that the BIOS passed
108
 
         * a bogus value and set DL to 0x80, since this is the only
109
 
         * possible boot drive. If GRUB is installed into a floppy,
110
 
         * this does nothing (only jump).
111
 
         */
112
 
        . = _start + GRUB_BOOT_MACHINE_DRIVE_CHECK
113
 
boot_drive_check:
114
 
        jmp     1f      /* grub-setup may overwrite this jump */
115
 
        testb   $0x80, %dl
116
 
        jnz     1f
117
 
        movb    $0x80, %dl
118
 
1:
119
 
 
120
 
        /*
121
 
         * ljmp to the next instruction because some bogus BIOSes
122
 
         * jump to 07C0:0000 instead of 0000:7C00.
123
 
         */
124
 
        ljmp    $0, $real_start
125
 
 
126
 
real_start:
127
 
 
128
 
        /* set up %ds and %ss as offset from 0 */
129
 
        xorw    %ax, %ax
130
 
        movw    %ax, %ds
131
 
        movw    %ax, %ss
132
 
 
133
 
        /* set up the REAL stack */
134
 
        movw    $GRUB_BOOT_MACHINE_STACK_SEG, %sp
135
 
 
136
 
        sti             /* we're safe again */
137
 
 
138
 
        /*
139
 
         *  Check if we have a forced disk reference here
140
 
         */
141
 
        movb   boot_drive, %al
142
 
        cmpb    $0xff, %al
143
 
        je      1f
144
 
        movb    %al, %dl
145
 
1:
146
 
        /* save drive reference first thing! */
147
 
        pushw   %dx
148
 
 
149
 
        /* print a notification message on the screen */
150
 
        MSG(notification_string)
151
 
 
152
 
        /* set %si to the disk address packet */
153
 
        movw    $disk_address_packet, %si
154
 
 
155
 
        /* do not probe LBA if the drive is a floppy */
156
 
        testb   $GRUB_BOOT_MACHINE_BIOS_HD_FLAG, %dl
157
 
        jz      LOCAL(chs_mode)
158
 
 
159
 
        /* check if LBA is supported */
160
 
        movb    $0x41, %ah
161
 
        movw    $0x55aa, %bx
162
 
        int     $0x13
163
 
 
164
 
        /*
165
 
         *  %dl may have been clobbered by INT 13, AH=41H.
166
 
         *  This happens, for example, with AST BIOS 1.04.
167
 
         */
168
 
        popw    %dx
169
 
        pushw   %dx
170
 
 
171
 
        /* use CHS if fails */
172
 
        jc      LOCAL(chs_mode)
173
 
        cmpw    $0xaa55, %bx
174
 
        jne     LOCAL(chs_mode)
175
 
 
176
 
        andw    $1, %cx
177
 
        jz      LOCAL(chs_mode)
178
 
 
179
 
lba_mode:
180
 
        xorw    %ax, %ax
181
 
        movw    %ax, 4(%si)
182
 
 
183
 
        incw    %ax
184
 
        /* set the mode to non-zero */
185
 
        movb    %al, -1(%si)
186
 
 
187
 
        /* the blocks */
188
 
        movw    %ax, 2(%si)
189
 
 
190
 
        /* the size and the reserved byte */
191
 
        movw    $0x0010, (%si)
192
 
 
193
 
        /* the absolute address */
194
 
        movl    kernel_sector, %ebx
195
 
        movl    %ebx, 8(%si)
196
 
        movl    kernel_sector + 4, %ebx
197
 
        movl    %ebx, 12(%si)
198
 
 
199
 
        /* the segment of buffer address */
200
 
        movw    $GRUB_BOOT_MACHINE_BUFFER_SEG, 6(%si)
201
 
 
202
 
/*
203
 
 * BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory
204
 
 *      Call with       %ah = 0x42
205
 
 *                      %dl = drive number
206
 
 *                      %ds:%si = segment:offset of disk address packet
207
 
 *      Return:
208
 
 *                      %al = 0x0 on success; err code on failure
209
 
 */
210
 
 
211
 
        movb    $0x42, %ah
212
 
        int     $0x13
213
 
 
214
 
        /* LBA read is not supported, so fallback to CHS.  */
215
 
        jc      LOCAL(chs_mode)
216
 
 
217
 
        movw    $GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
218
 
        jmp     LOCAL(copy_buffer)
219
 
 
220
 
LOCAL(chs_mode):
221
 
        /*
222
 
         *  Determine the hard disk geometry from the BIOS!
223
 
         *  We do this first, so that LS-120 IDE floppies work correctly.
224
 
         */
225
 
        movb    $8, %ah
226
 
        int     $0x13
227
 
        jnc     LOCAL(final_init)
228
 
 
229
 
        /*
230
 
         *  The call failed, so maybe use the floppy probe instead.
231
 
         */
232
 
        testb   $GRUB_BOOT_MACHINE_BIOS_HD_FLAG, %dl
233
 
        jz      LOCAL(floppy_probe)
234
 
 
235
 
        /* Nope, we definitely have a hard disk, and we're screwed. */
236
 
        jmp     LOCAL(hd_probe_error)
237
 
 
238
 
LOCAL(final_init):
239
 
        /* set the mode to zero */
240
 
        movzbl  %dh, %eax
241
 
        movb    %ah, -1(%si)
242
 
 
243
 
        /* save number of heads */
244
 
        incw    %ax
245
 
        movl    %eax, 4(%si)
246
 
 
247
 
        movzbw  %cl, %dx
248
 
        shlw    $2, %dx
249
 
        movb    %ch, %al
250
 
        movb    %dh, %ah
251
 
 
252
 
        /* save number of cylinders */
253
 
        incw    %ax
254
 
        movw    %ax, 8(%si)
255
 
 
256
 
        movzbw  %dl, %ax
257
 
        shrb    $2, %al
258
 
 
259
 
        /* save number of sectors */
260
 
        movl    %eax, (%si)
261
 
 
262
 
setup_sectors:
263
 
        /* load logical sector start (top half) */
264
 
        movl    kernel_sector + 4, %eax
265
 
 
266
 
        orl     %eax, %eax
267
 
        jnz     LOCAL(geometry_error)
268
 
 
269
 
        /* load logical sector start (bottom half) */
270
 
        movl    kernel_sector, %eax
271
 
 
272
 
        /* zero %edx */
273
 
        xorl    %edx, %edx
274
 
 
275
 
        /* divide by number of sectors */
276
 
        divl    (%si)
277
 
 
278
 
        /* save sector start */
279
 
        movb    %dl, %cl
280
 
 
281
 
        xorw    %dx, %dx        /* zero %edx */
282
 
        divl    4(%si)          /* divide by number of heads */
283
 
 
284
 
        /* do we need too many cylinders? */
285
 
        cmpw    8(%si), %ax
286
 
        jge     LOCAL(geometry_error)
287
 
 
288
 
        /* normalize sector start (1-based) */
289
 
        incb    %cl
290
 
 
291
 
        /* low bits of cylinder start */
292
 
        movb    %al, %ch
293
 
 
294
 
        /* high bits of cylinder start */
295
 
        xorb    %al, %al
296
 
        shrw    $2, %ax
297
 
        orb     %al, %cl
298
 
 
299
 
        /* save head start */
300
 
        movb    %dl, %al
301
 
 
302
 
        /* restore %dl */
303
 
        popw    %dx
304
 
 
305
 
        /* head start */
306
 
        movb    %al, %dh
307
 
 
308
 
/*
309
 
 * BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory
310
 
 *      Call with       %ah = 0x2
311
 
 *                      %al = number of sectors
312
 
 *                      %ch = cylinder
313
 
 *                      %cl = sector (bits 6-7 are high bits of "cylinder")
314
 
 *                      %dh = head
315
 
 *                      %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
316
 
 *                      %es:%bx = segment:offset of buffer
317
 
 *      Return:
318
 
 *                      %al = 0x0 on success; err code on failure
319
 
 */
320
 
 
321
 
        movw    $GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
322
 
        movw    %bx, %es        /* load %es segment with disk buffer */
323
 
 
324
 
        xorw    %bx, %bx        /* %bx = 0, put it at 0 in the segment */
325
 
        movw    $0x0201, %ax    /* function 2 */
326
 
        int     $0x13
327
 
 
328
 
        jc      LOCAL(read_error)
329
 
 
330
 
        movw    %es, %bx
331
 
 
332
 
LOCAL(copy_buffer):
333
 
        /*
334
 
         * We need to save %cx and %si because the startup code in
335
 
         * kernel uses them without initializing them.
336
 
         */
337
 
        pusha
338
 
        pushw   %ds
339
 
 
340
 
        movw    $0x100, %cx
341
 
        movw    %bx, %ds
342
 
        xorw    %si, %si
343
 
        movw    $GRUB_BOOT_MACHINE_KERNEL_ADDR, %di
344
 
        movw    %si, %es
345
 
 
346
 
        cld
347
 
 
348
 
        rep
349
 
        movsw
350
 
 
351
 
        popw    %ds
352
 
        popa
353
 
 
354
 
        /* boot kernel */
355
 
        jmp     *(kernel_address)
356
 
 
357
 
/* END OF MAIN LOOP */
358
 
 
359
 
/*
360
 
 * BIOS Geometry translation error (past the end of the disk geometry!).
361
 
 */
362
 
LOCAL(geometry_error):
363
 
        MSG(geometry_error_string)
364
 
        jmp     LOCAL(general_error)
365
 
 
366
 
/*
367
 
 * Disk probe failure.
368
 
 */
369
 
LOCAL(hd_probe_error):
370
 
        MSG(hd_probe_error_string)
371
 
        jmp     LOCAL(general_error)
372
 
 
373
 
/*
374
 
 * Read error on the disk.
375
 
 */
376
 
LOCAL(read_error):
377
 
        MSG(read_error_string)
378
 
 
379
 
LOCAL(general_error):
380
 
        MSG(general_error_string)
381
 
 
382
 
/* go here when you need to stop the machine hard after an error condition */
383
 
        /* tell the BIOS a boot failure, which may result in no effect */
384
 
        int     $0x18
385
 
LOCAL(stop):
386
 
        jmp     LOCAL(stop)
387
 
 
388
 
notification_string:    .asciz "GRUB "
389
 
geometry_error_string:  .asciz "Geom"
390
 
hd_probe_error_string:  .asciz "Hard Disk"
391
 
read_error_string:      .asciz "Read"
392
 
general_error_string:   .asciz " Error\r\n"
393
 
 
394
 
/*
395
 
 * message: write the string pointed to by %si
396
 
 *
397
 
 *   WARNING: trashes %si, %ax, and %bx
398
 
 */
399
 
 
400
 
        /*
401
 
         * Use BIOS "int 10H Function 0Eh" to write character in teletype mode
402
 
         *      %ah = 0xe       %al = character
403
 
         *      %bh = page      %bl = foreground color (graphics modes)
404
 
         */
405
 
1:
406
 
        movw    $0x0001, %bx
407
 
        movb    $0xe, %ah
408
 
        int     $0x10           /* display a byte */
409
 
LOCAL(message):
410
 
        lodsb
411
 
        cmpb    $0, %al
412
 
        jne     1b      /* if not end of string, jmp to display */
413
 
        ret
414
 
 
415
 
        /*
416
 
         *  Windows NT breaks compatibility by embedding a magic
417
 
         *  number here.
418
 
         */
419
 
 
420
 
        . = _start + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC
421
 
nt_magic:
422
 
        .long 0
423
 
        .word 0
424
 
 
425
 
        /*
426
 
         *  This is where an MBR would go if on a hard disk.  The code
427
 
         *  here isn't even referenced unless we're on a floppy.  Kinda
428
 
         *  sneaky, huh?
429
 
         */
430
 
 
431
 
        . = _start + GRUB_BOOT_MACHINE_PART_START
432
 
part_start:
433
 
 
434
 
probe_values:
435
 
        .byte   36, 18, 15, 9, 0
436
 
 
437
 
LOCAL(floppy_probe):
438
 
/*
439
 
 *  Perform floppy probe.
440
 
 */
441
 
 
442
 
        movw    $probe_values - 1, %si
443
 
 
444
 
LOCAL(probe_loop):
445
 
        /* reset floppy controller INT 13h AH=0 */
446
 
        xorw    %ax, %ax
447
 
        int     $0x13
448
 
 
449
 
        incw    %si
450
 
        movb    (%si), %cl
451
 
 
452
 
        /* if number of sectors is 0, display error and die */
453
 
        cmpb    $0, %cl
454
 
        jne     1f
455
 
 
456
 
/*
457
 
 * Floppy disk probe failure.
458
 
 */
459
 
        MSG(fd_probe_error_string)
460
 
        jmp     LOCAL(general_error)
461
 
 
462
 
/* "Floppy" */
463
 
fd_probe_error_string:  .asciz "Floppy"
464
 
 
465
 
1:
466
 
        /* perform read */
467
 
        movw    $GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
468
 
        movw    $0x201, %ax
469
 
        movb    $0, %ch
470
 
        movb    $0, %dh
471
 
        int     $0x13
472
 
 
473
 
        /* if error, jump to "LOCAL(probe_loop)" */
474
 
        jc      LOCAL(probe_loop)
475
 
 
476
 
        /* %cl is already the correct value! */
477
 
        movb    $1, %dh
478
 
        movb    $79, %ch
479
 
 
480
 
        jmp     LOCAL(final_init)
481
 
 
482
 
        . = _start + GRUB_BOOT_MACHINE_PART_END
483
 
 
484
 
/* the last 2 bytes in the sector 0 contain the signature */
485
 
        .word   GRUB_BOOT_MACHINE_SIGNATURE