~darkmuggle-deactivatedaccount/ubuntu/quantal/grub2/fix-872244

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