Dash:
[t2.git] / package / boot / grub / usb-cd.patch
blob31dad8e2772fb0374f192f628f1ff96f8756f223
1 # --- T2-COPYRIGHT-NOTE-BEGIN ---
2 # This copyright note is auto-generated by ./scripts/Create-CopyPatch.
3 #
4 # T2 SDE: package/.../grub/usb-cd.patch
5 # Copyright (C) 2011 The T2 SDE Project
6 #
7 # More information can be found in the files COPYING and README.
8 #
9 # This patch file is dual-licensed. It is available under the license the
10 # patched project is licensed under, as long as it is an OpenSource license
11 # as defined at http://www.opensource.org/ (e.g. BSD, X11) or under the terms
12 # of the GNU General Public License as published by the Free Software
13 # Foundation; either version 2 of the License, or (at your option) any later
14 # version.
15 # --- T2-COPYRIGHT-NOTE-END ---
17 Some Phoenix / Award BIOS does corrupt itself, if the disk system reset
18 or version query is called when booting from an USB CD-ROM. Strangely,
19 however, those Phoenix/Award BIOS did work fine booting from an internal
20 IDE CD. Whatever.
22 Avoid said calls and additionally incorporated another Award BIOS
23 fix, searching for an instruction sequence and extracting the
24 call address, as well as hardened reading (retry including decreased
25 sizes, also inspired by isolinux) and check the carry flag to pro-
26 actively further help potentially broken BIOSes, as there are so
27 many of those, ...
29 - Rene Rebe <rene@exactcode.de>
31 diff -ur grub-0.97/stage2/asm.S grub-0.97-fixed/stage2/asm.S
32 --- grub-0.97/stage2/asm.S 2004-06-19 18:55:22.000000000 +0200
33 +++ grub-0.97-fixed/stage2/asm.S 2007-09-30 15:35:34.000000000 +0200
34 @@ -139,7 +139,7 @@
35 ADDR32 movb %dl, EXT_C(boot_drive)
37 /* reset disk system (%ah = 0) */
38 - int $0x13
39 + /* int $0x13 */ /* appears to confuse Phoenix/Award BIOS with USB CDs -ReneR */
40 #endif
42 /* transition to protected mode */
43 @@ -971,7 +1060,10 @@
44 movw %bx, %ax
45 movw %cx, %ds
46 int $0x13 /* do the operation */
47 - movb %ah, %dl /* save return value */
48 + jc 1f /* carry flag indicates error -ReneR */
49 + xor %ah, %ah /* no error: clearn ah just in case, ... */
50 +1: movb %ah, %dl /* save return value */
52 /* clear the data segment */
53 xorw %ax, %ax
54 movw %ax, %ds
55 diff -ur grub-0.97/stage2/bios.c grub-0.97-fixed/stage2/bios.c
56 --- grub-0.97/stage2/bios.c 2004-03-27 17:34:04.000000000 +0100
57 +++ grub-0.97-fixed/stage2/bios.c 2007-09-30 15:40:29.000000000 +0200
58 @@ -61,27 +61,54 @@
59 unsigned long buffer;
60 unsigned long long block;
61 } __attribute__ ((packed)) dap;
63 + int retry_count = 4;
65 + while (nsec > 0 && retry_count > 0) {
67 - /* XXX: Don't check the geometry by default, because some buggy
68 - BIOSes don't return the number of total sectors correctly,
69 - even if they have working LBA support. Hell. */
70 + /* XXX: Don't check the geometry by default, because some buggy
71 + BIOSes don't return the number of total sectors correctly,
72 + even if they have working LBA support. Hell. */
73 #ifdef NO_BUGGY_BIOS_IN_THE_WORLD
74 - if (sector >= geometry->total_sectors)
75 - return BIOSDISK_ERROR_GEOMETRY;
76 + if (sector >= geometry->total_sectors)
77 + return BIOSDISK_ERROR_GEOMETRY;
78 #endif /* NO_BUGGY_BIOS_IN_THE_WORLD */
80 - /* FIXME: sizeof (DAP) must be 0x10. Should assert that the compiler
81 - can't add any padding. */
82 - dap.length = sizeof (dap);
83 - dap.block = sector;
84 - dap.blocks = nsec;
85 - dap.reserved = 0;
86 - /* This is undocumented part. The address is formated in
87 - SEGMENT:ADDRESS. */
88 - dap.buffer = segment << 16;
91 + /* FIXME: sizeof (DAP) must be 0x10. Should assert that the compiler
92 + can't add any padding. */
93 + dap.length = sizeof (dap);
94 + dap.block = sector;
95 + switch (retry_count) {
96 + case 1:
97 + dap.blocks = 1; break;
98 + case 2:
99 + dap.blocks = nsec / 2; break;
100 + default:
101 + dap.blocks = nsec;
103 + dap.reserved = 0;
104 + /* This is undocumented part. The address is formated in
105 + SEGMENT:ADDRESS. */
106 + dap.buffer = segment << 16;
108 + err = biosdisk_int13_extensions ((read + 0x42) << 8, drive, &dap);
110 + if (err && ! geometry->flags & BIOSDISK_FLAG_CDROM)
111 + break; /* only retry for CD-ROMs */
112 + if (err) {
113 + printf ("biosdisk: err: %x\n", (int) err);
114 + --retry_count;
117 + if (!err) {
118 + sector += dap.blocks;
119 + nsec -= dap.blocks;
120 + segment += geometry->sector_size / 16; /* 16 bytes per segment */
121 + retry_count = 3; /* refresh on success */
125 - err = biosdisk_int13_extensions ((read + 0x42) << 8, drive, &dap);
127 /* #undef NO_INT13_FALLBACK */
128 #ifndef NO_INT13_FALLBACK
129 if (err)
130 @@ -142,11 +168,42 @@
131 unsigned char heads;
133 unsigned char dummy[16];
134 - } __attribute__ ((packed)) cdrp;
135 + } __attribute__ ((packed)) cdrp __attribute__ ((aligned(8)));
137 grub_memset (&cdrp, 0, sizeof (cdrp));
138 cdrp.size = sizeof (cdrp) - sizeof (cdrp.dummy);
139 err = biosdisk_int13_extensions (0x4B01, drive, &cdrp);
141 + /* On error try to find a broken Award BIOS, idea and signature from isolinux.
142 + -ReneR */
143 +#if !defined(NO_BUGGY_BIOS_IN_THE_WORLD) && defined(FSYS_ISO9660)
144 + if (err || cdrp.drive_no != drive)
146 + const char award_string [] = { 0xb8,1,2,0xbb,0,0x7c,0xb9,6,0,0xba,0x80,1,0x9c,0x9a };
147 + char* bios_addr;
149 + /* printf ("get_cdinfo: failed. Searching for broken Award BIOS signature ...\n"); */
150 + for (bios_addr = (char*)0xf0000; bios_addr < (char*) 0xfffff; ++bios_addr)
151 + if (grub_memcmp (bios_addr, award_string, sizeof (award_string)) == 0)
152 + break;
154 + if (bios_addr != (void*)0xfffff)
156 + void** int13_vector = (void**) (0x13 * 4);
157 + void** call_addr = (void**)(bios_addr + 0x0e);
159 + /* printf ("get_cdinfo: found Award signature @ %x\n", bios_addr); */
160 + if (*int13_vector != *call_addr) {
161 + printf ("get_cdinfo: patching INT13 old: %x new: %x\n", *int13_vector, *call_addr);
163 + *int13_vector = *call_addr;
164 + err = biosdisk_int13_extensions (0x4B01, drive, &cdrp);
166 + /* else
167 + printf ("get_cdinfo: INT13 already pointing to same entry.\n"); */
170 +#endif
171 if (! err && cdrp.drive_no == drive)
173 if ((cdrp.media_type & 0x0F) == 0)