]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/grub-gentoo-14.patch
Merge remote-tracking branch 'stevee/mc-update' into thirteen
[people/pmueller/ipfire-2.x.git] / src / patches / grub-gentoo-14.patch
1 diff -Nur grub-0.97/acinclude.m4 grub-0.97-patched/acinclude.m4
2 --- grub-0.97/acinclude.m4 2004-04-27 22:48:06.000000000 +0200
3 +++ grub-0.97-patched/acinclude.m4 2012-11-11 17:07:12.710729053 +0100
4 @@ -57,7 +57,7 @@
5 fi
6 grub_cv_prog_objcopy_absolute=yes
7 for link_addr in 2000 8000 7C00; do
8 - if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -nostdlib -Wl,-N -Wl,-Ttext -Wl,$link_addr conftest.o -o conftest.exec]); then :
9 + if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} ${LDFLAGS} -nostdlib -Wl,-N -Wl,-Ttext -Wl,$link_addr conftest.o -o conftest.exec]); then :
10 else
11 AC_MSG_ERROR([${CC-cc} cannot link at address $link_addr])
12 fi
13 diff -Nur grub-0.97/ChangeLog grub-0.97-patched/ChangeLog
14 --- grub-0.97/ChangeLog 2005-05-08 04:47:02.000000000 +0200
15 +++ grub-0.97-patched/ChangeLog 2012-11-11 17:07:12.708728989 +0100
16 @@ -1,3 +1,127 @@
17 +2008-05-20 Robert Millan <rmh@aybabtu.com>
18 +
19 + * netboot/cs89x0.c: Fix license violation.
20 + * netboot/cs89x0.h: Likewise.
21 +
22 +2008-04-10 Pavel Roskin <proski@gnu.org>
23 +
24 + * configure.ac: Always use "_cv_" in cache variables for
25 + compatibility with Autoconf 2.62.
26 +
27 +2008-03-28 Robert Millan <rmh@aybabtu.com>
28 +
29 + Surpass 1 TiB disk addressing limit. Note: there are no plans to handle
30 + the 2 TiB disk limit in GRUB Legacy, since that would need considerable
31 + rework. If you have >2TiB disks, use GRUB 2 instead.
32 +
33 + * grub/asmstub.c (biosdisk): Add unsigned qualifier to `sector'.
34 + * stage2/bios.c (biosdisk): Likewise.
35 + * stage2/disk_io.c (rawread, devread, rawwrite, devwrite): Likewise.
36 + * stage2/shared.h (rawread, devread, rawwrite, devwrite): Likewise.
37 + * lib/device.c (get_drive_geometry): Replace BLKGETSIZE with
38 + BLKGETSIZE64.
39 +
40 +2007-10-29 Pavel Roskin <proski@gnu.org>
41 +
42 + * configure.ac: Test if '--build-id=none' is supported by the
43 + linker and add it to LDFLAGS if possible. Build ID causes
44 + objcopy to generate huge binary files.
45 + * aclocal.m4 (grub_PROG_OBJCOPY_ABSOLUTE): Use LDFLAGS when
46 + linking, so that build ID doesn't break the test.
47 + * stage1/Makefile.am: Preserve LDFLAGS, use stage1_exec_LDFLAGS.
48 +
49 +2007-02-22 Pavel Roskin <proski@gnu.org>
50 +
51 + * stage2/iso9660.h: Remove unnecessary packed attributes.
52 +
53 +2007-02-22 Robert Millan <rmh@aybabtu.com>
54 +
55 + * util/mkbimage: Update my email address, and remove my name from
56 + some places where unnecessary credit is given.
57 +
58 +2006-09-10 Pavel Roskin <proski@gnu.org>
59 +
60 + * netboot/natsemi.c: Fix compile error with gcc 4.1.1. Cast
61 + cannot make a variable volatile - it should be declared as such.
62 + * netboot/sis900.c: Likewise.
63 +
64 +2006-09-08 Pavel Roskin <proski@gnu.org>
65 +
66 + * netboot/etherboot.h: Remove incorrect extern declarations of
67 + the variables later declared static. Move BOOTP_DATA_ADDR ...
68 + * netboot/main.c: ... here. Eliminate end_of_rfc1533 - it's
69 + write-only.
70 +
71 +2006-06-24 Yoshinori K. Okuji <okuji@enbug.org>
72 +
73 + * docs/grub.texi: Changed the license term to the GNU Free
74 + Documentation License 1.2.
75 +
76 + * docs/multiboot.texi: Reformatted to show the license term
77 + and the version number explicitly.
78 +
79 + * docs/fdl.texi: New file.
80 +
81 + * docs/Makefile.am (grub_TEXINFOS): Added fdl.texi.
82 +
83 +2006-06-24 Robert Millan <robertmh@gnu.org>
84 +
85 + * lib/device.c (write_to_partition): /dev/ataraid/ and /dev/rd/
86 + partitions have a "p" prefix. Add it.
87 +
88 +2006-06-24 Robert Millan <robertmh@gnu.org>
89 +
90 + * lib/device.c (get_i2o_disk_name): New function.
91 + (init_device_map) [__linux__]: Add support for I2O devices.
92 +
93 +2006-05-02 Pavel Roskin <proski@gnu.org>
94 +
95 + * stage2/stage2.c (run_menu): Fix "savedefault" to save only top
96 + level menu positions. Remember current position when calling a
97 + submenu. Don't recalculate it when booting from a submenu.
98 +
99 + * grub/main.c (main): Make sure the boot drive number doesn't
100 + exceed 255.
101 +
102 +2006-05-02 Vesa Jaaskelainen <chaac@nic.fi>
103 +
104 + * stage2/shared.h (vbe_mode): Back ported aligment fix from GRUB 2
105 + to GRUB Legacy. Problem reported by Gerardo Richarte.
106 +
107 +2006-04-23 Robert Millan <robertmh@gnu.org>
108 +
109 + * grub/asmstub.c (get_diskinfo): Optimize sysctl routine.
110 +
111 +2006-04-20 Robert Millan <robertmh@gnu.org>
112 +
113 + Fixes for kernel of FreeBSD:
114 + * grub/asmstub.c (get_diskinfo): Toggle "kern.geom.debugflags" sysctl
115 + before opening a device for writing.
116 + * util/grub-install.in: Devices don't have this "r" prefix anymore.
117 +
118 +2006-04-16 Yoshinori K. Okuji <okuji@enbug.org>
119 +
120 + * docs/multiboot.texi: Correct the offset of address
121 + fields. Reported by Jeroen Dekkers.
122 +
123 +2006-03-21 Yoshinori K. Okuji <okuji@enbug.org>
124 +
125 + * stage2/builtins.c (setup_func): Specify the size of DEVICE to
126 + grub_strncat instead of a strange number 256. Reported by Vitaly
127 + Fertman <vitaly@namesys.com>.
128 +
129 +2005-09-29 Yoshinori K. Okuji <okuji@enbug.org>
130 +
131 + * docs/multiboot.texi: Fix a bug in the byte order of
132 + boot_device. I hope this won't affect any OS image.
133 + Increased the version number to 0.6.94.
134 +
135 +2005-09-28 Yoshinori K. Okuji <okuji@enbug.org>
136 +
137 + * stage2/boot.c (load_image): Even if an OS image is an ELF
138 + object, use the a.out kludge if MULTIBOOT_AOUT_KLUDGE is
139 + specified.
140 +
141 2005-05-08 Yoshinori K. Okuji <okuji@enbug.org>
142
143 * configure.ac (AC_INIT): Upgraded to 0.97.
144 diff -Nur grub-0.97/configure.ac grub-0.97-patched/configure.ac
145 --- grub-0.97/configure.ac 2005-05-08 04:36:03.000000000 +0200
146 +++ grub-0.97-patched/configure.ac 2012-11-11 17:07:12.752730394 +0100
147 @@ -21,8 +21,12 @@
148 AC_CANONICAL_HOST
149
150 case "$host_cpu" in
151 -i[[3456]]86) host_cpu=i386 ;;
152 -x86_64) host_cpu=x86_64 ;;
153 +i[[3456]]86)
154 + STAGE_MARCH="-march=$host_cpu"
155 + host_cpu=i386 ;;
156 +x86_64)
157 + STAGE_MARCH="-march=i686"
158 + host_cpu=x86_64 ;;
159 *) AC_MSG_ERROR([unsupported CPU type]) ;;
160 esac
161
162 @@ -56,12 +60,7 @@
163
164 AC_CHECK_TOOL(CC, gcc)
165 AC_PROG_CC
166 -# We need this for older versions of Autoconf.
167 -_AM_DEPENDENCIES(CC)
168 -
169 -dnl Because recent automake complains about AS, set it here.
170 -CCAS="$CC"
171 -AC_SUBST(CCAS)
172 +AM_PROG_AS
173
174 AC_ARG_WITH(binutils,
175 [ --with-binutils=DIR search the directory DIR to find binutils])
176 @@ -86,13 +85,13 @@
177 fi
178 STAGE1_CFLAGS="-O2"
179 GRUB_CFLAGS="-O2"
180 - AC_CACHE_CHECK([whether optimization for size works], size_flag, [
181 + AC_CACHE_CHECK([whether optimization for size works], grub_cv_cc_Os, [
182 saved_CFLAGS=$CFLAGS
183 CFLAGS="-Os -g"
184 - AC_TRY_COMPILE(, , size_flag=yes, size_flag=no)
185 + AC_TRY_COMPILE(, , grub_cv_cc_Os=yes, grub_cv_cc_Os=no)
186 CFLAGS=$saved_CFLAGS
187 ])
188 - if test "x$size_flag" = xyes; then
189 + if test "x$grub_cv_cc_Os" = xyes; then
190 STAGE2_CFLAGS="-Os"
191 else
192 STAGE2_CFLAGS="-O2 -fno-strength-reduce -fno-unroll-loops"
193 @@ -100,21 +99,38 @@
194 # OpenBSD has a GCC extension for protecting applications from
195 # stack smashing attacks, but GRUB doesn't want this feature.
196 AC_CACHE_CHECK([whether gcc has -fno-stack-protector],
197 - no_stack_protector_flag, [
198 + grub_cv_cc_no_stack_protector, [
199 saved_CFLAGS=$CFLAGS
200 CFLAGS="-fno-stack-protector"
201 AC_TRY_COMPILE(,
202 ,
203 - no_stack_protector_flag=yes,
204 - no_stack_protector_flag=no)
205 + grub_cv_cc_no_stack_protector=yes,
206 + grub_cv_cc_no_stack_protector=no)
207 CFLAGS=$saved_CFLAGS
208 ])
209 - if test "x$no_stack_protector_flag" = xyes; then
210 + if test "x$grub_cv_cc_no_stack_protector" = xyes; then
211 STAGE2_CFLAGS="$STAGE2_CFLAGS -fno-stack-protector"
212 fi
213 + # Position Independent Executables, but GRUB doesn't want this feature.
214 + AC_CACHE_CHECK([whether gcc has -fPIE on as default], grub_cv_cc_fpie, [
215 + AC_TRY_COMPILE(,[
216 + #if ! defined (__PIC__) || ! defined (__PIE__)
217 + #error
218 + #endif
219 + ],
220 + grub_cv_cc_fpie=yes,
221 + grub_cv_cc_fpie=no)
222 + ])
223 + if test "x$grub_cv_cc_fpie" = xyes; then
224 + STAGE1_CFLAGS="$STAGE1_CFLAGS -nopie"
225 + STAGE2_CFLAGS="$STAGE2_CFLAGS -nopie"
226 + fi
227 fi
228 fi
229
230 +STAGE1_CFLAGS="$STAGE1_CFLAGS -fno-strict-aliasing $STAGE_MARCH"
231 +STAGE2_CFLAGS="$STAGE2_CFLAGS -fno-strict-aliasing $STAGE_MARCH"
232 +GRUB_CFLAGS="$GRUB_CFLAGS -fno-strict-aliasing"
233 AC_SUBST(STAGE1_CFLAGS)
234 AC_SUBST(STAGE2_CFLAGS)
235 AC_SUBST(GRUB_CFLAGS)
236 @@ -123,33 +139,44 @@
237 CPPFLAGS="$CPPFLAGS -Wall -Wmissing-prototypes -Wunused -Wshadow"
238 CPPFLAGS="$CPPFLAGS -Wpointer-arith"
239
240 -AC_CACHE_CHECK([whether -Wundef works], undef_flag, [
241 +AC_CACHE_CHECK([whether -Wundef works], grub_cv_cc_Wundef, [
242 saved_CPPFLAGS="$CPPFLAGS"
243 CPPFLAGS="-Wundef"
244 - AC_TRY_COMPILE(, , undef_flag=yes, undef_flag=no)
245 + AC_TRY_COMPILE(, , grub_cv_cc_Wundef=yes, grub_cv_cc_Wundef=no)
246 CPPFLAGS="$saved_CPPFLAGS"
247 ])
248
249 # The options `-falign-*' are supported by gcc 3.0 or later.
250 # Probably it is sufficient to only check for -falign-loops.
251 -AC_CACHE_CHECK([whether -falign-loops works], [falign_loop_flag], [
252 +AC_CACHE_CHECK([whether -falign-loops works], [grub_cv_cc_falign_loop], [
253 saved_CPPFLAGS="$CPPFLAGS"
254 CPPFLAGS="-falign-loops=1"
255 - AC_TRY_COMPILE(, , [falign_loop_flag=yes], [falign_loop_flag=no])
256 + AC_TRY_COMPILE(, , [grub_cv_cc_falign_loop=yes], [grub_cv_cc_falign_loop=no])
257 CPPFLAGS="$saved_CPPFLAGS"
258 ])
259
260 # Force no alignment to save space.
261 -if test "x$falign_loop_flag" = xyes; then
262 +if test "x$grub_cv_cc_falign_loop" = xyes; then
263 CPPFLAGS="$CPPFLAGS -falign-jumps=1 -falign-loops=1 -falign-functions=1"
264 else
265 CPPFLAGS="$CPPFLAGS -malign-jumps=1 -malign-loops=1 -malign-functions=1"
266 fi
267
268 -if test "x$undef_flag" = xyes; then
269 +if test "x$grub_cv_cc_Wundef" = xyes; then
270 CPPFLAGS="$CPPFLAGS -Wundef"
271 fi
272
273 +# Check if build ID can be disabled in the linker
274 +AC_MSG_CHECKING([whether linker accepts `--build-id=none'])
275 +save_LDFLAGS="$LDFLAGS"
276 +LDFLAGS="$LDFLAGS -Wl,--build-id=none"
277 +AC_TRY_LINK(, , build_id_flag=yes, build_id_flag=no)
278 +AC_MSG_RESULT([$build_id_flag])
279 +LDFLAGS="$save_LDFLAGS"
280 +if test "x$build_id_flag" = xyes; then
281 + LDFLAGS="$LDFLAGS -Wl,--build-id=none"
282 +fi
283 +
284 if test "x$with_binutils" != x; then
285 dnl AC_PATH_TOOL(OBJCOPY, objcopy, , "$with_binutils:$PATH")
286 AC_PATH_PROG(OBJCOPY, objcopy, , "$with_binutils:$PATH")
287 @@ -595,6 +622,11 @@
288 [ --enable-diskless enable diskless support])
289 AM_CONDITIONAL(DISKLESS_SUPPORT, test "x$enable_diskless" = xyes)
290
291 +dnl Graphical splashscreen support
292 +AC_ARG_ENABLE(graphics,
293 + [ --disable-graphics disable graphics terminal support])
294 +AM_CONDITIONAL(GRAPHICS_SUPPORT, test "x$enable_graphics" != xno)
295 +
296 dnl Hercules terminal
297 AC_ARG_ENABLE(hercules,
298 [ --disable-hercules disable hercules terminal support])
299 diff -Nur grub-0.97/docs/fdl.texi grub-0.97-patched/docs/fdl.texi
300 --- grub-0.97/docs/fdl.texi 1970-01-01 01:00:00.000000000 +0100
301 +++ grub-0.97-patched/docs/fdl.texi 2012-11-11 17:07:12.712729117 +0100
302 @@ -0,0 +1,452 @@
303 +
304 +@node GNU Free Documentation License
305 +@appendixsec GNU Free Documentation License
306 +
307 +@cindex FDL, GNU Free Documentation License
308 +@center Version 1.2, November 2002
309 +
310 +@display
311 +Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc.
312 +51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
313 +
314 +Everyone is permitted to copy and distribute verbatim copies
315 +of this license document, but changing it is not allowed.
316 +@end display
317 +
318 +@enumerate 0
319 +@item
320 +PREAMBLE
321 +
322 +The purpose of this License is to make a manual, textbook, or other
323 +functional and useful document @dfn{free} in the sense of freedom: to
324 +assure everyone the effective freedom to copy and redistribute it,
325 +with or without modifying it, either commercially or noncommercially.
326 +Secondarily, this License preserves for the author and publisher a way
327 +to get credit for their work, while not being considered responsible
328 +for modifications made by others.
329 +
330 +This License is a kind of ``copyleft'', which means that derivative
331 +works of the document must themselves be free in the same sense. It
332 +complements the GNU General Public License, which is a copyleft
333 +license designed for free software.
334 +
335 +We have designed this License in order to use it for manuals for free
336 +software, because free software needs free documentation: a free
337 +program should come with manuals providing the same freedoms that the
338 +software does. But this License is not limited to software manuals;
339 +it can be used for any textual work, regardless of subject matter or
340 +whether it is published as a printed book. We recommend this License
341 +principally for works whose purpose is instruction or reference.
342 +
343 +@item
344 +APPLICABILITY AND DEFINITIONS
345 +
346 +This License applies to any manual or other work, in any medium, that
347 +contains a notice placed by the copyright holder saying it can be
348 +distributed under the terms of this License. Such a notice grants a
349 +world-wide, royalty-free license, unlimited in duration, to use that
350 +work under the conditions stated herein. The ``Document'', below,
351 +refers to any such manual or work. Any member of the public is a
352 +licensee, and is addressed as ``you''. You accept the license if you
353 +copy, modify or distribute the work in a way requiring permission
354 +under copyright law.
355 +
356 +A ``Modified Version'' of the Document means any work containing the
357 +Document or a portion of it, either copied verbatim, or with
358 +modifications and/or translated into another language.
359 +
360 +A ``Secondary Section'' is a named appendix or a front-matter section
361 +of the Document that deals exclusively with the relationship of the
362 +publishers or authors of the Document to the Document's overall
363 +subject (or to related matters) and contains nothing that could fall
364 +directly within that overall subject. (Thus, if the Document is in
365 +part a textbook of mathematics, a Secondary Section may not explain
366 +any mathematics.) The relationship could be a matter of historical
367 +connection with the subject or with related matters, or of legal,
368 +commercial, philosophical, ethical or political position regarding
369 +them.
370 +
371 +The ``Invariant Sections'' are certain Secondary Sections whose titles
372 +are designated, as being those of Invariant Sections, in the notice
373 +that says that the Document is released under this License. If a
374 +section does not fit the above definition of Secondary then it is not
375 +allowed to be designated as Invariant. The Document may contain zero
376 +Invariant Sections. If the Document does not identify any Invariant
377 +Sections then there are none.
378 +
379 +The ``Cover Texts'' are certain short passages of text that are listed,
380 +as Front-Cover Texts or Back-Cover Texts, in the notice that says that
381 +the Document is released under this License. A Front-Cover Text may
382 +be at most 5 words, and a Back-Cover Text may be at most 25 words.
383 +
384 +A ``Transparent'' copy of the Document means a machine-readable copy,
385 +represented in a format whose specification is available to the
386 +general public, that is suitable for revising the document
387 +straightforwardly with generic text editors or (for images composed of
388 +pixels) generic paint programs or (for drawings) some widely available
389 +drawing editor, and that is suitable for input to text formatters or
390 +for automatic translation to a variety of formats suitable for input
391 +to text formatters. A copy made in an otherwise Transparent file
392 +format whose markup, or absence of markup, has been arranged to thwart
393 +or discourage subsequent modification by readers is not Transparent.
394 +An image format is not Transparent if used for any substantial amount
395 +of text. A copy that is not ``Transparent'' is called ``Opaque''.
396 +
397 +Examples of suitable formats for Transparent copies include plain
398 +@sc{ascii} without markup, Texinfo input format, La@TeX{} input
399 +format, @acronym{SGML} or @acronym{XML} using a publicly available
400 +@acronym{DTD}, and standard-conforming simple @acronym{HTML},
401 +PostScript or @acronym{PDF} designed for human modification. Examples
402 +of transparent image formats include @acronym{PNG}, @acronym{XCF} and
403 +@acronym{JPG}. Opaque formats include proprietary formats that can be
404 +read and edited only by proprietary word processors, @acronym{SGML} or
405 +@acronym{XML} for which the @acronym{DTD} and/or processing tools are
406 +not generally available, and the machine-generated @acronym{HTML},
407 +PostScript or @acronym{PDF} produced by some word processors for
408 +output purposes only.
409 +
410 +The ``Title Page'' means, for a printed book, the title page itself,
411 +plus such following pages as are needed to hold, legibly, the material
412 +this License requires to appear in the title page. For works in
413 +formats which do not have any title page as such, ``Title Page'' means
414 +the text near the most prominent appearance of the work's title,
415 +preceding the beginning of the body of the text.
416 +
417 +A section ``Entitled XYZ'' means a named subunit of the Document whose
418 +title either is precisely XYZ or contains XYZ in parentheses following
419 +text that translates XYZ in another language. (Here XYZ stands for a
420 +specific section name mentioned below, such as ``Acknowledgements'',
421 +``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title''
422 +of such a section when you modify the Document means that it remains a
423 +section ``Entitled XYZ'' according to this definition.
424 +
425 +The Document may include Warranty Disclaimers next to the notice which
426 +states that this License applies to the Document. These Warranty
427 +Disclaimers are considered to be included by reference in this
428 +License, but only as regards disclaiming warranties: any other
429 +implication that these Warranty Disclaimers may have is void and has
430 +no effect on the meaning of this License.
431 +
432 +@item
433 +VERBATIM COPYING
434 +
435 +You may copy and distribute the Document in any medium, either
436 +commercially or noncommercially, provided that this License, the
437 +copyright notices, and the license notice saying this License applies
438 +to the Document are reproduced in all copies, and that you add no other
439 +conditions whatsoever to those of this License. You may not use
440 +technical measures to obstruct or control the reading or further
441 +copying of the copies you make or distribute. However, you may accept
442 +compensation in exchange for copies. If you distribute a large enough
443 +number of copies you must also follow the conditions in section 3.
444 +
445 +You may also lend copies, under the same conditions stated above, and
446 +you may publicly display copies.
447 +
448 +@item
449 +COPYING IN QUANTITY
450 +
451 +If you publish printed copies (or copies in media that commonly have
452 +printed covers) of the Document, numbering more than 100, and the
453 +Document's license notice requires Cover Texts, you must enclose the
454 +copies in covers that carry, clearly and legibly, all these Cover
455 +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
456 +the back cover. Both covers must also clearly and legibly identify
457 +you as the publisher of these copies. The front cover must present
458 +the full title with all words of the title equally prominent and
459 +visible. You may add other material on the covers in addition.
460 +Copying with changes limited to the covers, as long as they preserve
461 +the title of the Document and satisfy these conditions, can be treated
462 +as verbatim copying in other respects.
463 +
464 +If the required texts for either cover are too voluminous to fit
465 +legibly, you should put the first ones listed (as many as fit
466 +reasonably) on the actual cover, and continue the rest onto adjacent
467 +pages.
468 +
469 +If you publish or distribute Opaque copies of the Document numbering
470 +more than 100, you must either include a machine-readable Transparent
471 +copy along with each Opaque copy, or state in or with each Opaque copy
472 +a computer-network location from which the general network-using
473 +public has access to download using public-standard network protocols
474 +a complete Transparent copy of the Document, free of added material.
475 +If you use the latter option, you must take reasonably prudent steps,
476 +when you begin distribution of Opaque copies in quantity, to ensure
477 +that this Transparent copy will remain thus accessible at the stated
478 +location until at least one year after the last time you distribute an
479 +Opaque copy (directly or through your agents or retailers) of that
480 +edition to the public.
481 +
482 +It is requested, but not required, that you contact the authors of the
483 +Document well before redistributing any large number of copies, to give
484 +them a chance to provide you with an updated version of the Document.
485 +
486 +@item
487 +MODIFICATIONS
488 +
489 +You may copy and distribute a Modified Version of the Document under
490 +the conditions of sections 2 and 3 above, provided that you release
491 +the Modified Version under precisely this License, with the Modified
492 +Version filling the role of the Document, thus licensing distribution
493 +and modification of the Modified Version to whoever possesses a copy
494 +of it. In addition, you must do these things in the Modified Version:
495 +
496 +@enumerate A
497 +@item
498 +Use in the Title Page (and on the covers, if any) a title distinct
499 +from that of the Document, and from those of previous versions
500 +(which should, if there were any, be listed in the History section
501 +of the Document). You may use the same title as a previous version
502 +if the original publisher of that version gives permission.
503 +
504 +@item
505 +List on the Title Page, as authors, one or more persons or entities
506 +responsible for authorship of the modifications in the Modified
507 +Version, together with at least five of the principal authors of the
508 +Document (all of its principal authors, if it has fewer than five),
509 +unless they release you from this requirement.
510 +
511 +@item
512 +State on the Title page the name of the publisher of the
513 +Modified Version, as the publisher.
514 +
515 +@item
516 +Preserve all the copyright notices of the Document.
517 +
518 +@item
519 +Add an appropriate copyright notice for your modifications
520 +adjacent to the other copyright notices.
521 +
522 +@item
523 +Include, immediately after the copyright notices, a license notice
524 +giving the public permission to use the Modified Version under the
525 +terms of this License, in the form shown in the Addendum below.
526 +
527 +@item
528 +Preserve in that license notice the full lists of Invariant Sections
529 +and required Cover Texts given in the Document's license notice.
530 +
531 +@item
532 +Include an unaltered copy of this License.
533 +
534 +@item
535 +Preserve the section Entitled ``History'', Preserve its Title, and add
536 +to it an item stating at least the title, year, new authors, and
537 +publisher of the Modified Version as given on the Title Page. If
538 +there is no section Entitled ``History'' in the Document, create one
539 +stating the title, year, authors, and publisher of the Document as
540 +given on its Title Page, then add an item describing the Modified
541 +Version as stated in the previous sentence.
542 +
543 +@item
544 +Preserve the network location, if any, given in the Document for
545 +public access to a Transparent copy of the Document, and likewise
546 +the network locations given in the Document for previous versions
547 +it was based on. These may be placed in the ``History'' section.
548 +You may omit a network location for a work that was published at
549 +least four years before the Document itself, or if the original
550 +publisher of the version it refers to gives permission.
551 +
552 +@item
553 +For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve
554 +the Title of the section, and preserve in the section all the
555 +substance and tone of each of the contributor acknowledgements and/or
556 +dedications given therein.
557 +
558 +@item
559 +Preserve all the Invariant Sections of the Document,
560 +unaltered in their text and in their titles. Section numbers
561 +or the equivalent are not considered part of the section titles.
562 +
563 +@item
564 +Delete any section Entitled ``Endorsements''. Such a section
565 +may not be included in the Modified Version.
566 +
567 +@item
568 +Do not retitle any existing section to be Entitled ``Endorsements'' or
569 +to conflict in title with any Invariant Section.
570 +
571 +@item
572 +Preserve any Warranty Disclaimers.
573 +@end enumerate
574 +
575 +If the Modified Version includes new front-matter sections or
576 +appendices that qualify as Secondary Sections and contain no material
577 +copied from the Document, you may at your option designate some or all
578 +of these sections as invariant. To do this, add their titles to the
579 +list of Invariant Sections in the Modified Version's license notice.
580 +These titles must be distinct from any other section titles.
581 +
582 +You may add a section Entitled ``Endorsements'', provided it contains
583 +nothing but endorsements of your Modified Version by various
584 +parties---for example, statements of peer review or that the text has
585 +been approved by an organization as the authoritative definition of a
586 +standard.
587 +
588 +You may add a passage of up to five words as a Front-Cover Text, and a
589 +passage of up to 25 words as a Back-Cover Text, to the end of the list
590 +of Cover Texts in the Modified Version. Only one passage of
591 +Front-Cover Text and one of Back-Cover Text may be added by (or
592 +through arrangements made by) any one entity. If the Document already
593 +includes a cover text for the same cover, previously added by you or
594 +by arrangement made by the same entity you are acting on behalf of,
595 +you may not add another; but you may replace the old one, on explicit
596 +permission from the previous publisher that added the old one.
597 +
598 +The author(s) and publisher(s) of the Document do not by this License
599 +give permission to use their names for publicity for or to assert or
600 +imply endorsement of any Modified Version.
601 +
602 +@item
603 +COMBINING DOCUMENTS
604 +
605 +You may combine the Document with other documents released under this
606 +License, under the terms defined in section 4 above for modified
607 +versions, provided that you include in the combination all of the
608 +Invariant Sections of all of the original documents, unmodified, and
609 +list them all as Invariant Sections of your combined work in its
610 +license notice, and that you preserve all their Warranty Disclaimers.
611 +
612 +The combined work need only contain one copy of this License, and
613 +multiple identical Invariant Sections may be replaced with a single
614 +copy. If there are multiple Invariant Sections with the same name but
615 +different contents, make the title of each such section unique by
616 +adding at the end of it, in parentheses, the name of the original
617 +author or publisher of that section if known, or else a unique number.
618 +Make the same adjustment to the section titles in the list of
619 +Invariant Sections in the license notice of the combined work.
620 +
621 +In the combination, you must combine any sections Entitled ``History''
622 +in the various original documents, forming one section Entitled
623 +``History''; likewise combine any sections Entitled ``Acknowledgements'',
624 +and any sections Entitled ``Dedications''. You must delete all
625 +sections Entitled ``Endorsements.''
626 +
627 +@item
628 +COLLECTIONS OF DOCUMENTS
629 +
630 +You may make a collection consisting of the Document and other documents
631 +released under this License, and replace the individual copies of this
632 +License in the various documents with a single copy that is included in
633 +the collection, provided that you follow the rules of this License for
634 +verbatim copying of each of the documents in all other respects.
635 +
636 +You may extract a single document from such a collection, and distribute
637 +it individually under this License, provided you insert a copy of this
638 +License into the extracted document, and follow this License in all
639 +other respects regarding verbatim copying of that document.
640 +
641 +@item
642 +AGGREGATION WITH INDEPENDENT WORKS
643 +
644 +A compilation of the Document or its derivatives with other separate
645 +and independent documents or works, in or on a volume of a storage or
646 +distribution medium, is called an ``aggregate'' if the copyright
647 +resulting from the compilation is not used to limit the legal rights
648 +of the compilation's users beyond what the individual works permit.
649 +When the Document is included in an aggregate, this License does not
650 +apply to the other works in the aggregate which are not themselves
651 +derivative works of the Document.
652 +
653 +If the Cover Text requirement of section 3 is applicable to these
654 +copies of the Document, then if the Document is less than one half of
655 +the entire aggregate, the Document's Cover Texts may be placed on
656 +covers that bracket the Document within the aggregate, or the
657 +electronic equivalent of covers if the Document is in electronic form.
658 +Otherwise they must appear on printed covers that bracket the whole
659 +aggregate.
660 +
661 +@item
662 +TRANSLATION
663 +
664 +Translation is considered a kind of modification, so you may
665 +distribute translations of the Document under the terms of section 4.
666 +Replacing Invariant Sections with translations requires special
667 +permission from their copyright holders, but you may include
668 +translations of some or all Invariant Sections in addition to the
669 +original versions of these Invariant Sections. You may include a
670 +translation of this License, and all the license notices in the
671 +Document, and any Warranty Disclaimers, provided that you also include
672 +the original English version of this License and the original versions
673 +of those notices and disclaimers. In case of a disagreement between
674 +the translation and the original version of this License or a notice
675 +or disclaimer, the original version will prevail.
676 +
677 +If a section in the Document is Entitled ``Acknowledgements'',
678 +``Dedications'', or ``History'', the requirement (section 4) to Preserve
679 +its Title (section 1) will typically require changing the actual
680 +title.
681 +
682 +@item
683 +TERMINATION
684 +
685 +You may not copy, modify, sublicense, or distribute the Document except
686 +as expressly provided for under this License. Any other attempt to
687 +copy, modify, sublicense or distribute the Document is void, and will
688 +automatically terminate your rights under this License. However,
689 +parties who have received copies, or rights, from you under this
690 +License will not have their licenses terminated so long as such
691 +parties remain in full compliance.
692 +
693 +@item
694 +FUTURE REVISIONS OF THIS LICENSE
695 +
696 +The Free Software Foundation may publish new, revised versions
697 +of the GNU Free Documentation License from time to time. Such new
698 +versions will be similar in spirit to the present version, but may
699 +differ in detail to address new problems or concerns. See
700 +@uref{http://www.gnu.org/copyleft/}.
701 +
702 +Each version of the License is given a distinguishing version number.
703 +If the Document specifies that a particular numbered version of this
704 +License ``or any later version'' applies to it, you have the option of
705 +following the terms and conditions either of that specified version or
706 +of any later version that has been published (not as a draft) by the
707 +Free Software Foundation. If the Document does not specify a version
708 +number of this License, you may choose any version ever published (not
709 +as a draft) by the Free Software Foundation.
710 +@end enumerate
711 +
712 +@page
713 +@appendixsubsec ADDENDUM: How to use this License for your documents
714 +
715 +To use this License in a document you have written, include a copy of
716 +the License in the document and put the following copyright and
717 +license notices just after the title page:
718 +
719 +@smallexample
720 +@group
721 + Copyright (C) @var{year} @var{your name}.
722 + Permission is granted to copy, distribute and/or modify this document
723 + under the terms of the GNU Free Documentation License, Version 1.2
724 + or any later version published by the Free Software Foundation;
725 + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
726 + Texts. A copy of the license is included in the section entitled ``GNU
727 + Free Documentation License''.
728 +@end group
729 +@end smallexample
730 +
731 +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
732 +replace the ``with...Texts.'' line with this:
733 +
734 +@smallexample
735 +@group
736 + with the Invariant Sections being @var{list their titles}, with
737 + the Front-Cover Texts being @var{list}, and with the Back-Cover Texts
738 + being @var{list}.
739 +@end group
740 +@end smallexample
741 +
742 +If you have Invariant Sections without Cover Texts, or some other
743 +combination of the three, merge those two alternatives to suit the
744 +situation.
745 +
746 +If your document contains nontrivial examples of program code, we
747 +recommend releasing these examples in parallel under your choice of
748 +free software license, such as the GNU General Public License,
749 +to permit their use in free software.
750 +
751 +@c Local Variables:
752 +@c ispell-local-pdict: "ispell-dict"
753 +@c End:
754 +
755 diff -Nur grub-0.97/docs/grub.8 grub-0.97-patched/docs/grub.8
756 --- grub-0.97/docs/grub.8 2005-05-08 04:48:56.000000000 +0200
757 +++ grub-0.97-patched/docs/grub.8 2012-11-11 17:07:12.715729211 +0100
758 @@ -1,5 +1,5 @@
759 .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.23.
760 -.TH GRUB "8" "May 2005" "grub (GNU GRUB 0.97)" FSF
761 +.TH GRUB "8" "June 2006" "grub (GNU GRUB 0.97)" FSF
762 .SH NAME
763 grub \- the grub shell
764 .SH SYNOPSIS
765 diff -Nur grub-0.97/docs/grub.8.additions grub-0.97-patched/docs/grub.8.additions
766 --- grub-0.97/docs/grub.8.additions 1970-01-01 01:00:00.000000000 +0100
767 +++ grub-0.97-patched/docs/grub.8.additions 2012-11-11 17:07:12.702728798 +0100
768 @@ -0,0 +1,3 @@
769 +[SEE ALSO]
770 +.BR update-grub (8),
771 +.BR grub-install (8).
772 diff -Nur grub-0.97/docs/grub-install.8 grub-0.97-patched/docs/grub-install.8
773 --- grub-0.97/docs/grub-install.8 2005-05-08 04:48:56.000000000 +0200
774 +++ grub-0.97-patched/docs/grub-install.8 2012-11-11 17:07:12.713729149 +0100
775 @@ -1,5 +1,5 @@
776 .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.23.
777 -.TH GRUB-INSTALL "8" "May 2005" "grub-install (GNU GRUB 0.97)" FSF
778 +.TH GRUB-INSTALL "8" "June 2006" "grub-install (GNU GRUB 0.97)" FSF
779 .SH NAME
780 grub-install \- install GRUB on your drive
781 .SH SYNOPSIS
782 diff -Nur grub-0.97/docs/grub-install.8.additions grub-0.97-patched/docs/grub-install.8.additions
783 --- grub-0.97/docs/grub-install.8.additions 1970-01-01 01:00:00.000000000 +0100
784 +++ grub-0.97-patched/docs/grub-install.8.additions 2012-11-11 17:07:12.703728829 +0100
785 @@ -0,0 +1,3 @@
786 +[SEE ALSO]
787 +.BR grub (8),
788 +.BR update-grub (8).
789 diff -Nur grub-0.97/docs/grub-md5-crypt.8 grub-0.97-patched/docs/grub-md5-crypt.8
790 --- grub-0.97/docs/grub-md5-crypt.8 2005-05-08 04:48:56.000000000 +0200
791 +++ grub-0.97-patched/docs/grub-md5-crypt.8 2012-11-11 17:07:12.713729149 +0100
792 @@ -1,5 +1,5 @@
793 .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.23.
794 -.TH GRUB-MD5-CRYPT "8" "May 2005" "grub-md5-crypt (GNU GRUB )" FSF
795 +.TH GRUB-MD5-CRYPT "8" "June 2006" "grub-md5-crypt (GNU GRUB )" FSF
796 .SH NAME
797 grub-md5-crypt \- Encrypt a password in MD5 format
798 .SH SYNOPSIS
799 diff -Nur grub-0.97/docs/grub-terminfo.8 grub-0.97-patched/docs/grub-terminfo.8
800 --- grub-0.97/docs/grub-terminfo.8 2005-05-08 04:48:56.000000000 +0200
801 +++ grub-0.97-patched/docs/grub-terminfo.8 2012-11-11 17:07:12.714729180 +0100
802 @@ -1,5 +1,5 @@
803 .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.23.
804 -.TH GRUB-TERMINFO "8" "May 2005" "grub-terminfo (GNU GRUB 0.97)" FSF
805 +.TH GRUB-TERMINFO "8" "June 2006" "grub-terminfo (GNU GRUB 0.97)" FSF
806 .SH NAME
807 grub-terminfo \- Generate a terminfo command from a terminfo name
808 .SH SYNOPSIS
809 diff -Nur grub-0.97/docs/grub.texi grub-0.97-patched/docs/grub.texi
810 --- grub-0.97/docs/grub.texi 2005-05-08 04:59:59.000000000 +0200
811 +++ grub-0.97-patched/docs/grub.texi 2012-11-11 17:07:12.717729276 +0100
812 @@ -2,22 +2,41 @@
813 @c -*-texinfo-*-
814 @c %**start of header
815 @setfilename grub.info
816 -@settitle GRUB Manual
817 -@c %**end of header
818 -
819 @include version.texi
820 -
821 +@settitle GNU GRUB Manual @value{VERSION}
822 @c Unify all our little indices for now.
823 @syncodeindex fn cp
824 @syncodeindex vr cp
825 @syncodeindex ky cp
826 @syncodeindex pg cp
827 @syncodeindex tp cp
828 +@c %**end of header
829
830 @footnotestyle separate
831 @paragraphindent 3
832 @finalout
833
834 +@copying
835 +This manual is for GNU GRUB (version @value{VERSION},
836 +@value{UPDATED}).
837 +
838 +Copyright @copyright{} 1999,2000,2001,2002,2004,2006 Free Software Foundation, Inc.
839 +
840 +@quotation
841 +Permission is granted to copy, distribute and/or modify this document
842 +under the terms of the GNU Free Documentation License, Version 1.2 or
843 +any later version published by the Free Software Foundation; with no
844 +Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,''
845 +and with the Back-Cover Texts as in (a) below. A copy of the
846 +license is included in the section entitled ``GNU Free Documentation
847 +License.''
848 +
849 +(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
850 +this GNU Manual, like GNU software. Copies published by the Free
851 +Software Foundation raise funds for GNU development.''
852 +@end quotation
853 +@end copying
854 +
855 @dircategory Kernel
856 @direntry
857 * GRUB: (grub). The GRand Unified Bootloader
858 @@ -34,53 +53,16 @@
859
860 @setchapternewpage odd
861
862 -@ifinfo
863 -Copyright @copyright{} 1999,2000,2001,2002,2004 Free Software Foundation, Inc.
864 -
865 -Permission is granted to make and distribute verbatim copies of
866 -this manual provided the copyright notice and this permission notice
867 -are preserved on all copies.
868 -
869 -@ignore
870 -Permission is granted to process this file through TeX and print the
871 -results, provided the printed document carries a copying permission
872 -notice identical to this one except for the removal of this paragraph
873 -(this paragraph not being relevant to the printed manual).
874 -
875 -@end ignore
876 -
877 -Permission is granted to copy and distribute modified versions of this
878 -manual under the conditions for verbatim copying, provided also that
879 -the entire resulting derived work is distributed under the terms of a
880 -permission notice identical to this one.
881 -
882 -Permission is granted to copy and distribute translations of this manual
883 -into another language, under the above conditions for modified versions.
884 -@end ifinfo
885 -
886 @titlepage
887 @sp 10
888 -@title the GRUB manual
889 +@title the GNU GRUB manual
890 @subtitle The GRand Unified Bootloader, version @value{VERSION}, @value{UPDATED}.
891 @author Gordon Matzigkeit
892 @author Yoshinori K. Okuji
893 @c The following two commands start the copyright page.
894 @page
895 @vskip 0pt plus 1filll
896 -Copyright @copyright{} 1999,2000,2001,2002,2004 Free Software Foundation, Inc.
897 -
898 -Permission is granted to make and distribute verbatim copies of
899 -this manual provided the copyright notice and this permission notice
900 -are preserved on all copies.
901 -Permission is granted to copy and distribute modified versions of this
902 -manual under the conditions for verbatim copying, provided that the entire
903 -resulting derived work is distributed under the terms of a permission
904 -notice identical to this one.
905 -
906 -Permission is granted to copy and distribute translations of this manual
907 -into another language, under the above conditions for modified versions,
908 -except that this permission notice may be stated in a translation approved
909 -by Free Software Foundation.
910 +@insertcopying
911 @end titlepage
912
913 @c Output the table of contents at the beginning.
914 @@ -91,12 +73,14 @@
915
916 @ifnottex
917 @node Top
918 -@top GRUB manual
919 +@top GNU GRUB manual
920
921 This is the documentation of GNU GRUB, the GRand Unified Bootloader,
922 a flexible and powerful boot loader program for @sc{pc}s.
923
924 This edition documents version @value{VERSION}.
925 +
926 +@insertcopying
927 @end ifnottex
928
929 @menu
930 @@ -124,6 +108,7 @@
931 * Reporting bugs:: Where you should send a bug report
932 * Future:: Some future plans on GRUB
933 * Internals:: Hacking GRUB
934 +* Copying This Manual:: Copying This Manual
935 * Index::
936 @end menu
937
938 @@ -3965,6 +3950,16 @@
939 @include internals.texi
940
941
942 +@node Copying This Manual
943 +@appendix Copying This Manual
944 +
945 +@menu
946 +* GNU Free Documentation License:: License for copying this manual.
947 +@end menu
948 +
949 +@include fdl.texi
950 +
951 +
952 @node Index
953 @unnumbered Index
954
955 diff -Nur grub-0.97/docs/help2man grub-0.97-patched/docs/help2man
956 --- grub-0.97/docs/help2man 2003-07-09 13:45:36.000000000 +0200
957 +++ grub-0.97-patched/docs/help2man 2012-11-11 17:07:12.701728766 +0100
958 @@ -455,7 +455,9 @@
959 $include{$sect} .= <<EOT;
960 The full documentation for
961 .B $program
962 -is maintained as a Texinfo manual. If the
963 +is maintained as a Texinfo manual in the
964 +.B grub-doc
965 +package. If the
966 .B info
967 and
968 .B $program
969 diff -Nur grub-0.97/docs/Makefile.am grub-0.97-patched/docs/Makefile.am
970 --- grub-0.97/docs/Makefile.am 2003-07-09 13:45:35.000000000 +0200
971 +++ grub-0.97-patched/docs/Makefile.am 2012-11-11 17:07:12.711729085 +0100
972 @@ -1,5 +1,5 @@
973 info_TEXINFOS = grub.texi multiboot.texi
974 -grub_TEXINFOS = internals.texi
975 +grub_TEXINFOS = internals.texi fdl.texi
976 EXAMPLES = boot.S kernel.c multiboot.h
977 multiboot_TEXINFOS = boot.S.texi kernel.c.texi multiboot.h.texi
978 man_MANS = grub.8 mbchk.1 grub-install.8 grub-md5-crypt.8 grub-terminfo.8
979 @@ -37,14 +37,14 @@
980 $(SHELL) $(srcdir)/$(SRC2TEXI) $(srcdir) $< $@
981
982 if MAINTAINER_MODE
983 -$(srcdir)/grub.8: ../grub/grub $(srcdir)/$(HELP2MAN)
984 +$(srcdir)/grub.8: ../grub/grub $(srcdir)/$(HELP2MAN) $(srcdir)/grub.8.additions
985 $(PERL) $(srcdir)/$(HELP2MAN) --name="the grub shell" \
986 - --section=8 --output=$@ $<
987 + --section=8 --include=$@.additions --output=$@ $<
988
989 -$(srcdir)/grub-install.8: ../util/grub-install $(srcdir)/$(HELP2MAN)
990 +$(srcdir)/grub-install.8: ../util/grub-install $(srcdir)/$(HELP2MAN) $(srcdir)/grub-install.8.additions
991 chmod 755 $<
992 $(PERL) $(srcdir)/$(HELP2MAN) --name="install GRUB on your drive" \
993 - --section=8 --output=$@ $<
994 + --section=8 --include=$@.additions --output=$@ $<
995
996 $(srcdir)/mbchk.1: ../util/mbchk $(srcdir)/$(HELP2MAN)
997 $(PERL) $(srcdir)/$(HELP2MAN) \
998 diff -Nur grub-0.97/docs/mbchk.1 grub-0.97-patched/docs/mbchk.1
999 --- grub-0.97/docs/mbchk.1 2005-05-08 04:48:56.000000000 +0200
1000 +++ grub-0.97-patched/docs/mbchk.1 2012-11-11 17:07:12.717729276 +0100
1001 @@ -1,5 +1,5 @@
1002 .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.23.
1003 -.TH MBCHK "1" "May 2005" "mbchk (GNU GRUB 0.97)" FSF
1004 +.TH MBCHK "1" "June 2006" "mbchk (GNU GRUB 0.97)" FSF
1005 .SH NAME
1006 mbchk \- check the format of a Multiboot kernel
1007 .SH SYNOPSIS
1008 diff -Nur grub-0.97/docs/menu.lst grub-0.97-patched/docs/menu.lst
1009 --- grub-0.97/docs/menu.lst 2004-05-11 14:11:17.000000000 +0200
1010 +++ grub-0.97-patched/docs/menu.lst 2012-11-11 17:07:07.225553829 +0100
1011 @@ -11,6 +11,9 @@
1012 # Fallback to the second entry.
1013 fallback 1
1014
1015 +# Splash image to show behind grub.
1016 +splashimage=(hd0,0)/boot/grub/splash.xpm.gz
1017 +
1018 # For booting GNU/Hurd
1019 title GNU/Hurd
1020 root (hd0,0)
1021 @@ -23,6 +26,11 @@
1022 kernel /vmlinuz root=/dev/hdb1
1023 #initrd /initrd.img
1024
1025 +# For booting Gentoo with the static rescue shell
1026 +title Gentoo (rescue shell)
1027 +root (hd1,0)
1028 +kernel /vmlinuz root=/dev/hdb1 init=/bin/bb
1029 +
1030 # For booting GNU/kFreeBSD
1031 title GNU/kFreeBSD
1032 root (hd0,2,a)
1033 diff -Nur grub-0.97/docs/menu.lst.orig grub-0.97-patched/docs/menu.lst.orig
1034 --- grub-0.97/docs/menu.lst.orig 1970-01-01 01:00:00.000000000 +0100
1035 +++ grub-0.97-patched/docs/menu.lst.orig 2004-05-11 14:11:17.000000000 +0200
1036 @@ -0,0 +1,82 @@
1037 +#
1038 +# Sample boot menu configuration file
1039 +#
1040 +
1041 +# Boot automatically after 30 secs.
1042 +timeout 30
1043 +
1044 +# By default, boot the first entry.
1045 +default 0
1046 +
1047 +# Fallback to the second entry.
1048 +fallback 1
1049 +
1050 +# For booting GNU/Hurd
1051 +title GNU/Hurd
1052 +root (hd0,0)
1053 +kernel /boot/gnumach.gz root=hd0s1
1054 +module /boot/serverboot.gz
1055 +
1056 +# For booting GNU/Linux
1057 +title GNU/Linux
1058 +root (hd1,0)
1059 +kernel /vmlinuz root=/dev/hdb1
1060 +#initrd /initrd.img
1061 +
1062 +# For booting GNU/kFreeBSD
1063 +title GNU/kFreeBSD
1064 +root (hd0,2,a)
1065 +kernel /boot/loader.gz
1066 +
1067 +# For booting GNU/kNetBSD
1068 +title GNU/kNetBSD
1069 +root (hd0,2,a)
1070 +kernel --type=netbsd /boot/knetbsd.gz
1071 +
1072 +# For booting Mach (getting kernel from floppy)
1073 +title Utah Mach4 multiboot
1074 +root (hd0,2)
1075 +pause Insert the diskette now\a!!
1076 +kernel (fd0)/boot/kernel root=hd0s3
1077 +module (fd0)/boot/bootstrap
1078 +
1079 +# For booting FreeBSD
1080 +title FreeBSD
1081 +root (hd0,2,a)
1082 +kernel /boot/loader
1083 +
1084 +# For booting NetBSD
1085 +title NetBSD
1086 +root (hd0,2,a)
1087 +kernel --type=netbsd /netbsd
1088 +
1089 +# For booting OpenBSD
1090 +title OpenBSD
1091 +root (hd0,2,a)
1092 +kernel --type=netbsd /bsd
1093 +
1094 +# For booting OS/2
1095 +title OS/2
1096 +root (hd0,1)
1097 +makeactive
1098 +# chainload OS/2 bootloader from the first sector
1099 +chainloader +1
1100 +# This is similar to "chainload", but loads a specific file
1101 +#chainloader /boot/chain.os2
1102 +
1103 +# For booting Windows NT or Windows95
1104 +title Windows NT / Windows 95 boot menu
1105 +rootnoverify (hd0,0)
1106 +makeactive
1107 +chainloader +1
1108 +# For loading DOS if Windows NT is installed
1109 +# chainload /bootsect.dos
1110 +
1111 +# For installing GRUB into the hard disk
1112 +title Install GRUB into the hard disk
1113 +root (hd0,0)
1114 +setup (hd0)
1115 +
1116 +# Change the colors.
1117 +title Change the colors
1118 +color light-green/brown blink-red/blue
1119 diff -Nur grub-0.97/docs/multiboot.texi grub-0.97-patched/docs/multiboot.texi
1120 --- grub-0.97/docs/multiboot.texi 2003-07-09 13:45:36.000000000 +0200
1121 +++ grub-0.97-patched/docs/multiboot.texi 2012-11-11 17:07:12.718729309 +0100
1122 @@ -1,32 +1,28 @@
1123 \input texinfo @c -*-texinfo-*-
1124 -@c -*-texinfo-*-
1125 @c %**start of header
1126 @setfilename multiboot.info
1127 -@settitle Multiboot Specification
1128 -@c %**end of header
1129 -
1130 +@set VERSION 0.6.95
1131 +@settitle Multiboot Specification version @value{VERSION}
1132 @c Unify all our little indices for now.
1133 @syncodeindex fn cp
1134 @syncodeindex vr cp
1135 @syncodeindex ky cp
1136 @syncodeindex pg cp
1137 @syncodeindex tp cp
1138 +@c %**end of header
1139
1140 @footnotestyle separate
1141 @paragraphindent 3
1142 @finalout
1143
1144 +@copying
1145 +Copyright @copyright{} 1995,96 Bryan Ford <baford@@cs.utah.edu>
1146
1147 -@dircategory Kernel
1148 -@direntry
1149 -* Multiboot Specification: (multiboot). Multiboot Specification.
1150 -@end direntry
1151 +Copyright @copyright{} 1995,96 Erich Stefan Boleyn <erich@@uruk.org>
1152
1153 -@ifinfo
1154 -Copyright @copyright{} 1995, 96 Bryan Ford <baford@@cs.utah.edu>
1155 -Copyright @copyright{} 1995, 96 Erich Stefan Boleyn <erich@@uruk.org>
1156 -Copyright @copyright{} 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
1157 +Copyright @copyright{} 1999,2000,2001,2002,2005,2006 Free Software Foundation, Inc.
1158
1159 +@quotation
1160 Permission is granted to make and distribute verbatim copies of
1161 this manual provided the copyright notice and this permission notice
1162 are preserved on all copies.
1163 @@ -36,7 +32,6 @@
1164 results, provided the printed document carries a copying permission
1165 notice identical to this one except for the removal of this paragraph
1166 (this paragraph not being relevant to the printed manual).
1167 -
1168 @end ignore
1169
1170 Permission is granted to copy and distribute modified versions of this
1171 @@ -45,31 +40,23 @@
1172 permission notice identical to this one.
1173
1174 Permission is granted to copy and distribute translations of this manual
1175 -into another language, under the above conditions for modified versions.
1176 -@end ifinfo
1177 +into another language, under the above conditions for modified
1178 +versions.
1179 +@end quotation
1180 +@end copying
1181 +
1182 +@dircategory Kernel
1183 +@direntry
1184 +* Multiboot Specification: (multiboot). Multiboot Specification.
1185 +@end direntry
1186
1187 @titlepage
1188 @sp 10
1189 -@title The Multiboot Specification
1190 +@title The Multiboot Specification version @value{VERSION}
1191 @author Yoshinori K. Okuji, Bryan Ford, Erich Stefan Boleyn, Kunihiro Ishiguro
1192 @page
1193 -
1194 @vskip 0pt plus 1filll
1195 -Copyright @copyright{} 1995, 96 Bryan Ford <baford@@cs.utah.edu>
1196 -Copyright @copyright{} 1995, 96 Erich Stefan Boleyn <erich@@uruk.org>
1197 -Copyright @copyright{} 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
1198 -
1199 -Permission is granted to make and distribute verbatim copies of
1200 -this manual provided the copyright notice and this permission notice
1201 -are preserved on all copies.
1202 -
1203 -Permission is granted to copy and distribute modified versions of this
1204 -manual under the conditions for verbatim copying, provided also that
1205 -the entire resulting derived work is distributed under the terms of a
1206 -permission notice identical to this one.
1207 -
1208 -Permission is granted to copy and distribute translations of this manual
1209 -into another language, under the above conditions for modified versions.
1210 +@insertcopying
1211 @end titlepage
1212
1213 @finalout
1214 @@ -80,7 +67,9 @@
1215 @top Multiboot Specification
1216
1217 This file documents Multiboot Specification, the proposal for the boot
1218 -sequence standard. This edition documents version 0.6.93.
1219 +sequence standard. This edition documents version @value{VERSION}.
1220 +
1221 +@insertcopying
1222 @end ifnottex
1223
1224 @menu
1225 @@ -426,7 +415,7 @@
1226 kernel.
1227
1228 If bit 16 in the @samp{flags} word is set, then the fields at offsets
1229 -8-24 in the Multiboot header are valid, and the boot loader should use
1230 +12-28 in the Multiboot header are valid, and the boot loader should use
1231 them instead of the fields in the actual executable header to calculate
1232 where to load the OS image. This information does not need to be
1233 provided if the kernel image is in @sc{elf} format, but it @emph{must}
1234 @@ -677,7 +666,7 @@
1235 @example
1236 @group
1237 +-------+-------+-------+-------+
1238 -| drive | part1 | part2 | part3 |
1239 +| part3 | part2 | part1 | drive |
1240 +-------+-------+-------+-------+
1241 @end group
1242 @end example
1243 @@ -1197,6 +1186,17 @@
1244 @item
1245 The maintainer changes to the GNU GRUB maintainer team
1246 @email{bug-grub@@gnu.org}, from Bryan Ford and Erich Stefan Boleyn.
1247 +
1248 +@item
1249 +The byte order of the @samp{boot_device} in Multiboot information is
1250 +reversed. This was a mistake.
1251 +
1252 +@item
1253 +The offset of the address fields were wrong.
1254 +
1255 +@item
1256 +The format is adapted to a newer Texinfo, and the version number is
1257 +specified more explicitly in the title.
1258 @end itemize
1259
1260 @item 0.6
1261 diff -Nur grub-0.97/grub/asmstub.c grub-0.97-patched/grub/asmstub.c
1262 --- grub-0.97/grub/asmstub.c 2005-02-16 21:45:14.000000000 +0100
1263 +++ grub-0.97-patched/grub/asmstub.c 2012-11-11 17:07:12.719729342 +0100
1264 @@ -42,6 +42,7 @@
1265 #include <sys/time.h>
1266 #include <termios.h>
1267 #include <signal.h>
1268 +#include <sys/mman.h>
1269
1270 #ifdef __linux__
1271 # include <sys/ioctl.h> /* ioctl */
1272 @@ -55,6 +56,10 @@
1273 # endif /* ! BLKFLSBUF */
1274 #endif /* __linux__ */
1275
1276 +#if defined(__FreeBSD_kernel__) || defined(__FreeBSD__)
1277 +# include <sys/sysctl.h>
1278 +#endif
1279 +
1280 /* We want to prevent any circularararity in our stubs, as well as
1281 libc name clashes. */
1282 #define WITHOUT_LIBC_STUBS 1
1283 @@ -79,7 +84,7 @@
1284 struct apm_info apm_bios_info;
1285
1286 /* Emulation requirements. */
1287 -char *grub_scratch_mem = 0;
1288 +void *grub_scratch_mem = 0;
1289
1290 struct geometry *disks = 0;
1291
1292 @@ -103,14 +108,62 @@
1293 static unsigned int serial_speed;
1294 #endif /* SIMULATE_SLOWNESS_OF_SERIAL */
1295
1296 +/* This allocates page-aligned storage of the specified size, which must be
1297 + * a multiple of the page size as determined by calling sysconf(_SC_PAGESIZE)
1298 + */
1299 +#ifdef __linux__
1300 +static void *
1301 +grub_mmap_alloc(size_t len)
1302 +{
1303 + int mmap_flags = MAP_ANONYMOUS|MAP_PRIVATE;
1304 +
1305 +#ifdef MAP_32BIT
1306 + mmap_flags |= MAP_32BIT;
1307 +#endif
1308 + /* Mark the simulated stack executable, as GCC uses stack trampolines
1309 + * to implement nested functions. */
1310 + return mmap(NULL, len, PROT_READ|PROT_WRITE|PROT_EXEC, mmap_flags, -1, 0);
1311 +}
1312 +#else /* !defined(__linux__) */
1313 +static void *
1314 +grub_mmap_alloc(size_t len)
1315 +{
1316 + int fd = 0, offset = 0, ret = 0;
1317 + void *pa = MAP_FAILED;
1318 + char template[] = "/tmp/grub_mmap_alloc_XXXXXX";
1319 + int e;
1320 +
1321 + fd = mkstemp(template);
1322 + if (fd < 0)
1323 + return pa;
1324 +
1325 + unlink(template);
1326 +
1327 + ret = ftruncate(fd, len);
1328 + if (ret < 0)
1329 + return pa;
1330 +
1331 + /* Mark the simulated stack executable, as GCC uses stack trampolines
1332 + * to implement nested functions. */
1333 + pa = mmap(NULL, len, PROT_READ|PROT_WRITE|PROT_EXEC,
1334 + MAP_PRIVATE, fd, offset);
1335 +
1336 + e = errno;
1337 + close(fd);
1338 + errno = e;
1339 + return pa;
1340 +}
1341 +#endif /* defined(__linux__) */
1342 +
1343 /* The main entry point into this mess. */
1344 int
1345 grub_stage2 (void)
1346 {
1347 /* These need to be static, because they survive our stack transitions. */
1348 static int status = 0;
1349 - static char *realstack;
1350 - char *scratch, *simstack;
1351 + static void *realstack;
1352 + void *simstack_alloc_base, *simstack;
1353 + size_t simstack_size, page_size;
1354 int i;
1355
1356 auto void doit (void);
1357 @@ -142,9 +195,35 @@
1358 }
1359
1360 assert (grub_scratch_mem == 0);
1361 - scratch = malloc (0x100000 + EXTENDED_MEMSIZE + 15);
1362 - assert (scratch);
1363 - grub_scratch_mem = (char *) ((((int) scratch) >> 4) << 4);
1364 +
1365 + /* Allocate enough pages for 0x100000 + EXTENDED_SIZE + 15, and
1366 + * make sure the memory is aligned to a multiple of the system's
1367 + * page size */
1368 + page_size = sysconf (_SC_PAGESIZE);
1369 + simstack_size = ( 0x100000 + EXTENDED_MEMSIZE + 15);
1370 + if (simstack_size % page_size)
1371 + {
1372 + /* If we're not on a page_size boundary, round up to the next one */
1373 + simstack_size &= ~(page_size-1);
1374 + simstack_size += page_size;
1375 + }
1376 +
1377 + /* Add one for a PROT_NONE boundary page at each end. */
1378 + simstack_size += 2 * page_size;
1379 +
1380 + simstack_alloc_base = grub_mmap_alloc(simstack_size);
1381 + assert (simstack_alloc_base != MAP_FAILED);
1382 +
1383 + /* mark pages above and below our simstack area as innaccessable.
1384 + * If the implementation we're using doesn't support that, then the
1385 + * new protection modes are undefined. It's safe to just ignore
1386 + * them, though. It'd be nice if we knew that we'd get a SEGV for
1387 + * touching the area, but that's all. it'd be nice to have. */
1388 + mprotect (simstack_alloc_base, page_size, PROT_NONE);
1389 + mprotect ((void *)((unsigned long)simstack_alloc_base +
1390 + simstack_size - page_size), page_size, PROT_NONE);
1391 +
1392 + grub_scratch_mem = (void *)((unsigned long)simstack_alloc_base + page_size);
1393
1394 /* FIXME: simulate the memory holes using mprot, if available. */
1395
1396 @@ -217,7 +296,7 @@
1397 device_map = 0;
1398 free (disks);
1399 disks = 0;
1400 - free (scratch);
1401 + munmap(simstack_alloc_base, simstack_size);
1402 grub_scratch_mem = 0;
1403
1404 if (serial_device)
1405 @@ -777,7 +856,39 @@
1406
1407 /* Open read/write, or read-only if that failed. */
1408 if (! read_only)
1409 - disks[drive].flags = open (devname, O_RDWR);
1410 + {
1411 +/* By default, kernel of FreeBSD does not allow overwriting MBR */
1412 +#if defined(__FreeBSD_kernel__) || defined(__FreeBSD__)
1413 +#define GEOM_SYSCTL "kern.geom.debugflags"
1414 + int old_flags, flags;
1415 + size_t sizeof_int = sizeof (int);
1416 +
1417 + if (sysctlbyname (GEOM_SYSCTL, &old_flags, &sizeof_int, NULL, 0) != 0)
1418 + grub_printf ("failed to get " GEOM_SYSCTL "sysctl: %s\n", strerror (errno));
1419 +
1420 + if ((old_flags & 0x10) == 0)
1421 + {
1422 + /* "allow foot shooting", see geom(4) */
1423 + flags = old_flags | 0x10;
1424 +
1425 + if (sysctlbyname (GEOM_SYSCTL, NULL, NULL, &flags, sizeof (int)) != 0)
1426 + {
1427 + flags = old_flags;
1428 + grub_printf ("failed to set " GEOM_SYSCTL "sysctl: %s\n", strerror (errno));
1429 + }
1430 + }
1431 + else
1432 + flags = old_flags;
1433 +#endif
1434 + disks[drive].flags = open (devname, O_RDWR);
1435 +#if defined(__FreeBSD_kernel__) || defined(__FreeBSD__)
1436 + if (flags != old_flags)
1437 + {
1438 + if (sysctlbyname (GEOM_SYSCTL, NULL, NULL, &old_flags, sizeof (int)) != 0)
1439 + grub_printf ("failed to set " GEOM_SYSCTL "sysctl: %s\n", strerror (errno));
1440 + }
1441 +#endif
1442 + }
1443
1444 if (disks[drive].flags == -1)
1445 {
1446 @@ -926,7 +1037,7 @@
1447
1448 int
1449 biosdisk (int subfunc, int drive, struct geometry *geometry,
1450 - int sector, int nsec, int segment)
1451 + unsigned int sector, int nsec, int segment)
1452 {
1453 char *buf;
1454 int fd = geometry->flags;
1455 diff -Nur grub-0.97/grub/asmstub.c.orig grub-0.97-patched/grub/asmstub.c.orig
1456 --- grub-0.97/grub/asmstub.c.orig 1970-01-01 01:00:00.000000000 +0100
1457 +++ grub-0.97-patched/grub/asmstub.c.orig 2005-02-16 21:45:14.000000000 +0100
1458 @@ -0,0 +1,1275 @@
1459 +/* asmstub.c - a version of shared_src/asm.S that works under Unix */
1460 +/*
1461 + * GRUB -- GRand Unified Bootloader
1462 + * Copyright (C) 1999,2000,2001,2002,2004 Free Software Foundation, Inc.
1463 + *
1464 + * This program is free software; you can redistribute it and/or modify
1465 + * it under the terms of the GNU General Public License as published by
1466 + * the Free Software Foundation; either version 2 of the License, or
1467 + * (at your option) any later version.
1468 + *
1469 + * This program is distributed in the hope that it will be useful,
1470 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1471 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1472 + * GNU General Public License for more details.
1473 + *
1474 + * You should have received a copy of the GNU General Public License
1475 + * along with this program; if not, write to the Free Software
1476 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1477 + */
1478 +
1479 +/* Try to use glibc's transparant LFS support. */
1480 +#define _LARGEFILE_SOURCE 1
1481 +/* lseek becomes synonymous with lseek64. */
1482 +#define _FILE_OFFSET_BITS 64
1483 +
1484 +/* Simulator entry point. */
1485 +int grub_stage2 (void);
1486 +
1487 +#include <stdlib.h>
1488 +#include <string.h>
1489 +#include <ctype.h>
1490 +#include <assert.h>
1491 +#include <stdio.h>
1492 +#include <sys/types.h>
1493 +#include <sys/stat.h>
1494 +#include <fcntl.h>
1495 +#include <time.h>
1496 +#include <errno.h>
1497 +#include <string.h>
1498 +#include <unistd.h>
1499 +#include <setjmp.h>
1500 +#include <sys/time.h>
1501 +#include <termios.h>
1502 +#include <signal.h>
1503 +
1504 +#ifdef __linux__
1505 +# include <sys/ioctl.h> /* ioctl */
1506 +# if !defined(__GLIBC__) || \
1507 + ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
1508 +/* Maybe libc doesn't have large file support. */
1509 +# include <linux/unistd.h> /* _llseek */
1510 +# endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */
1511 +# ifndef BLKFLSBUF
1512 +# define BLKFLSBUF _IO (0x12,97) /* flush buffer cache */
1513 +# endif /* ! BLKFLSBUF */
1514 +#endif /* __linux__ */
1515 +
1516 +/* We want to prevent any circularararity in our stubs, as well as
1517 + libc name clashes. */
1518 +#define WITHOUT_LIBC_STUBS 1
1519 +#include <shared.h>
1520 +#include <device.h>
1521 +#include <serial.h>
1522 +#include <term.h>
1523 +
1524 +/* Simulated memory sizes. */
1525 +#define EXTENDED_MEMSIZE (3 * 1024 * 1024) /* 3MB */
1526 +#define CONVENTIONAL_MEMSIZE (640 * 1024) /* 640kB */
1527 +
1528 +unsigned long install_partition = 0x20000;
1529 +unsigned long boot_drive = 0;
1530 +int saved_entryno = 0;
1531 +char version_string[] = VERSION;
1532 +char config_file[128] = "/boot/grub/menu.lst"; /* FIXME: arbitrary */
1533 +unsigned long linux_text_len = 0;
1534 +char *linux_data_tmp_addr = 0;
1535 +char *linux_data_real_addr = 0;
1536 +unsigned short io_map[IO_MAP_SIZE];
1537 +struct apm_info apm_bios_info;
1538 +
1539 +/* Emulation requirements. */
1540 +char *grub_scratch_mem = 0;
1541 +
1542 +struct geometry *disks = 0;
1543 +
1544 +/* The map between BIOS drives and UNIX device file names. */
1545 +char **device_map = 0;
1546 +
1547 +/* The jump buffer for exiting correctly. */
1548 +static jmp_buf env_for_exit;
1549 +
1550 +/* The current color for console. */
1551 +int console_current_color = A_NORMAL;
1552 +
1553 +/* The file descriptor for a serial device. */
1554 +static int serial_fd = -1;
1555 +
1556 +/* The file name of a serial device. */
1557 +static char *serial_device = 0;
1558 +
1559 +#ifdef SIMULATE_SLOWNESS_OF_SERIAL
1560 +/* The speed of a serial device. */
1561 +static unsigned int serial_speed;
1562 +#endif /* SIMULATE_SLOWNESS_OF_SERIAL */
1563 +
1564 +/* The main entry point into this mess. */
1565 +int
1566 +grub_stage2 (void)
1567 +{
1568 + /* These need to be static, because they survive our stack transitions. */
1569 + static int status = 0;
1570 + static char *realstack;
1571 + char *scratch, *simstack;
1572 + int i;
1573 +
1574 + auto void doit (void);
1575 +
1576 + /* We need a nested function so that we get a clean stack frame,
1577 + regardless of how the code is optimized. */
1578 + void doit (void)
1579 + {
1580 + /* Make sure our stack lives in the simulated memory area. */
1581 + asm volatile ("movl %%esp, %0\n\tmovl %1, %%esp\n"
1582 + : "=&r" (realstack) : "r" (simstack));
1583 +
1584 + /* Do a setjmp here for the stop command. */
1585 + if (! setjmp (env_for_exit))
1586 + {
1587 + /* Actually enter the generic stage2 code. */
1588 + status = 0;
1589 + init_bios_info ();
1590 + }
1591 + else
1592 + {
1593 + /* If ERRNUM is non-zero, then set STATUS to non-zero. */
1594 + if (errnum)
1595 + status = 1;
1596 + }
1597 +
1598 + /* Replace our stack before we use any local variables. */
1599 + asm volatile ("movl %0, %%esp\n" : : "r" (realstack));
1600 + }
1601 +
1602 + assert (grub_scratch_mem == 0);
1603 + scratch = malloc (0x100000 + EXTENDED_MEMSIZE + 15);
1604 + assert (scratch);
1605 + grub_scratch_mem = (char *) ((((int) scratch) >> 4) << 4);
1606 +
1607 + /* FIXME: simulate the memory holes using mprot, if available. */
1608 +
1609 + assert (disks == 0);
1610 + disks = malloc (NUM_DISKS * sizeof (*disks));
1611 + assert (disks);
1612 + /* Initialize DISKS. */
1613 + for (i = 0; i < NUM_DISKS; i++)
1614 + disks[i].flags = -1;
1615 +
1616 + if (! init_device_map (&device_map, device_map_file, floppy_disks))
1617 + return 1;
1618 +
1619 + /* Check some invariants. */
1620 + assert ((SCRATCHSEG << 4) == SCRATCHADDR);
1621 + assert ((BUFFERSEG << 4) == BUFFERADDR);
1622 + assert (BUFFERADDR + BUFFERLEN == SCRATCHADDR);
1623 + assert (FSYS_BUF % 16 == 0);
1624 + assert (FSYS_BUF + FSYS_BUFLEN == BUFFERADDR);
1625 +
1626 +#ifdef HAVE_LIBCURSES
1627 + /* Get into char-at-a-time mode. */
1628 + if (use_curses)
1629 + {
1630 + initscr ();
1631 + cbreak ();
1632 + noecho ();
1633 + nonl ();
1634 + scrollok (stdscr, TRUE);
1635 + keypad (stdscr, TRUE);
1636 + wtimeout (stdscr, 100);
1637 + signal (SIGWINCH, SIG_IGN);
1638 + }
1639 +#endif
1640 +
1641 + /* Make sure that actual writing is done. */
1642 + sync ();
1643 +
1644 + /* Set our stack, and go for it. */
1645 + simstack = (char *) PROTSTACKINIT;
1646 + doit ();
1647 +
1648 + /* I don't know if this is necessary really. */
1649 + sync ();
1650 +
1651 +#ifdef HAVE_LIBCURSES
1652 + if (use_curses)
1653 + endwin ();
1654 +#endif
1655 +
1656 + /* Close off the file descriptors we used. */
1657 + for (i = 0; i < NUM_DISKS; i ++)
1658 + if (disks[i].flags != -1)
1659 + {
1660 +#ifdef __linux__
1661 + /* In Linux, invalidate the buffer cache. In other OSes, reboot
1662 + is one of the solutions... */
1663 + ioctl (disks[i].flags, BLKFLSBUF, 0);
1664 +#else
1665 +# warning "In your operating system, the buffer cache will not be flushed."
1666 +#endif
1667 + close (disks[i].flags);
1668 + }
1669 +
1670 + if (serial_fd >= 0)
1671 + close (serial_fd);
1672 +
1673 + /* Release memory. */
1674 + restore_device_map (device_map);
1675 + device_map = 0;
1676 + free (disks);
1677 + disks = 0;
1678 + free (scratch);
1679 + grub_scratch_mem = 0;
1680 +
1681 + if (serial_device)
1682 + free (serial_device);
1683 + serial_device = 0;
1684 +
1685 + /* Ahh... at last we're ready to return to caller. */
1686 + return status;
1687 +}
1688 +
1689 +/* Assign DRIVE to a device name DEVICE. */
1690 +void
1691 +assign_device_name (int drive, const char *device)
1692 +{
1693 + /* If DRIVE is already assigned, free it. */
1694 + if (device_map[drive])
1695 + free (device_map[drive]);
1696 +
1697 + /* If the old one is already opened, close it. */
1698 + if (disks[drive].flags != -1)
1699 + {
1700 + close (disks[drive].flags);
1701 + disks[drive].flags = -1;
1702 + }
1703 +
1704 + /* Assign DRIVE to DEVICE. */
1705 + if (! device)
1706 + device_map[drive] = 0;
1707 + else
1708 + device_map[drive] = strdup (device);
1709 +}
1710 +
1711 +void
1712 +stop (void)
1713 +{
1714 +#ifdef HAVE_LIBCURSES
1715 + if (use_curses)
1716 + endwin ();
1717 +#endif
1718 +
1719 + /* Jump to doit. */
1720 + longjmp (env_for_exit, 1);
1721 +}
1722 +
1723 +void
1724 +grub_reboot (void)
1725 +{
1726 + stop ();
1727 +}
1728 +
1729 +void
1730 +grub_halt (int no_apm)
1731 +{
1732 + stop ();
1733 +}
1734 +
1735 +/* calls for direct boot-loader chaining */
1736 +void
1737 +chain_stage1 (unsigned long segment, unsigned long offset,
1738 + unsigned long part_table_addr)
1739 +{
1740 + stop ();
1741 +}
1742 +
1743 +
1744 +void
1745 +chain_stage2 (unsigned long segment, unsigned long offset, int second_sector)
1746 +{
1747 + stop ();
1748 +}
1749 +
1750 +
1751 +/* do some funky stuff, then boot linux */
1752 +void
1753 +linux_boot (void)
1754 +{
1755 + stop ();
1756 +}
1757 +
1758 +
1759 +/* For bzImage kernels. */
1760 +void
1761 +big_linux_boot (void)
1762 +{
1763 + stop ();
1764 +}
1765 +
1766 +
1767 +/* booting a multiboot executable */
1768 +void
1769 +multi_boot (int start, int mb_info)
1770 +{
1771 + stop ();
1772 +}
1773 +
1774 +/* sets it to linear or wired A20 operation */
1775 +void
1776 +gateA20 (int linear)
1777 +{
1778 + /* Nothing to do in the simulator. */
1779 +}
1780 +
1781 +/* Set up the int15 handler. */
1782 +void
1783 +set_int15_handler (void)
1784 +{
1785 + /* Nothing to do in the simulator. */
1786 +}
1787 +
1788 +/* Restore the original int15 handler. */
1789 +void
1790 +unset_int15_handler (void)
1791 +{
1792 + /* Nothing to do in the simulator. */
1793 +}
1794 +
1795 +/* The key map. */
1796 +unsigned short bios_key_map[KEY_MAP_SIZE + 1];
1797 +unsigned short ascii_key_map[KEY_MAP_SIZE + 1];
1798 +
1799 +/* Copy MAP to the drive map and set up the int13 handler. */
1800 +void
1801 +set_int13_handler (unsigned short *map)
1802 +{
1803 + /* Nothing to do in the simulator. */
1804 +}
1805 +
1806 +int
1807 +get_code_end (void)
1808 +{
1809 + /* Just return a little area for simulation. */
1810 + return BOOTSEC_LOCATION + (60 * 1024);
1811 +}
1812 +
1813 +
1814 +/* memory probe routines */
1815 +int
1816 +get_memsize (int type)
1817 +{
1818 + if (! type)
1819 + return CONVENTIONAL_MEMSIZE >> 10;
1820 + else
1821 + return EXTENDED_MEMSIZE >> 10;
1822 +}
1823 +
1824 +
1825 +/* get_eisamemsize() : return packed EISA memory map, lower 16 bits is
1826 + * memory between 1M and 16M in 1K parts, upper 16 bits is
1827 + * memory above 16M in 64K parts. If error, return -1.
1828 + */
1829 +int
1830 +get_eisamemsize (void)
1831 +{
1832 + return (EXTENDED_MEMSIZE >> 10);
1833 +}
1834 +
1835 +
1836 +#define MMAR_DESC_TYPE_AVAILABLE 1 /* available to OS */
1837 +#define MMAR_DESC_TYPE_RESERVED 2 /* not available */
1838 +#define MMAR_DESC_TYPE_ACPI_RECLAIM 3 /* usable by OS after reading ACPI */
1839 +#define MMAR_DESC_TYPE_ACPI_NVS 4 /* required to save between NVS sessions */
1840 +
1841 +#define MMAR_DESC_LENGTH 20
1842 +
1843 +/* Fetch the next entry in the memory map and return the continuation
1844 + value. DESC is a pointer to the descriptor buffer, and CONT is the
1845 + previous continuation value (0 to get the first entry in the
1846 + map). */
1847 +int
1848 +get_mmap_entry (struct mmar_desc *desc, int cont)
1849 +{
1850 + /* Record the memory map statically. */
1851 + static struct mmar_desc desc_table[] =
1852 + {
1853 + /* The conventional memory. */
1854 + {
1855 + MMAR_DESC_LENGTH,
1856 + 0,
1857 + CONVENTIONAL_MEMSIZE,
1858 + MMAR_DESC_TYPE_AVAILABLE
1859 + },
1860 + /* BIOS RAM and ROM (such as video memory). */
1861 + {
1862 + MMAR_DESC_LENGTH,
1863 + CONVENTIONAL_MEMSIZE,
1864 + 0x100000 - CONVENTIONAL_MEMSIZE,
1865 + MMAR_DESC_TYPE_RESERVED
1866 + },
1867 + /* The extended memory. */
1868 + {
1869 + MMAR_DESC_LENGTH,
1870 + 0x100000,
1871 + EXTENDED_MEMSIZE,
1872 + MMAR_DESC_TYPE_AVAILABLE
1873 + }
1874 + };
1875 +
1876 + int num = sizeof (desc_table) / sizeof (*desc_table);
1877 +
1878 + if (cont < 0 || cont >= num)
1879 + {
1880 + /* Should not happen. */
1881 + desc->desc_len = 0;
1882 + }
1883 + else
1884 + {
1885 + /* Copy the entry. */
1886 + *desc = desc_table[cont++];
1887 +
1888 + /* If the next entry exists, return the index. */
1889 + if (cont < num)
1890 + return cont;
1891 + }
1892 +
1893 + return 0;
1894 +}
1895 +
1896 +/* Track the int13 handler. */
1897 +void
1898 +track_int13 (int drive)
1899 +{
1900 + /* Nothing to do in the simulator. */
1901 +}
1902 +
1903 +/* Get the ROM configuration table. */
1904 +unsigned long
1905 +get_rom_config_table (void)
1906 +{
1907 + return 0;
1908 +}
1909 +
1910 +/* Get APM BIOS information. */
1911 +void
1912 +get_apm_info (void)
1913 +{
1914 + /* Nothing to do in the simulator. */
1915 +}
1916 +
1917 +/* Get VBE controller information. */
1918 +int
1919 +get_vbe_controller_info (struct vbe_controller *controller)
1920 +{
1921 + /* Always fails. */
1922 + return 0;
1923 +}
1924 +
1925 +/* Get VBE mode information. */
1926 +int
1927 +get_vbe_mode_info (int mode_number, struct vbe_mode *mode)
1928 +{
1929 + /* Always fails. */
1930 + return 0;
1931 +}
1932 +
1933 +/* Set VBE mode. */
1934 +int
1935 +set_vbe_mode (int mode_number)
1936 +{
1937 + /* Always fails. */
1938 + return 0;
1939 +}
1940 +
1941 +/* low-level timing info */
1942 +int
1943 +getrtsecs (void)
1944 +{
1945 + /* FIXME: exact value is not important, so just return time_t for now. */
1946 + return time (0);
1947 +}
1948 +
1949 +int
1950 +currticks (void)
1951 +{
1952 + struct timeval tv;
1953 + long csecs;
1954 + int ticks_per_csec, ticks_per_usec;
1955 +
1956 + /* Note: 18.2 ticks/sec. */
1957 +
1958 + /* Get current time. */
1959 + gettimeofday (&tv, 0);
1960 +
1961 + /* Compute centiseconds. */
1962 + csecs = tv.tv_sec / 10;
1963 +
1964 + /* Ticks per centisecond. */
1965 + ticks_per_csec = csecs * 182;
1966 +
1967 + /* Ticks per microsecond. */
1968 + ticks_per_usec = (((tv.tv_sec - csecs * 10) * 1000000 + tv.tv_usec)
1969 + * 182 / 10000000);
1970 +
1971 + /* Sum them. */
1972 + return ticks_per_csec + ticks_per_usec;
1973 +}
1974 +
1975 +/* displays an ASCII character. IBM displays will translate some
1976 + characters to special graphical ones */
1977 +void
1978 +console_putchar (int c)
1979 +{
1980 + /* Curses doesn't have VGA fonts. */
1981 + switch (c)
1982 + {
1983 + case DISP_UL:
1984 + c = ACS_ULCORNER;
1985 + break;
1986 + case DISP_UR:
1987 + c = ACS_URCORNER;
1988 + break;
1989 + case DISP_LL:
1990 + c = ACS_LLCORNER;
1991 + break;
1992 + case DISP_LR:
1993 + c = ACS_LRCORNER;
1994 + break;
1995 + case DISP_HORIZ:
1996 + c = ACS_HLINE;
1997 + break;
1998 + case DISP_VERT:
1999 + c = ACS_VLINE;
2000 + break;
2001 + case DISP_LEFT:
2002 + c = ACS_LARROW;
2003 + break;
2004 + case DISP_RIGHT:
2005 + c = ACS_RARROW;
2006 + break;
2007 + case DISP_UP:
2008 + c = ACS_UARROW;
2009 + break;
2010 + case DISP_DOWN:
2011 + c = ACS_DARROW;
2012 + break;
2013 + default:
2014 + break;
2015 + }
2016 +
2017 +#ifdef HAVE_LIBCURSES
2018 + if (use_curses)
2019 + {
2020 + /* In ncurses, a newline is treated badly, so we emulate it in our
2021 + own way. */
2022 + if (c == '\n')
2023 + {
2024 + int x, y;
2025 +
2026 + getyx (stdscr, y, x);
2027 + if (y + 1 == LINES)
2028 + scroll (stdscr);
2029 + else
2030 + move (y + 1, x);
2031 + }
2032 + else if (isprint (c))
2033 + {
2034 + int x, y;
2035 +
2036 + getyx (stdscr, y, x);
2037 + if (x + 1 == COLS)
2038 + {
2039 + console_putchar ('\r');
2040 + console_putchar ('\n');
2041 + }
2042 + addch (c | console_current_color);
2043 + }
2044 + else
2045 + {
2046 + addch (c);
2047 + }
2048 +
2049 +#ifdef REFRESH_IMMEDIATELY
2050 + refresh ();
2051 +#endif
2052 + }
2053 + else
2054 +#endif
2055 + {
2056 + /* CR is not used in Unix. */
2057 + if (c != '\r')
2058 + putchar (c);
2059 + }
2060 +}
2061 +
2062 +/* The store for ungetch simulation. This is necessary, because
2063 + ncurses-1.9.9g is still used in the world and its ungetch is
2064 + completely broken. */
2065 +#ifdef HAVE_LIBCURSES
2066 +static int save_char = ERR;
2067 +#endif
2068 +
2069 +static int
2070 +console_translate_key (int c)
2071 +{
2072 + switch (c)
2073 + {
2074 + case KEY_LEFT:
2075 + return 2;
2076 + case KEY_RIGHT:
2077 + return 6;
2078 + case KEY_UP:
2079 + return 16;
2080 + case KEY_DOWN:
2081 + return 14;
2082 + case KEY_DC:
2083 + return 4;
2084 + case KEY_BACKSPACE:
2085 + return 8;
2086 + case KEY_HOME:
2087 + return 1;
2088 + case KEY_END:
2089 + return 5;
2090 + case KEY_PPAGE:
2091 + return 7;
2092 + case KEY_NPAGE:
2093 + return 3;
2094 + default:
2095 + break;
2096 + }
2097 +
2098 + return c;
2099 +}
2100 +
2101 +/* like 'getkey', but doesn't wait, returns -1 if nothing available */
2102 +int
2103 +console_checkkey (void)
2104 +{
2105 +#ifdef HAVE_LIBCURSES
2106 + if (use_curses)
2107 + {
2108 + int c;
2109 +
2110 + /* Check for SAVE_CHAR. This should not be true, because this
2111 + means checkkey is called twice continuously. */
2112 + if (save_char != ERR)
2113 + return save_char;
2114 +
2115 + c = getch ();
2116 + /* If C is not ERR, then put it back in the input queue. */
2117 + if (c != ERR)
2118 + save_char = c;
2119 + return console_translate_key (c);
2120 + }
2121 +#endif
2122 +
2123 + /* Just pretend they hit the space bar, then read the real key when
2124 + they call getkey. */
2125 + return ' ';
2126 +}
2127 +
2128 +/* returns packed BIOS/ASCII code */
2129 +int
2130 +console_getkey (void)
2131 +{
2132 + int c;
2133 +
2134 +#ifdef HAVE_LIBCURSES
2135 + if (use_curses)
2136 + {
2137 + /* If checkkey has already got a character, then return it. */
2138 + if (save_char != ERR)
2139 + {
2140 + c = save_char;
2141 + save_char = ERR;
2142 + return console_translate_key (c);
2143 + }
2144 +
2145 + wtimeout (stdscr, -1);
2146 + c = getch ();
2147 + wtimeout (stdscr, 100);
2148 + }
2149 + else
2150 +#endif
2151 + c = getchar ();
2152 +
2153 + /* Quit if we get EOF. */
2154 + if (c == -1)
2155 + stop ();
2156 +
2157 + return console_translate_key (c);
2158 +}
2159 +
2160 +/* returns packed values, LSB+1 is x, LSB is y */
2161 +int
2162 +console_getxy (void)
2163 +{
2164 + int y, x;
2165 +#ifdef HAVE_LIBCURSES
2166 + if (use_curses)
2167 + getyx (stdscr, y, x);
2168 + else
2169 +#endif
2170 + y = x = 0;
2171 + return (x << 8) | (y & 0xff);
2172 +}
2173 +
2174 +void
2175 +console_gotoxy (int x, int y)
2176 +{
2177 +#ifdef HAVE_LIBCURSES
2178 + if (use_curses)
2179 + move (y, x);
2180 +#endif
2181 +}
2182 +
2183 +/* low-level character I/O */
2184 +void
2185 +console_cls (void)
2186 +{
2187 +#ifdef HAVE_LIBCURSES
2188 + if (use_curses)
2189 + clear ();
2190 +#endif
2191 +}
2192 +
2193 +void
2194 +console_setcolorstate (color_state state)
2195 +{
2196 + console_current_color =
2197 + (state == COLOR_STATE_HIGHLIGHT) ? A_REVERSE : A_NORMAL;
2198 +}
2199 +
2200 +void
2201 +console_setcolor (int normal_color, int highlight_color)
2202 +{
2203 + /* Nothing to do. */
2204 +}
2205 +
2206 +int
2207 +console_setcursor (int on)
2208 +{
2209 + return 1;
2210 +}
2211 +
2212 +/* Low-level disk I/O. Our stubbed version just returns a file
2213 + descriptor, not the actual geometry. */
2214 +int
2215 +get_diskinfo (int drive, struct geometry *geometry)
2216 +{
2217 + /* FIXME: this function is truly horrid. We try opening the device,
2218 + then severely abuse the GEOMETRY->flags field to pass a file
2219 + descriptor to biosdisk. Thank God nobody's looking at this comment,
2220 + or my reputation would be ruined. --Gord */
2221 +
2222 + /* See if we have a cached device. */
2223 + if (disks[drive].flags == -1)
2224 + {
2225 + /* The unpartitioned device name: /dev/XdX */
2226 + char *devname = device_map[drive];
2227 + char buf[512];
2228 +
2229 + if (! devname)
2230 + return -1;
2231 +
2232 + if (verbose)
2233 + grub_printf ("Attempt to open drive 0x%x (%s)\n",
2234 + drive, devname);
2235 +
2236 + /* Open read/write, or read-only if that failed. */
2237 + if (! read_only)
2238 + disks[drive].flags = open (devname, O_RDWR);
2239 +
2240 + if (disks[drive].flags == -1)
2241 + {
2242 + if (read_only || errno == EACCES || errno == EROFS || errno == EPERM)
2243 + {
2244 + disks[drive].flags = open (devname, O_RDONLY);
2245 + if (disks[drive].flags == -1)
2246 + {
2247 + assign_device_name (drive, 0);
2248 + return -1;
2249 + }
2250 + }
2251 + else
2252 + {
2253 + assign_device_name (drive, 0);
2254 + return -1;
2255 + }
2256 + }
2257 +
2258 + /* Attempt to read the first sector. */
2259 + if (read (disks[drive].flags, buf, 512) != 512)
2260 + {
2261 + close (disks[drive].flags);
2262 + disks[drive].flags = -1;
2263 + assign_device_name (drive, 0);
2264 + return -1;
2265 + }
2266 +
2267 + if (disks[drive].flags != -1)
2268 + get_drive_geometry (&disks[drive], device_map, drive);
2269 + }
2270 +
2271 + if (disks[drive].flags == -1)
2272 + return -1;
2273 +
2274 +#ifdef __linux__
2275 + /* In Linux, invalidate the buffer cache, so that left overs
2276 + from other program in the cache are flushed and seen by us */
2277 + ioctl (disks[drive].flags, BLKFLSBUF, 0);
2278 +#endif
2279 +
2280 + *geometry = disks[drive];
2281 + return 0;
2282 +}
2283 +
2284 +/* Read LEN bytes from FD in BUF. Return less than or equal to zero if an
2285 + error occurs, otherwise return LEN. */
2286 +static int
2287 +nread (int fd, char *buf, size_t len)
2288 +{
2289 + int size = len;
2290 +
2291 + while (len)
2292 + {
2293 + int ret = read (fd, buf, len);
2294 +
2295 + if (ret <= 0)
2296 + {
2297 + if (errno == EINTR)
2298 + continue;
2299 + else
2300 + return ret;
2301 + }
2302 +
2303 + len -= ret;
2304 + buf += ret;
2305 + }
2306 +
2307 + return size;
2308 +}
2309 +
2310 +/* Write LEN bytes from BUF to FD. Return less than or equal to zero if an
2311 + error occurs, otherwise return LEN. */
2312 +static int
2313 +nwrite (int fd, char *buf, size_t len)
2314 +{
2315 + int size = len;
2316 +
2317 + while (len)
2318 + {
2319 + int ret = write (fd, buf, len);
2320 +
2321 + if (ret <= 0)
2322 + {
2323 + if (errno == EINTR)
2324 + continue;
2325 + else
2326 + return ret;
2327 + }
2328 +
2329 + len -= ret;
2330 + buf += ret;
2331 + }
2332 +
2333 + return size;
2334 +}
2335 +
2336 +/* Dump BUF in the format of hexadecimal numbers. */
2337 +static void
2338 +hex_dump (void *buf, size_t size)
2339 +{
2340 + /* FIXME: How to determine which length is readable? */
2341 +#define MAX_COLUMN 70
2342 +
2343 + /* use unsigned char for numerical computations */
2344 + unsigned char *ptr = buf;
2345 + /* count the width of the line */
2346 + int column = 0;
2347 + /* how many bytes written */
2348 + int count = 0;
2349 +
2350 + while (size > 0)
2351 + {
2352 + /* high 4 bits */
2353 + int hi = *ptr >> 4;
2354 + /* low 4 bits */
2355 + int low = *ptr & 0xf;
2356 +
2357 + /* grub_printf does not handle prefix number, such as %2x, so
2358 + format the number by hand... */
2359 + grub_printf ("%x%x", hi, low);
2360 + column += 2;
2361 + count++;
2362 + ptr++;
2363 + size--;
2364 +
2365 + /* Insert space or newline with the interval 4 bytes. */
2366 + if (size != 0 && (count % 4) == 0)
2367 + {
2368 + if (column < MAX_COLUMN)
2369 + {
2370 + grub_printf (" ");
2371 + column++;
2372 + }
2373 + else
2374 + {
2375 + grub_printf ("\n");
2376 + column = 0;
2377 + }
2378 + }
2379 + }
2380 +
2381 + /* Add a newline at the end for readability. */
2382 + grub_printf ("\n");
2383 +}
2384 +
2385 +int
2386 +biosdisk (int subfunc, int drive, struct geometry *geometry,
2387 + int sector, int nsec, int segment)
2388 +{
2389 + char *buf;
2390 + int fd = geometry->flags;
2391 +
2392 + /* Get the file pointer from the geometry, and make sure it matches. */
2393 + if (fd == -1 || fd != disks[drive].flags)
2394 + return BIOSDISK_ERROR_GEOMETRY;
2395 +
2396 + /* Seek to the specified location. */
2397 +#if defined(__linux__) && (!defined(__GLIBC__) || \
2398 + ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
2399 + /* Maybe libc doesn't have large file support. */
2400 + {
2401 + loff_t offset, result;
2402 + static int _llseek (uint filedes, ulong hi, ulong lo,
2403 + loff_t *res, uint wh);
2404 + _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
2405 + loff_t *, res, uint, wh);
2406 +
2407 + offset = (loff_t) sector * (loff_t) SECTOR_SIZE;
2408 + if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
2409 + return -1;
2410 + }
2411 +#else
2412 + {
2413 + off_t offset = (off_t) sector * (off_t) SECTOR_SIZE;
2414 +
2415 + if (lseek (fd, offset, SEEK_SET) != offset)
2416 + return -1;
2417 + }
2418 +#endif
2419 +
2420 + buf = (char *) (segment << 4);
2421 +
2422 + switch (subfunc)
2423 + {
2424 + case BIOSDISK_READ:
2425 +#ifdef __linux__
2426 + if (sector == 0 && nsec > 1)
2427 + {
2428 + /* Work around a bug in linux's ez remapping. Linux remaps all
2429 + sectors that are read together with the MBR in one read. It
2430 + should only remap the MBR, so we split the read in two
2431 + parts. -jochen */
2432 + if (nread (fd, buf, SECTOR_SIZE) != SECTOR_SIZE)
2433 + return -1;
2434 + buf += SECTOR_SIZE;
2435 + nsec--;
2436 + }
2437 +#endif
2438 + if (nread (fd, buf, nsec * SECTOR_SIZE) != nsec * SECTOR_SIZE)
2439 + return -1;
2440 + break;
2441 +
2442 + case BIOSDISK_WRITE:
2443 + if (verbose)
2444 + {
2445 + grub_printf ("Write %d sectors starting from %d sector"
2446 + " to drive 0x%x (%s)\n",
2447 + nsec, sector, drive, device_map[drive]);
2448 + hex_dump (buf, nsec * SECTOR_SIZE);
2449 + }
2450 + if (! read_only)
2451 + if (nwrite (fd, buf, nsec * SECTOR_SIZE) != nsec * SECTOR_SIZE)
2452 + return -1;
2453 + break;
2454 +
2455 + default:
2456 + grub_printf ("unknown subfunc %d\n", subfunc);
2457 + break;
2458 + }
2459 +
2460 + return 0;
2461 +}
2462 +
2463 +
2464 +void
2465 +stop_floppy (void)
2466 +{
2467 + /* NOTUSED */
2468 +}
2469 +
2470 +/* Fetch a key from a serial device. */
2471 +int
2472 +serial_hw_fetch (void)
2473 +{
2474 + fd_set fds;
2475 + struct timeval to;
2476 + char c;
2477 +
2478 + /* Wait only for the serial device. */
2479 + FD_ZERO (&fds);
2480 + FD_SET (serial_fd, &fds);
2481 +
2482 + to.tv_sec = 0;
2483 + to.tv_usec = 0;
2484 +
2485 + if (select (serial_fd + 1, &fds, 0, 0, &to) > 0)
2486 + {
2487 + if (nread (serial_fd, &c, 1) != 1)
2488 + stop ();
2489 +
2490 + return c;
2491 + }
2492 +
2493 + return -1;
2494 +}
2495 +
2496 +/* Put a character to a serial device. */
2497 +void
2498 +serial_hw_put (int c)
2499 +{
2500 + char ch = (char) c;
2501 +
2502 + if (nwrite (serial_fd, &ch, 1) != 1)
2503 + stop ();
2504 +}
2505 +
2506 +void
2507 +serial_hw_delay (void)
2508 +{
2509 +#ifdef SIMULATE_SLOWNESS_OF_SERIAL
2510 + struct timeval otv, tv;
2511 +
2512 + gettimeofday (&otv, 0);
2513 +
2514 + while (1)
2515 + {
2516 + long delta;
2517 +
2518 + gettimeofday (&tv, 0);
2519 + delta = tv.tv_usec - otv.tv_usec;
2520 + if (delta < 0)
2521 + delta += 1000000;
2522 +
2523 + if (delta >= 1000000 / (serial_speed >> 3))
2524 + break;
2525 + }
2526 +#endif /* SIMULATE_SLOWNESS_OF_SERIAL */
2527 +}
2528 +
2529 +static speed_t
2530 +get_termios_speed (int speed)
2531 +{
2532 + switch (speed)
2533 + {
2534 + case 2400: return B2400;
2535 + case 4800: return B4800;
2536 + case 9600: return B9600;
2537 + case 19200: return B19200;
2538 + case 38400: return B38400;
2539 +#ifdef B57600
2540 + case 57600: return B57600;
2541 +#endif
2542 +#ifdef B115200
2543 + case 115200: return B115200;
2544 +#endif
2545 + }
2546 +
2547 + return B0;
2548 +}
2549 +
2550 +/* Get the port number of the unit UNIT. In the grub shell, this doesn't
2551 + make sense. */
2552 +unsigned short
2553 +serial_hw_get_port (int unit)
2554 +{
2555 + return 0;
2556 +}
2557 +
2558 +/* Initialize a serial device. In the grub shell, PORT is unused. */
2559 +int
2560 +serial_hw_init (unsigned short port, unsigned int speed,
2561 + int word_len, int parity, int stop_bit_len)
2562 +{
2563 + struct termios termios;
2564 + speed_t termios_speed;
2565 + int i;
2566 +
2567 + /* Check if the file name is specified. */
2568 + if (! serial_device)
2569 + return 0;
2570 +
2571 + /* If a serial device is already opened, close it first. */
2572 + if (serial_fd >= 0)
2573 + close (serial_fd);
2574 +
2575 + /* Open the device file. */
2576 + serial_fd = open (serial_device,
2577 + O_RDWR | O_NOCTTY
2578 +#if defined(O_SYNC)
2579 + /* O_SYNC is used in Linux (and some others?). */
2580 + | O_SYNC
2581 +#elif defined(O_FSYNC)
2582 + /* O_FSYNC is used in FreeBSD. */
2583 + | O_FSYNC
2584 +#endif
2585 + );
2586 + if (serial_fd < 0)
2587 + return 0;
2588 +
2589 + /* Get the termios parameters. */
2590 + if (tcgetattr (serial_fd, &termios))
2591 + goto fail;
2592 +
2593 + /* Raw mode. */
2594 + cfmakeraw (&termios);
2595 +
2596 + /* Set the speed. */
2597 + termios_speed = get_termios_speed (speed);
2598 + if (termios_speed == B0)
2599 + goto fail;
2600 +
2601 + cfsetispeed (&termios, termios_speed);
2602 + cfsetospeed (&termios, termios_speed);
2603 +
2604 + /* Set the word length. */
2605 + termios.c_cflag &= ~CSIZE;
2606 + switch (word_len)
2607 + {
2608 + case UART_5BITS_WORD:
2609 + termios.c_cflag |= CS5;
2610 + break;
2611 + case UART_6BITS_WORD:
2612 + termios.c_cflag |= CS6;
2613 + break;
2614 + case UART_7BITS_WORD:
2615 + termios.c_cflag |= CS7;
2616 + break;
2617 + case UART_8BITS_WORD:
2618 + termios.c_cflag |= CS8;
2619 + break;
2620 + default:
2621 + goto fail;
2622 + }
2623 +
2624 + /* Set the parity. */
2625 + switch (parity)
2626 + {
2627 + case UART_NO_PARITY:
2628 + termios.c_cflag &= ~PARENB;
2629 + break;
2630 + case UART_ODD_PARITY:
2631 + termios.c_cflag |= PARENB;
2632 + termios.c_cflag |= PARODD;
2633 + break;
2634 + case UART_EVEN_PARITY:
2635 + termios.c_cflag |= PARENB;
2636 + termios.c_cflag &= ~PARODD;
2637 + break;
2638 + default:
2639 + goto fail;
2640 + }
2641 +
2642 + /* Set the length of stop bit. */
2643 + switch (stop_bit_len)
2644 + {
2645 + case UART_1_STOP_BIT:
2646 + termios.c_cflag &= ~CSTOPB;
2647 + break;
2648 + case UART_2_STOP_BITS:
2649 + termios.c_cflag |= CSTOPB;
2650 + break;
2651 + default:
2652 + goto fail;
2653 + }
2654 +
2655 + /* Set the parameters. */
2656 + if (tcsetattr (serial_fd, TCSANOW, &termios))
2657 + goto fail;
2658 +
2659 +#ifdef SIMULATE_SLOWNESS_OF_SERIAL
2660 + serial_speed = speed;
2661 +#endif /* SIMUATE_SLOWNESS_OF_SERIAL */
2662 +
2663 + /* Get rid of the flag TERM_NEED_INIT from the serial terminal. */
2664 + for (i = 0; term_table[i].name; i++)
2665 + {
2666 + if (strcmp (term_table[i].name, "serial") == 0)
2667 + {
2668 + term_table[i].flags &= ~(TERM_NEED_INIT);
2669 + break;
2670 + }
2671 + }
2672 +
2673 + return 1;
2674 +
2675 + fail:
2676 + close (serial_fd);
2677 + serial_fd = -1;
2678 + return 0;
2679 +}
2680 +
2681 +/* Set the file name of a serial device (or a pty device). This is a
2682 + function specific to the grub shell. */
2683 +void
2684 +serial_set_device (const char *device)
2685 +{
2686 + if (serial_device)
2687 + free (serial_device);
2688 +
2689 + serial_device = strdup (device);
2690 +}
2691 +
2692 +/* There is no difference between console and hercules in the grub shell. */
2693 +void
2694 +hercules_putchar (int c)
2695 +{
2696 + console_putchar (c);
2697 +}
2698 +
2699 +int
2700 +hercules_getxy (void)
2701 +{
2702 + return console_getxy ();
2703 +}
2704 +
2705 +void
2706 +hercules_gotoxy (int x, int y)
2707 +{
2708 + console_gotoxy (x, y);
2709 +}
2710 +
2711 +void
2712 +hercules_cls (void)
2713 +{
2714 + console_cls ();
2715 +}
2716 +
2717 +void
2718 +hercules_setcolorstate (color_state state)
2719 +{
2720 + console_setcolorstate (state);
2721 +}
2722 +
2723 +void
2724 +hercules_setcolor (int normal_color, int highlight_color)
2725 +{
2726 + console_setcolor (normal_color, highlight_color);
2727 +}
2728 +
2729 +int
2730 +hercules_setcursor (int on)
2731 +{
2732 + return 1;
2733 +}
2734 diff -Nur grub-0.97/grub/main.c grub-0.97-patched/grub/main.c
2735 --- grub-0.97/grub/main.c 2003-07-09 13:45:36.000000000 +0200
2736 +++ grub-0.97-patched/grub/main.c 2012-11-11 17:07:12.720729374 +0100
2737 @@ -32,6 +32,7 @@
2738 #define WITHOUT_LIBC_STUBS 1
2739 #include <shared.h>
2740 #include <term.h>
2741 +#include <device.h>
2742
2743 char *program_name = 0;
2744 int use_config_file = 1;
2745 @@ -140,10 +141,7 @@
2746 program_name = argv[0];
2747 default_boot_drive = boot_drive;
2748 default_install_partition = install_partition;
2749 - if (config_file)
2750 - default_config_file = config_file;
2751 - else
2752 - default_config_file = "NONE";
2753 + default_config_file = config_file;
2754
2755 /* Parse command-line options. */
2756 do
2757 @@ -192,6 +190,12 @@
2758 perror ("strtoul");
2759 exit (1);
2760 }
2761 + if (boot_drive >= NUM_DISKS)
2762 + {
2763 + fprintf (stderr, "boot_drive should be from 0 to %d\n",
2764 + NUM_DISKS - 1);
2765 + exit (1);
2766 + }
2767 break;
2768
2769 case OPT_NO_CONFIG_FILE:
2770 diff -Nur grub-0.97/grub/main.c.orig grub-0.97-patched/grub/main.c.orig
2771 --- grub-0.97/grub/main.c.orig 1970-01-01 01:00:00.000000000 +0100
2772 +++ grub-0.97-patched/grub/main.c.orig 2003-07-09 13:45:36.000000000 +0200
2773 @@ -0,0 +1,265 @@
2774 +/* main.c - experimental GRUB stage2 that runs under Unix */
2775 +/*
2776 + * GRUB -- GRand Unified Bootloader
2777 + * Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc.
2778 + *
2779 + * This program is free software; you can redistribute it and/or modify
2780 + * it under the terms of the GNU General Public License as published by
2781 + * the Free Software Foundation; either version 2 of the License, or
2782 + * (at your option) any later version.
2783 + *
2784 + * This program is distributed in the hope that it will be useful,
2785 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2786 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2787 + * GNU General Public License for more details.
2788 + *
2789 + * You should have received a copy of the GNU General Public License
2790 + * along with this program; if not, write to the Free Software
2791 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2792 + */
2793 +
2794 +/* Simulator entry point. */
2795 +int grub_stage2 (void);
2796 +
2797 +#include <stdio.h>
2798 +#include <getopt.h>
2799 +#include <unistd.h>
2800 +#include <string.h>
2801 +#include <stdlib.h>
2802 +#include <limits.h>
2803 +#include <setjmp.h>
2804 +
2805 +#define WITHOUT_LIBC_STUBS 1
2806 +#include <shared.h>
2807 +#include <term.h>
2808 +
2809 +char *program_name = 0;
2810 +int use_config_file = 1;
2811 +int use_preset_menu = 0;
2812 +#ifdef HAVE_LIBCURSES
2813 +int use_curses = 1;
2814 +#else
2815 +int use_curses = 0;
2816 +#endif
2817 +int verbose = 0;
2818 +int read_only = 0;
2819 +int floppy_disks = 1;
2820 +char *device_map_file = 0;
2821 +static int default_boot_drive;
2822 +static int default_install_partition;
2823 +static char *default_config_file;
2824 +
2825 +#define OPT_HELP -2
2826 +#define OPT_VERSION -3
2827 +#define OPT_HOLD -4
2828 +#define OPT_CONFIG_FILE -5
2829 +#define OPT_INSTALL_PARTITION -6
2830 +#define OPT_BOOT_DRIVE -7
2831 +#define OPT_NO_CONFIG_FILE -8
2832 +#define OPT_NO_CURSES -9
2833 +#define OPT_BATCH -10
2834 +#define OPT_VERBOSE -11
2835 +#define OPT_READ_ONLY -12
2836 +#define OPT_PROBE_SECOND_FLOPPY -13
2837 +#define OPT_NO_FLOPPY -14
2838 +#define OPT_DEVICE_MAP -15
2839 +#define OPT_PRESET_MENU -16
2840 +#define OPT_NO_PAGER -17
2841 +#define OPTSTRING ""
2842 +
2843 +static struct option longopts[] =
2844 +{
2845 + {"batch", no_argument, 0, OPT_BATCH},
2846 + {"boot-drive", required_argument, 0, OPT_BOOT_DRIVE},
2847 + {"config-file", required_argument, 0, OPT_CONFIG_FILE},
2848 + {"device-map", required_argument, 0, OPT_DEVICE_MAP},
2849 + {"help", no_argument, 0, OPT_HELP},
2850 + {"hold", optional_argument, 0, OPT_HOLD},
2851 + {"install-partition", required_argument, 0, OPT_INSTALL_PARTITION},
2852 + {"no-config-file", no_argument, 0, OPT_NO_CONFIG_FILE},
2853 + {"no-curses", no_argument, 0, OPT_NO_CURSES},
2854 + {"no-floppy", no_argument, 0, OPT_NO_FLOPPY},
2855 + {"no-pager", no_argument, 0, OPT_NO_PAGER},
2856 + {"preset-menu", no_argument, 0, OPT_PRESET_MENU},
2857 + {"probe-second-floppy", no_argument, 0, OPT_PROBE_SECOND_FLOPPY},
2858 + {"read-only", no_argument, 0, OPT_READ_ONLY},
2859 + {"verbose", no_argument, 0, OPT_VERBOSE},
2860 + {"version", no_argument, 0, OPT_VERSION},
2861 + {0},
2862 +};
2863 +
2864 +
2865 +static void
2866 +usage (int status)
2867 +{
2868 + if (status)
2869 + fprintf (stderr, "Try ``grub --help'' for more information.\n");
2870 + else
2871 + printf ("\
2872 +Usage: grub [OPTION]...\n\
2873 +\n\
2874 +Enter the GRand Unified Bootloader command shell.\n\
2875 +\n\
2876 + --batch turn on batch mode for non-interactive use\n\
2877 + --boot-drive=DRIVE specify stage2 boot_drive [default=0x%x]\n\
2878 + --config-file=FILE specify stage2 config_file [default=%s]\n\
2879 + --device-map=FILE use the device map file FILE\n\
2880 + --help display this message and exit\n\
2881 + --hold wait until a debugger will attach\n\
2882 + --install-partition=PAR specify stage2 install_partition [default=0x%x]\n\
2883 + --no-config-file do not use the config file\n\
2884 + --no-curses do not use curses\n\
2885 + --no-floppy do not probe any floppy drive\n\
2886 + --no-pager do not use internal pager\n\
2887 + --preset-menu use the preset menu\n\
2888 + --probe-second-floppy probe the second floppy drive\n\
2889 + --read-only do not write anything to devices\n\
2890 + --verbose print verbose messages\n\
2891 + --version print version information and exit\n\
2892 +\n\
2893 +Report bugs to <bug-grub@gnu.org>.\n\
2894 +",
2895 + default_boot_drive, default_config_file,
2896 + default_install_partition);
2897 +
2898 + exit (status);
2899 +}
2900 +
2901 +
2902 +int
2903 +main (int argc, char **argv)
2904 +{
2905 + int c;
2906 + int hold = 0;
2907 +
2908 + /* First of all, call sync so that all in-core data is scheduled to be
2909 + actually written to disks. This is very important because GRUB does
2910 + not use ordinary stdio interface but raw devices. */
2911 + sync ();
2912 +
2913 + program_name = argv[0];
2914 + default_boot_drive = boot_drive;
2915 + default_install_partition = install_partition;
2916 + if (config_file)
2917 + default_config_file = config_file;
2918 + else
2919 + default_config_file = "NONE";
2920 +
2921 + /* Parse command-line options. */
2922 + do
2923 + {
2924 + c = getopt_long (argc, argv, OPTSTRING, longopts, 0);
2925 + switch (c)
2926 + {
2927 + case EOF:
2928 + /* Fall through the bottom of the loop. */
2929 + break;
2930 +
2931 + case OPT_HELP:
2932 + usage (0);
2933 + break;
2934 +
2935 + case OPT_VERSION:
2936 + printf ("grub (GNU GRUB " VERSION ")\n");
2937 + exit (0);
2938 + break;
2939 +
2940 + case OPT_HOLD:
2941 + if (! optarg)
2942 + hold = -1;
2943 + else
2944 + hold = atoi (optarg);
2945 + break;
2946 +
2947 + case OPT_CONFIG_FILE:
2948 + strncpy (config_file, optarg, 127); /* FIXME: arbitrary */
2949 + config_file[127] = '\0';
2950 + break;
2951 +
2952 + case OPT_INSTALL_PARTITION:
2953 + install_partition = strtoul (optarg, 0, 0);
2954 + if (install_partition == ULONG_MAX)
2955 + {
2956 + perror ("strtoul");
2957 + exit (1);
2958 + }
2959 + break;
2960 +
2961 + case OPT_BOOT_DRIVE:
2962 + boot_drive = strtoul (optarg, 0, 0);
2963 + if (boot_drive == ULONG_MAX)
2964 + {
2965 + perror ("strtoul");
2966 + exit (1);
2967 + }
2968 + break;
2969 +
2970 + case OPT_NO_CONFIG_FILE:
2971 + use_config_file = 0;
2972 + break;
2973 +
2974 + case OPT_NO_CURSES:
2975 + use_curses = 0;
2976 + break;
2977 +
2978 + case OPT_NO_PAGER:
2979 + use_pager = 0;
2980 + break;
2981 +
2982 + case OPT_BATCH:
2983 + /* This is the same as "--no-config-file --no-curses --no-pager". */
2984 + use_config_file = 0;
2985 + use_curses = 0;
2986 + use_pager = 0;
2987 + break;
2988 +
2989 + case OPT_READ_ONLY:
2990 + read_only = 1;
2991 + break;
2992 +
2993 + case OPT_VERBOSE:
2994 + verbose = 1;
2995 + break;
2996 +
2997 + case OPT_NO_FLOPPY:
2998 + floppy_disks = 0;
2999 + break;
3000 +
3001 + case OPT_PROBE_SECOND_FLOPPY:
3002 + floppy_disks = 2;
3003 + break;
3004 +
3005 + case OPT_DEVICE_MAP:
3006 + device_map_file = strdup (optarg);
3007 + break;
3008 +
3009 + case OPT_PRESET_MENU:
3010 + use_preset_menu = 1;
3011 + break;
3012 +
3013 + default:
3014 + usage (1);
3015 + }
3016 + }
3017 + while (c != EOF);
3018 +
3019 + /* Wait until the HOLD variable is cleared by an attached debugger. */
3020 + if (hold && verbose)
3021 + printf ("Run \"gdb %s %d\", and set HOLD to zero.\n",
3022 + program_name, (int) getpid ());
3023 + while (hold)
3024 + {
3025 + if (hold > 0)
3026 + hold--;
3027 +
3028 + sleep (1);
3029 + }
3030 +
3031 + /* If we don't have curses (!HAVE_LIBCURSES or --no-curses or
3032 + --batch) put terminal to dumb for better handling of line i/o */
3033 + if (! use_curses)
3034 + current_term->flags = TERM_NO_EDIT | TERM_DUMB;
3035 +
3036 + /* Transfer control to the stage2 simulator. */
3037 + exit (grub_stage2 ());
3038 +}
3039 diff -Nur grub-0.97/lib/device.c grub-0.97-patched/lib/device.c
3040 --- grub-0.97/lib/device.c 2005-03-28 01:14:25.000000000 +0200
3041 +++ grub-0.97-patched/lib/device.c 2012-11-11 17:07:12.748730268 +0100
3042 @@ -69,9 +69,9 @@
3043 # ifndef CDROM_GET_CAPABILITY
3044 # define CDROM_GET_CAPABILITY 0x5331 /* get capabilities */
3045 # endif /* ! CDROM_GET_CAPABILITY */
3046 -# ifndef BLKGETSIZE
3047 -# define BLKGETSIZE _IO(0x12,96) /* return device size */
3048 -# endif /* ! BLKGETSIZE */
3049 +# ifndef BLKGETSIZE64
3050 +# define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size */
3051 +# endif /* ! BLKGETSIZE64 */
3052 #endif /* __linux__ */
3053
3054 /* Use __FreeBSD_kernel__ instead of __FreeBSD__ for compatibility with
3055 @@ -131,6 +131,152 @@
3056 #include <shared.h>
3057 #include <device.h>
3058
3059 +#if defined(__linux__)
3060 +/* The 2.6 kernel has removed all of the geometry handling for IDE drives
3061 + * that did fixups for LBA, etc. This means that the geometry we get
3062 + * with the ioctl has a good chance of being wrong. So, we get to
3063 + * also know about partition tables and try to read what the geometry
3064 + * is there. *grumble* Very closely based on code from cfdisk
3065 + */
3066 +static void get_kernel_geometry(int fd, long long *cyl, int *heads, int *sectors) {
3067 + struct hd_geometry hdg;
3068 +
3069 + if (ioctl (fd, HDIO_GETGEO, &hdg))
3070 + return;
3071 +
3072 + *cyl = hdg.cylinders;
3073 + *heads = hdg.heads;
3074 + *sectors = hdg.sectors;
3075 +}
3076 +
3077 +struct partition {
3078 + unsigned char boot_ind; /* 0x80 - active */
3079 + unsigned char head; /* starting head */
3080 + unsigned char sector; /* starting sector */
3081 + unsigned char cyl; /* starting cylinder */
3082 + unsigned char sys_ind; /* What partition type */
3083 + unsigned char end_head; /* end head */
3084 + unsigned char end_sector; /* end sector */
3085 + unsigned char end_cyl; /* end cylinder */
3086 + unsigned char start4[4]; /* starting sector counting from 0 */
3087 + unsigned char size4[4]; /* nr of sectors in partition */
3088 +};
3089 +
3090 +#define ALIGNMENT 2
3091 +typedef union {
3092 + struct {
3093 + unsigned char align[ALIGNMENT];
3094 + unsigned char b[SECTOR_SIZE];
3095 + } c;
3096 + struct {
3097 + unsigned char align[ALIGNMENT];
3098 + unsigned char buffer[0x1BE];
3099 + struct partition part[4];
3100 + unsigned char magicflag[2];
3101 + } p;
3102 +} partition_table;
3103 +
3104 +#define PART_TABLE_FLAG0 0x55
3105 +#define PART_TABLE_FLAG1 0xAA
3106 +
3107 +static void
3108 +get_partition_table_geometry(partition_table *bufp, long long *cyl, int *heads,
3109 + int *sectors) {
3110 + struct partition *p;
3111 + int i,h,s,hh,ss;
3112 + int first = 1;
3113 + int bad = 0;
3114 +
3115 + if (bufp->p.magicflag[0] != PART_TABLE_FLAG0 ||
3116 + bufp->p.magicflag[1] != PART_TABLE_FLAG1) {
3117 + /* Matthew Wilcox: slightly friendlier version of
3118 + fatal(_("Bad signature on partition table"), 3);
3119 + */
3120 + fprintf(stderr, "Unknown partition table signature\n");
3121 + return;
3122 + }
3123 +
3124 + hh = ss = 0;
3125 + for (i=0; i<4; i++) {
3126 + p = &(bufp->p.part[i]);
3127 + if (p->sys_ind != 0) {
3128 + h = p->end_head + 1;
3129 + s = (p->end_sector & 077);
3130 + if (first) {
3131 + hh = h;
3132 + ss = s;
3133 + first = 0;
3134 + } else if (hh != h || ss != s)
3135 + bad = 1;
3136 + }
3137 + }
3138 +
3139 + if (!first && !bad) {
3140 + *heads = hh;
3141 + *sectors = ss;
3142 + }
3143 +}
3144 +
3145 +static long long my_lseek (unsigned int fd, long long offset,
3146 + unsigned int origin)
3147 +{
3148 +#if defined(__linux__) && (!defined(__GLIBC__) || \
3149 + ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
3150 + /* Maybe libc doesn't have large file support. */
3151 + loff_t offset, result;
3152 + static int _llseek (uint filedes, ulong hi, ulong lo,
3153 + loff_t *res, uint wh);
3154 + _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
3155 + loff_t *, res, uint, wh);
3156 +
3157 + if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET) < 0)
3158 + return (long long) -1;
3159 + return result;
3160 +#else
3161 + return lseek(fd, offset, SEEK_SET);
3162 +#endif
3163 +}
3164 +
3165 +static void get_linux_geometry (int fd, struct geometry *geom) {
3166 + long long kern_cyl = 0; int kern_head = 0, kern_sectors = 0;
3167 + long long pt_cyl = 0; int pt_head = 0, pt_sectors = 0;
3168 + partition_table bufp;
3169 + char *buff, *buf_unaligned;
3170 +
3171 + buf_unaligned = malloc(sizeof(partition_table) + 4095);
3172 + buff = (char *) (((unsigned long)buf_unaligned + 4096 - 1) &
3173 + (~(4096-1)));
3174 +
3175 + get_kernel_geometry(fd, &kern_cyl, &kern_head, &kern_sectors);
3176 +
3177 + if (my_lseek (fd, 0*SECTOR_SIZE, SEEK_SET) < 0) {
3178 + fprintf(stderr, "Unable to seek");
3179 + }
3180 +
3181 + if (read(fd, buff, SECTOR_SIZE) == SECTOR_SIZE) {
3182 + memcpy(bufp.c.b, buff, SECTOR_SIZE);
3183 + get_partition_table_geometry(&bufp, &pt_cyl, &pt_head, &pt_sectors);
3184 + } else {
3185 + fprintf(stderr, "Unable to read partition table: %s\n", strerror(errno));
3186 + }
3187 +
3188 + if (pt_head && pt_sectors) {
3189 + int cyl_size;
3190 +
3191 + geom->heads = pt_head;
3192 + geom->sectors = pt_sectors;
3193 + cyl_size = pt_head * pt_sectors;
3194 + geom->cylinders = geom->total_sectors/cyl_size;
3195 + } else {
3196 + geom->heads = kern_head;
3197 + geom->sectors = kern_sectors;
3198 + geom->cylinders = kern_cyl;
3199 + }
3200 +
3201 + return;
3202 +}
3203 +#endif
3204 +
3205 /* Get the geometry of a drive DRIVE. */
3206 void
3207 get_drive_geometry (struct geometry *geom, char **map, int drive)
3208 @@ -151,20 +297,16 @@
3209 #if defined(__linux__)
3210 /* Linux */
3211 {
3212 - struct hd_geometry hdg;
3213 - unsigned long nr;
3214 + unsigned long long nr;
3215
3216 - if (ioctl (fd, HDIO_GETGEO, &hdg))
3217 - goto fail;
3218 -
3219 - if (ioctl (fd, BLKGETSIZE, &nr))
3220 + if (ioctl (fd, BLKGETSIZE64, &nr))
3221 goto fail;
3222
3223 /* Got the geometry, so save it. */
3224 - geom->cylinders = hdg.cylinders;
3225 - geom->heads = hdg.heads;
3226 - geom->sectors = hdg.sectors;
3227 - geom->total_sectors = nr;
3228 + get_linux_geometry(fd, geom);
3229 + if (!geom->heads && !geom->cylinders && !geom->sectors)
3230 + goto fail;
3231 + geom->total_sectors = nr / 512;
3232
3233 goto success;
3234 }
3235 @@ -403,10 +545,28 @@
3236 }
3237
3238 static void
3239 +get_cciss_disk_name (char *name, int controller, int drive)
3240 +{
3241 + sprintf (name, "/dev/cciss/c%dd%d", controller, drive);
3242 +}
3243 +
3244 +static void
3245 +get_ida_disk_name (char *name, int controller, int drive)
3246 +{
3247 + sprintf (name, "/dev/ida/c%dd%d", controller, drive);
3248 +}
3249 +
3250 +static void
3251 get_ataraid_disk_name (char *name, int unit)
3252 {
3253 sprintf (name, "/dev/ataraid/d%c", unit + '0');
3254 }
3255 +
3256 +static void
3257 +get_i2o_disk_name (char *name, char unit)
3258 +{
3259 + sprintf (name, "/dev/i2o/hd%c", unit);
3260 +}
3261 #endif
3262
3263 /* Check if DEVICE can be read. If an error occurs, return zero,
3264 @@ -801,6 +961,97 @@
3265 }
3266 }
3267 }
3268 +
3269 + /* This is for I2O - we have /dev/i2o/hd<logical drive><partition> */
3270 + {
3271 + int unit;
3272 +
3273 + for (unit = 'a'; unit < 'f'; unit++)
3274 + {
3275 + char name[24];
3276 +
3277 + get_i2o_disk_name (name, unit);
3278 + if (check_device (name))
3279 + {
3280 + (*map)[num_hd + 0x80] = strdup (name);
3281 + assert ((*map)[num_hd + 0x80]);
3282 +
3283 + /* If the device map file is opened, write the map. */
3284 + if (fp)
3285 + fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
3286 +
3287 + num_hd++;
3288 + }
3289 + }
3290 + }
3291 +
3292 + /* This is for CCISS, its like the DAC960 - we have
3293 + /dev/cciss/<controller>d<logical drive>p<partition>
3294 +
3295 + It currently supports up to 3 controllers, 10 logical volumes
3296 + and 10 partitions
3297 +
3298 + Code gratuitously copied from DAC960 above.
3299 + Horms <horms@verge.net.au> 23rd July 2004
3300 + */
3301 + {
3302 + int controller, drive;
3303 +
3304 + for (controller = 0; controller < 2; controller++)
3305 + {
3306 + for (drive = 0; drive < 9; drive++)
3307 + {
3308 + char name[24];
3309 +
3310 + get_cciss_disk_name (name, controller, drive);
3311 + if (check_device (name))
3312 + {
3313 + (*map)[num_hd + 0x80] = strdup (name);
3314 + assert ((*map)[num_hd + 0x80]);
3315 +
3316 + /* If the device map file is opened, write the map. */
3317 + if (fp)
3318 + fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
3319 +
3320 + num_hd++;
3321 + }
3322 + }
3323 + }
3324 + }
3325 +
3326 + /* This is for Compaq Smart Array, its like the DAC960 - we have
3327 + /dev/ida/<controller>d<logical drive>p<partition>
3328 +
3329 + It currently supports up to 3 controllers, 10 logical volumes
3330 + and 15 partitions
3331 +
3332 + Code gratuitously copied from DAC960 above.
3333 + Piotr Roszatycki <dexter@debian.org>
3334 + */
3335 + {
3336 + int controller, drive;
3337 +
3338 + for (controller = 0; controller < 2; controller++)
3339 + {
3340 + for (drive = 0; drive < 9; drive++)
3341 + {
3342 + char name[24];
3343 +
3344 + get_ida_disk_name (name, controller, drive);
3345 + if (check_device (name))
3346 + {
3347 + (*map)[num_hd + 0x80] = strdup (name);
3348 + assert ((*map)[num_hd + 0x80]);
3349 +
3350 + /* If the device map file is opened, write the map. */
3351 + if (fp)
3352 + fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
3353 +
3354 + num_hd++;
3355 + }
3356 + }
3357 + }
3358 + }
3359 #endif /* __linux__ */
3360
3361 /* OK, close the device map file if opened. */
3362 @@ -844,6 +1095,7 @@
3363 {
3364 char dev[PATH_MAX]; /* XXX */
3365 int fd;
3366 + off_t offset = (off_t) sector * (off_t) SECTOR_SIZE;
3367
3368 if ((partition & 0x00FF00) != 0x00FF00)
3369 {
3370 @@ -861,6 +1113,14 @@
3371 if (strcmp (dev + strlen(dev) - 5, "/disc") == 0)
3372 strcpy (dev + strlen(dev) - 5, "/part");
3373 }
3374 + else
3375 + {
3376 + if ((strncmp (dev, "/dev/ataraid/", 13) == 0) ||
3377 + (strncmp (dev, "/dev/ida/", 9) == 0) ||
3378 + (strncmp (dev, "/dev/cciss/", 11) == 0) ||
3379 + (strncmp (dev, "/dev/rd/", 8) == 0))
3380 + strcpy (dev + strlen(dev), "p");
3381 + }
3382 sprintf (dev + strlen(dev), "%d", ((partition >> 16) & 0xFF) + 1);
3383
3384 /* Open the partition. */
3385 @@ -870,35 +1130,13 @@
3386 errnum = ERR_NO_PART;
3387 return 0;
3388 }
3389 -
3390 -#if defined(__linux__) && (!defined(__GLIBC__) || \
3391 - ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
3392 - /* Maybe libc doesn't have large file support. */
3393 - {
3394 - loff_t offset, result;
3395 - static int _llseek (uint filedes, ulong hi, ulong lo,
3396 - loff_t *res, uint wh);
3397 - _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
3398 - loff_t *, res, uint, wh);
3399
3400 - offset = (loff_t) sector * (loff_t) SECTOR_SIZE;
3401 - if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
3402 - {
3403 - errnum = ERR_DEV_VALUES;
3404 - return 0;
3405 - }
3406 - }
3407 -#else
3408 - {
3409 - off_t offset = (off_t) sector * (off_t) SECTOR_SIZE;
3410
3411 - if (lseek (fd, offset, SEEK_SET) != offset)
3412 - {
3413 - errnum = ERR_DEV_VALUES;
3414 - return 0;
3415 - }
3416 - }
3417 -#endif
3418 + if (my_lseek(fd, offset, SEEK_SET) != offset)
3419 + {
3420 + errnum = ERR_DEV_VALUES;
3421 + return 0;
3422 + }
3423
3424 if (write (fd, buf, size * SECTOR_SIZE) != (size * SECTOR_SIZE))
3425 {
3426 diff -Nur grub-0.97/netboot/cs89x0.c grub-0.97-patched/netboot/cs89x0.c
3427 --- grub-0.97/netboot/cs89x0.c 2003-07-09 13:45:37.000000000 +0200
3428 +++ grub-0.97-patched/netboot/cs89x0.c 2012-11-11 17:07:12.722729437 +0100
3429 @@ -1,3 +1,21 @@
3430 +/**
3431 + Per an email message from Russ Nelson <nelson@crynwr.com> on
3432 + 18 March 2008 this file is now licensed under GPL Version 2.
3433 +
3434 + From: Russ Nelson <nelson@crynwr.com>
3435 + Date: Tue, 18 Mar 2008 12:42:00 -0400
3436 + Subject: Re: [Etherboot-developers] cs89x0 driver in etherboot
3437 + -- quote from email
3438 + As copyright holder, if I say it doesn't conflict with the GPL,
3439 + then it doesn't conflict with the GPL.
3440 +
3441 + However, there's no point in causing people's brains to overheat,
3442 + so yes, I grant permission for the code to be relicensed under the
3443 + GPLv2. Please make sure that this change in licensing makes its
3444 + way upstream. -russ
3445 + -- quote from email
3446 +**/
3447 +
3448 /* cs89x0.c: A Crystal Semiconductor CS89[02]0 driver for etherboot. */
3449 /*
3450 Permission is granted to distribute the enclosed cs89x0.[ch] driver
3451 diff -Nur grub-0.97/netboot/cs89x0.h grub-0.97-patched/netboot/cs89x0.h
3452 --- grub-0.97/netboot/cs89x0.h 2003-07-09 13:45:37.000000000 +0200
3453 +++ grub-0.97-patched/netboot/cs89x0.h 2012-11-11 17:07:12.723729469 +0100
3454 @@ -1,3 +1,21 @@
3455 +/**
3456 + Per an email message from Russ Nelson <nelson@crynwr.com> on
3457 + 18 March 2008 this file is now licensed under GPL Version 2.
3458 +
3459 + From: Russ Nelson <nelson@crynwr.com>
3460 + Date: Tue, 18 Mar 2008 12:42:00 -0400
3461 + Subject: Re: [Etherboot-developers] cs89x0 driver in etherboot
3462 + -- quote from email
3463 + As copyright holder, if I say it doesn't conflict with the GPL,
3464 + then it doesn't conflict with the GPL.
3465 +
3466 + However, there's no point in causing people's brains to overheat,
3467 + so yes, I grant permission for the code to be relicensed under the
3468 + GPLv2. Please make sure that this change in licensing makes its
3469 + way upstream. -russ
3470 + -- quote from email
3471 +**/
3472 +
3473 /* Copyright, 1988-1992, Russell Nelson, Crynwr Software
3474
3475 This program is free software; you can redistribute it and/or modify
3476 diff -Nur grub-0.97/netboot/etherboot.h grub-0.97-patched/netboot/etherboot.h
3477 --- grub-0.97/netboot/etherboot.h 2003-07-09 13:45:37.000000000 +0200
3478 +++ grub-0.97-patched/netboot/etherboot.h 2012-11-11 17:07:12.723729469 +0100
3479 @@ -531,9 +531,6 @@
3480 extern int network_ready;
3481 extern struct rom_info rom;
3482 extern struct arptable_t arptable[MAX_ARP];
3483 -extern struct bootpd_t bootp_data;
3484 -#define BOOTP_DATA_ADDR (&bootp_data)
3485 -extern unsigned char *end_of_rfc1533;
3486
3487 /* config.c */
3488 extern struct nic nic;
3489 diff -Nur grub-0.97/netboot/main.c grub-0.97-patched/netboot/main.c
3490 --- grub-0.97/netboot/main.c 2004-05-21 00:19:33.000000000 +0200
3491 +++ grub-0.97-patched/netboot/main.c 2012-11-11 17:07:12.724729500 +0100
3492 @@ -56,7 +56,8 @@
3493 static unsigned long netmask;
3494 static struct bootpd_t bootp_data;
3495 static unsigned long xid;
3496 -static unsigned char *end_of_rfc1533 = NULL;
3497 +
3498 +#define BOOTP_DATA_ADDR (&bootp_data)
3499
3500 #ifndef NO_DHCP_SUPPORT
3501 #endif /* NO_DHCP_SUPPORT */
3502 @@ -83,7 +84,9 @@
3503 RFC2132_MAX_SIZE,2, /* request as much as we can */
3504 ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,
3505 RFC2132_PARAM_LIST, 4, RFC1533_NETMASK, RFC1533_GATEWAY,
3506 - RFC1533_HOSTNAME, RFC1533_EXTENSIONPATH
3507 + RFC1533_HOSTNAME, RFC1533_EXTENSIONPATH,
3508 + /* Vendor class identifier */
3509 + RFC2132_VENDOR_CLASS_ID, 10, 'G', 'R', 'U', 'B', 'C', 'l', 'i', 'e', 'n', 't',
3510 };
3511
3512 static const unsigned char dhcprequest[] =
3513 @@ -103,6 +106,8 @@
3514 /* Etherboot vendortags */
3515 RFC1533_VENDOR_MAGIC,
3516 RFC1533_VENDOR_CONFIGFILE,
3517 + /* Vendor class identifier */
3518 + RFC2132_VENDOR_CLASS_ID, 10, 'G', 'R', 'U', 'B', 'C', 'l', 'i', 'e', 'n', 't',
3519 };
3520
3521 #endif /* ! NO_DHCP_SUPPORT */
3522 @@ -701,7 +706,7 @@
3523 "adcw %%ax,%0\n\t" /* add carry of previous iteration */
3524 "loop 1b\n\t"
3525 "adcw $0,%0" /* add carry of last iteration */
3526 - : "=b" (*sum), "=S"(start), "=c"(len)
3527 + : "=r" (*sum), "=S"(start), "=c"(len)
3528 : "0"(*sum), "1"(start), "2"(len)
3529 : "ax", "cc"
3530 );
3531 @@ -967,7 +972,6 @@
3532
3533 if (block == 0)
3534 {
3535 - end_of_rfc1533 = NULL;
3536 vendorext_isvalid = 0;
3537
3538 if (grub_memcmp (p, rfc1533_cookie, 4))
3539 @@ -1021,7 +1025,7 @@
3540 }
3541 else if (c == RFC1533_END)
3542 {
3543 - end_of_rfc1533 = endp = p;
3544 + endp = p;
3545 continue;
3546 }
3547 else if (c == RFC1533_NETMASK)
3548 diff -Nur grub-0.97/netboot/natsemi.c grub-0.97-patched/netboot/natsemi.c
3549 --- grub-0.97/netboot/natsemi.c 2003-07-09 13:45:38.000000000 +0200
3550 +++ grub-0.97-patched/netboot/natsemi.c 2012-11-11 17:07:12.724729500 +0100
3551 @@ -608,7 +608,7 @@
3552 const char *p) /* Packet */
3553 {
3554 u32 status, to, nstype;
3555 - u32 tx_status;
3556 + volatile u32 tx_status;
3557
3558 /* Stop the transmitter */
3559 outl(TxOff, ioaddr + ChipCmd);
3560 @@ -647,7 +647,7 @@
3561
3562 to = currticks() + TX_TIMEOUT;
3563
3564 - while ((((volatile u32) tx_status=txd.cmdsts) & OWN) && (currticks() < to))
3565 + while (((tx_status=txd.cmdsts) & OWN) && (currticks() < to))
3566 /* wait */ ;
3567
3568 if (currticks() >= to) {
3569 diff -Nur grub-0.97/netboot/pci.c grub-0.97-patched/netboot/pci.c
3570 --- grub-0.97/netboot/pci.c 2003-07-09 13:45:38.000000000 +0200
3571 +++ grub-0.97-patched/netboot/pci.c 2012-11-11 17:07:07.227553894 +0100
3572 @@ -105,13 +105,16 @@
3573
3574 save_flags(flags);
3575 __asm__(
3576 + "pushl %%ebx\n\t" /* save %ebx */
3577 #ifdef ABSOLUTE_WITHOUT_ASTERISK
3578 - "lcall (%%edi)"
3579 + "lcall (%%edi)\n\t"
3580 #else
3581 - "lcall *(%%edi)"
3582 + "lcall *(%%edi)\n\t"
3583 #endif
3584 + "movl %%ebx, %1\n\t" /* capture what was in %ebx */
3585 + "popl %%ebx\n\t" /* restore %ebx */
3586 : "=a" (return_code),
3587 - "=b" (address),
3588 + "=r" (address),
3589 "=c" (length),
3590 "=d" (entry)
3591 : "0" (service),
3592 @@ -141,18 +144,21 @@
3593
3594 save_flags(flags);
3595 __asm__(
3596 + "pushl %%ebx\n\t" /* save %ebx */
3597 + "movl %3, %%ebx\n\t" /* put the value into ebx */
3598 #ifdef ABSOLUTE_WITHOUT_ASTERISK
3599 "lcall (%%esi)\n\t"
3600 #else
3601 "lcall *(%%esi)\n\t"
3602 #endif
3603 "jc 1f\n\t"
3604 - "xor %%ah, %%ah\n"
3605 + "popl %%ebx\n\t" /* restore %ebx */
3606 + "xor %%ah, %%ah\n\t"
3607 "1:"
3608 : "=c" (*value),
3609 "=a" (ret)
3610 : "1" (PCIBIOS_READ_CONFIG_BYTE),
3611 - "b" (bx),
3612 + "r" (bx),
3613 "D" ((long) where),
3614 "S" (&pci_indirect));
3615 restore_flags(flags);
3616 @@ -168,18 +174,21 @@
3617
3618 save_flags(flags);
3619 __asm__(
3620 + "pushl %%ebx\n\t" /* save %ebx */
3621 + "movl %3, %%ebx\n\t" /* put the value into ebx */
3622 #ifdef ABSOLUTE_WITHOUT_ASTERISK
3623 "lcall (%%esi)\n\t"
3624 #else
3625 "lcall *(%%esi)\n\t"
3626 #endif
3627 "jc 1f\n\t"
3628 - "xor %%ah, %%ah\n"
3629 + "popl %%ebx\n\t" /* restore %ebx */
3630 + "xor %%ah, %%ah\n\t"
3631 "1:"
3632 : "=c" (*value),
3633 "=a" (ret)
3634 : "1" (PCIBIOS_READ_CONFIG_WORD),
3635 - "b" (bx),
3636 + "r" (bx),
3637 "D" ((long) where),
3638 "S" (&pci_indirect));
3639 restore_flags(flags);
3640 @@ -195,18 +204,21 @@
3641
3642 save_flags(flags);
3643 __asm__(
3644 + "pushl %%ebx\n\t" /* save %ebx */
3645 + "movl %3, %%ebx\n\t" /* put the value into ebx */
3646 #ifdef ABSOLUTE_WITHOUT_ASTERISK
3647 "lcall (%%esi)\n\t"
3648 #else
3649 "lcall *(%%esi)\n\t"
3650 #endif
3651 "jc 1f\n\t"
3652 - "xor %%ah, %%ah\n"
3653 + "popl %%ebx\n\t" /* restore %ebx */
3654 + "xor %%ah, %%ah\n\t"
3655 "1:"
3656 : "=c" (*value),
3657 "=a" (ret)
3658 : "1" (PCIBIOS_READ_CONFIG_DWORD),
3659 - "b" (bx),
3660 + "r" (bx),
3661 "D" ((long) where),
3662 "S" (&pci_indirect));
3663 restore_flags(flags);
3664 @@ -222,18 +234,21 @@
3665
3666 save_flags(flags); cli();
3667 __asm__(
3668 + "pushl %%ebx\n\t" /* save %ebx */
3669 + "movl %3, %%ebx\n\t" /* put the value into ebx */
3670 #ifdef ABSOLUTE_WITHOUT_ASTERISK
3671 "lcall (%%esi)\n\t"
3672 #else
3673 "lcall *(%%esi)\n\t"
3674 #endif
3675 "jc 1f\n\t"
3676 - "xor %%ah, %%ah\n"
3677 + "popl %%ebx\n\t" /* restore %ebx */
3678 + "xor %%ah, %%ah\n\t"
3679 "1:"
3680 : "=a" (ret)
3681 : "0" (PCIBIOS_WRITE_CONFIG_BYTE),
3682 "c" (value),
3683 - "b" (bx),
3684 + "r" (bx),
3685 "D" ((long) where),
3686 "S" (&pci_indirect));
3687 restore_flags(flags);
3688 @@ -249,18 +264,21 @@
3689
3690 save_flags(flags); cli();
3691 __asm__(
3692 + "pushl %%ebx\n\t" /* save %ebx */
3693 + "movl %3, %%ebx\n\t" /* put the value into ebx */
3694 #ifdef ABSOLUTE_WITHOUT_ASTERISK
3695 "lcall (%%esi)\n\t"
3696 #else
3697 "lcall *(%%esi)\n\t"
3698 #endif
3699 "jc 1f\n\t"
3700 - "xor %%ah, %%ah\n"
3701 + "popl %%ebx\n\t" /* restore %ebx */
3702 + "xor %%ah, %%ah\n\t"
3703 "1:"
3704 : "=a" (ret)
3705 : "0" (PCIBIOS_WRITE_CONFIG_WORD),
3706 "c" (value),
3707 - "b" (bx),
3708 + "r" (bx),
3709 "D" ((long) where),
3710 "S" (&pci_indirect));
3711 restore_flags(flags);
3712 @@ -276,18 +294,21 @@
3713
3714 save_flags(flags); cli();
3715 __asm__(
3716 + "pushl %%ebx\n\t" /* save %ebx */
3717 + "movl %3, %%ebx\n\t" /* put the value into ebx */
3718 #ifdef ABSOLUTE_WITHOUT_ASTERISK
3719 "lcall (%%esi)\n\t"
3720 #else
3721 "lcall *(%%esi)\n\t"
3722 #endif
3723 "jc 1f\n\t"
3724 - "xor %%ah, %%ah\n"
3725 + "popl %%ebx\n\t" /* restore %ebx */
3726 + "xor %%ah, %%ah\n\t"
3727 "1:"
3728 : "=a" (ret)
3729 : "0" (PCIBIOS_WRITE_CONFIG_DWORD),
3730 "c" (value),
3731 - "b" (bx),
3732 + "r" (bx),
3733 "D" ((long) where),
3734 "S" (&pci_indirect));
3735 restore_flags(flags);
3736 @@ -308,20 +329,22 @@
3737
3738 save_flags(flags);
3739 __asm__(
3740 + "pushl %%ebx\n\t" /* save %ebx */
3741 #ifdef ABSOLUTE_WITHOUT_ASTERISK
3742 "lcall (%%edi)\n\t"
3743 #else
3744 "lcall *(%%edi)\n\t"
3745 #endif
3746 "jc 1f\n\t"
3747 - "xor %%ah, %%ah\n"
3748 + "xor %%ah, %%ah\n\t"
3749 "1:\tshl $8, %%eax\n\t"
3750 - "movw %%bx, %%ax"
3751 + "movw %%bx, %%ax\n\t"
3752 + "popl %%ebx\n\t" /* restore %ebx */
3753 : "=d" (signature),
3754 "=a" (pack)
3755 : "1" (PCIBIOS_PCI_BIOS_PRESENT),
3756 "D" (&pci_indirect)
3757 - : "bx", "cx");
3758 + : "cx");
3759 restore_flags(flags);
3760
3761 present_status = (pack >> 16) & 0xff;
3762 diff -Nur grub-0.97/netboot/sis900.c grub-0.97-patched/netboot/sis900.c
3763 --- grub-0.97/netboot/sis900.c 2003-07-09 13:45:38.000000000 +0200
3764 +++ grub-0.97-patched/netboot/sis900.c 2012-11-11 17:07:12.725729531 +0100
3765 @@ -901,7 +901,7 @@
3766 const char *p) /* Packet */
3767 {
3768 u32 status, to, nstype;
3769 - u32 tx_status;
3770 + volatile u32 tx_status;
3771
3772 /* Stop the transmitter */
3773 outl(TxDIS, ioaddr + cr);
3774 @@ -940,7 +940,7 @@
3775
3776 to = currticks() + TX_TIMEOUT;
3777
3778 - while ((((volatile u32) tx_status=txd.cmdsts) & OWN) && (currticks() < to))
3779 + while (((tx_status=txd.cmdsts) & OWN) && (currticks() < to))
3780 /* wait */ ;
3781
3782 if (currticks() >= to) {
3783 diff -Nur grub-0.97/stage1/Makefile.am grub-0.97-patched/stage1/Makefile.am
3784 --- grub-0.97/stage1/Makefile.am 2004-07-16 13:44:56.000000000 +0200
3785 +++ grub-0.97-patched/stage1/Makefile.am 2012-11-11 17:07:12.747730236 +0100
3786 @@ -1,11 +1,11 @@
3787 -pkglibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
3788 -nodist_pkglib_DATA = stage1
3789 +stagedir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
3790 +nodist_stage_DATA = stage1
3791
3792 -CLEANFILES = $(nodist_pkglib_DATA)
3793 +CLEANFILES = $(nodist_stage_DATA)
3794
3795 # We can't use builtins or standard includes.
3796 AM_CCASFLAGS = $(STAGE1_CFLAGS) -fno-builtin -nostdinc
3797 -LDFLAGS = -nostdlib -Wl,-N,-Ttext,7C00
3798 +stage1_exec_LDFLAGS = -nostdlib -Wl,-N,-Ttext,7C00
3799
3800 noinst_PROGRAMS = stage1.exec
3801 stage1_exec_SOURCES = stage1.S stage1.h
3802 diff -Nur grub-0.97/stage2/asm.S grub-0.97-patched/stage2/asm.S
3803 --- grub-0.97/stage2/asm.S 2004-06-19 18:55:22.000000000 +0200
3804 +++ grub-0.97-patched/stage2/asm.S 2012-11-11 17:07:03.850446017 +0100
3805 @@ -1651,7 +1651,29 @@
3806 jnz 3f
3807 ret
3808
3809 -3: /* use keyboard controller */
3810 +3: /*
3811 + * try to switch gateA20 using PORT92, the "Fast A20 and Init"
3812 + * register
3813 + */
3814 + mov $0x92, %dx
3815 + inb %dx, %al
3816 + /* skip the port92 code if it's unimplemented (read returns 0xff) */
3817 + cmpb $0xff, %al
3818 + jz 6f
3819 +
3820 + /* set or clear bit1, the ALT_A20_GATE bit */
3821 + movb 4(%esp), %ah
3822 + testb %ah, %ah
3823 + jz 4f
3824 + orb $2, %al
3825 + jmp 5f
3826 +4: and $0xfd, %al
3827 +
3828 + /* clear the INIT_NOW bit don't accidently reset the machine */
3829 +5: and $0xfe, %al
3830 + outb %al, %dx
3831 +
3832 +6: /* use keyboard controller */
3833 pushl %eax
3834
3835 call gloop1
3836 @@ -1661,9 +1683,12 @@
3837
3838 gloopint1:
3839 inb $K_STATUS
3840 + cmpb $0xff, %al
3841 + jz gloopint1_done
3842 andb $K_IBUF_FUL, %al
3843 jnz gloopint1
3844
3845 +gloopint1_done:
3846 movb $KB_OUTPUT_MASK, %al
3847 cmpb $0, 0x8(%esp)
3848 jz gdoit
3849 @@ -1684,6 +1709,8 @@
3850
3851 gloop1:
3852 inb $K_STATUS
3853 + cmpb $0xff, %al
3854 + jz gloop2ret
3855 andb $K_IBUF_FUL, %al
3856 jnz gloop1
3857
3858 @@ -1991,6 +2018,11 @@
3859 ENTRY(console_getkey)
3860 push %ebp
3861
3862 +wait_for_key:
3863 + call EXT_C(console_checkkey)
3864 + incl %eax
3865 + jz wait_for_key
3866 +
3867 call EXT_C(prot_to_real)
3868 .code16
3869
3870 @@ -2216,6 +2248,156 @@
3871 pop %ebx
3872 pop %ebp
3873 ret
3874 +
3875 +/* graphics mode functions */
3876 +#ifdef SUPPORT_GRAPHICS
3877 +VARIABLE(cursorX)
3878 +.word 0
3879 +VARIABLE(cursorY)
3880 +.word 0
3881 +VARIABLE(cursorCount)
3882 +.word 0
3883 +VARIABLE(cursorBuf)
3884 +.byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
3885 +
3886 +
3887 +/*
3888 + * int set_videomode(mode)
3889 + * BIOS call "INT 10H Function 0h" to set video mode
3890 + * Call with %ah = 0x0
3891 + * %al = video mode
3892 + * Returns old videomode.
3893 + */
3894 +ENTRY(set_videomode)
3895 + push %ebp
3896 + push %ebx
3897 + push %ecx
3898 +
3899 + movb 0x10(%esp), %cl
3900 +
3901 + call EXT_C(prot_to_real)
3902 + .code16
3903 +
3904 + xorw %bx, %bx
3905 + movb $0xf, %ah
3906 + int $0x10 /* Get Current Video mode */
3907 + movb %al, %ch
3908 + xorb %ah, %ah
3909 + movb %cl, %al
3910 + int $0x10 /* Set Video mode */
3911 +
3912 + DATA32 call EXT_C(real_to_prot)
3913 + .code32
3914 +
3915 + xorb %ah, %ah
3916 + movb %ch, %al
3917 +
3918 + pop %ecx
3919 + pop %ebx
3920 + pop %ebp
3921 + ret
3922 +
3923 +
3924 +/*
3925 + * unsigned char * graphics_get_font()
3926 + * BIOS call "INT 10H Function 11h" to set font
3927 + * Call with %ah = 0x11
3928 + */
3929 +ENTRY(graphics_get_font)
3930 + push %ebp
3931 + push %ebx
3932 + push %ecx
3933 + push %edx
3934 +
3935 + call EXT_C(prot_to_real)
3936 + .code16
3937 +
3938 + movw $0x1130, %ax
3939 + movb $6, %bh /* font 8x16 */
3940 + int $0x10
3941 + movw %bp, %dx
3942 + movw %es, %cx
3943 +
3944 + DATA32 call EXT_C(real_to_prot)
3945 + .code32
3946 +
3947 + xorl %eax, %eax
3948 + movw %cx, %ax
3949 + shll $4, %eax
3950 + movw %dx, %ax
3951 +
3952 + pop %edx
3953 + pop %ecx
3954 + pop %ebx
3955 + pop %ebp
3956 + ret
3957 +
3958 +
3959 +
3960 +/*
3961 + * graphics_set_palette(index, red, green, blue)
3962 + * BIOS call "INT 10H Function 10h" to set individual dac register
3963 + * Call with %ah = 0x10
3964 + * %bx = register number
3965 + * %ch = new value for green (0-63)
3966 + * %cl = new value for blue (0-63)
3967 + * %dh = new value for red (0-63)
3968 + */
3969 +
3970 +ENTRY(graphics_set_palette)
3971 + push %ebp
3972 + push %eax
3973 + push %ebx
3974 + push %ecx
3975 + push %edx
3976 +
3977 + movw $0x3c8, %bx /* address write mode register */
3978 +
3979 + /* wait vertical retrace */
3980 +
3981 + movw $0x3da, %dx
3982 +l1b: inb %dx, %al /* wait vertical active display */
3983 + test $8, %al
3984 + jnz l1b
3985 +
3986 +l2b: inb %dx, %al /* wait vertical retrace */
3987 + test $8, %al
3988 + jnz l2b
3989 +
3990 + mov %bx, %dx
3991 + movb 0x18(%esp), %al /* index */
3992 + outb %al, %dx
3993 + inc %dx
3994 +
3995 + movb 0x1c(%esp), %al /* red */
3996 + outb %al, %dx
3997 +
3998 + movb 0x20(%esp), %al /* green */
3999 + outb %al, %dx
4000 +
4001 + movb 0x24(%esp), %al /* blue */
4002 + outb %al, %dx
4003 +
4004 + movw 0x18(%esp), %bx
4005 +
4006 + call EXT_C(prot_to_real)
4007 + .code16
4008 +
4009 + movb %bl, %bh
4010 + movw $0x1000, %ax
4011 + int $0x10
4012 +
4013 + DATA32 call EXT_C(real_to_prot)
4014 + .code32
4015 +
4016 + pop %edx
4017 + pop %ecx
4018 + pop %ebx
4019 + pop %eax
4020 + pop %ebp
4021 + ret
4022 +
4023 +#endif /* SUPPORT_GRAPHICS */
4024
4025 /*
4026 * getrtsecs()
4027 diff -Nur grub-0.97/stage2/bios.c grub-0.97-patched/stage2/bios.c
4028 --- grub-0.97/stage2/bios.c 2004-03-27 17:34:04.000000000 +0100
4029 +++ grub-0.97-patched/stage2/bios.c 2012-11-11 17:07:12.751730363 +0100
4030 @@ -47,7 +47,7 @@
4031 return the error number. Otherwise, return 0. */
4032 int
4033 biosdisk (int read, int drive, struct geometry *geometry,
4034 - int sector, int nsec, int segment)
4035 + unsigned int sector, int nsec, int segment)
4036 {
4037 int err;
4038
4039 @@ -60,7 +60,18 @@
4040 unsigned short blocks;
4041 unsigned long buffer;
4042 unsigned long long block;
4043 - } __attribute__ ((packed)) dap;
4044 +
4045 + /* This structure is passed in the stack. A buggy BIOS could write
4046 + * garbage data to the tail of the struct and hang the machine. So
4047 + * we need this protection. - Tinybit
4048 + */
4049 + unsigned char dummy[16];
4050 + } __attribute__ ((packed)) *dap;
4051 +
4052 + /* Even the above protection is not enough to avoid stupid actions by
4053 + * buggy BIOSes. So we do it in the 0040:0000 segment. - Tinybit
4054 + */
4055 + dap = (struct disk_address_packet *)0x580;
4056
4057 /* XXX: Don't check the geometry by default, because some buggy
4058 BIOSes don't return the number of total sectors correctly,
4059 @@ -72,15 +83,15 @@
4060
4061 /* FIXME: sizeof (DAP) must be 0x10. Should assert that the compiler
4062 can't add any padding. */
4063 - dap.length = sizeof (dap);
4064 - dap.block = sector;
4065 - dap.blocks = nsec;
4066 - dap.reserved = 0;
4067 + dap->length = 0x10;
4068 + dap->block = sector;
4069 + dap->blocks = nsec;
4070 + dap->reserved = 0;
4071 /* This is undocumented part. The address is formated in
4072 SEGMENT:ADDRESS. */
4073 - dap.buffer = segment << 16;
4074 + dap->buffer = segment << 16;
4075
4076 - err = biosdisk_int13_extensions ((read + 0x42) << 8, drive, &dap);
4077 + err = biosdisk_int13_extensions ((read + 0x42) << 8, drive, dap);
4078
4079 /* #undef NO_INT13_FALLBACK */
4080 #ifndef NO_INT13_FALLBACK
4081 diff -Nur grub-0.97/stage2/boot.c grub-0.97-patched/stage2/boot.c
4082 --- grub-0.97/stage2/boot.c 2004-03-30 13:44:08.000000000 +0200
4083 +++ grub-0.97-patched/stage2/boot.c 2012-11-11 17:07:12.727729596 +0100
4084 @@ -1,7 +1,7 @@
4085 /* boot.c - load and bootstrap a kernel */
4086 /*
4087 * GRUB -- GRand Unified Bootloader
4088 - * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
4089 + * Copyright (C) 1999,2000,2001,2002,2003,2004,2005 Free Software Foundation, Inc.
4090 *
4091 * This program is free software; you can redistribute it and/or modify
4092 * it under the terms of the GNU General Public License as published by
4093 @@ -96,7 +96,7 @@
4094 lh = (struct linux_kernel_header *) buffer;
4095
4096 /* ELF loading supported if multiboot, FreeBSD and NetBSD. */
4097 - if ((type == KERNEL_TYPE_MULTIBOOT
4098 + if (((type == KERNEL_TYPE_MULTIBOOT && ! (flags & MULTIBOOT_AOUT_KLUDGE))
4099 || pu.elf->e_ident[EI_OSABI] == ELFOSABI_FREEBSD
4100 || grub_strcmp (pu.elf->e_ident + EI_BRAND, "FreeBSD") == 0
4101 || suggested_type == KERNEL_TYPE_NETBSD)
4102 @@ -241,7 +241,7 @@
4103 }
4104
4105 if (lh->version >= 0x0202)
4106 - lh->cmd_line_ptr = linux_data_real_addr + LINUX_CL_OFFSET;
4107 + lh->cmd_line_ptr = linux_data_real_addr + LINUX_CL_0202_PRM_OFFSET;
4108 else
4109 {
4110 lh->cl_magic = LINUX_CL_MAGIC;
4111 @@ -407,6 +407,15 @@
4112 while (dest < linux_data_tmp_addr + LINUX_CL_END_OFFSET && *src)
4113 *(dest++) = *(src++);
4114
4115 + {
4116 + char *src = skip_to (0, arg);
4117 + char *dest = linux_data_tmp_addr + LINUX_CL_0202_PRM_OFFSET;
4118 +
4119 + while (dest < linux_data_tmp_addr + LINUX_CL_0202_PRM_END_OFFSET && *src)
4120 + *(dest++) = *(src++);
4121 + *dest = 0;
4122 + }
4123 +
4124 /* Old Linux kernels have problems determining the amount of
4125 the available memory. To work around this problem, we add
4126 the "mem" option to the kernel command line. This has its
4127 @@ -824,8 +833,11 @@
4128 moveto = (mbi.mem_upper + 0x400) << 10;
4129
4130 moveto = (moveto - len) & 0xfffff000;
4131 - max_addr = (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0203
4132 - ? lh->initrd_addr_max : LINUX_INITRD_MAX_ADDRESS);
4133 + max_addr = LINUX_INITRD_MAX_ADDRESS;
4134 + if (lh->header == LINUX_MAGIC_SIGNATURE &&
4135 + lh->version >= 0x0203 &&
4136 + lh->initrd_addr_max < max_addr)
4137 + max_addr = lh->initrd_addr_max;
4138 if (moveto + len >= max_addr)
4139 moveto = (max_addr - len) & 0xfffff000;
4140
4141 diff -Nur grub-0.97/stage2/boot.c.orig grub-0.97-patched/stage2/boot.c.orig
4142 --- grub-0.97/stage2/boot.c.orig 1970-01-01 01:00:00.000000000 +0100
4143 +++ grub-0.97-patched/stage2/boot.c.orig 2004-03-30 13:44:08.000000000 +0200
4144 @@ -0,0 +1,1020 @@
4145 +/* boot.c - load and bootstrap a kernel */
4146 +/*
4147 + * GRUB -- GRand Unified Bootloader
4148 + * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
4149 + *
4150 + * This program is free software; you can redistribute it and/or modify
4151 + * it under the terms of the GNU General Public License as published by
4152 + * the Free Software Foundation; either version 2 of the License, or
4153 + * (at your option) any later version.
4154 + *
4155 + * This program is distributed in the hope that it will be useful,
4156 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4157 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4158 + * GNU General Public License for more details.
4159 + *
4160 + * You should have received a copy of the GNU General Public License
4161 + * along with this program; if not, write to the Free Software
4162 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
4163 + */
4164 +
4165 +
4166 +#include "shared.h"
4167 +
4168 +#include "freebsd.h"
4169 +#include "imgact_aout.h"
4170 +#include "i386-elf.h"
4171 +
4172 +static int cur_addr;
4173 +entry_func entry_addr;
4174 +static struct mod_list mll[99];
4175 +static int linux_mem_size;
4176 +
4177 +/*
4178 + * The next two functions, 'load_image' and 'load_module', are the building
4179 + * blocks of the multiboot loader component. They handle essentially all
4180 + * of the gory details of loading in a bootable image and the modules.
4181 + */
4182 +
4183 +kernel_t
4184 +load_image (char *kernel, char *arg, kernel_t suggested_type,
4185 + unsigned long load_flags)
4186 +{
4187 + int len, i, exec_type = 0, align_4k = 1;
4188 + entry_func real_entry_addr = 0;
4189 + kernel_t type = KERNEL_TYPE_NONE;
4190 + unsigned long flags = 0, text_len = 0, data_len = 0, bss_len = 0;
4191 + char *str = 0, *str2 = 0;
4192 + struct linux_kernel_header *lh;
4193 + union
4194 + {
4195 + struct multiboot_header *mb;
4196 + struct exec *aout;
4197 + Elf32_Ehdr *elf;
4198 + }
4199 + pu;
4200 + /* presuming that MULTIBOOT_SEARCH is large enough to encompass an
4201 + executable header */
4202 + unsigned char buffer[MULTIBOOT_SEARCH];
4203 +
4204 + /* sets the header pointer to point to the beginning of the
4205 + buffer by default */
4206 + pu.aout = (struct exec *) buffer;
4207 +
4208 + if (!grub_open (kernel))
4209 + return KERNEL_TYPE_NONE;
4210 +
4211 + if (!(len = grub_read (buffer, MULTIBOOT_SEARCH)) || len < 32)
4212 + {
4213 + grub_close ();
4214 +
4215 + if (!errnum)
4216 + errnum = ERR_EXEC_FORMAT;
4217 +
4218 + return KERNEL_TYPE_NONE;
4219 + }
4220 +
4221 + for (i = 0; i < len; i++)
4222 + {
4223 + if (MULTIBOOT_FOUND ((int) (buffer + i), len - i))
4224 + {
4225 + flags = ((struct multiboot_header *) (buffer + i))->flags;
4226 + if (flags & MULTIBOOT_UNSUPPORTED)
4227 + {
4228 + grub_close ();
4229 + errnum = ERR_BOOT_FEATURES;
4230 + return KERNEL_TYPE_NONE;
4231 + }
4232 + type = KERNEL_TYPE_MULTIBOOT;
4233 + str2 = "Multiboot";
4234 + break;
4235 + }
4236 + }
4237 +
4238 + /* Use BUFFER as a linux kernel header, if the image is Linux zImage
4239 + or bzImage. */
4240 + lh = (struct linux_kernel_header *) buffer;
4241 +
4242 + /* ELF loading supported if multiboot, FreeBSD and NetBSD. */
4243 + if ((type == KERNEL_TYPE_MULTIBOOT
4244 + || pu.elf->e_ident[EI_OSABI] == ELFOSABI_FREEBSD
4245 + || grub_strcmp (pu.elf->e_ident + EI_BRAND, "FreeBSD") == 0
4246 + || suggested_type == KERNEL_TYPE_NETBSD)
4247 + && len > sizeof (Elf32_Ehdr)
4248 + && BOOTABLE_I386_ELF ((*((Elf32_Ehdr *) buffer))))
4249 + {
4250 + if (type == KERNEL_TYPE_MULTIBOOT)
4251 + entry_addr = (entry_func) pu.elf->e_entry;
4252 + else
4253 + entry_addr = (entry_func) (pu.elf->e_entry & 0xFFFFFF);
4254 +
4255 + if (entry_addr < (entry_func) 0x100000)
4256 + errnum = ERR_BELOW_1MB;
4257 +
4258 + /* don't want to deal with ELF program header at some random
4259 + place in the file -- this generally won't happen */
4260 + if (pu.elf->e_phoff == 0 || pu.elf->e_phnum == 0
4261 + || ((pu.elf->e_phoff + (pu.elf->e_phentsize * pu.elf->e_phnum))
4262 + >= len))
4263 + errnum = ERR_EXEC_FORMAT;
4264 + str = "elf";
4265 +
4266 + if (type == KERNEL_TYPE_NONE)
4267 + {
4268 + /* At the moment, there is no way to identify a NetBSD ELF
4269 + kernel, so rely on the suggested type by the user. */
4270 + if (suggested_type == KERNEL_TYPE_NETBSD)
4271 + {
4272 + str2 = "NetBSD";
4273 + type = suggested_type;
4274 + }
4275 + else
4276 + {
4277 + str2 = "FreeBSD";
4278 + type = KERNEL_TYPE_FREEBSD;
4279 + }
4280 + }
4281 + }
4282 + else if (flags & MULTIBOOT_AOUT_KLUDGE)
4283 + {
4284 + pu.mb = (struct multiboot_header *) (buffer + i);
4285 + entry_addr = (entry_func) pu.mb->entry_addr;
4286 + cur_addr = pu.mb->load_addr;
4287 + /* first offset into file */
4288 + grub_seek (i - (pu.mb->header_addr - cur_addr));
4289 +
4290 + /* If the load end address is zero, load the whole contents. */
4291 + if (! pu.mb->load_end_addr)
4292 + pu.mb->load_end_addr = cur_addr + filemax;
4293 +
4294 + text_len = pu.mb->load_end_addr - cur_addr;
4295 + data_len = 0;
4296 +
4297 + /* If the bss end address is zero, assume that there is no bss area. */
4298 + if (! pu.mb->bss_end_addr)
4299 + pu.mb->bss_end_addr = pu.mb->load_end_addr;
4300 +
4301 + bss_len = pu.mb->bss_end_addr - pu.mb->load_end_addr;
4302 +
4303 + if (pu.mb->header_addr < pu.mb->load_addr
4304 + || pu.mb->load_end_addr <= pu.mb->load_addr
4305 + || pu.mb->bss_end_addr < pu.mb->load_end_addr
4306 + || (pu.mb->header_addr - pu.mb->load_addr) > i)
4307 + errnum = ERR_EXEC_FORMAT;
4308 +
4309 + if (cur_addr < 0x100000)
4310 + errnum = ERR_BELOW_1MB;
4311 +
4312 + pu.aout = (struct exec *) buffer;
4313 + exec_type = 2;
4314 + str = "kludge";
4315 + }
4316 + else if (len > sizeof (struct exec) && !N_BADMAG ((*(pu.aout))))
4317 + {
4318 + entry_addr = (entry_func) pu.aout->a_entry;
4319 +
4320 + if (type == KERNEL_TYPE_NONE)
4321 + {
4322 + /*
4323 + * If it doesn't have a Multiboot header, then presume
4324 + * it is either a FreeBSD or NetBSD executable. If so,
4325 + * then use a magic number of normal ordering, ZMAGIC to
4326 + * determine if it is FreeBSD.
4327 + *
4328 + * This is all because freebsd and netbsd seem to require
4329 + * masking out some address bits... differently for each
4330 + * one... plus of course we need to know which booting
4331 + * method to use.
4332 + */
4333 + entry_addr = (entry_func) ((int) entry_addr & 0xFFFFFF);
4334 +
4335 + if (buffer[0] == 0xb && buffer[1] == 1)
4336 + {
4337 + type = KERNEL_TYPE_FREEBSD;
4338 + cur_addr = (int) entry_addr;
4339 + str2 = "FreeBSD";
4340 + }
4341 + else
4342 + {
4343 + type = KERNEL_TYPE_NETBSD;
4344 + cur_addr = (int) entry_addr & 0xF00000;
4345 + if (N_GETMAGIC ((*(pu.aout))) != NMAGIC)
4346 + align_4k = 0;
4347 + str2 = "NetBSD";
4348 + }
4349 + }
4350 +
4351 + /* first offset into file */
4352 + grub_seek (N_TXTOFF (*(pu.aout)));
4353 + text_len = pu.aout->a_text;
4354 + data_len = pu.aout->a_data;
4355 + bss_len = pu.aout->a_bss;
4356 +
4357 + if (cur_addr < 0x100000)
4358 + errnum = ERR_BELOW_1MB;
4359 +
4360 + exec_type = 1;
4361 + str = "a.out";
4362 + }
4363 + else if (lh->boot_flag == BOOTSEC_SIGNATURE
4364 + && lh->setup_sects <= LINUX_MAX_SETUP_SECTS)
4365 + {
4366 + int big_linux = 0;
4367 + int setup_sects = lh->setup_sects;
4368 +
4369 + if (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0200)
4370 + {
4371 + big_linux = (lh->loadflags & LINUX_FLAG_BIG_KERNEL);
4372 + lh->type_of_loader = LINUX_BOOT_LOADER_TYPE;
4373 +
4374 + /* Put the real mode part at as a high location as possible. */
4375 + linux_data_real_addr
4376 + = (char *) ((mbi.mem_lower << 10) - LINUX_SETUP_MOVE_SIZE);
4377 + /* But it must not exceed the traditional area. */
4378 + if (linux_data_real_addr > (char *) LINUX_OLD_REAL_MODE_ADDR)
4379 + linux_data_real_addr = (char *) LINUX_OLD_REAL_MODE_ADDR;
4380 +
4381 + if (lh->version >= 0x0201)
4382 + {
4383 + lh->heap_end_ptr = LINUX_HEAP_END_OFFSET;
4384 + lh->loadflags |= LINUX_FLAG_CAN_USE_HEAP;
4385 + }
4386 +
4387 + if (lh->version >= 0x0202)
4388 + lh->cmd_line_ptr = linux_data_real_addr + LINUX_CL_OFFSET;
4389 + else
4390 + {
4391 + lh->cl_magic = LINUX_CL_MAGIC;
4392 + lh->cl_offset = LINUX_CL_OFFSET;
4393 + lh->setup_move_size = LINUX_SETUP_MOVE_SIZE;
4394 + }
4395 + }
4396 + else
4397 + {
4398 + /* Your kernel is quite old... */
4399 + lh->cl_magic = LINUX_CL_MAGIC;
4400 + lh->cl_offset = LINUX_CL_OFFSET;
4401 +
4402 + setup_sects = LINUX_DEFAULT_SETUP_SECTS;
4403 +
4404 + linux_data_real_addr = (char *) LINUX_OLD_REAL_MODE_ADDR;
4405 + }
4406 +
4407 + /* If SETUP_SECTS is not set, set it to the default (4). */
4408 + if (! setup_sects)
4409 + setup_sects = LINUX_DEFAULT_SETUP_SECTS;
4410 +
4411 + data_len = setup_sects << 9;
4412 + text_len = filemax - data_len - SECTOR_SIZE;
4413 +
4414 + linux_data_tmp_addr = (char *) LINUX_BZIMAGE_ADDR + text_len;
4415 +
4416 + if (! big_linux
4417 + && text_len > linux_data_real_addr - (char *) LINUX_ZIMAGE_ADDR)
4418 + {
4419 + grub_printf (" linux 'zImage' kernel too big, try 'make bzImage'\n");
4420 + errnum = ERR_WONT_FIT;
4421 + }
4422 + else if (linux_data_real_addr + LINUX_SETUP_MOVE_SIZE
4423 + > RAW_ADDR ((char *) (mbi.mem_lower << 10)))
4424 + errnum = ERR_WONT_FIT;
4425 + else
4426 + {
4427 + grub_printf (" [Linux-%s, setup=0x%x, size=0x%x]\n",
4428 + (big_linux ? "bzImage" : "zImage"), data_len, text_len);
4429 +
4430 + /* Video mode selection support. What a mess! */
4431 + /* NOTE: Even the word "mess" is not still enough to
4432 + represent how wrong and bad the Linux video support is,
4433 + but I don't want to hear complaints from Linux fanatics
4434 + any more. -okuji */
4435 + {
4436 + char *vga;
4437 +
4438 + /* Find the substring "vga=". */
4439 + vga = grub_strstr (arg, "vga=");
4440 + if (vga)
4441 + {
4442 + char *value = vga + 4;
4443 + int vid_mode;
4444 +
4445 + /* Handle special strings. */
4446 + if (substring ("normal", value) < 1)
4447 + vid_mode = LINUX_VID_MODE_NORMAL;
4448 + else if (substring ("ext", value) < 1)
4449 + vid_mode = LINUX_VID_MODE_EXTENDED;
4450 + else if (substring ("ask", value) < 1)
4451 + vid_mode = LINUX_VID_MODE_ASK;
4452 + else if (safe_parse_maxint (&value, &vid_mode))
4453 + ;
4454 + else
4455 + {
4456 + /* ERRNUM is already set inside the function
4457 + safe_parse_maxint. */
4458 + grub_close ();
4459 + return KERNEL_TYPE_NONE;
4460 + }
4461 +
4462 + lh->vid_mode = vid_mode;
4463 + }
4464 + }
4465 +
4466 + /* Check the mem= option to limit memory used for initrd. */
4467 + {
4468 + char *mem;
4469 +
4470 + mem = grub_strstr (arg, "mem=");
4471 + if (mem)
4472 + {
4473 + char *value = mem + 4;
4474 +
4475 + safe_parse_maxint (&value, &linux_mem_size);
4476 + switch (errnum)
4477 + {
4478 + case ERR_NUMBER_OVERFLOW:
4479 + /* If an overflow occurs, use the maximum address for
4480 + initrd instead. This is good, because MAXINT is
4481 + greater than LINUX_INITRD_MAX_ADDRESS. */
4482 + linux_mem_size = LINUX_INITRD_MAX_ADDRESS;
4483 + errnum = ERR_NONE;
4484 + break;
4485 +
4486 + case ERR_NONE:
4487 + {
4488 + int shift = 0;
4489 +
4490 + switch (grub_tolower (*value))
4491 + {
4492 + case 'g':
4493 + shift += 10;
4494 + case 'm':
4495 + shift += 10;
4496 + case 'k':
4497 + shift += 10;
4498 + default:
4499 + break;
4500 + }
4501 +
4502 + /* Check an overflow. */
4503 + if (linux_mem_size > (MAXINT >> shift))
4504 + linux_mem_size = LINUX_INITRD_MAX_ADDRESS;
4505 + else
4506 + linux_mem_size <<= shift;
4507 + }
4508 + break;
4509 +
4510 + default:
4511 + linux_mem_size = 0;
4512 + errnum = ERR_NONE;
4513 + break;
4514 + }
4515 + }
4516 + else
4517 + linux_mem_size = 0;
4518 + }
4519 +
4520 + /* It is possible that DATA_LEN + SECTOR_SIZE is greater than
4521 + MULTIBOOT_SEARCH, so the data may have been read partially. */
4522 + if (data_len + SECTOR_SIZE <= MULTIBOOT_SEARCH)
4523 + grub_memmove (linux_data_tmp_addr, buffer,
4524 + data_len + SECTOR_SIZE);
4525 + else
4526 + {
4527 + grub_memmove (linux_data_tmp_addr, buffer, MULTIBOOT_SEARCH);
4528 + grub_read (linux_data_tmp_addr + MULTIBOOT_SEARCH,
4529 + data_len + SECTOR_SIZE - MULTIBOOT_SEARCH);
4530 + }
4531 +
4532 + if (lh->header != LINUX_MAGIC_SIGNATURE ||
4533 + lh->version < 0x0200)
4534 + /* Clear the heap space. */
4535 + grub_memset (linux_data_tmp_addr + ((setup_sects + 1) << 9),
4536 + 0,
4537 + (64 - setup_sects - 1) << 9);
4538 +
4539 + /* Copy command-line plus memory hack to staging area.
4540 + NOTE: Linux has a bug that it doesn't handle multiple spaces
4541 + between two options and a space after a "mem=" option isn't
4542 + removed correctly so the arguments to init could be like
4543 + {"init", "", "", NULL}. This affects some not-very-clever
4544 + shells. Thus, the code below does a trick to avoid the bug.
4545 + That is, copy "mem=XXX" to the end of the command-line, and
4546 + avoid to copy spaces unnecessarily. Hell. */
4547 + {
4548 + char *src = skip_to (0, arg);
4549 + char *dest = linux_data_tmp_addr + LINUX_CL_OFFSET;
4550 +
4551 + while (dest < linux_data_tmp_addr + LINUX_CL_END_OFFSET && *src)
4552 + *(dest++) = *(src++);
4553 +
4554 + /* Old Linux kernels have problems determining the amount of
4555 + the available memory. To work around this problem, we add
4556 + the "mem" option to the kernel command line. This has its
4557 + own drawbacks because newer kernels can determine the
4558 + memory map more accurately. Boot protocol 2.03, which
4559 + appeared in Linux 2.4.18, provides a pointer to the kernel
4560 + version string, so we could check it. But since kernel
4561 + 2.4.18 and newer are known to detect memory reliably, boot
4562 + protocol 2.03 already implies that the kernel is new
4563 + enough. The "mem" option is added if neither of the
4564 + following conditions is met:
4565 + 1) The "mem" option is already present.
4566 + 2) The "kernel" command is used with "--no-mem-option".
4567 + 3) GNU GRUB is configured not to pass the "mem" option.
4568 + 4) The kernel supports boot protocol 2.03 or newer. */
4569 + if (! grub_strstr (arg, "mem=")
4570 + && ! (load_flags & KERNEL_LOAD_NO_MEM_OPTION)
4571 + && lh->version < 0x0203 /* kernel version < 2.4.18 */
4572 + && dest + 15 < linux_data_tmp_addr + LINUX_CL_END_OFFSET)
4573 + {
4574 + *dest++ = ' ';
4575 + *dest++ = 'm';
4576 + *dest++ = 'e';
4577 + *dest++ = 'm';
4578 + *dest++ = '=';
4579 +
4580 + dest = convert_to_ascii (dest, 'u', (extended_memory + 0x400));
4581 + *dest++ = 'K';
4582 + }
4583 +
4584 + *dest = 0;
4585 + }
4586 +
4587 + /* offset into file */
4588 + grub_seek (data_len + SECTOR_SIZE);
4589 +
4590 + cur_addr = (int) linux_data_tmp_addr + LINUX_SETUP_MOVE_SIZE;
4591 + grub_read ((char *) LINUX_BZIMAGE_ADDR, text_len);
4592 +
4593 + if (errnum == ERR_NONE)
4594 + {
4595 + grub_close ();
4596 +
4597 + /* Sanity check. */
4598 + if (suggested_type != KERNEL_TYPE_NONE
4599 + && ((big_linux && suggested_type != KERNEL_TYPE_BIG_LINUX)
4600 + || (! big_linux && suggested_type != KERNEL_TYPE_LINUX)))
4601 + {
4602 + errnum = ERR_EXEC_FORMAT;
4603 + return KERNEL_TYPE_NONE;
4604 + }
4605 +
4606 + /* Ugly hack. */
4607 + linux_text_len = text_len;
4608 +
4609 + return big_linux ? KERNEL_TYPE_BIG_LINUX : KERNEL_TYPE_LINUX;
4610 + }
4611 + }
4612 + }
4613 + else /* no recognizable format */
4614 + errnum = ERR_EXEC_FORMAT;
4615 +
4616 + /* return if error */
4617 + if (errnum)
4618 + {
4619 + grub_close ();
4620 + return KERNEL_TYPE_NONE;
4621 + }
4622 +
4623 + /* fill the multiboot info structure */
4624 + mbi.cmdline = (int) arg;
4625 + mbi.mods_count = 0;
4626 + mbi.mods_addr = 0;
4627 + mbi.boot_device = (current_drive << 24) | current_partition;
4628 + mbi.flags &= ~(MB_INFO_MODS | MB_INFO_AOUT_SYMS | MB_INFO_ELF_SHDR);
4629 + mbi.syms.a.tabsize = 0;
4630 + mbi.syms.a.strsize = 0;
4631 + mbi.syms.a.addr = 0;
4632 + mbi.syms.a.pad = 0;
4633 +
4634 + printf (" [%s-%s", str2, str);
4635 +
4636 + str = "";
4637 +
4638 + if (exec_type) /* can be loaded like a.out */
4639 + {
4640 + if (flags & MULTIBOOT_AOUT_KLUDGE)
4641 + str = "-and-data";
4642 +
4643 + printf (", loadaddr=0x%x, text%s=0x%x", cur_addr, str, text_len);
4644 +
4645 + /* read text, then read data */
4646 + if (grub_read ((char *) RAW_ADDR (cur_addr), text_len) == text_len)
4647 + {
4648 + cur_addr += text_len;
4649 +
4650 + if (!(flags & MULTIBOOT_AOUT_KLUDGE))
4651 + {
4652 + /* we have to align to a 4K boundary */
4653 + if (align_4k)
4654 + cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
4655 + else
4656 + printf (", C");
4657 +
4658 + printf (", data=0x%x", data_len);
4659 +
4660 + if ((grub_read ((char *) RAW_ADDR (cur_addr), data_len)
4661 + != data_len)
4662 + && !errnum)
4663 + errnum = ERR_EXEC_FORMAT;
4664 + cur_addr += data_len;
4665 + }
4666 +
4667 + if (!errnum)
4668 + {
4669 + memset ((char *) RAW_ADDR (cur_addr), 0, bss_len);
4670 + cur_addr += bss_len;
4671 +
4672 + printf (", bss=0x%x", bss_len);
4673 + }
4674 + }
4675 + else if (!errnum)
4676 + errnum = ERR_EXEC_FORMAT;
4677 +
4678 + if (!errnum && pu.aout->a_syms
4679 + && pu.aout->a_syms < (filemax - filepos))
4680 + {
4681 + int symtab_err, orig_addr = cur_addr;
4682 +
4683 + /* we should align to a 4K boundary here for good measure */
4684 + if (align_4k)
4685 + cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
4686 +
4687 + mbi.syms.a.addr = cur_addr;
4688 +
4689 + *((int *) RAW_ADDR (cur_addr)) = pu.aout->a_syms;
4690 + cur_addr += sizeof (int);
4691 +
4692 + printf (", symtab=0x%x", pu.aout->a_syms);
4693 +
4694 + if (grub_read ((char *) RAW_ADDR (cur_addr), pu.aout->a_syms)
4695 + == pu.aout->a_syms)
4696 + {
4697 + cur_addr += pu.aout->a_syms;
4698 + mbi.syms.a.tabsize = pu.aout->a_syms;
4699 +
4700 + if (grub_read ((char *) &i, sizeof (int)) == sizeof (int))
4701 + {
4702 + *((int *) RAW_ADDR (cur_addr)) = i;
4703 + cur_addr += sizeof (int);
4704 +
4705 + mbi.syms.a.strsize = i;
4706 +
4707 + i -= sizeof (int);
4708 +
4709 + printf (", strtab=0x%x", i);
4710 +
4711 + symtab_err = (grub_read ((char *) RAW_ADDR (cur_addr), i)
4712 + != i);
4713 + cur_addr += i;
4714 + }
4715 + else
4716 + symtab_err = 1;
4717 + }
4718 + else
4719 + symtab_err = 1;
4720 +
4721 + if (symtab_err)
4722 + {
4723 + printf ("(bad)");
4724 + cur_addr = orig_addr;
4725 + mbi.syms.a.tabsize = 0;
4726 + mbi.syms.a.strsize = 0;
4727 + mbi.syms.a.addr = 0;
4728 + }
4729 + else
4730 + mbi.flags |= MB_INFO_AOUT_SYMS;
4731 + }
4732 + }
4733 + else
4734 + /* ELF executable */
4735 + {
4736 + unsigned loaded = 0, memaddr, memsiz, filesiz;
4737 + Elf32_Phdr *phdr;
4738 +
4739 + /* reset this to zero for now */
4740 + cur_addr = 0;
4741 +
4742 + /* scan for program segments */
4743 + for (i = 0; i < pu.elf->e_phnum; i++)
4744 + {
4745 + phdr = (Elf32_Phdr *)
4746 + (pu.elf->e_phoff + ((int) buffer)
4747 + + (pu.elf->e_phentsize * i));
4748 + if (phdr->p_type == PT_LOAD)
4749 + {
4750 + /* offset into file */
4751 + grub_seek (phdr->p_offset);
4752 + filesiz = phdr->p_filesz;
4753 +
4754 + if (type == KERNEL_TYPE_FREEBSD || type == KERNEL_TYPE_NETBSD)
4755 + memaddr = RAW_ADDR (phdr->p_paddr & 0xFFFFFF);
4756 + else
4757 + memaddr = RAW_ADDR (phdr->p_paddr);
4758 +
4759 + memsiz = phdr->p_memsz;
4760 + if (memaddr < RAW_ADDR (0x100000))
4761 + errnum = ERR_BELOW_1MB;
4762 +
4763 + /* If the memory range contains the entry address, get the
4764 + physical address here. */
4765 + if (type == KERNEL_TYPE_MULTIBOOT
4766 + && (unsigned) entry_addr >= phdr->p_vaddr
4767 + && (unsigned) entry_addr < phdr->p_vaddr + memsiz)
4768 + real_entry_addr = (entry_func) ((unsigned) entry_addr
4769 + + memaddr - phdr->p_vaddr);
4770 +
4771 + /* make sure we only load what we're supposed to! */
4772 + if (filesiz > memsiz)
4773 + filesiz = memsiz;
4774 + /* mark memory as used */
4775 + if (cur_addr < memaddr + memsiz)
4776 + cur_addr = memaddr + memsiz;
4777 + printf (", <0x%x:0x%x:0x%x>", memaddr, filesiz,
4778 + memsiz - filesiz);
4779 + /* increment number of segments */
4780 + loaded++;
4781 +
4782 + /* load the segment */
4783 + if (memcheck (memaddr, memsiz)
4784 + && grub_read ((char *) memaddr, filesiz) == filesiz)
4785 + {
4786 + if (memsiz > filesiz)
4787 + memset ((char *) (memaddr + filesiz), 0, memsiz - filesiz);
4788 + }
4789 + else
4790 + break;
4791 + }
4792 + }
4793 +
4794 + if (! errnum)
4795 + {
4796 + if (! loaded)
4797 + errnum = ERR_EXEC_FORMAT;
4798 + else
4799 + {
4800 + /* Load ELF symbols. */
4801 + Elf32_Shdr *shdr = NULL;
4802 + int tab_size, sec_size;
4803 + int symtab_err = 0;
4804 +
4805 + mbi.syms.e.num = pu.elf->e_shnum;
4806 + mbi.syms.e.size = pu.elf->e_shentsize;
4807 + mbi.syms.e.shndx = pu.elf->e_shstrndx;
4808 +
4809 + /* We should align to a 4K boundary here for good measure. */
4810 + if (align_4k)
4811 + cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
4812 +
4813 + tab_size = pu.elf->e_shentsize * pu.elf->e_shnum;
4814 +
4815 + grub_seek (pu.elf->e_shoff);
4816 + if (grub_read ((char *) RAW_ADDR (cur_addr), tab_size)
4817 + == tab_size)
4818 + {
4819 + mbi.syms.e.addr = cur_addr;
4820 + shdr = (Elf32_Shdr *) mbi.syms.e.addr;
4821 + cur_addr += tab_size;
4822 +
4823 + printf (", shtab=0x%x", cur_addr);
4824 +
4825 + for (i = 0; i < mbi.syms.e.num; i++)
4826 + {
4827 + /* This section is a loaded section,
4828 + so we don't care. */
4829 + if (shdr[i].sh_addr != 0)
4830 + continue;
4831 +
4832 + /* This section is empty, so we don't care. */
4833 + if (shdr[i].sh_size == 0)
4834 + continue;
4835 +
4836 + /* Align the section to a sh_addralign bits boundary. */
4837 + cur_addr = ((cur_addr + shdr[i].sh_addralign) &
4838 + - (int) shdr[i].sh_addralign);
4839 +
4840 + grub_seek (shdr[i].sh_offset);
4841 +
4842 + sec_size = shdr[i].sh_size;
4843 +
4844 + if (! (memcheck (cur_addr, sec_size)
4845 + && (grub_read ((char *) RAW_ADDR (cur_addr),
4846 + sec_size)
4847 + == sec_size)))
4848 + {
4849 + symtab_err = 1;
4850 + break;
4851 + }
4852 +
4853 + shdr[i].sh_addr = cur_addr;
4854 + cur_addr += sec_size;
4855 + }
4856 + }
4857 + else
4858 + symtab_err = 1;
4859 +
4860 + if (mbi.syms.e.addr < RAW_ADDR(0x10000))
4861 + symtab_err = 1;
4862 +
4863 + if (symtab_err)
4864 + {
4865 + printf ("(bad)");
4866 + mbi.syms.e.num = 0;
4867 + mbi.syms.e.size = 0;
4868 + mbi.syms.e.addr = 0;
4869 + mbi.syms.e.shndx = 0;
4870 + cur_addr = 0;
4871 + }
4872 + else
4873 + mbi.flags |= MB_INFO_ELF_SHDR;
4874 + }
4875 + }
4876 + }
4877 +
4878 + if (! errnum)
4879 + {
4880 + grub_printf (", entry=0x%x]\n", (unsigned) entry_addr);
4881 +
4882 + /* If the entry address is physically different from that of the ELF
4883 + header, correct it here. */
4884 + if (real_entry_addr)
4885 + entry_addr = real_entry_addr;
4886 + }
4887 + else
4888 + {
4889 + putchar ('\n');
4890 + type = KERNEL_TYPE_NONE;
4891 + }
4892 +
4893 + grub_close ();
4894 +
4895 + /* Sanity check. */
4896 + if (suggested_type != KERNEL_TYPE_NONE && suggested_type != type)
4897 + {
4898 + errnum = ERR_EXEC_FORMAT;
4899 + return KERNEL_TYPE_NONE;
4900 + }
4901 +
4902 + return type;
4903 +}
4904 +
4905 +int
4906 +load_module (char *module, char *arg)
4907 +{
4908 + int len;
4909 +
4910 + /* if we are supposed to load on 4K boundaries */
4911 + cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
4912 +
4913 + if (!grub_open (module))
4914 + return 0;
4915 +
4916 + len = grub_read ((char *) cur_addr, -1);
4917 + if (! len)
4918 + {
4919 + grub_close ();
4920 + return 0;
4921 + }
4922 +
4923 + printf (" [Multiboot-module @ 0x%x, 0x%x bytes]\n", cur_addr, len);
4924 +
4925 + /* these two simply need to be set if any modules are loaded at all */
4926 + mbi.flags |= MB_INFO_MODS;
4927 + mbi.mods_addr = (int) mll;
4928 +
4929 + mll[mbi.mods_count].cmdline = (int) arg;
4930 + mll[mbi.mods_count].mod_start = cur_addr;
4931 + cur_addr += len;
4932 + mll[mbi.mods_count].mod_end = cur_addr;
4933 + mll[mbi.mods_count].pad = 0;
4934 +
4935 + /* increment number of modules included */
4936 + mbi.mods_count++;
4937 +
4938 + grub_close ();
4939 + return 1;
4940 +}
4941 +
4942 +int
4943 +load_initrd (char *initrd)
4944 +{
4945 + int len;
4946 + unsigned long moveto;
4947 + unsigned long max_addr;
4948 + struct linux_kernel_header *lh
4949 + = (struct linux_kernel_header *) (cur_addr - LINUX_SETUP_MOVE_SIZE);
4950 +
4951 +#ifndef NO_DECOMPRESSION
4952 + no_decompression = 1;
4953 +#endif
4954 +
4955 + if (! grub_open (initrd))
4956 + goto fail;
4957 +
4958 + len = grub_read ((char *) cur_addr, -1);
4959 + if (! len)
4960 + {
4961 + grub_close ();
4962 + goto fail;
4963 + }
4964 +
4965 + if (linux_mem_size)
4966 + moveto = linux_mem_size;
4967 + else
4968 + moveto = (mbi.mem_upper + 0x400) << 10;
4969 +
4970 + moveto = (moveto - len) & 0xfffff000;
4971 + max_addr = (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0203
4972 + ? lh->initrd_addr_max : LINUX_INITRD_MAX_ADDRESS);
4973 + if (moveto + len >= max_addr)
4974 + moveto = (max_addr - len) & 0xfffff000;
4975 +
4976 + /* XXX: Linux 2.3.xx has a bug in the memory range check, so avoid
4977 + the last page.
4978 + XXX: Linux 2.2.xx has a bug in the memory range check, which is
4979 + worse than that of Linux 2.3.xx, so avoid the last 64kb. *sigh* */
4980 + moveto -= 0x10000;
4981 + memmove ((void *) RAW_ADDR (moveto), (void *) cur_addr, len);
4982 +
4983 + printf (" [Linux-initrd @ 0x%x, 0x%x bytes]\n", moveto, len);
4984 +
4985 + /* FIXME: Should check if the kernel supports INITRD. */
4986 + lh->ramdisk_image = RAW_ADDR (moveto);
4987 + lh->ramdisk_size = len;
4988 +
4989 + grub_close ();
4990 +
4991 + fail:
4992 +
4993 +#ifndef NO_DECOMPRESSION
4994 + no_decompression = 0;
4995 +#endif
4996 +
4997 + return ! errnum;
4998 +}
4999 +
5000 +
5001 +#ifdef GRUB_UTIL
5002 +/* Dummy function to fake the *BSD boot. */
5003 +static void
5004 +bsd_boot_entry (int flags, int bootdev, int sym_start, int sym_end,
5005 + int mem_upper, int mem_lower)
5006 +{
5007 + stop ();
5008 +}
5009 +#endif
5010 +
5011 +
5012 +/*
5013 + * All "*_boot" commands depend on the images being loaded into memory
5014 + * correctly, the variables in this file being set up correctly, and
5015 + * the root partition being set in the 'saved_drive' and 'saved_partition'
5016 + * variables.
5017 + */
5018 +
5019 +
5020 +void
5021 +bsd_boot (kernel_t type, int bootdev, char *arg)
5022 +{
5023 + char *str;
5024 + int clval = 0, i;
5025 + struct bootinfo bi;
5026 +
5027 +#ifdef GRUB_UTIL
5028 + entry_addr = (entry_func) bsd_boot_entry;
5029 +#else
5030 + stop_floppy ();
5031 +#endif
5032 +
5033 + while (*(++arg) && *arg != ' ');
5034 + str = arg;
5035 + while (*str)
5036 + {
5037 + if (*str == '-')
5038 + {
5039 + while (*str && *str != ' ')
5040 + {
5041 + if (*str == 'C')
5042 + clval |= RB_CDROM;
5043 + if (*str == 'a')
5044 + clval |= RB_ASKNAME;
5045 + if (*str == 'b')
5046 + clval |= RB_HALT;
5047 + if (*str == 'c')
5048 + clval |= RB_CONFIG;
5049 + if (*str == 'd')
5050 + clval |= RB_KDB;
5051 + if (*str == 'D')
5052 + clval |= RB_MULTIPLE;
5053 + if (*str == 'g')
5054 + clval |= RB_GDB;
5055 + if (*str == 'h')
5056 + clval |= RB_SERIAL;
5057 + if (*str == 'm')
5058 + clval |= RB_MUTE;
5059 + if (*str == 'r')
5060 + clval |= RB_DFLTROOT;
5061 + if (*str == 's')
5062 + clval |= RB_SINGLE;
5063 + if (*str == 'v')
5064 + clval |= RB_VERBOSE;
5065 + str++;
5066 + }
5067 + continue;
5068 + }
5069 + str++;
5070 + }
5071 +
5072 + if (type == KERNEL_TYPE_FREEBSD)
5073 + {
5074 + clval |= RB_BOOTINFO;
5075 +
5076 + bi.bi_version = BOOTINFO_VERSION;
5077 +
5078 + *arg = 0;
5079 + while ((--arg) > (char *) MB_CMDLINE_BUF && *arg != '/');
5080 + if (*arg == '/')
5081 + bi.bi_kernelname = arg + 1;
5082 + else
5083 + bi.bi_kernelname = 0;
5084 +
5085 + bi.bi_nfs_diskless = 0;
5086 + bi.bi_n_bios_used = 0; /* this field is apparently unused */
5087 +
5088 + for (i = 0; i < N_BIOS_GEOM; i++)
5089 + {
5090 + struct geometry geom;
5091 +
5092 + /* XXX Should check the return value. */
5093 + get_diskinfo (i + 0x80, &geom);
5094 + /* FIXME: If HEADS or SECTORS is greater than 255, then this will
5095 + break the geometry information. That is a drawback of BSD
5096 + but not of GRUB. */
5097 + bi.bi_bios_geom[i] = (((geom.cylinders - 1) << 16)
5098 + + (((geom.heads - 1) & 0xff) << 8)
5099 + + (geom.sectors & 0xff));
5100 + }
5101 +
5102 + bi.bi_size = sizeof (struct bootinfo);
5103 + bi.bi_memsizes_valid = 1;
5104 + bi.bi_bios_dev = saved_drive;
5105 + bi.bi_basemem = mbi.mem_lower;
5106 + bi.bi_extmem = extended_memory;
5107 +
5108 + if (mbi.flags & MB_INFO_AOUT_SYMS)
5109 + {
5110 + bi.bi_symtab = mbi.syms.a.addr;
5111 + bi.bi_esymtab = mbi.syms.a.addr + 4
5112 + + mbi.syms.a.tabsize + mbi.syms.a.strsize;
5113 + }
5114 +#if 0
5115 + else if (mbi.flags & MB_INFO_ELF_SHDR)
5116 + {
5117 + /* FIXME: Should check if a symbol table exists and, if exists,
5118 + pass the table to BI. */
5119 + }
5120 +#endif
5121 + else
5122 + {
5123 + bi.bi_symtab = 0;
5124 + bi.bi_esymtab = 0;
5125 + }
5126 +
5127 + /* call entry point */
5128 + (*entry_addr) (clval, bootdev, 0, 0, 0, ((int) (&bi)));
5129 + }
5130 + else
5131 + {
5132 + /*
5133 + * We now pass the various bootstrap parameters to the loaded
5134 + * image via the argument list.
5135 + *
5136 + * This is the official list:
5137 + *
5138 + * arg0 = 8 (magic)
5139 + * arg1 = boot flags
5140 + * arg2 = boot device
5141 + * arg3 = start of symbol table (0 if not loaded)
5142 + * arg4 = end of symbol table (0 if not loaded)
5143 + * arg5 = transfer address from image
5144 + * arg6 = transfer address for next image pointer
5145 + * arg7 = conventional memory size (640)
5146 + * arg8 = extended memory size (8196)
5147 + *
5148 + * ...in actuality, we just pass the parameters used by the kernel.
5149 + */
5150 +
5151 + /* call entry point */
5152 + unsigned long end_mark;
5153 +
5154 + if (mbi.flags & MB_INFO_AOUT_SYMS)
5155 + end_mark = (mbi.syms.a.addr + 4
5156 + + mbi.syms.a.tabsize + mbi.syms.a.strsize);
5157 + else
5158 + /* FIXME: it should be mbi.syms.e.size. */
5159 + end_mark = 0;
5160 +
5161 + (*entry_addr) (clval, bootdev, 0, end_mark,
5162 + extended_memory, mbi.mem_lower);
5163 + }
5164 +}
5165 diff -Nur grub-0.97/stage2/builtins.c grub-0.97-patched/stage2/builtins.c
5166 --- grub-0.97/stage2/builtins.c 2005-02-15 22:58:23.000000000 +0100
5167 +++ grub-0.97-patched/stage2/builtins.c 2012-11-11 17:07:12.729729661 +0100
5168 @@ -131,63 +131,98 @@
5169 }
5170
5171 \f
5172 +/* blocklist_read_helper nee disk_read_blocklist_func was a nested
5173 + * function, to which pointers were taken and exposed globally. Even
5174 + * in the GNU-C nested functions extension, they have local linkage,
5175 + * and aren't guaranteed to be accessable *at all* outside of their
5176 + * containing scope.
5177 + *
5178 + * Above and beyond all of that, the variables within blocklist_func_context
5179 + * are originally local variables, with local (not even static) linkage,
5180 + * from within blocklist_func. These were each referenced by
5181 + * disk_read_blocklist_func, which is only called from other functions
5182 + * through a globally scoped pointer.
5183 + *
5184 + * The documentation in GCC actually uses the words "all hell will break
5185 + * loose" to describe this scenario.
5186 + *
5187 + * Also, "start_sector" was also used uninitialized, but gcc doesn't warn
5188 + * about it (possibly because of the scoping madness?)
5189 + */
5190 +
5191 +static struct {
5192 + int start_sector;
5193 + int num_sectors;
5194 + int num_entries;
5195 + int last_length;
5196 +} blocklist_func_context = {
5197 + .start_sector = 0,
5198 + .num_sectors = 0,
5199 + .num_entries = 0,
5200 + .last_length = 0
5201 +};
5202 +
5203 +/* Collect contiguous blocks into one entry as many as possible,
5204 + and print the blocklist notation on the screen. */
5205 +static void
5206 +blocklist_read_helper (int sector, int offset, int length)
5207 +{
5208 + int *start_sector = &blocklist_func_context.start_sector;
5209 + int *num_sectors = &blocklist_func_context.num_sectors;
5210 + int *num_entries = &blocklist_func_context.num_entries;
5211 + int *last_length = &blocklist_func_context.last_length;
5212 +
5213 + if (*num_sectors > 0)
5214 + {
5215 + if (*start_sector + *num_sectors == sector
5216 + && offset == 0 && *last_length == SECTOR_SIZE)
5217 + {
5218 + *num_sectors++;
5219 + *last_length = length;
5220 + return;
5221 + }
5222 + else
5223 + {
5224 + if (*last_length == SECTOR_SIZE)
5225 + grub_printf ("%s%d+%d", *num_entries ? "," : "",
5226 + *start_sector - part_start, *num_sectors);
5227 + else if (*num_sectors > 1)
5228 + grub_printf ("%s%d+%d,%d[0-%d]", *num_entries ? "," : "",
5229 + *start_sector - part_start, *num_sectors-1,
5230 + *start_sector + *num_sectors-1 - part_start,
5231 + *last_length);
5232 + else
5233 + grub_printf ("%s%d[0-%d]", *num_entries ? "," : "",
5234 + *start_sector - part_start, *last_length);
5235 + *num_entries++;
5236 + *num_sectors = 0;
5237 + }
5238 + }
5239 +
5240 + if (offset > 0)
5241 + {
5242 + grub_printf("%s%d[%d-%d]", *num_entries ? "," : "",
5243 + sector-part_start, offset, offset+length);
5244 + *num_entries++;
5245 + }
5246 + else
5247 + {
5248 + *start_sector = sector;
5249 + *num_sectors = 1;
5250 + *last_length = length;
5251 + }
5252 +}
5253 +
5254 /* blocklist */
5255 static int
5256 blocklist_func (char *arg, int flags)
5257 {
5258 char *dummy = (char *) RAW_ADDR (0x100000);
5259 - int start_sector;
5260 - int num_sectors = 0;
5261 - int num_entries = 0;
5262 - int last_length = 0;
5263
5264 - auto void disk_read_blocklist_func (int sector, int offset, int length);
5265 + int *start_sector = &blocklist_func_context.start_sector;
5266 + int *num_sectors = &blocklist_func_context.num_sectors;
5267 + int *num_entries = &blocklist_func_context.num_entries;
5268
5269 - /* Collect contiguous blocks into one entry as many as possible,
5270 - and print the blocklist notation on the screen. */
5271 - auto void disk_read_blocklist_func (int sector, int offset, int length)
5272 - {
5273 - if (num_sectors > 0)
5274 - {
5275 - if (start_sector + num_sectors == sector
5276 - && offset == 0 && last_length == SECTOR_SIZE)
5277 - {
5278 - num_sectors++;
5279 - last_length = length;
5280 - return;
5281 - }
5282 - else
5283 - {
5284 - if (last_length == SECTOR_SIZE)
5285 - grub_printf ("%s%d+%d", num_entries ? "," : "",
5286 - start_sector - part_start, num_sectors);
5287 - else if (num_sectors > 1)
5288 - grub_printf ("%s%d+%d,%d[0-%d]", num_entries ? "," : "",
5289 - start_sector - part_start, num_sectors-1,
5290 - start_sector + num_sectors-1 - part_start,
5291 - last_length);
5292 - else
5293 - grub_printf ("%s%d[0-%d]", num_entries ? "," : "",
5294 - start_sector - part_start, last_length);
5295 - num_entries++;
5296 - num_sectors = 0;
5297 - }
5298 - }
5299 -
5300 - if (offset > 0)
5301 - {
5302 - grub_printf("%s%d[%d-%d]", num_entries ? "," : "",
5303 - sector-part_start, offset, offset+length);
5304 - num_entries++;
5305 - }
5306 - else
5307 - {
5308 - start_sector = sector;
5309 - num_sectors = 1;
5310 - last_length = length;
5311 - }
5312 - }
5313 -
5314 /* Open the file. */
5315 if (! grub_open (arg))
5316 return 1;
5317 @@ -206,15 +241,15 @@
5318 grub_printf (")");
5319
5320 /* Read in the whole file to DUMMY. */
5321 - disk_read_hook = disk_read_blocklist_func;
5322 + disk_read_hook = blocklist_read_helper;
5323 if (! grub_read (dummy, -1))
5324 goto fail;
5325
5326 /* The last entry may not be printed yet. Don't check if it is a
5327 * full sector, since it doesn't matter if we read too much. */
5328 - if (num_sectors > 0)
5329 - grub_printf ("%s%d+%d", num_entries ? "," : "",
5330 - start_sector - part_start, num_sectors);
5331 + if (*num_sectors > 0)
5332 + grub_printf ("%s%d+%d", *num_entries ? "," : "",
5333 + *start_sector - part_start, *num_sectors);
5334
5335 grub_printf ("\n");
5336
5337 @@ -852,6 +887,138 @@
5338 };
5339 #endif /* SUPPORT_NETBOOT */
5340
5341 +static int terminal_func (char *arg, int flags);
5342 +
5343 +#ifdef SUPPORT_GRAPHICS
5344 +\f
5345 +static int splashimage_func(char *arg, int flags) {
5346 + char splashimage[64];
5347 + int i;
5348 +
5349 + /* filename can only be 64 characters due to our buffer size */
5350 + if (strlen(arg) > 63)
5351 + return 1;
5352 + if (flags == BUILTIN_CMDLINE) {
5353 + if (!grub_open(arg))
5354 + return 1;
5355 + grub_close();
5356 + }
5357 +
5358 + strcpy(splashimage, arg);
5359 +
5360 + /* get rid of TERM_NEED_INIT from the graphics terminal. */
5361 + for (i = 0; term_table[i].name; i++) {
5362 + if (grub_strcmp (term_table[i].name, "graphics") == 0) {
5363 + term_table[i].flags &= ~TERM_NEED_INIT;
5364 + break;
5365 + }
5366 + }
5367 +
5368 + graphics_set_splash(splashimage);
5369 +
5370 + if (flags == BUILTIN_CMDLINE && graphics_inited) {
5371 + graphics_end();
5372 + graphics_init();
5373 + graphics_cls();
5374 + }
5375 +
5376 + /* FIXME: should we be explicitly switching the terminal as a
5377 + * side effect here? */
5378 + terminal_func("graphics", flags);
5379 +
5380 + return 0;
5381 +}
5382 +
5383 +static struct builtin builtin_splashimage =
5384 +{
5385 + "splashimage",
5386 + splashimage_func,
5387 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
5388 + "splashimage FILE",
5389 + "Load FILE as the background image when in graphics mode."
5390 +};
5391 +
5392 +\f
5393 +/* foreground */
5394 +static int
5395 +foreground_func(char *arg, int flags)
5396 +{
5397 + if (grub_strlen(arg) == 6) {
5398 + int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2;
5399 + int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2;
5400 + int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2;
5401 +
5402 + foreground = (r << 16) | (g << 8) | b;
5403 + if (graphics_inited)
5404 + graphics_set_palette(15, r, g, b);
5405 +
5406 + return (0);
5407 + }
5408 +
5409 + return (1);
5410 +}
5411 +
5412 +static struct builtin builtin_foreground =
5413 +{
5414 + "foreground",
5415 + foreground_func,
5416 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
5417 + "foreground RRGGBB",
5418 + "Sets the foreground color when in graphics mode."
5419 + "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal."
5420 +};
5421 +
5422 +\f
5423 +/* background */
5424 +static int
5425 +background_func(char *arg, int flags)
5426 +{
5427 + if (grub_strlen(arg) == 6) {
5428 + int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2;
5429 + int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2;
5430 + int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2;
5431 +
5432 + background = (r << 16) | (g << 8) | b;
5433 + if (graphics_inited)
5434 + graphics_set_palette(0, r, g, b);
5435 + return (0);
5436 + }
5437 +
5438 + return (1);
5439 +}
5440 +
5441 +static struct builtin builtin_background =
5442 +{
5443 + "background",
5444 + background_func,
5445 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
5446 + "background RRGGBB",
5447 + "Sets the background color when in graphics mode."
5448 + "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal."
5449 +};
5450 +
5451 +#endif /* SUPPORT_GRAPHICS */
5452 +
5453 +\f
5454 +/* clear */
5455 +static int
5456 +clear_func()
5457 +{
5458 + if (current_term->cls)
5459 + current_term->cls();
5460 +
5461 + return 0;
5462 +}
5463 +
5464 +static struct builtin builtin_clear =
5465 +{
5466 + "clear",
5467 + clear_func,
5468 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
5469 + "clear",
5470 + "Clear the screen"
5471 +};
5472 +
5473 \f
5474 /* displayapm */
5475 static int
5476 @@ -1233,14 +1400,15 @@
5477 for (drive = 0x80; drive < 0x88; drive++)
5478 {
5479 unsigned long part = 0xFFFFFF;
5480 - unsigned long start, len, offset, ext_offset;
5481 - int type, entry;
5482 + unsigned long start, len, offset, ext_offset, gpt_offset;
5483 + int type, entry, gpt_count, gpt_size;
5484 char buf[SECTOR_SIZE];
5485
5486 current_drive = drive;
5487 while (next_partition (drive, 0xFFFFFF, &part, &type,
5488 &start, &len, &offset, &entry,
5489 - &ext_offset, buf))
5490 + &ext_offset, &gpt_offset,
5491 + &gpt_count, &gpt_size, buf))
5492 {
5493 if (type != PC_SLICE_TYPE_NONE
5494 && ! IS_PC_SLICE_TYPE_BSD (type)
5495 @@ -1740,6 +1908,77 @@
5496
5497 \f
5498 /* install */
5499 +static struct {
5500 + int saved_sector;
5501 + int installaddr;
5502 + int installlist;
5503 + char *stage2_first_buffer;
5504 +} install_func_context = {
5505 + .saved_sector = 0,
5506 + .installaddr = 0,
5507 + .installlist = 0,
5508 + .stage2_first_buffer = NULL,
5509 +};
5510 +
5511 +/* Save the first sector of Stage2 in STAGE2_SECT. */
5512 +/* Formerly disk_read_savesect_func with local scope inside install_func */
5513 +static void
5514 +install_savesect_helper(int sector, int offset, int length)
5515 +{
5516 + if (debug)
5517 + printf ("[%d]", sector);
5518 +
5519 + /* ReiserFS has files which sometimes contain data not aligned
5520 + on sector boundaries. Returning an error is better than
5521 + silently failing. */
5522 + if (offset != 0 || length != SECTOR_SIZE)
5523 + errnum = ERR_UNALIGNED;
5524 +
5525 + install_func_context.saved_sector = sector;
5526 +}
5527 +
5528 +/* Write SECTOR to INSTALLLIST, and update INSTALLADDR and INSTALLSECT. */
5529 +/* Formerly disk_read_blocklist_func with local scope inside install_func */
5530 +static void
5531 +install_blocklist_helper (int sector, int offset, int length)
5532 +{
5533 + int *installaddr = &install_func_context.installaddr;
5534 + int *installlist = &install_func_context.installlist;
5535 + char **stage2_first_buffer = &install_func_context.stage2_first_buffer;
5536 + /* Was the last sector full? */
5537 + static int last_length = SECTOR_SIZE;
5538 +
5539 + if (debug)
5540 + printf("[%d]", sector);
5541 +
5542 + if (offset != 0 || last_length != SECTOR_SIZE)
5543 + {
5544 + /* We found a non-sector-aligned data block. */
5545 + errnum = ERR_UNALIGNED;
5546 + return;
5547 + }
5548 +
5549 + last_length = length;
5550 +
5551 + if (*((unsigned long *) (*installlist - 4))
5552 + + *((unsigned short *) *installlist) != sector
5553 + || *installlist == (int) *stage2_first_buffer + SECTOR_SIZE + 4)
5554 + {
5555 + *installlist -= 8;
5556 +
5557 + if (*((unsigned long *) (*installlist - 8)))
5558 + errnum = ERR_WONT_FIT;
5559 + else
5560 + {
5561 + *((unsigned short *) (*installlist + 2)) = (*installaddr >> 4);
5562 + *((unsigned long *) (*installlist - 4)) = sector;
5563 + }
5564 + }
5565 +
5566 + *((unsigned short *) *installlist) += 1;
5567 + *installaddr += 512;
5568 +}
5569 +
5570 static int
5571 install_func (char *arg, int flags)
5572 {
5573 @@ -1747,8 +1986,12 @@
5574 char *stage1_buffer = (char *) RAW_ADDR (0x100000);
5575 char *stage2_buffer = stage1_buffer + SECTOR_SIZE;
5576 char *old_sect = stage2_buffer + SECTOR_SIZE;
5577 - char *stage2_first_buffer = old_sect + SECTOR_SIZE;
5578 - char *stage2_second_buffer = stage2_first_buffer + SECTOR_SIZE;
5579 + /* stage2_first_buffer used to be defined as:
5580 + * char *stage2_first_buffer = old_sect + SECTOR_SIZE; */
5581 + char **stage2_first_buffer = &install_func_context.stage2_first_buffer;
5582 + /* and stage2_second_buffer was:
5583 + * char *stage2_second_buffer = stage2_first_buffer + SECTOR_SIZE; */
5584 + char *stage2_second_buffer = old_sect + SECTOR_SIZE + SECTOR_SIZE;
5585 /* XXX: Probably SECTOR_SIZE is reasonable. */
5586 char *config_filename = stage2_second_buffer + SECTOR_SIZE;
5587 char *dummy = config_filename + SECTOR_SIZE;
5588 @@ -1757,10 +2000,11 @@
5589 int src_drive, src_partition, src_part_start;
5590 int i;
5591 struct geometry dest_geom, src_geom;
5592 - int saved_sector;
5593 + int *saved_sector = &install_func_context.saved_sector;
5594 int stage2_first_sector, stage2_second_sector;
5595 char *ptr;
5596 - int installaddr, installlist;
5597 + int *installaddr = &install_func_context.installaddr;
5598 + int *installlist = &install_func_context.installlist;
5599 /* Point to the location of the name of a configuration file in Stage 2. */
5600 char *config_file_location;
5601 /* If FILE is a Stage 1.5? */
5602 @@ -1769,67 +2013,13 @@
5603 int is_open = 0;
5604 /* If LBA is forced? */
5605 int is_force_lba = 0;
5606 - /* Was the last sector full? */
5607 - int last_length = SECTOR_SIZE;
5608 -
5609 +
5610 + *stage2_first_buffer = old_sect + SECTOR_SIZE;
5611 #ifdef GRUB_UTIL
5612 /* If the Stage 2 is in a partition mounted by an OS, this will store
5613 the filename under the OS. */
5614 char *stage2_os_file = 0;
5615 #endif /* GRUB_UTIL */
5616 -
5617 - auto void disk_read_savesect_func (int sector, int offset, int length);
5618 - auto void disk_read_blocklist_func (int sector, int offset, int length);
5619 -
5620 - /* Save the first sector of Stage2 in STAGE2_SECT. */
5621 - auto void disk_read_savesect_func (int sector, int offset, int length)
5622 - {
5623 - if (debug)
5624 - printf ("[%d]", sector);
5625 -
5626 - /* ReiserFS has files which sometimes contain data not aligned
5627 - on sector boundaries. Returning an error is better than
5628 - silently failing. */
5629 - if (offset != 0 || length != SECTOR_SIZE)
5630 - errnum = ERR_UNALIGNED;
5631 -
5632 - saved_sector = sector;
5633 - }
5634 -
5635 - /* Write SECTOR to INSTALLLIST, and update INSTALLADDR and
5636 - INSTALLSECT. */
5637 - auto void disk_read_blocklist_func (int sector, int offset, int length)
5638 - {
5639 - if (debug)
5640 - printf("[%d]", sector);
5641 -
5642 - if (offset != 0 || last_length != SECTOR_SIZE)
5643 - {
5644 - /* We found a non-sector-aligned data block. */
5645 - errnum = ERR_UNALIGNED;
5646 - return;
5647 - }
5648 -
5649 - last_length = length;
5650 -
5651 - if (*((unsigned long *) (installlist - 4))
5652 - + *((unsigned short *) installlist) != sector
5653 - || installlist == (int) stage2_first_buffer + SECTOR_SIZE + 4)
5654 - {
5655 - installlist -= 8;
5656 -
5657 - if (*((unsigned long *) (installlist - 8)))
5658 - errnum = ERR_WONT_FIT;
5659 - else
5660 - {
5661 - *((unsigned short *) (installlist + 2)) = (installaddr >> 4);
5662 - *((unsigned long *) (installlist - 4)) = sector;
5663 - }
5664 - }
5665 -
5666 - *((unsigned short *) installlist) += 1;
5667 - installaddr += 512;
5668 - }
5669
5670 /* First, check the GNU-style long option. */
5671 while (1)
5672 @@ -1862,10 +2052,10 @@
5673 addr = skip_to (0, file);
5674
5675 /* Get the installation address. */
5676 - if (! safe_parse_maxint (&addr, &installaddr))
5677 + if (! safe_parse_maxint (&addr, installaddr))
5678 {
5679 /* ADDR is not specified. */
5680 - installaddr = 0;
5681 + *installaddr = 0;
5682 ptr = addr;
5683 errnum = 0;
5684 }
5685 @@ -1961,17 +2151,17 @@
5686 = 0x9090;
5687
5688 /* Read the first sector of Stage 2. */
5689 - disk_read_hook = disk_read_savesect_func;
5690 - if (grub_read (stage2_first_buffer, SECTOR_SIZE) != SECTOR_SIZE)
5691 + disk_read_hook = install_savesect_helper;
5692 + if (grub_read (*stage2_first_buffer, SECTOR_SIZE) != SECTOR_SIZE)
5693 goto fail;
5694
5695 - stage2_first_sector = saved_sector;
5696 + stage2_first_sector = *saved_sector;
5697
5698 /* Read the second sector of Stage 2. */
5699 if (grub_read (stage2_second_buffer, SECTOR_SIZE) != SECTOR_SIZE)
5700 goto fail;
5701
5702 - stage2_second_sector = saved_sector;
5703 + stage2_second_sector = *saved_sector;
5704
5705 /* Check for the version of Stage 2. */
5706 if (*((short *) (stage2_second_buffer + STAGE2_VER_MAJ_OFFS))
5707 @@ -1987,27 +2177,27 @@
5708
5709 /* If INSTALLADDR is not specified explicitly in the command-line,
5710 determine it by the Stage 2 id. */
5711 - if (! installaddr)
5712 + if (! *installaddr)
5713 {
5714 if (! is_stage1_5)
5715 /* Stage 2. */
5716 - installaddr = 0x8000;
5717 + *installaddr = 0x8000;
5718 else
5719 /* Stage 1.5. */
5720 - installaddr = 0x2000;
5721 + *installaddr = 0x2000;
5722 }
5723
5724 *((unsigned long *) (stage1_buffer + STAGE1_STAGE2_SECTOR))
5725 = stage2_first_sector;
5726 *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_ADDRESS))
5727 - = installaddr;
5728 + = *installaddr;
5729 *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_SEGMENT))
5730 - = installaddr >> 4;
5731 + = *installaddr >> 4;
5732
5733 - i = (int) stage2_first_buffer + SECTOR_SIZE - 4;
5734 + i = (int) *stage2_first_buffer + SECTOR_SIZE - 4;
5735 while (*((unsigned long *) i))
5736 {
5737 - if (i < (int) stage2_first_buffer
5738 + if (i < (int) *stage2_first_buffer
5739 || (*((int *) (i - 4)) & 0x80000000)
5740 || *((unsigned short *) i) >= 0xA00
5741 || *((short *) (i + 2)) == 0)
5742 @@ -2021,13 +2211,13 @@
5743 i -= 8;
5744 }
5745
5746 - installlist = (int) stage2_first_buffer + SECTOR_SIZE + 4;
5747 - installaddr += SECTOR_SIZE;
5748 + *installlist = (int) *stage2_first_buffer + SECTOR_SIZE + 4;
5749 + *installaddr += SECTOR_SIZE;
5750
5751 /* Read the whole of Stage2 except for the first sector. */
5752 grub_seek (SECTOR_SIZE);
5753
5754 - disk_read_hook = disk_read_blocklist_func;
5755 + disk_read_hook = install_blocklist_helper;
5756 if (! grub_read (dummy, -1))
5757 goto fail;
5758
5759 @@ -2110,7 +2300,7 @@
5760 /* Skip the first sector. */
5761 grub_seek (SECTOR_SIZE);
5762
5763 - disk_read_hook = disk_read_savesect_func;
5764 + disk_read_hook = install_savesect_helper;
5765 if (grub_read (stage2_buffer, SECTOR_SIZE) != SECTOR_SIZE)
5766 goto fail;
5767
5768 @@ -2180,7 +2370,7 @@
5769 else
5770 #endif /* GRUB_UTIL */
5771 {
5772 - if (! devwrite (saved_sector - part_start, 1, stage2_buffer))
5773 + if (! devwrite (*saved_sector - part_start, 1, stage2_buffer))
5774 goto fail;
5775 }
5776 }
5777 @@ -2202,7 +2392,7 @@
5778 goto fail;
5779 }
5780
5781 - if (fwrite (stage2_first_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE)
5782 + if (fwrite (*stage2_first_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE)
5783 {
5784 fclose (fp);
5785 errnum = ERR_WRITE;
5786 @@ -2229,7 +2419,7 @@
5787 goto fail;
5788
5789 if (! devwrite (stage2_first_sector - src_part_start, 1,
5790 - stage2_first_buffer))
5791 + *stage2_first_buffer))
5792 goto fail;
5793
5794 if (! devwrite (stage2_second_sector - src_part_start, 1,
5795 @@ -2815,8 +3005,8 @@
5796 {
5797 int new_type;
5798 unsigned long part = 0xFFFFFF;
5799 - unsigned long start, len, offset, ext_offset;
5800 - int entry, type;
5801 + unsigned long start, len, offset, ext_offset, gpt_offset;
5802 + int entry, type, gpt_count, gpt_size;
5803 char mbr[512];
5804
5805 /* Get the drive and the partition. */
5806 @@ -2853,8 +3043,15 @@
5807 /* Look for the partition. */
5808 while (next_partition (current_drive, 0xFFFFFF, &part, &type,
5809 &start, &len, &offset, &entry,
5810 - &ext_offset, mbr))
5811 + &ext_offset, &gpt_offset, &gpt_count, &gpt_size, mbr))
5812 {
5813 + /* The partition may not be a GPT partition. */
5814 + if (gpt_offset != 0)
5815 + {
5816 + errnum = ERR_BAD_ARGUMENT;
5817 + return 1;
5818 + }
5819 +
5820 if (part == current_partition)
5821 {
5822 /* Found. */
5823 @@ -3830,15 +4027,15 @@
5824 {
5825 char tmp[16];
5826 grub_sprintf (tmp, ",%d", (partition >> 16) & 0xFF);
5827 - grub_strncat (device, tmp, 256);
5828 + grub_strncat (device, tmp, sizeof (device));
5829 }
5830 if ((partition & 0x00FF00) != 0x00FF00)
5831 {
5832 char tmp[16];
5833 grub_sprintf (tmp, ",%c", 'a' + ((partition >> 8) & 0xFF));
5834 - grub_strncat (device, tmp, 256);
5835 + grub_strncat (device, tmp, sizeof (device));
5836 }
5837 - grub_strncat (device, ")", 256);
5838 + grub_strncat (device, ")", sizeof (device));
5839 }
5840
5841 int embed_stage1_5 (char *stage1_5, int drive, int partition)
5842 @@ -4085,7 +4282,7 @@
5843 };
5844
5845 \f
5846 -#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
5847 +#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS)
5848 /* terminal */
5849 static int
5850 terminal_func (char *arg, int flags)
5851 @@ -4244,17 +4441,21 @@
5852 end:
5853 current_term = term_table + default_term;
5854 current_term->flags = term_flags;
5855 -
5856 +
5857 if (lines)
5858 max_lines = lines;
5859 else
5860 - /* 24 would be a good default value. */
5861 - max_lines = 24;
5862 -
5863 + max_lines = current_term->max_lines;
5864 +
5865 /* If the interface is currently the command-line,
5866 restart it to repaint the screen. */
5867 - if (current_term != prev_term && (flags & BUILTIN_CMDLINE))
5868 + if ((current_term != prev_term) && (flags & BUILTIN_CMDLINE)){
5869 + if (prev_term->shutdown)
5870 + prev_term->shutdown();
5871 + if (current_term->startup)
5872 + current_term->startup();
5873 grub_longjmp (restart_cmdline_env, 0);
5874 + }
5875
5876 return 0;
5877 }
5878 @@ -4264,7 +4465,7 @@
5879 "terminal",
5880 terminal_func,
5881 BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
5882 - "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] [--silent] [console] [serial] [hercules]",
5883 + "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] [--silent] [console] [serial] [hercules] [graphics]",
5884 "Select a terminal. When multiple terminals are specified, wait until"
5885 " you push any key to continue. If both console and serial are specified,"
5886 " the terminal to which you input a key first will be selected. If no"
5887 @@ -4276,7 +4477,7 @@
5888 " seconds. The option --lines specifies the maximum number of lines."
5889 " The option --silent is used to suppress messages."
5890 };
5891 -#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
5892 +#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */
5893
5894 \f
5895 #ifdef SUPPORT_SERIAL
5896 @@ -4795,6 +4996,9 @@
5897 /* The table of builtin commands. Sorted in dictionary order. */
5898 struct builtin *builtin_table[] =
5899 {
5900 +#ifdef SUPPORT_GRAPHICS
5901 + &builtin_background,
5902 +#endif
5903 &builtin_blocklist,
5904 &builtin_boot,
5905 #ifdef SUPPORT_NETBOOT
5906 @@ -4802,6 +5006,7 @@
5907 #endif /* SUPPORT_NETBOOT */
5908 &builtin_cat,
5909 &builtin_chainloader,
5910 + &builtin_clear,
5911 &builtin_cmp,
5912 &builtin_color,
5913 &builtin_configfile,
5914 @@ -4821,6 +5026,9 @@
5915 &builtin_embed,
5916 &builtin_fallback,
5917 &builtin_find,
5918 +#ifdef SUPPORT_GRAPHICS
5919 + &builtin_foreground,
5920 +#endif
5921 &builtin_fstest,
5922 &builtin_geometry,
5923 &builtin_halt,
5924 @@ -4864,9 +5072,12 @@
5925 #endif /* SUPPORT_SERIAL */
5926 &builtin_setkey,
5927 &builtin_setup,
5928 -#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
5929 +#ifdef SUPPORT_GRAPHICS
5930 + &builtin_splashimage,
5931 +#endif /* SUPPORT_GRAPHICS */
5932 +#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS)
5933 &builtin_terminal,
5934 -#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
5935 +#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */
5936 #ifdef SUPPORT_SERIAL
5937 &builtin_terminfo,
5938 #endif /* SUPPORT_SERIAL */
5939 diff -Nur grub-0.97/stage2/builtins.c.orig grub-0.97-patched/stage2/builtins.c.orig
5940 --- grub-0.97/stage2/builtins.c.orig 1970-01-01 01:00:00.000000000 +0100
5941 +++ grub-0.97-patched/stage2/builtins.c.orig 2005-02-15 22:58:23.000000000 +0100
5942 @@ -0,0 +1,4884 @@
5943 +/* builtins.c - the GRUB builtin commands */
5944 +/*
5945 + * GRUB -- GRand Unified Bootloader
5946 + * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
5947 + *
5948 + * This program is free software; you can redistribute it and/or modify
5949 + * it under the terms of the GNU General Public License as published by
5950 + * the Free Software Foundation; either version 2 of the License, or
5951 + * (at your option) any later version.
5952 + *
5953 + * This program is distributed in the hope that it will be useful,
5954 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5955 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5956 + * GNU General Public License for more details.
5957 + *
5958 + * You should have received a copy of the GNU General Public License
5959 + * along with this program; if not, write to the Free Software
5960 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
5961 + */
5962 +
5963 +/* Include stdio.h before shared.h, because we can't define
5964 + WITHOUT_LIBC_STUBS here. */
5965 +#ifdef GRUB_UTIL
5966 +# include <stdio.h>
5967 +#endif
5968 +
5969 +#include <shared.h>
5970 +#include <filesys.h>
5971 +#include <term.h>
5972 +
5973 +#ifdef SUPPORT_NETBOOT
5974 +# define GRUB 1
5975 +# include <etherboot.h>
5976 +#endif
5977 +
5978 +#ifdef SUPPORT_SERIAL
5979 +# include <serial.h>
5980 +# include <terminfo.h>
5981 +#endif
5982 +
5983 +#ifdef GRUB_UTIL
5984 +# include <device.h>
5985 +#else /* ! GRUB_UTIL */
5986 +# include <apic.h>
5987 +# include <smp-imps.h>
5988 +#endif /* ! GRUB_UTIL */
5989 +
5990 +#ifdef USE_MD5_PASSWORDS
5991 +# include <md5.h>
5992 +#endif
5993 +
5994 +/* The type of kernel loaded. */
5995 +kernel_t kernel_type;
5996 +/* The boot device. */
5997 +static int bootdev;
5998 +/* True when the debug mode is turned on, and false
5999 + when it is turned off. */
6000 +int debug = 0;
6001 +/* The default entry. */
6002 +int default_entry = 0;
6003 +/* The fallback entry. */
6004 +int fallback_entryno;
6005 +int fallback_entries[MAX_FALLBACK_ENTRIES];
6006 +/* The number of current entry. */
6007 +int current_entryno;
6008 +/* The address for Multiboot command-line buffer. */
6009 +static char *mb_cmdline;
6010 +/* The password. */
6011 +char *password;
6012 +/* The password type. */
6013 +password_t password_type;
6014 +/* The flag for indicating that the user is authoritative. */
6015 +int auth = 0;
6016 +/* The timeout. */
6017 +int grub_timeout = -1;
6018 +/* Whether to show the menu or not. */
6019 +int show_menu = 1;
6020 +/* The BIOS drive map. */
6021 +static unsigned short bios_drive_map[DRIVE_MAP_SIZE + 1];
6022 +
6023 +/* Prototypes for allowing straightfoward calling of builtins functions
6024 + inside other functions. */
6025 +static int configfile_func (char *arg, int flags);
6026 +
6027 +/* Initialize the data for builtins. */
6028 +void
6029 +init_builtins (void)
6030 +{
6031 + kernel_type = KERNEL_TYPE_NONE;
6032 + /* BSD and chainloading evil hacks! */
6033 + bootdev = set_bootdev (0);
6034 + mb_cmdline = (char *) MB_CMDLINE_BUF;
6035 +}
6036 +
6037 +/* Initialize the data for the configuration file. */
6038 +void
6039 +init_config (void)
6040 +{
6041 + default_entry = 0;
6042 + password = 0;
6043 + fallback_entryno = -1;
6044 + fallback_entries[0] = -1;
6045 + grub_timeout = -1;
6046 +}
6047 +
6048 +/* Check a password for correctness. Returns 0 if password was
6049 + correct, and a value != 0 for error, similarly to strcmp. */
6050 +int
6051 +check_password (char *entered, char* expected, password_t type)
6052 +{
6053 + switch (type)
6054 + {
6055 + case PASSWORD_PLAIN:
6056 + return strcmp (entered, expected);
6057 +
6058 +#ifdef USE_MD5_PASSWORDS
6059 + case PASSWORD_MD5:
6060 + return check_md5_password (entered, expected);
6061 +#endif
6062 + default:
6063 + /* unsupported password type: be secure */
6064 + return 1;
6065 + }
6066 +}
6067 +
6068 +/* Print which sector is read when loading a file. */
6069 +static void
6070 +disk_read_print_func (int sector, int offset, int length)
6071 +{
6072 + grub_printf ("[%d,%d,%d]", sector, offset, length);
6073 +}
6074 +
6075 +\f
6076 +/* blocklist */
6077 +static int
6078 +blocklist_func (char *arg, int flags)
6079 +{
6080 + char *dummy = (char *) RAW_ADDR (0x100000);
6081 + int start_sector;
6082 + int num_sectors = 0;
6083 + int num_entries = 0;
6084 + int last_length = 0;
6085 +
6086 + auto void disk_read_blocklist_func (int sector, int offset, int length);
6087 +
6088 + /* Collect contiguous blocks into one entry as many as possible,
6089 + and print the blocklist notation on the screen. */
6090 + auto void disk_read_blocklist_func (int sector, int offset, int length)
6091 + {
6092 + if (num_sectors > 0)
6093 + {
6094 + if (start_sector + num_sectors == sector
6095 + && offset == 0 && last_length == SECTOR_SIZE)
6096 + {
6097 + num_sectors++;
6098 + last_length = length;
6099 + return;
6100 + }
6101 + else
6102 + {
6103 + if (last_length == SECTOR_SIZE)
6104 + grub_printf ("%s%d+%d", num_entries ? "," : "",
6105 + start_sector - part_start, num_sectors);
6106 + else if (num_sectors > 1)
6107 + grub_printf ("%s%d+%d,%d[0-%d]", num_entries ? "," : "",
6108 + start_sector - part_start, num_sectors-1,
6109 + start_sector + num_sectors-1 - part_start,
6110 + last_length);
6111 + else
6112 + grub_printf ("%s%d[0-%d]", num_entries ? "," : "",
6113 + start_sector - part_start, last_length);
6114 + num_entries++;
6115 + num_sectors = 0;
6116 + }
6117 + }
6118 +
6119 + if (offset > 0)
6120 + {
6121 + grub_printf("%s%d[%d-%d]", num_entries ? "," : "",
6122 + sector-part_start, offset, offset+length);
6123 + num_entries++;
6124 + }
6125 + else
6126 + {
6127 + start_sector = sector;
6128 + num_sectors = 1;
6129 + last_length = length;
6130 + }
6131 + }
6132 +
6133 + /* Open the file. */
6134 + if (! grub_open (arg))
6135 + return 1;
6136 +
6137 + /* Print the device name. */
6138 + grub_printf ("(%cd%d",
6139 + (current_drive & 0x80) ? 'h' : 'f',
6140 + current_drive & ~0x80);
6141 +
6142 + if ((current_partition & 0xFF0000) != 0xFF0000)
6143 + grub_printf (",%d", (current_partition >> 16) & 0xFF);
6144 +
6145 + if ((current_partition & 0x00FF00) != 0x00FF00)
6146 + grub_printf (",%c", 'a' + ((current_partition >> 8) & 0xFF));
6147 +
6148 + grub_printf (")");
6149 +
6150 + /* Read in the whole file to DUMMY. */
6151 + disk_read_hook = disk_read_blocklist_func;
6152 + if (! grub_read (dummy, -1))
6153 + goto fail;
6154 +
6155 + /* The last entry may not be printed yet. Don't check if it is a
6156 + * full sector, since it doesn't matter if we read too much. */
6157 + if (num_sectors > 0)
6158 + grub_printf ("%s%d+%d", num_entries ? "," : "",
6159 + start_sector - part_start, num_sectors);
6160 +
6161 + grub_printf ("\n");
6162 +
6163 + fail:
6164 + disk_read_hook = 0;
6165 + grub_close ();
6166 + return errnum;
6167 +}
6168 +
6169 +static struct builtin builtin_blocklist =
6170 +{
6171 + "blocklist",
6172 + blocklist_func,
6173 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
6174 + "blocklist FILE",
6175 + "Print the blocklist notation of the file FILE."
6176 +};
6177 +
6178 +/* boot */
6179 +static int
6180 +boot_func (char *arg, int flags)
6181 +{
6182 + /* Clear the int15 handler if we can boot the kernel successfully.
6183 + This assumes that the boot code never fails only if KERNEL_TYPE is
6184 + not KERNEL_TYPE_NONE. Is this assumption is bad? */
6185 + if (kernel_type != KERNEL_TYPE_NONE)
6186 + unset_int15_handler ();
6187 +
6188 +#ifdef SUPPORT_NETBOOT
6189 + /* Shut down the networking. */
6190 + cleanup_net ();
6191 +#endif
6192 +
6193 + switch (kernel_type)
6194 + {
6195 + case KERNEL_TYPE_FREEBSD:
6196 + case KERNEL_TYPE_NETBSD:
6197 + /* *BSD */
6198 + bsd_boot (kernel_type, bootdev, (char *) mbi.cmdline);
6199 + break;
6200 +
6201 + case KERNEL_TYPE_LINUX:
6202 + /* Linux */
6203 + linux_boot ();
6204 + break;
6205 +
6206 + case KERNEL_TYPE_BIG_LINUX:
6207 + /* Big Linux */
6208 + big_linux_boot ();
6209 + break;
6210 +
6211 + case KERNEL_TYPE_CHAINLOADER:
6212 + /* Chainloader */
6213 +
6214 + /* Check if we should set the int13 handler. */
6215 + if (bios_drive_map[0] != 0)
6216 + {
6217 + int i;
6218 +
6219 + /* Search for SAVED_DRIVE. */
6220 + for (i = 0; i < DRIVE_MAP_SIZE; i++)
6221 + {
6222 + if (! bios_drive_map[i])
6223 + break;
6224 + else if ((bios_drive_map[i] & 0xFF) == saved_drive)
6225 + {
6226 + /* Exchage SAVED_DRIVE with the mapped drive. */
6227 + saved_drive = (bios_drive_map[i] >> 8) & 0xFF;
6228 + break;
6229 + }
6230 + }
6231 +
6232 + /* Set the handler. This is somewhat dangerous. */
6233 + set_int13_handler (bios_drive_map);
6234 + }
6235 +
6236 + gateA20 (0);
6237 + boot_drive = saved_drive;
6238 + chain_stage1 (0, BOOTSEC_LOCATION, boot_part_addr);
6239 + break;
6240 +
6241 + case KERNEL_TYPE_MULTIBOOT:
6242 + /* Multiboot */
6243 + multi_boot ((int) entry_addr, (int) &mbi);
6244 + break;
6245 +
6246 + default:
6247 + errnum = ERR_BOOT_COMMAND;
6248 + return 1;
6249 + }
6250 +
6251 + return 0;
6252 +}
6253 +
6254 +static struct builtin builtin_boot =
6255 +{
6256 + "boot",
6257 + boot_func,
6258 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
6259 + "boot",
6260 + "Boot the OS/chain-loader which has been loaded."
6261 +};
6262 +
6263 +\f
6264 +#ifdef SUPPORT_NETBOOT
6265 +/* bootp */
6266 +static int
6267 +bootp_func (char *arg, int flags)
6268 +{
6269 + int with_configfile = 0;
6270 +
6271 + if (grub_memcmp (arg, "--with-configfile", sizeof ("--with-configfile") - 1)
6272 + == 0)
6273 + {
6274 + with_configfile = 1;
6275 + arg = skip_to (0, arg);
6276 + }
6277 +
6278 + if (! bootp ())
6279 + {
6280 + if (errnum == ERR_NONE)
6281 + errnum = ERR_DEV_VALUES;
6282 +
6283 + return 1;
6284 + }
6285 +
6286 + /* Notify the configuration. */
6287 + print_network_configuration ();
6288 +
6289 + /* XXX: this can cause an endless loop, but there is no easy way to
6290 + detect such a loop unfortunately. */
6291 + if (with_configfile)
6292 + configfile_func (config_file, flags);
6293 +
6294 + return 0;
6295 +}
6296 +
6297 +static struct builtin builtin_bootp =
6298 +{
6299 + "bootp",
6300 + bootp_func,
6301 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
6302 + "bootp [--with-configfile]",
6303 + "Initialize a network device via BOOTP. If the option `--with-configfile'"
6304 + " is given, try to load a configuration file specified by the 150 vendor"
6305 + " tag."
6306 +};
6307 +#endif /* SUPPORT_NETBOOT */
6308 +
6309 +\f
6310 +/* cat */
6311 +static int
6312 +cat_func (char *arg, int flags)
6313 +{
6314 + char c;
6315 +
6316 + if (! grub_open (arg))
6317 + return 1;
6318 +
6319 + while (grub_read (&c, 1))
6320 + {
6321 + /* Because running "cat" with a binary file can confuse the terminal,
6322 + print only some characters as they are. */
6323 + if (grub_isspace (c) || (c >= ' ' && c <= '~'))
6324 + grub_putchar (c);
6325 + else
6326 + grub_putchar ('?');
6327 + }
6328 +
6329 + grub_close ();
6330 + return 0;
6331 +}
6332 +
6333 +static struct builtin builtin_cat =
6334 +{
6335 + "cat",
6336 + cat_func,
6337 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
6338 + "cat FILE",
6339 + "Print the contents of the file FILE."
6340 +};
6341 +
6342 +\f
6343 +/* chainloader */
6344 +static int
6345 +chainloader_func (char *arg, int flags)
6346 +{
6347 + int force = 0;
6348 + char *file = arg;
6349 +
6350 + /* If the option `--force' is specified? */
6351 + if (substring ("--force", arg) <= 0)
6352 + {
6353 + force = 1;
6354 + file = skip_to (0, arg);
6355 + }
6356 +
6357 + /* Open the file. */
6358 + if (! grub_open (file))
6359 + {
6360 + kernel_type = KERNEL_TYPE_NONE;
6361 + return 1;
6362 + }
6363 +
6364 + /* Read the first block. */
6365 + if (grub_read ((char *) BOOTSEC_LOCATION, SECTOR_SIZE) != SECTOR_SIZE)
6366 + {
6367 + grub_close ();
6368 + kernel_type = KERNEL_TYPE_NONE;
6369 +
6370 + /* This below happens, if a file whose size is less than 512 bytes
6371 + is loaded. */
6372 + if (errnum == ERR_NONE)
6373 + errnum = ERR_EXEC_FORMAT;
6374 +
6375 + return 1;
6376 + }
6377 +
6378 + /* If not loading it forcibly, check for the signature. */
6379 + if (! force
6380 + && (*((unsigned short *) (BOOTSEC_LOCATION + BOOTSEC_SIG_OFFSET))
6381 + != BOOTSEC_SIGNATURE))
6382 + {
6383 + grub_close ();
6384 + errnum = ERR_EXEC_FORMAT;
6385 + kernel_type = KERNEL_TYPE_NONE;
6386 + return 1;
6387 + }
6388 +
6389 + grub_close ();
6390 + kernel_type = KERNEL_TYPE_CHAINLOADER;
6391 +
6392 + /* XXX: Windows evil hack. For now, only the first five letters are
6393 + checked. */
6394 + if (IS_PC_SLICE_TYPE_FAT (current_slice)
6395 + && ! grub_memcmp ((char *) BOOTSEC_LOCATION + BOOTSEC_BPB_SYSTEM_ID,
6396 + "MSWIN", 5))
6397 + *((unsigned long *) (BOOTSEC_LOCATION + BOOTSEC_BPB_HIDDEN_SECTORS))
6398 + = part_start;
6399 +
6400 + errnum = ERR_NONE;
6401 +
6402 + return 0;
6403 +}
6404 +
6405 +static struct builtin builtin_chainloader =
6406 +{
6407 + "chainloader",
6408 + chainloader_func,
6409 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
6410 + "chainloader [--force] FILE",
6411 + "Load the chain-loader FILE. If --force is specified, then load it"
6412 + " forcibly, whether the boot loader signature is present or not."
6413 +};
6414 +
6415 +\f
6416 +/* This function could be used to debug new filesystem code. Put a file
6417 + in the new filesystem and the same file in a well-tested filesystem.
6418 + Then, run "cmp" with the files. If no output is obtained, probably
6419 + the code is good, otherwise investigate what's wrong... */
6420 +/* cmp FILE1 FILE2 */
6421 +static int
6422 +cmp_func (char *arg, int flags)
6423 +{
6424 + /* The filenames. */
6425 + char *file1, *file2;
6426 + /* The addresses. */
6427 + char *addr1, *addr2;
6428 + int i;
6429 + /* The size of the file. */
6430 + int size;
6431 +
6432 + /* Get the filenames from ARG. */
6433 + file1 = arg;
6434 + file2 = skip_to (0, arg);
6435 + if (! *file1 || ! *file2)
6436 + {
6437 + errnum = ERR_BAD_ARGUMENT;
6438 + return 1;
6439 + }
6440 +
6441 + /* Terminate the filenames for convenience. */
6442 + nul_terminate (file1);
6443 + nul_terminate (file2);
6444 +
6445 + /* Read the whole data from FILE1. */
6446 + addr1 = (char *) RAW_ADDR (0x100000);
6447 + if (! grub_open (file1))
6448 + return 1;
6449 +
6450 + /* Get the size. */
6451 + size = filemax;
6452 + if (grub_read (addr1, -1) != size)
6453 + {
6454 + grub_close ();
6455 + return 1;
6456 + }
6457 +
6458 + grub_close ();
6459 +
6460 + /* Read the whole data from FILE2. */
6461 + addr2 = addr1 + size;
6462 + if (! grub_open (file2))
6463 + return 1;
6464 +
6465 + /* Check if the size of FILE2 is equal to the one of FILE2. */
6466 + if (size != filemax)
6467 + {
6468 + grub_printf ("Differ in size: 0x%x [%s], 0x%x [%s]\n",
6469 + size, file1, filemax, file2);
6470 + grub_close ();
6471 + return 0;
6472 + }
6473 +
6474 + if (! grub_read (addr2, -1))
6475 + {
6476 + grub_close ();
6477 + return 1;
6478 + }
6479 +
6480 + grub_close ();
6481 +
6482 + /* Now compare ADDR1 with ADDR2. */
6483 + for (i = 0; i < size; i++)
6484 + {
6485 + if (addr1[i] != addr2[i])
6486 + grub_printf ("Differ at the offset %d: 0x%x [%s], 0x%x [%s]\n",
6487 + i, (unsigned) addr1[i], file1,
6488 + (unsigned) addr2[i], file2);
6489 + }
6490 +
6491 + return 0;
6492 +}
6493 +
6494 +static struct builtin builtin_cmp =
6495 +{
6496 + "cmp",
6497 + cmp_func,
6498 + BUILTIN_CMDLINE,
6499 + "cmp FILE1 FILE2",
6500 + "Compare the file FILE1 with the FILE2 and inform the different values"
6501 + " if any."
6502 +};
6503 +
6504 +\f
6505 +/* color */
6506 +/* Set new colors used for the menu interface. Support two methods to
6507 + specify a color name: a direct integer representation and a symbolic
6508 + color name. An example of the latter is "blink-light-gray/blue". */
6509 +static int
6510 +color_func (char *arg, int flags)
6511 +{
6512 + char *normal;
6513 + char *highlight;
6514 + int new_normal_color;
6515 + int new_highlight_color;
6516 + static char *color_list[16] =
6517 + {
6518 + "black",
6519 + "blue",
6520 + "green",
6521 + "cyan",
6522 + "red",
6523 + "magenta",
6524 + "brown",
6525 + "light-gray",
6526 + "dark-gray",
6527 + "light-blue",
6528 + "light-green",
6529 + "light-cyan",
6530 + "light-red",
6531 + "light-magenta",
6532 + "yellow",
6533 + "white"
6534 + };
6535 +
6536 + auto int color_number (char *str);
6537 +
6538 + /* Convert the color name STR into the magical number. */
6539 + auto int color_number (char *str)
6540 + {
6541 + char *ptr;
6542 + int i;
6543 + int color = 0;
6544 +
6545 + /* Find the separator. */
6546 + for (ptr = str; *ptr && *ptr != '/'; ptr++)
6547 + ;
6548 +
6549 + /* If not found, return -1. */
6550 + if (! *ptr)
6551 + return -1;
6552 +
6553 + /* Terminate the string STR. */
6554 + *ptr++ = 0;
6555 +
6556 + /* If STR contains the prefix "blink-", then set the `blink' bit
6557 + in COLOR. */
6558 + if (substring ("blink-", str) <= 0)
6559 + {
6560 + color = 0x80;
6561 + str += 6;
6562 + }
6563 +
6564 + /* Search for the color name. */
6565 + for (i = 0; i < 16; i++)
6566 + if (grub_strcmp (color_list[i], str) == 0)
6567 + {
6568 + color |= i;
6569 + break;
6570 + }
6571 +
6572 + if (i == 16)
6573 + return -1;
6574 +
6575 + str = ptr;
6576 + nul_terminate (str);
6577 +
6578 + /* Search for the color name. */
6579 + for (i = 0; i < 8; i++)
6580 + if (grub_strcmp (color_list[i], str) == 0)
6581 + {
6582 + color |= i << 4;
6583 + break;
6584 + }
6585 +
6586 + if (i == 8)
6587 + return -1;
6588 +
6589 + return color;
6590 + }
6591 +
6592 + normal = arg;
6593 + highlight = skip_to (0, arg);
6594 +
6595 + new_normal_color = color_number (normal);
6596 + if (new_normal_color < 0 && ! safe_parse_maxint (&normal, &new_normal_color))
6597 + return 1;
6598 +
6599 + /* The second argument is optional, so set highlight_color
6600 + to inverted NORMAL_COLOR. */
6601 + if (! *highlight)
6602 + new_highlight_color = ((new_normal_color >> 4)
6603 + | ((new_normal_color & 0xf) << 4));
6604 + else
6605 + {
6606 + new_highlight_color = color_number (highlight);
6607 + if (new_highlight_color < 0
6608 + && ! safe_parse_maxint (&highlight, &new_highlight_color))
6609 + return 1;
6610 + }
6611 +
6612 + if (current_term->setcolor)
6613 + current_term->setcolor (new_normal_color, new_highlight_color);
6614 +
6615 + return 0;
6616 +}
6617 +
6618 +static struct builtin builtin_color =
6619 +{
6620 + "color",
6621 + color_func,
6622 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
6623 + "color NORMAL [HIGHLIGHT]",
6624 + "Change the menu colors. The color NORMAL is used for most"
6625 + " lines in the menu, and the color HIGHLIGHT is used to highlight the"
6626 + " line where the cursor points. If you omit HIGHLIGHT, then the"
6627 + " inverted color of NORMAL is used for the highlighted line."
6628 + " The format of a color is \"FG/BG\". FG and BG are symbolic color names."
6629 + " A symbolic color name must be one of these: black, blue, green,"
6630 + " cyan, red, magenta, brown, light-gray, dark-gray, light-blue,"
6631 + " light-green, light-cyan, light-red, light-magenta, yellow and white."
6632 + " But only the first eight names can be used for BG. You can prefix"
6633 + " \"blink-\" to FG if you want a blinking foreground color."
6634 +};
6635 +
6636 +\f
6637 +/* configfile */
6638 +static int
6639 +configfile_func (char *arg, int flags)
6640 +{
6641 + char *new_config = config_file;
6642 +
6643 + /* Check if the file ARG is present. */
6644 + if (! grub_open (arg))
6645 + return 1;
6646 +
6647 + grub_close ();
6648 +
6649 + /* Copy ARG to CONFIG_FILE. */
6650 + while ((*new_config++ = *arg++) != 0)
6651 + ;
6652 +
6653 +#ifdef GRUB_UTIL
6654 + /* Force to load the configuration file. */
6655 + use_config_file = 1;
6656 +#endif
6657 +
6658 + /* Make sure that the user will not be authoritative. */
6659 + auth = 0;
6660 +
6661 + /* Restart cmain. */
6662 + grub_longjmp (restart_env, 0);
6663 +
6664 + /* Never reach here. */
6665 + return 0;
6666 +}
6667 +
6668 +static struct builtin builtin_configfile =
6669 +{
6670 + "configfile",
6671 + configfile_func,
6672 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
6673 + "configfile FILE",
6674 + "Load FILE as the configuration file."
6675 +};
6676 +
6677 +\f
6678 +/* debug */
6679 +static int
6680 +debug_func (char *arg, int flags)
6681 +{
6682 + if (debug)
6683 + {
6684 + debug = 0;
6685 + grub_printf (" Debug mode is turned off\n");
6686 + }
6687 + else
6688 + {
6689 + debug = 1;
6690 + grub_printf (" Debug mode is turned on\n");
6691 + }
6692 +
6693 + return 0;
6694 +}
6695 +
6696 +static struct builtin builtin_debug =
6697 +{
6698 + "debug",
6699 + debug_func,
6700 + BUILTIN_CMDLINE,
6701 + "debug",
6702 + "Turn on/off the debug mode."
6703 +};
6704 +
6705 +\f
6706 +/* default */
6707 +static int
6708 +default_func (char *arg, int flags)
6709 +{
6710 +#ifndef SUPPORT_DISKLESS
6711 + if (grub_strcmp (arg, "saved") == 0)
6712 + {
6713 + default_entry = saved_entryno;
6714 + return 0;
6715 + }
6716 +#endif /* SUPPORT_DISKLESS */
6717 +
6718 + if (! safe_parse_maxint (&arg, &default_entry))
6719 + return 1;
6720 +
6721 + return 0;
6722 +}
6723 +
6724 +static struct builtin builtin_default =
6725 +{
6726 + "default",
6727 + default_func,
6728 + BUILTIN_MENU,
6729 +#if 0
6730 + "default [NUM | `saved']",
6731 + "Set the default entry to entry number NUM (if not specified, it is"
6732 + " 0, the first entry) or the entry number saved by savedefault."
6733 +#endif
6734 +};
6735 +
6736 +\f
6737 +#ifdef GRUB_UTIL
6738 +/* device */
6739 +static int
6740 +device_func (char *arg, int flags)
6741 +{
6742 + char *drive = arg;
6743 + char *device;
6744 +
6745 + /* Get the drive number from DRIVE. */
6746 + if (! set_device (drive))
6747 + return 1;
6748 +
6749 + /* Get the device argument. */
6750 + device = skip_to (0, drive);
6751 +
6752 + /* Terminate DEVICE. */
6753 + nul_terminate (device);
6754 +
6755 + if (! *device || ! check_device (device))
6756 + {
6757 + errnum = ERR_FILE_NOT_FOUND;
6758 + return 1;
6759 + }
6760 +
6761 + assign_device_name (current_drive, device);
6762 +
6763 + return 0;
6764 +}
6765 +
6766 +static struct builtin builtin_device =
6767 +{
6768 + "device",
6769 + device_func,
6770 + BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
6771 + "device DRIVE DEVICE",
6772 + "Specify DEVICE as the actual drive for a BIOS drive DRIVE. This command"
6773 + " can be used only in the grub shell."
6774 +};
6775 +#endif /* GRUB_UTIL */
6776 +
6777 +\f
6778 +#ifdef SUPPORT_NETBOOT
6779 +/* dhcp */
6780 +static int
6781 +dhcp_func (char *arg, int flags)
6782 +{
6783 + /* For now, this is an alias for bootp. */
6784 + return bootp_func (arg, flags);
6785 +}
6786 +
6787 +static struct builtin builtin_dhcp =
6788 +{
6789 + "dhcp",
6790 + dhcp_func,
6791 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
6792 + "dhcp",
6793 + "Initialize a network device via DHCP."
6794 +};
6795 +#endif /* SUPPORT_NETBOOT */
6796 +
6797 +\f
6798 +/* displayapm */
6799 +static int
6800 +displayapm_func (char *arg, int flags)
6801 +{
6802 + if (mbi.flags & MB_INFO_APM_TABLE)
6803 + {
6804 + grub_printf ("APM BIOS information:\n"
6805 + " Version: 0x%x\n"
6806 + " 32-bit CS: 0x%x\n"
6807 + " Offset: 0x%x\n"
6808 + " 16-bit CS: 0x%x\n"
6809 + " 16-bit DS: 0x%x\n"
6810 + " 32-bit CS length: 0x%x\n"
6811 + " 16-bit CS length: 0x%x\n"
6812 + " 16-bit DS length: 0x%x\n",
6813 + (unsigned) apm_bios_info.version,
6814 + (unsigned) apm_bios_info.cseg,
6815 + apm_bios_info.offset,
6816 + (unsigned) apm_bios_info.cseg_16,
6817 + (unsigned) apm_bios_info.dseg_16,
6818 + (unsigned) apm_bios_info.cseg_len,
6819 + (unsigned) apm_bios_info.cseg_16_len,
6820 + (unsigned) apm_bios_info.dseg_16_len);
6821 + }
6822 + else
6823 + {
6824 + grub_printf ("No APM BIOS found or probe failed\n");
6825 + }
6826 +
6827 + return 0;
6828 +}
6829 +
6830 +static struct builtin builtin_displayapm =
6831 +{
6832 + "displayapm",
6833 + displayapm_func,
6834 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
6835 + "displayapm",
6836 + "Display APM BIOS information."
6837 +};
6838 +
6839 +\f
6840 +/* displaymem */
6841 +static int
6842 +displaymem_func (char *arg, int flags)
6843 +{
6844 + if (get_eisamemsize () != -1)
6845 + grub_printf (" EISA Memory BIOS Interface is present\n");
6846 + if (get_mmap_entry ((void *) SCRATCHADDR, 0) != 0
6847 + || *((int *) SCRATCHADDR) != 0)
6848 + grub_printf (" Address Map BIOS Interface is present\n");
6849 +
6850 + grub_printf (" Lower memory: %uK, "
6851 + "Upper memory (to first chipset hole): %uK\n",
6852 + mbi.mem_lower, mbi.mem_upper);
6853 +
6854 + if (mbi.flags & MB_INFO_MEM_MAP)
6855 + {
6856 + struct AddrRangeDesc *map = (struct AddrRangeDesc *) mbi.mmap_addr;
6857 + int end_addr = mbi.mmap_addr + mbi.mmap_length;
6858 +
6859 + grub_printf (" [Address Range Descriptor entries "
6860 + "immediately follow (values are 64-bit)]\n");
6861 + while (end_addr > (int) map)
6862 + {
6863 + char *str;
6864 +
6865 + if (map->Type == MB_ARD_MEMORY)
6866 + str = "Usable RAM";
6867 + else
6868 + str = "Reserved";
6869 + grub_printf (" %s: Base Address: 0x%x X 4GB + 0x%x,\n"
6870 + " Length: 0x%x X 4GB + 0x%x bytes\n",
6871 + str,
6872 + (unsigned long) (map->BaseAddr >> 32),
6873 + (unsigned long) (map->BaseAddr & 0xFFFFFFFF),
6874 + (unsigned long) (map->Length >> 32),
6875 + (unsigned long) (map->Length & 0xFFFFFFFF));
6876 +
6877 + map = ((struct AddrRangeDesc *) (((int) map) + 4 + map->size));
6878 + }
6879 + }
6880 +
6881 + return 0;
6882 +}
6883 +
6884 +static struct builtin builtin_displaymem =
6885 +{
6886 + "displaymem",
6887 + displaymem_func,
6888 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
6889 + "displaymem",
6890 + "Display what GRUB thinks the system address space map of the"
6891 + " machine is, including all regions of physical RAM installed."
6892 +};
6893 +
6894 +\f
6895 +/* dump FROM TO */
6896 +#ifdef GRUB_UTIL
6897 +static int
6898 +dump_func (char *arg, int flags)
6899 +{
6900 + char *from, *to;
6901 + FILE *fp;
6902 + char c;
6903 +
6904 + from = arg;
6905 + to = skip_to (0, arg);
6906 + if (! *from || ! *to)
6907 + {
6908 + errnum = ERR_BAD_ARGUMENT;
6909 + return 1;
6910 + }
6911 +
6912 + nul_terminate (from);
6913 + nul_terminate (to);
6914 +
6915 + if (! grub_open (from))
6916 + return 1;
6917 +
6918 + fp = fopen (to, "w");
6919 + if (! fp)
6920 + {
6921 + errnum = ERR_WRITE;
6922 + return 1;
6923 + }
6924 +
6925 + while (grub_read (&c, 1))
6926 + if (fputc (c, fp) == EOF)
6927 + {
6928 + errnum = ERR_WRITE;
6929 + fclose (fp);
6930 + return 1;
6931 + }
6932 +
6933 + if (fclose (fp) == EOF)
6934 + {
6935 + errnum = ERR_WRITE;
6936 + return 1;
6937 + }
6938 +
6939 + grub_close ();
6940 + return 0;
6941 +}
6942 +
6943 +static struct builtin builtin_dump =
6944 + {
6945 + "dump",
6946 + dump_func,
6947 + BUILTIN_CMDLINE,
6948 + "dump FROM TO",
6949 + "Dump the contents of the file FROM to the file TO. FROM must be"
6950 + " a GRUB file and TO must be an OS file."
6951 + };
6952 +#endif /* GRUB_UTIL */
6953 +
6954 +\f
6955 +static char embed_info[32];
6956 +/* embed */
6957 +/* Embed a Stage 1.5 in the first cylinder after MBR or in the
6958 + bootloader block in a FFS. */
6959 +static int
6960 +embed_func (char *arg, int flags)
6961 +{
6962 + char *stage1_5;
6963 + char *device;
6964 + char *stage1_5_buffer = (char *) RAW_ADDR (0x100000);
6965 + int len, size;
6966 + int sector;
6967 +
6968 + stage1_5 = arg;
6969 + device = skip_to (0, stage1_5);
6970 +
6971 + /* Open a Stage 1.5. */
6972 + if (! grub_open (stage1_5))
6973 + return 1;
6974 +
6975 + /* Read the whole of the Stage 1.5. */
6976 + len = grub_read (stage1_5_buffer, -1);
6977 + grub_close ();
6978 +
6979 + if (errnum)
6980 + return 1;
6981 +
6982 + size = (len + SECTOR_SIZE - 1) / SECTOR_SIZE;
6983 +
6984 + /* Get the device where the Stage 1.5 will be embedded. */
6985 + set_device (device);
6986 + if (errnum)
6987 + return 1;
6988 +
6989 + if (current_partition == 0xFFFFFF)
6990 + {
6991 + /* Embed it after the MBR. */
6992 +
6993 + char mbr[SECTOR_SIZE];
6994 + char ezbios_check[2*SECTOR_SIZE];
6995 + int i;
6996 +
6997 + /* Open the partition. */
6998 + if (! open_partition ())
6999 + return 1;
7000 +
7001 + /* No floppy has MBR. */
7002 + if (! (current_drive & 0x80))
7003 + {
7004 + errnum = ERR_DEV_VALUES;
7005 + return 1;
7006 + }
7007 +
7008 + /* Read the MBR of CURRENT_DRIVE. */
7009 + if (! rawread (current_drive, PC_MBR_SECTOR, 0, SECTOR_SIZE, mbr))
7010 + return 1;
7011 +
7012 + /* Sanity check. */
7013 + if (! PC_MBR_CHECK_SIG (mbr))
7014 + {
7015 + errnum = ERR_BAD_PART_TABLE;
7016 + return 1;
7017 + }
7018 +
7019 + /* Check if the disk can store the Stage 1.5. */
7020 + for (i = 0; i < 4; i++)
7021 + if (PC_SLICE_TYPE (mbr, i) && PC_SLICE_START (mbr, i) - 1 < size)
7022 + {
7023 + errnum = ERR_NO_DISK_SPACE;
7024 + return 1;
7025 + }
7026 +
7027 + /* Check for EZ-BIOS signature. It should be in the third
7028 + * sector, but due to remapping it can appear in the second, so
7029 + * load and check both.
7030 + */
7031 + if (! rawread (current_drive, 1, 0, 2 * SECTOR_SIZE, ezbios_check))
7032 + return 1;
7033 +
7034 + if (! memcmp (ezbios_check + 3, "AERMH", 5)
7035 + || ! memcmp (ezbios_check + 512 + 3, "AERMH", 5))
7036 + {
7037 + /* The space after the MBR is used by EZ-BIOS which we must
7038 + * not overwrite.
7039 + */
7040 + errnum = ERR_NO_DISK_SPACE;
7041 + return 1;
7042 + }
7043 +
7044 + sector = 1;
7045 + }
7046 + else
7047 + {
7048 + /* Embed it in the bootloader block in the filesystem. */
7049 + int start_sector;
7050 +
7051 + /* Open the partition. */
7052 + if (! open_device ())
7053 + return 1;
7054 +
7055 + /* Check if the current slice supports embedding. */
7056 + if (fsys_table[fsys_type].embed_func == 0
7057 + || ! fsys_table[fsys_type].embed_func (&start_sector, size))
7058 + {
7059 + errnum = ERR_DEV_VALUES;
7060 + return 1;
7061 + }
7062 +
7063 + sector = part_start + start_sector;
7064 + }
7065 +
7066 + /* Clear the cache. */
7067 + buf_track = -1;
7068 +
7069 + /* Now perform the embedding. */
7070 + if (! devwrite (sector - part_start, size, stage1_5_buffer))
7071 + return 1;
7072 +
7073 + grub_printf (" %d sectors are embedded.\n", size);
7074 + grub_sprintf (embed_info, "%d+%d", sector - part_start, size);
7075 + return 0;
7076 +}
7077 +
7078 +static struct builtin builtin_embed =
7079 +{
7080 + "embed",
7081 + embed_func,
7082 + BUILTIN_CMDLINE,
7083 + "embed STAGE1_5 DEVICE",
7084 + "Embed the Stage 1.5 STAGE1_5 in the sectors after MBR if DEVICE"
7085 + " is a drive, or in the \"bootloader\" area if DEVICE is a FFS partition."
7086 + " Print the number of sectors which STAGE1_5 occupies if successful."
7087 +};
7088 +
7089 +\f
7090 +/* fallback */
7091 +static int
7092 +fallback_func (char *arg, int flags)
7093 +{
7094 + int i = 0;
7095 +
7096 + while (*arg)
7097 + {
7098 + int entry;
7099 + int j;
7100 +
7101 + if (! safe_parse_maxint (&arg, &entry))
7102 + return 1;
7103 +
7104 + /* Remove duplications to prevent infinite looping. */
7105 + for (j = 0; j < i; j++)
7106 + if (entry == fallback_entries[j])
7107 + break;
7108 + if (j != i)
7109 + continue;
7110 +
7111 + fallback_entries[i++] = entry;
7112 + if (i == MAX_FALLBACK_ENTRIES)
7113 + break;
7114 +
7115 + arg = skip_to (0, arg);
7116 + }
7117 +
7118 + if (i < MAX_FALLBACK_ENTRIES)
7119 + fallback_entries[i] = -1;
7120 +
7121 + fallback_entryno = (i == 0) ? -1 : 0;
7122 +
7123 + return 0;
7124 +}
7125 +
7126 +static struct builtin builtin_fallback =
7127 +{
7128 + "fallback",
7129 + fallback_func,
7130 + BUILTIN_MENU,
7131 +#if 0
7132 + "fallback NUM...",
7133 + "Go into unattended boot mode: if the default boot entry has any"
7134 + " errors, instead of waiting for the user to do anything, it"
7135 + " immediately starts over using the NUM entry (same numbering as the"
7136 + " `default' command). This obviously won't help if the machine"
7137 + " was rebooted by a kernel that GRUB loaded."
7138 +#endif
7139 +};
7140 +
7141 +\f
7142 +/* find */
7143 +/* Search for the filename ARG in all of partitions. */
7144 +static int
7145 +find_func (char *arg, int flags)
7146 +{
7147 + char *filename = arg;
7148 + unsigned long drive;
7149 + unsigned long tmp_drive = saved_drive;
7150 + unsigned long tmp_partition = saved_partition;
7151 + int got_file = 0;
7152 +
7153 + /* Floppies. */
7154 + for (drive = 0; drive < 8; drive++)
7155 + {
7156 + current_drive = drive;
7157 + current_partition = 0xFFFFFF;
7158 +
7159 + if (open_device ())
7160 + {
7161 + saved_drive = current_drive;
7162 + saved_partition = current_partition;
7163 + if (grub_open (filename))
7164 + {
7165 + grub_close ();
7166 + grub_printf (" (fd%d)\n", drive);
7167 + got_file = 1;
7168 + }
7169 + }
7170 +
7171 + errnum = ERR_NONE;
7172 + }
7173 +
7174 + /* Hard disks. */
7175 + for (drive = 0x80; drive < 0x88; drive++)
7176 + {
7177 + unsigned long part = 0xFFFFFF;
7178 + unsigned long start, len, offset, ext_offset;
7179 + int type, entry;
7180 + char buf[SECTOR_SIZE];
7181 +
7182 + current_drive = drive;
7183 + while (next_partition (drive, 0xFFFFFF, &part, &type,
7184 + &start, &len, &offset, &entry,
7185 + &ext_offset, buf))
7186 + {
7187 + if (type != PC_SLICE_TYPE_NONE
7188 + && ! IS_PC_SLICE_TYPE_BSD (type)
7189 + && ! IS_PC_SLICE_TYPE_EXTENDED (type))
7190 + {
7191 + current_partition = part;
7192 + if (open_device ())
7193 + {
7194 + saved_drive = current_drive;
7195 + saved_partition = current_partition;
7196 + if (grub_open (filename))
7197 + {
7198 + int bsd_part = (part >> 8) & 0xFF;
7199 + int pc_slice = part >> 16;
7200 +
7201 + grub_close ();
7202 +
7203 + if (bsd_part == 0xFF)
7204 + grub_printf (" (hd%d,%d)\n",
7205 + drive - 0x80, pc_slice);
7206 + else
7207 + grub_printf (" (hd%d,%d,%c)\n",
7208 + drive - 0x80, pc_slice, bsd_part + 'a');
7209 +
7210 + got_file = 1;
7211 + }
7212 + }
7213 + }
7214 +
7215 + /* We want to ignore any error here. */
7216 + errnum = ERR_NONE;
7217 + }
7218 +
7219 + /* next_partition always sets ERRNUM in the last call, so clear
7220 + it. */
7221 + errnum = ERR_NONE;
7222 + }
7223 +
7224 + saved_drive = tmp_drive;
7225 + saved_partition = tmp_partition;
7226 +
7227 + if (got_file)
7228 + {
7229 + errnum = ERR_NONE;
7230 + return 0;
7231 + }
7232 +
7233 + errnum = ERR_FILE_NOT_FOUND;
7234 + return 1;
7235 +}
7236 +
7237 +static struct builtin builtin_find =
7238 +{
7239 + "find",
7240 + find_func,
7241 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
7242 + "find FILENAME",
7243 + "Search for the filename FILENAME in all of partitions and print the list of"
7244 + " the devices which contain the file."
7245 +};
7246 +
7247 +\f
7248 +/* fstest */
7249 +static int
7250 +fstest_func (char *arg, int flags)
7251 +{
7252 + if (disk_read_hook)
7253 + {
7254 + disk_read_hook = NULL;
7255 + printf (" Filesystem tracing is now off\n");
7256 + }
7257 + else
7258 + {
7259 + disk_read_hook = disk_read_print_func;
7260 + printf (" Filesystem tracing is now on\n");
7261 + }
7262 +
7263 + return 0;
7264 +}
7265 +
7266 +static struct builtin builtin_fstest =
7267 +{
7268 + "fstest",
7269 + fstest_func,
7270 + BUILTIN_CMDLINE,
7271 + "fstest",
7272 + "Toggle filesystem test mode."
7273 +};
7274 +
7275 +\f
7276 +/* geometry */
7277 +static int
7278 +geometry_func (char *arg, int flags)
7279 +{
7280 + struct geometry geom;
7281 + char *msg;
7282 + char *device = arg;
7283 +#ifdef GRUB_UTIL
7284 + char *ptr;
7285 +#endif
7286 +
7287 + /* Get the device number. */
7288 + set_device (device);
7289 + if (errnum)
7290 + return 1;
7291 +
7292 + /* Check for the geometry. */
7293 + if (get_diskinfo (current_drive, &geom))
7294 + {
7295 + errnum = ERR_NO_DISK;
7296 + return 1;
7297 + }
7298 +
7299 + /* Attempt to read the first sector, because some BIOSes turns out not
7300 + to support LBA even though they set the bit 0 in the support
7301 + bitmap, only after reading something actually. */
7302 + if (biosdisk (BIOSDISK_READ, current_drive, &geom, 0, 1, SCRATCHSEG))
7303 + {
7304 + errnum = ERR_READ;
7305 + return 1;
7306 + }
7307 +
7308 +#ifdef GRUB_UTIL
7309 + ptr = skip_to (0, device);
7310 + if (*ptr)
7311 + {
7312 + char *cylinder, *head, *sector, *total_sector;
7313 + int num_cylinder, num_head, num_sector, num_total_sector;
7314 +
7315 + cylinder = ptr;
7316 + head = skip_to (0, cylinder);
7317 + sector = skip_to (0, head);
7318 + total_sector = skip_to (0, sector);
7319 + if (! safe_parse_maxint (&cylinder, &num_cylinder)
7320 + || ! safe_parse_maxint (&head, &num_head)
7321 + || ! safe_parse_maxint (&sector, &num_sector))
7322 + return 1;
7323 +
7324 + disks[current_drive].cylinders = num_cylinder;
7325 + disks[current_drive].heads = num_head;
7326 + disks[current_drive].sectors = num_sector;
7327 +
7328 + if (safe_parse_maxint (&total_sector, &num_total_sector))
7329 + disks[current_drive].total_sectors = num_total_sector;
7330 + else
7331 + disks[current_drive].total_sectors
7332 + = num_cylinder * num_head * num_sector;
7333 + errnum = 0;
7334 +
7335 + geom = disks[current_drive];
7336 + buf_drive = -1;
7337 + }
7338 +#endif /* GRUB_UTIL */
7339 +
7340 +#ifdef GRUB_UTIL
7341 + msg = device_map[current_drive];
7342 +#else
7343 + if (geom.flags & BIOSDISK_FLAG_LBA_EXTENSION)
7344 + msg = "LBA";
7345 + else
7346 + msg = "CHS";
7347 +#endif
7348 +
7349 + grub_printf ("drive 0x%x: C/H/S = %d/%d/%d, "
7350 + "The number of sectors = %d, %s\n",
7351 + current_drive,
7352 + geom.cylinders, geom.heads, geom.sectors,
7353 + geom.total_sectors, msg);
7354 + real_open_partition (1);
7355 +
7356 + return 0;
7357 +}
7358 +
7359 +static struct builtin builtin_geometry =
7360 +{
7361 + "geometry",
7362 + geometry_func,
7363 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
7364 + "geometry DRIVE [CYLINDER HEAD SECTOR [TOTAL_SECTOR]]",
7365 + "Print the information for a drive DRIVE. In the grub shell, you can"
7366 + " set the geometry of the drive arbitrarily. The number of the cylinders,"
7367 + " the one of the heads, the one of the sectors and the one of the total"
7368 + " sectors are set to CYLINDER, HEAD, SECTOR and TOTAL_SECTOR,"
7369 + " respectively. If you omit TOTAL_SECTOR, then it will be calculated based"
7370 + " on the C/H/S values automatically."
7371 +};
7372 +
7373 +\f
7374 +/* halt */
7375 +static int
7376 +halt_func (char *arg, int flags)
7377 +{
7378 + int no_apm;
7379 +
7380 + no_apm = (grub_memcmp (arg, "--no-apm", 8) == 0);
7381 + grub_halt (no_apm);
7382 +
7383 + /* Never reach here. */
7384 + return 1;
7385 +}
7386 +
7387 +static struct builtin builtin_halt =
7388 +{
7389 + "halt",
7390 + halt_func,
7391 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
7392 + "halt [--no-apm]",
7393 + "Halt your system. If APM is avaiable on it, turn off the power using"
7394 + " the APM BIOS, unless you specify the option `--no-apm'."
7395 +};
7396 +
7397 +\f
7398 +/* help */
7399 +#define MAX_SHORT_DOC_LEN 39
7400 +#define MAX_LONG_DOC_LEN 66
7401 +
7402 +static int
7403 +help_func (char *arg, int flags)
7404 +{
7405 + int all = 0;
7406 +
7407 + if (grub_memcmp (arg, "--all", sizeof ("--all") - 1) == 0)
7408 + {
7409 + all = 1;
7410 + arg = skip_to (0, arg);
7411 + }
7412 +
7413 + if (! *arg)
7414 + {
7415 + /* Invoked with no argument. Print the list of the short docs. */
7416 + struct builtin **builtin;
7417 + int left = 1;
7418 +
7419 + for (builtin = builtin_table; *builtin != 0; builtin++)
7420 + {
7421 + int len;
7422 + int i;
7423 +
7424 + /* If this cannot be used in the command-line interface,
7425 + skip this. */
7426 + if (! ((*builtin)->flags & BUILTIN_CMDLINE))
7427 + continue;
7428 +
7429 + /* If this doesn't need to be listed automatically and "--all"
7430 + is not specified, skip this. */
7431 + if (! all && ! ((*builtin)->flags & BUILTIN_HELP_LIST))
7432 + continue;
7433 +
7434 + len = grub_strlen ((*builtin)->short_doc);
7435 + /* If the length of SHORT_DOC is too long, truncate it. */
7436 + if (len > MAX_SHORT_DOC_LEN - 1)
7437 + len = MAX_SHORT_DOC_LEN - 1;
7438 +
7439 + for (i = 0; i < len; i++)
7440 + grub_putchar ((*builtin)->short_doc[i]);
7441 +
7442 + for (; i < MAX_SHORT_DOC_LEN; i++)
7443 + grub_putchar (' ');
7444 +
7445 + if (! left)
7446 + grub_putchar ('\n');
7447 +
7448 + left = ! left;
7449 + }
7450 +
7451 + /* If the last entry was at the left column, no newline was printed
7452 + at the end. */
7453 + if (! left)
7454 + grub_putchar ('\n');
7455 + }
7456 + else
7457 + {
7458 + /* Invoked with one or more patterns. */
7459 + do
7460 + {
7461 + struct builtin **builtin;
7462 + char *next_arg;
7463 +
7464 + /* Get the next argument. */
7465 + next_arg = skip_to (0, arg);
7466 +
7467 + /* Terminate ARG. */
7468 + nul_terminate (arg);
7469 +
7470 + for (builtin = builtin_table; *builtin; builtin++)
7471 + {
7472 + /* Skip this if this is only for the configuration file. */
7473 + if (! ((*builtin)->flags & BUILTIN_CMDLINE))
7474 + continue;
7475 +
7476 + if (substring (arg, (*builtin)->name) < 1)
7477 + {
7478 + char *doc = (*builtin)->long_doc;
7479 +
7480 + /* At first, print the name and the short doc. */
7481 + grub_printf ("%s: %s\n",
7482 + (*builtin)->name, (*builtin)->short_doc);
7483 +
7484 + /* Print the long doc. */
7485 + while (*doc)
7486 + {
7487 + int len = grub_strlen (doc);
7488 + int i;
7489 +
7490 + /* If LEN is too long, fold DOC. */
7491 + if (len > MAX_LONG_DOC_LEN)
7492 + {
7493 + /* Fold this line at the position of a space. */
7494 + for (len = MAX_LONG_DOC_LEN; len > 0; len--)
7495 + if (doc[len - 1] == ' ')
7496 + break;
7497 + }
7498 +
7499 + grub_printf (" ");
7500 + for (i = 0; i < len; i++)
7501 + grub_putchar (*doc++);
7502 + grub_putchar ('\n');
7503 + }
7504 + }
7505 + }
7506 +
7507 + arg = next_arg;
7508 + }
7509 + while (*arg);
7510 + }
7511 +
7512 + return 0;
7513 +}
7514 +
7515 +static struct builtin builtin_help =
7516 +{
7517 + "help",
7518 + help_func,
7519 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
7520 + "help [--all] [PATTERN ...]",
7521 + "Display helpful information about builtin commands. Not all commands"
7522 + " aren't shown without the option `--all'."
7523 +};
7524 +
7525 +\f
7526 +/* hiddenmenu */
7527 +static int
7528 +hiddenmenu_func (char *arg, int flags)
7529 +{
7530 + show_menu = 0;
7531 + return 0;
7532 +}
7533 +
7534 +static struct builtin builtin_hiddenmenu =
7535 +{
7536 + "hiddenmenu",
7537 + hiddenmenu_func,
7538 + BUILTIN_MENU,
7539 +#if 0
7540 + "hiddenmenu",
7541 + "Hide the menu."
7542 +#endif
7543 +};
7544 +
7545 +\f
7546 +/* hide */
7547 +static int
7548 +hide_func (char *arg, int flags)
7549 +{
7550 + if (! set_device (arg))
7551 + return 1;
7552 +
7553 + if (! set_partition_hidden_flag (1))
7554 + return 1;
7555 +
7556 + return 0;
7557 +}
7558 +
7559 +static struct builtin builtin_hide =
7560 +{
7561 + "hide",
7562 + hide_func,
7563 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
7564 + "hide PARTITION",
7565 + "Hide PARTITION by setting the \"hidden\" bit in"
7566 + " its partition type code."
7567 +};
7568 +
7569 +\f
7570 +#ifdef SUPPORT_NETBOOT
7571 +/* ifconfig */
7572 +static int
7573 +ifconfig_func (char *arg, int flags)
7574 +{
7575 + char *svr = 0, *ip = 0, *gw = 0, *sm = 0;
7576 +
7577 + if (! eth_probe ())
7578 + {
7579 + grub_printf ("No ethernet card found.\n");
7580 + errnum = ERR_DEV_VALUES;
7581 + return 1;
7582 + }
7583 +
7584 + while (*arg)
7585 + {
7586 + if (! grub_memcmp ("--server=", arg, sizeof ("--server=") - 1))
7587 + svr = arg + sizeof("--server=") - 1;
7588 + else if (! grub_memcmp ("--address=", arg, sizeof ("--address=") - 1))
7589 + ip = arg + sizeof ("--address=") - 1;
7590 + else if (! grub_memcmp ("--gateway=", arg, sizeof ("--gateway=") - 1))
7591 + gw = arg + sizeof ("--gateway=") - 1;
7592 + else if (! grub_memcmp ("--mask=", arg, sizeof("--mask=") - 1))
7593 + sm = arg + sizeof ("--mask=") - 1;
7594 + else
7595 + {
7596 + errnum = ERR_BAD_ARGUMENT;
7597 + return 1;
7598 + }
7599 +
7600 + arg = skip_to (0, arg);
7601 + }
7602 +
7603 + if (! ifconfig (ip, sm, gw, svr))
7604 + {
7605 + errnum = ERR_BAD_ARGUMENT;
7606 + return 1;
7607 + }
7608 +
7609 + print_network_configuration ();
7610 + return 0;
7611 +}
7612 +
7613 +static struct builtin builtin_ifconfig =
7614 +{
7615 + "ifconfig",
7616 + ifconfig_func,
7617 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
7618 + "ifconfig [--address=IP] [--gateway=IP] [--mask=MASK] [--server=IP]",
7619 + "Configure the IP address, the netmask, the gateway and the server"
7620 + " address or print current network configuration."
7621 +};
7622 +#endif /* SUPPORT_NETBOOT */
7623 +
7624 +\f
7625 +/* impsprobe */
7626 +static int
7627 +impsprobe_func (char *arg, int flags)
7628 +{
7629 +#ifdef GRUB_UTIL
7630 + /* In the grub shell, we cannot probe IMPS. */
7631 + errnum = ERR_UNRECOGNIZED;
7632 + return 1;
7633 +#else /* ! GRUB_UTIL */
7634 + if (!imps_probe ())
7635 + printf (" No MPS information found or probe failed\n");
7636 +
7637 + return 0;
7638 +#endif /* ! GRUB_UTIL */
7639 +}
7640 +
7641 +static struct builtin builtin_impsprobe =
7642 +{
7643 + "impsprobe",
7644 + impsprobe_func,
7645 + BUILTIN_CMDLINE,
7646 + "impsprobe",
7647 + "Probe the Intel Multiprocessor Specification 1.1 or 1.4"
7648 + " configuration table and boot the various CPUs which are found into"
7649 + " a tight loop."
7650 +};
7651 +
7652 +\f
7653 +/* initrd */
7654 +static int
7655 +initrd_func (char *arg, int flags)
7656 +{
7657 + switch (kernel_type)
7658 + {
7659 + case KERNEL_TYPE_LINUX:
7660 + case KERNEL_TYPE_BIG_LINUX:
7661 + if (! load_initrd (arg))
7662 + return 1;
7663 + break;
7664 +
7665 + default:
7666 + errnum = ERR_NEED_LX_KERNEL;
7667 + return 1;
7668 + }
7669 +
7670 + return 0;
7671 +}
7672 +
7673 +static struct builtin builtin_initrd =
7674 +{
7675 + "initrd",
7676 + initrd_func,
7677 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
7678 + "initrd FILE [ARG ...]",
7679 + "Load an initial ramdisk FILE for a Linux format boot image and set the"
7680 + " appropriate parameters in the Linux setup area in memory."
7681 +};
7682 +
7683 +\f
7684 +/* install */
7685 +static int
7686 +install_func (char *arg, int flags)
7687 +{
7688 + char *stage1_file, *dest_dev, *file, *addr;
7689 + char *stage1_buffer = (char *) RAW_ADDR (0x100000);
7690 + char *stage2_buffer = stage1_buffer + SECTOR_SIZE;
7691 + char *old_sect = stage2_buffer + SECTOR_SIZE;
7692 + char *stage2_first_buffer = old_sect + SECTOR_SIZE;
7693 + char *stage2_second_buffer = stage2_first_buffer + SECTOR_SIZE;
7694 + /* XXX: Probably SECTOR_SIZE is reasonable. */
7695 + char *config_filename = stage2_second_buffer + SECTOR_SIZE;
7696 + char *dummy = config_filename + SECTOR_SIZE;
7697 + int new_drive = GRUB_INVALID_DRIVE;
7698 + int dest_drive, dest_partition, dest_sector;
7699 + int src_drive, src_partition, src_part_start;
7700 + int i;
7701 + struct geometry dest_geom, src_geom;
7702 + int saved_sector;
7703 + int stage2_first_sector, stage2_second_sector;
7704 + char *ptr;
7705 + int installaddr, installlist;
7706 + /* Point to the location of the name of a configuration file in Stage 2. */
7707 + char *config_file_location;
7708 + /* If FILE is a Stage 1.5? */
7709 + int is_stage1_5 = 0;
7710 + /* Must call grub_close? */
7711 + int is_open = 0;
7712 + /* If LBA is forced? */
7713 + int is_force_lba = 0;
7714 + /* Was the last sector full? */
7715 + int last_length = SECTOR_SIZE;
7716 +
7717 +#ifdef GRUB_UTIL
7718 + /* If the Stage 2 is in a partition mounted by an OS, this will store
7719 + the filename under the OS. */
7720 + char *stage2_os_file = 0;
7721 +#endif /* GRUB_UTIL */
7722 +
7723 + auto void disk_read_savesect_func (int sector, int offset, int length);
7724 + auto void disk_read_blocklist_func (int sector, int offset, int length);
7725 +
7726 + /* Save the first sector of Stage2 in STAGE2_SECT. */
7727 + auto void disk_read_savesect_func (int sector, int offset, int length)
7728 + {
7729 + if (debug)
7730 + printf ("[%d]", sector);
7731 +
7732 + /* ReiserFS has files which sometimes contain data not aligned
7733 + on sector boundaries. Returning an error is better than
7734 + silently failing. */
7735 + if (offset != 0 || length != SECTOR_SIZE)
7736 + errnum = ERR_UNALIGNED;
7737 +
7738 + saved_sector = sector;
7739 + }
7740 +
7741 + /* Write SECTOR to INSTALLLIST, and update INSTALLADDR and
7742 + INSTALLSECT. */
7743 + auto void disk_read_blocklist_func (int sector, int offset, int length)
7744 + {
7745 + if (debug)
7746 + printf("[%d]", sector);
7747 +
7748 + if (offset != 0 || last_length != SECTOR_SIZE)
7749 + {
7750 + /* We found a non-sector-aligned data block. */
7751 + errnum = ERR_UNALIGNED;
7752 + return;
7753 + }
7754 +
7755 + last_length = length;
7756 +
7757 + if (*((unsigned long *) (installlist - 4))
7758 + + *((unsigned short *) installlist) != sector
7759 + || installlist == (int) stage2_first_buffer + SECTOR_SIZE + 4)
7760 + {
7761 + installlist -= 8;
7762 +
7763 + if (*((unsigned long *) (installlist - 8)))
7764 + errnum = ERR_WONT_FIT;
7765 + else
7766 + {
7767 + *((unsigned short *) (installlist + 2)) = (installaddr >> 4);
7768 + *((unsigned long *) (installlist - 4)) = sector;
7769 + }
7770 + }
7771 +
7772 + *((unsigned short *) installlist) += 1;
7773 + installaddr += 512;
7774 + }
7775 +
7776 + /* First, check the GNU-style long option. */
7777 + while (1)
7778 + {
7779 + if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0)
7780 + {
7781 + is_force_lba = 1;
7782 + arg = skip_to (0, arg);
7783 + }
7784 +#ifdef GRUB_UTIL
7785 + else if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) == 0)
7786 + {
7787 + stage2_os_file = arg + sizeof ("--stage2=") - 1;
7788 + arg = skip_to (0, arg);
7789 + nul_terminate (stage2_os_file);
7790 + }
7791 +#endif /* GRUB_UTIL */
7792 + else
7793 + break;
7794 + }
7795 +
7796 + stage1_file = arg;
7797 + dest_dev = skip_to (0, stage1_file);
7798 + if (*dest_dev == 'd')
7799 + {
7800 + new_drive = 0;
7801 + dest_dev = skip_to (0, dest_dev);
7802 + }
7803 + file = skip_to (0, dest_dev);
7804 + addr = skip_to (0, file);
7805 +
7806 + /* Get the installation address. */
7807 + if (! safe_parse_maxint (&addr, &installaddr))
7808 + {
7809 + /* ADDR is not specified. */
7810 + installaddr = 0;
7811 + ptr = addr;
7812 + errnum = 0;
7813 + }
7814 + else
7815 + ptr = skip_to (0, addr);
7816 +
7817 +#ifndef NO_DECOMPRESSION
7818 + /* Do not decompress Stage 1 or Stage 2. */
7819 + no_decompression = 1;
7820 +#endif
7821 +
7822 + /* Read Stage 1. */
7823 + is_open = grub_open (stage1_file);
7824 + if (! is_open
7825 + || ! grub_read (stage1_buffer, SECTOR_SIZE) == SECTOR_SIZE)
7826 + goto fail;
7827 +
7828 + /* Read the old sector from DEST_DEV. */
7829 + if (! set_device (dest_dev)
7830 + || ! open_partition ()
7831 + || ! devread (0, 0, SECTOR_SIZE, old_sect))
7832 + goto fail;
7833 +
7834 + /* Store the information for the destination device. */
7835 + dest_drive = current_drive;
7836 + dest_partition = current_partition;
7837 + dest_geom = buf_geom;
7838 + dest_sector = part_start;
7839 +
7840 + /* Copy the possible DOS BPB, 59 bytes at byte offset 3. */
7841 + grub_memmove (stage1_buffer + BOOTSEC_BPB_OFFSET,
7842 + old_sect + BOOTSEC_BPB_OFFSET,
7843 + BOOTSEC_BPB_LENGTH);
7844 +
7845 + /* If for a hard disk, copy the possible MBR/extended part table. */
7846 + if (dest_drive & 0x80)
7847 + grub_memmove (stage1_buffer + STAGE1_WINDOWS_NT_MAGIC,
7848 + old_sect + STAGE1_WINDOWS_NT_MAGIC,
7849 + STAGE1_PARTEND - STAGE1_WINDOWS_NT_MAGIC);
7850 +
7851 + /* Check for the version and the signature of Stage 1. */
7852 + if (*((short *)(stage1_buffer + STAGE1_VER_MAJ_OFFS)) != COMPAT_VERSION
7853 + || (*((unsigned short *) (stage1_buffer + BOOTSEC_SIG_OFFSET))
7854 + != BOOTSEC_SIGNATURE))
7855 + {
7856 + errnum = ERR_BAD_VERSION;
7857 + goto fail;
7858 + }
7859 +
7860 + /* This below is not true any longer. But should we leave this alone? */
7861 +
7862 + /* If DEST_DRIVE is a floppy, Stage 2 must have the iteration probe
7863 + routine. */
7864 + if (! (dest_drive & 0x80)
7865 + && (*((unsigned char *) (stage1_buffer + BOOTSEC_PART_OFFSET)) == 0x80
7866 + || stage1_buffer[BOOTSEC_PART_OFFSET] == 0))
7867 + {
7868 + errnum = ERR_BAD_VERSION;
7869 + goto fail;
7870 + }
7871 +
7872 + grub_close ();
7873 +
7874 + /* Open Stage 2. */
7875 + is_open = grub_open (file);
7876 + if (! is_open)
7877 + goto fail;
7878 +
7879 + src_drive = current_drive;
7880 + src_partition = current_partition;
7881 + src_part_start = part_start;
7882 + src_geom = buf_geom;
7883 +
7884 + if (! new_drive)
7885 + new_drive = src_drive;
7886 + else if (src_drive != dest_drive)
7887 + grub_printf ("Warning: the option `d' was not used, but the Stage 1 will"
7888 + " be installed on a\ndifferent drive than the drive where"
7889 + " the Stage 2 resides.\n");
7890 +
7891 + /* Set the boot drive. */
7892 + *((unsigned char *) (stage1_buffer + STAGE1_BOOT_DRIVE)) = new_drive;
7893 +
7894 + /* Set the "force LBA" flag. */
7895 + *((unsigned char *) (stage1_buffer + STAGE1_FORCE_LBA)) = is_force_lba;
7896 +
7897 + /* If DEST_DRIVE is a hard disk, enable the workaround, which is
7898 + for buggy BIOSes which don't pass boot drive correctly. Instead,
7899 + they pass 0x00 or 0x01 even when booted from 0x80. */
7900 + if (dest_drive & BIOS_FLAG_FIXED_DISK)
7901 + /* Replace the jmp (2 bytes) with double nop's. */
7902 + *((unsigned short *) (stage1_buffer + STAGE1_BOOT_DRIVE_CHECK))
7903 + = 0x9090;
7904 +
7905 + /* Read the first sector of Stage 2. */
7906 + disk_read_hook = disk_read_savesect_func;
7907 + if (grub_read (stage2_first_buffer, SECTOR_SIZE) != SECTOR_SIZE)
7908 + goto fail;
7909 +
7910 + stage2_first_sector = saved_sector;
7911 +
7912 + /* Read the second sector of Stage 2. */
7913 + if (grub_read (stage2_second_buffer, SECTOR_SIZE) != SECTOR_SIZE)
7914 + goto fail;
7915 +
7916 + stage2_second_sector = saved_sector;
7917 +
7918 + /* Check for the version of Stage 2. */
7919 + if (*((short *) (stage2_second_buffer + STAGE2_VER_MAJ_OFFS))
7920 + != COMPAT_VERSION)
7921 + {
7922 + errnum = ERR_BAD_VERSION;
7923 + goto fail;
7924 + }
7925 +
7926 + /* Check for the Stage 2 id. */
7927 + if (stage2_second_buffer[STAGE2_STAGE2_ID] != STAGE2_ID_STAGE2)
7928 + is_stage1_5 = 1;
7929 +
7930 + /* If INSTALLADDR is not specified explicitly in the command-line,
7931 + determine it by the Stage 2 id. */
7932 + if (! installaddr)
7933 + {
7934 + if (! is_stage1_5)
7935 + /* Stage 2. */
7936 + installaddr = 0x8000;
7937 + else
7938 + /* Stage 1.5. */
7939 + installaddr = 0x2000;
7940 + }
7941 +
7942 + *((unsigned long *) (stage1_buffer + STAGE1_STAGE2_SECTOR))
7943 + = stage2_first_sector;
7944 + *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_ADDRESS))
7945 + = installaddr;
7946 + *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_SEGMENT))
7947 + = installaddr >> 4;
7948 +
7949 + i = (int) stage2_first_buffer + SECTOR_SIZE - 4;
7950 + while (*((unsigned long *) i))
7951 + {
7952 + if (i < (int) stage2_first_buffer
7953 + || (*((int *) (i - 4)) & 0x80000000)
7954 + || *((unsigned short *) i) >= 0xA00
7955 + || *((short *) (i + 2)) == 0)
7956 + {
7957 + errnum = ERR_BAD_VERSION;
7958 + goto fail;
7959 + }
7960 +
7961 + *((int *) i) = 0;
7962 + *((int *) (i - 4)) = 0;
7963 + i -= 8;
7964 + }
7965 +
7966 + installlist = (int) stage2_first_buffer + SECTOR_SIZE + 4;
7967 + installaddr += SECTOR_SIZE;
7968 +
7969 + /* Read the whole of Stage2 except for the first sector. */
7970 + grub_seek (SECTOR_SIZE);
7971 +
7972 + disk_read_hook = disk_read_blocklist_func;
7973 + if (! grub_read (dummy, -1))
7974 + goto fail;
7975 +
7976 + disk_read_hook = 0;
7977 +
7978 + /* Find a string for the configuration filename. */
7979 + config_file_location = stage2_second_buffer + STAGE2_VER_STR_OFFS;
7980 + while (*(config_file_location++))
7981 + ;
7982 +
7983 + /* Set the "force LBA" flag for Stage2. */
7984 + *((unsigned char *) (stage2_second_buffer + STAGE2_FORCE_LBA))
7985 + = is_force_lba;
7986 +
7987 + if (*ptr == 'p')
7988 + {
7989 + *((long *) (stage2_second_buffer + STAGE2_INSTALLPART))
7990 + = src_partition;
7991 + if (is_stage1_5)
7992 + {
7993 + /* Reset the device information in FILE if it is a Stage 1.5. */
7994 + unsigned long device = 0xFFFFFFFF;
7995 +
7996 + grub_memmove (config_file_location, (char *) &device,
7997 + sizeof (device));
7998 + }
7999 +
8000 + ptr = skip_to (0, ptr);
8001 + }
8002 +
8003 + if (*ptr)
8004 + {
8005 + grub_strcpy (config_filename, ptr);
8006 + nul_terminate (config_filename);
8007 +
8008 + if (! is_stage1_5)
8009 + /* If it is a Stage 2, just copy PTR to CONFIG_FILE_LOCATION. */
8010 + grub_strcpy (config_file_location, ptr);
8011 + else
8012 + {
8013 + char *real_config;
8014 + unsigned long device;
8015 +
8016 + /* Translate the external device syntax to the internal device
8017 + syntax. */
8018 + if (! (real_config = set_device (ptr)))
8019 + {
8020 + /* The Stage 2 PTR does not contain the device name, so
8021 + use the root device instead. */
8022 + errnum = ERR_NONE;
8023 + current_drive = saved_drive;
8024 + current_partition = saved_partition;
8025 + real_config = ptr;
8026 + }
8027 +
8028 + if (current_drive == src_drive)
8029 + {
8030 + /* If the drive where the Stage 2 resides is the same as
8031 + the one where the Stage 1.5 resides, do not embed the
8032 + drive number. */
8033 + current_drive = GRUB_INVALID_DRIVE;
8034 + }
8035 +
8036 + device = (current_drive << 24) | current_partition;
8037 + grub_memmove (config_file_location, (char *) &device,
8038 + sizeof (device));
8039 + grub_strcpy (config_file_location + sizeof (device),
8040 + real_config);
8041 + }
8042 +
8043 + /* If a Stage 1.5 is used, then we need to modify the Stage2. */
8044 + if (is_stage1_5)
8045 + {
8046 + char *real_config_filename = skip_to (0, ptr);
8047 +
8048 + is_open = grub_open (config_filename);
8049 + if (! is_open)
8050 + goto fail;
8051 +
8052 + /* Skip the first sector. */
8053 + grub_seek (SECTOR_SIZE);
8054 +
8055 + disk_read_hook = disk_read_savesect_func;
8056 + if (grub_read (stage2_buffer, SECTOR_SIZE) != SECTOR_SIZE)
8057 + goto fail;
8058 +
8059 + disk_read_hook = 0;
8060 + grub_close ();
8061 + is_open = 0;
8062 +
8063 + /* Sanity check. */
8064 + if (*(stage2_buffer + STAGE2_STAGE2_ID) != STAGE2_ID_STAGE2)
8065 + {
8066 + errnum = ERR_BAD_VERSION;
8067 + goto fail;
8068 + }
8069 +
8070 + /* Set the "force LBA" flag for Stage2. */
8071 + *(stage2_buffer + STAGE2_FORCE_LBA) = is_force_lba;
8072 +
8073 + /* If REAL_CONFIG_FILENAME is specified, copy it to the Stage2. */
8074 + if (*real_config_filename)
8075 + {
8076 + /* Specified */
8077 + char *location;
8078 +
8079 + /* Find a string for the configuration filename. */
8080 + location = stage2_buffer + STAGE2_VER_STR_OFFS;
8081 + while (*(location++))
8082 + ;
8083 +
8084 + /* Copy the name. */
8085 + grub_strcpy (location, real_config_filename);
8086 + }
8087 +
8088 + /* Write it to the disk. */
8089 + buf_track = -1;
8090 +
8091 +#ifdef GRUB_UTIL
8092 + /* In the grub shell, access the Stage 2 via the OS filesystem
8093 + service, if possible. */
8094 + if (stage2_os_file)
8095 + {
8096 + FILE *fp;
8097 +
8098 + fp = fopen (stage2_os_file, "r+");
8099 + if (! fp)
8100 + {
8101 + errnum = ERR_FILE_NOT_FOUND;
8102 + goto fail;
8103 + }
8104 +
8105 + if (fseek (fp, SECTOR_SIZE, SEEK_SET) != 0)
8106 + {
8107 + fclose (fp);
8108 + errnum = ERR_BAD_VERSION;
8109 + goto fail;
8110 + }
8111 +
8112 + if (fwrite (stage2_buffer, 1, SECTOR_SIZE, fp)
8113 + != SECTOR_SIZE)
8114 + {
8115 + fclose (fp);
8116 + errnum = ERR_WRITE;
8117 + goto fail;
8118 + }
8119 +
8120 + fclose (fp);
8121 + }
8122 + else
8123 +#endif /* GRUB_UTIL */
8124 + {
8125 + if (! devwrite (saved_sector - part_start, 1, stage2_buffer))
8126 + goto fail;
8127 + }
8128 + }
8129 + }
8130 +
8131 + /* Clear the cache. */
8132 + buf_track = -1;
8133 +
8134 + /* Write the modified sectors of Stage2 to the disk. */
8135 +#ifdef GRUB_UTIL
8136 + if (! is_stage1_5 && stage2_os_file)
8137 + {
8138 + FILE *fp;
8139 +
8140 + fp = fopen (stage2_os_file, "r+");
8141 + if (! fp)
8142 + {
8143 + errnum = ERR_FILE_NOT_FOUND;
8144 + goto fail;
8145 + }
8146 +
8147 + if (fwrite (stage2_first_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE)
8148 + {
8149 + fclose (fp);
8150 + errnum = ERR_WRITE;
8151 + goto fail;
8152 + }
8153 +
8154 + if (fwrite (stage2_second_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE)
8155 + {
8156 + fclose (fp);
8157 + errnum = ERR_WRITE;
8158 + goto fail;
8159 + }
8160 +
8161 + fclose (fp);
8162 + }
8163 + else
8164 +#endif /* GRUB_UTIL */
8165 + {
8166 + /* The first. */
8167 + current_drive = src_drive;
8168 + current_partition = src_partition;
8169 +
8170 + if (! open_partition ())
8171 + goto fail;
8172 +
8173 + if (! devwrite (stage2_first_sector - src_part_start, 1,
8174 + stage2_first_buffer))
8175 + goto fail;
8176 +
8177 + if (! devwrite (stage2_second_sector - src_part_start, 1,
8178 + stage2_second_buffer))
8179 + goto fail;
8180 + }
8181 +
8182 + /* Write the modified sector of Stage 1 to the disk. */
8183 + current_drive = dest_drive;
8184 + current_partition = dest_partition;
8185 + if (! open_partition ())
8186 + goto fail;
8187 +
8188 + devwrite (0, 1, stage1_buffer);
8189 +
8190 + fail:
8191 + if (is_open)
8192 + grub_close ();
8193 +
8194 + disk_read_hook = 0;
8195 +
8196 +#ifndef NO_DECOMPRESSION
8197 + no_decompression = 0;
8198 +#endif
8199 +
8200 + return errnum;
8201 +}
8202 +
8203 +static struct builtin builtin_install =
8204 +{
8205 + "install",
8206 + install_func,
8207 + BUILTIN_CMDLINE,
8208 + "install [--stage2=STAGE2_FILE] [--force-lba] STAGE1 [d] DEVICE STAGE2 [ADDR] [p] [CONFIG_FILE] [REAL_CONFIG_FILE]",
8209 + "Install STAGE1 on DEVICE, and install a blocklist for loading STAGE2"
8210 + " as a Stage 2. If the option `d' is present, the Stage 1 will always"
8211 + " look for the disk where STAGE2 was installed, rather than using"
8212 + " the booting drive. The Stage 2 will be loaded at address ADDR, which"
8213 + " will be determined automatically if you don't specify it. If"
8214 + " the option `p' or CONFIG_FILE is present, then the first block"
8215 + " of Stage 2 is patched with new values of the partition and name"
8216 + " of the configuration file used by the true Stage 2 (for a Stage 1.5,"
8217 + " this is the name of the true Stage 2) at boot time. If STAGE2 is a Stage"
8218 + " 1.5 and REAL_CONFIG_FILE is present, then the Stage 2 CONFIG_FILE is"
8219 + " patched with the configuration filename REAL_CONFIG_FILE."
8220 + " If the option `--force-lba' is specified, disable some sanity checks"
8221 + " for LBA mode. If the option `--stage2' is specified, rewrite the Stage"
8222 + " 2 via your OS's filesystem instead of the raw device."
8223 +};
8224 +
8225 +\f
8226 +/* ioprobe */
8227 +static int
8228 +ioprobe_func (char *arg, int flags)
8229 +{
8230 +#ifdef GRUB_UTIL
8231 +
8232 + errnum = ERR_UNRECOGNIZED;
8233 + return 1;
8234 +
8235 +#else /* ! GRUB_UTIL */
8236 +
8237 + unsigned short *port;
8238 +
8239 + /* Get the drive number. */
8240 + set_device (arg);
8241 + if (errnum)
8242 + return 1;
8243 +
8244 + /* Clean out IO_MAP. */
8245 + grub_memset ((char *) io_map, 0, IO_MAP_SIZE * sizeof (unsigned short));
8246 +
8247 + /* Track the int13 handler. */
8248 + track_int13 (current_drive);
8249 +
8250 + /* Print out the result. */
8251 + for (port = io_map; *port != 0; port++)
8252 + grub_printf (" 0x%x", (unsigned int) *port);
8253 +
8254 + return 0;
8255 +
8256 +#endif /* ! GRUB_UTIL */
8257 +}
8258 +
8259 +static struct builtin builtin_ioprobe =
8260 +{
8261 + "ioprobe",
8262 + ioprobe_func,
8263 + BUILTIN_CMDLINE,
8264 + "ioprobe DRIVE",
8265 + "Probe I/O ports used for the drive DRIVE."
8266 +};
8267 +
8268 +\f
8269 +/* kernel */
8270 +static int
8271 +kernel_func (char *arg, int flags)
8272 +{
8273 + int len;
8274 + kernel_t suggested_type = KERNEL_TYPE_NONE;
8275 + unsigned long load_flags = 0;
8276 +
8277 +#ifndef AUTO_LINUX_MEM_OPT
8278 + load_flags |= KERNEL_LOAD_NO_MEM_OPTION;
8279 +#endif
8280 +
8281 + /* Deal with GNU-style long options. */
8282 + while (1)
8283 + {
8284 + /* If the option `--type=TYPE' is specified, convert the string to
8285 + a kernel type. */
8286 + if (grub_memcmp (arg, "--type=", 7) == 0)
8287 + {
8288 + arg += 7;
8289 +
8290 + if (grub_memcmp (arg, "netbsd", 6) == 0)
8291 + suggested_type = KERNEL_TYPE_NETBSD;
8292 + else if (grub_memcmp (arg, "freebsd", 7) == 0)
8293 + suggested_type = KERNEL_TYPE_FREEBSD;
8294 + else if (grub_memcmp (arg, "openbsd", 7) == 0)
8295 + /* XXX: For now, OpenBSD is identical to NetBSD, from GRUB's
8296 + point of view. */
8297 + suggested_type = KERNEL_TYPE_NETBSD;
8298 + else if (grub_memcmp (arg, "linux", 5) == 0)
8299 + suggested_type = KERNEL_TYPE_LINUX;
8300 + else if (grub_memcmp (arg, "biglinux", 8) == 0)
8301 + suggested_type = KERNEL_TYPE_BIG_LINUX;
8302 + else if (grub_memcmp (arg, "multiboot", 9) == 0)
8303 + suggested_type = KERNEL_TYPE_MULTIBOOT;
8304 + else
8305 + {
8306 + errnum = ERR_BAD_ARGUMENT;
8307 + return 1;
8308 + }
8309 + }
8310 + /* If the `--no-mem-option' is specified, don't pass a Linux's mem
8311 + option automatically. If the kernel is another type, this flag
8312 + has no effect. */
8313 + else if (grub_memcmp (arg, "--no-mem-option", 15) == 0)
8314 + load_flags |= KERNEL_LOAD_NO_MEM_OPTION;
8315 + else
8316 + break;
8317 +
8318 + /* Try the next. */
8319 + arg = skip_to (0, arg);
8320 + }
8321 +
8322 + len = grub_strlen (arg);
8323 +
8324 + /* Reset MB_CMDLINE. */
8325 + mb_cmdline = (char *) MB_CMDLINE_BUF;
8326 + if (len + 1 > MB_CMDLINE_BUFLEN)
8327 + {
8328 + errnum = ERR_WONT_FIT;
8329 + return 1;
8330 + }
8331 +
8332 + /* Copy the command-line to MB_CMDLINE. */
8333 + grub_memmove (mb_cmdline, arg, len + 1);
8334 + kernel_type = load_image (arg, mb_cmdline, suggested_type, load_flags);
8335 + if (kernel_type == KERNEL_TYPE_NONE)
8336 + return 1;
8337 +
8338 + mb_cmdline += len + 1;
8339 + return 0;
8340 +}
8341 +
8342 +static struct builtin builtin_kernel =
8343 +{
8344 + "kernel",
8345 + kernel_func,
8346 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
8347 + "kernel [--no-mem-option] [--type=TYPE] FILE [ARG ...]",
8348 + "Attempt to load the primary boot image from FILE. The rest of the"
8349 + " line is passed verbatim as the \"kernel command line\". Any modules"
8350 + " must be reloaded after using this command. The option --type is used"
8351 + " to suggest what type of kernel to be loaded. TYPE must be either of"
8352 + " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and"
8353 + " \"multiboot\". The option --no-mem-option tells GRUB not to pass a"
8354 + " Linux's mem option automatically."
8355 +};
8356 +
8357 +\f
8358 +/* lock */
8359 +static int
8360 +lock_func (char *arg, int flags)
8361 +{
8362 + if (! auth && password)
8363 + {
8364 + errnum = ERR_PRIVILEGED;
8365 + return 1;
8366 + }
8367 +
8368 + return 0;
8369 +}
8370 +
8371 +static struct builtin builtin_lock =
8372 +{
8373 + "lock",
8374 + lock_func,
8375 + BUILTIN_CMDLINE,
8376 + "lock",
8377 + "Break a command execution unless the user is authenticated."
8378 +};
8379 +
8380 +\f
8381 +/* makeactive */
8382 +static int
8383 +makeactive_func (char *arg, int flags)
8384 +{
8385 + if (! make_saved_active ())
8386 + return 1;
8387 +
8388 + return 0;
8389 +}
8390 +
8391 +static struct builtin builtin_makeactive =
8392 +{
8393 + "makeactive",
8394 + makeactive_func,
8395 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
8396 + "makeactive",
8397 + "Set the active partition on the root disk to GRUB's root device."
8398 + " This command is limited to _primary_ PC partitions on a hard disk."
8399 +};
8400 +
8401 +\f
8402 +/* map */
8403 +/* Map FROM_DRIVE to TO_DRIVE. */
8404 +static int
8405 +map_func (char *arg, int flags)
8406 +{
8407 + char *to_drive;
8408 + char *from_drive;
8409 + unsigned long to, from;
8410 + int i;
8411 +
8412 + to_drive = arg;
8413 + from_drive = skip_to (0, arg);
8414 +
8415 + /* Get the drive number for TO_DRIVE. */
8416 + set_device (to_drive);
8417 + if (errnum)
8418 + return 1;
8419 + to = current_drive;
8420 +
8421 + /* Get the drive number for FROM_DRIVE. */
8422 + set_device (from_drive);
8423 + if (errnum)
8424 + return 1;
8425 + from = current_drive;
8426 +
8427 + /* Search for an empty slot in BIOS_DRIVE_MAP. */
8428 + for (i = 0; i < DRIVE_MAP_SIZE; i++)
8429 + {
8430 + /* Perhaps the user wants to override the map. */
8431 + if ((bios_drive_map[i] & 0xff) == from)
8432 + break;
8433 +
8434 + if (! bios_drive_map[i])
8435 + break;
8436 + }
8437 +
8438 + if (i == DRIVE_MAP_SIZE)
8439 + {
8440 + errnum = ERR_WONT_FIT;
8441 + return 1;
8442 + }
8443 +
8444 + if (to == from)
8445 + /* If TO is equal to FROM, delete the entry. */
8446 + grub_memmove ((char *) &bios_drive_map[i], (char *) &bios_drive_map[i + 1],
8447 + sizeof (unsigned short) * (DRIVE_MAP_SIZE - i));
8448 + else
8449 + bios_drive_map[i] = from | (to << 8);
8450 +
8451 + return 0;
8452 +}
8453 +
8454 +static struct builtin builtin_map =
8455 +{
8456 + "map",
8457 + map_func,
8458 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
8459 + "map TO_DRIVE FROM_DRIVE",
8460 + "Map the drive FROM_DRIVE to the drive TO_DRIVE. This is necessary"
8461 + " when you chain-load some operating systems, such as DOS, if such an"
8462 + " OS resides at a non-first drive."
8463 +};
8464 +
8465 +\f
8466 +#ifdef USE_MD5_PASSWORDS
8467 +/* md5crypt */
8468 +static int
8469 +md5crypt_func (char *arg, int flags)
8470 +{
8471 + char crypted[36];
8472 + char key[32];
8473 + unsigned int seed;
8474 + int i;
8475 + const char *const seedchars =
8476 + "./0123456789ABCDEFGHIJKLMNOPQRST"
8477 + "UVWXYZabcdefghijklmnopqrstuvwxyz";
8478 +
8479 + /* First create a salt. */
8480 +
8481 + /* The magical prefix. */
8482 + grub_memset (crypted, 0, sizeof (crypted));
8483 + grub_memmove (crypted, "$1$", 3);
8484 +
8485 + /* Create the length of a salt. */
8486 + seed = currticks ();
8487 +
8488 + /* Generate a salt. */
8489 + for (i = 0; i < 8 && seed; i++)
8490 + {
8491 + /* FIXME: This should be more random. */
8492 + crypted[3 + i] = seedchars[seed & 0x3f];
8493 + seed >>= 6;
8494 + }
8495 +
8496 + /* A salt must be terminated with `$', if it is less than 8 chars. */
8497 + crypted[3 + i] = '$';
8498 +
8499 +#ifdef DEBUG_MD5CRYPT
8500 + grub_printf ("salt = %s\n", crypted);
8501 +#endif
8502 +
8503 + /* Get a password. */
8504 + grub_memset (key, 0, sizeof (key));
8505 + get_cmdline ("Password: ", key, sizeof (key) - 1, '*', 0);
8506 +
8507 + /* Crypt the key. */
8508 + make_md5_password (key, crypted);
8509 +
8510 + grub_printf ("Encrypted: %s\n", crypted);
8511 + return 0;
8512 +}
8513 +
8514 +static struct builtin builtin_md5crypt =
8515 +{
8516 + "md5crypt",
8517 + md5crypt_func,
8518 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
8519 + "md5crypt",
8520 + "Generate a password in MD5 format."
8521 +};
8522 +#endif /* USE_MD5_PASSWORDS */
8523 +
8524 +\f
8525 +/* module */
8526 +static int
8527 +module_func (char *arg, int flags)
8528 +{
8529 + int len = grub_strlen (arg);
8530 +
8531 + switch (kernel_type)
8532 + {
8533 + case KERNEL_TYPE_MULTIBOOT:
8534 + if (mb_cmdline + len + 1 > (char *) MB_CMDLINE_BUF + MB_CMDLINE_BUFLEN)
8535 + {
8536 + errnum = ERR_WONT_FIT;
8537 + return 1;
8538 + }
8539 + grub_memmove (mb_cmdline, arg, len + 1);
8540 + if (! load_module (arg, mb_cmdline))
8541 + return 1;
8542 + mb_cmdline += len + 1;
8543 + break;
8544 +
8545 + case KERNEL_TYPE_LINUX:
8546 + case KERNEL_TYPE_BIG_LINUX:
8547 + if (! load_initrd (arg))
8548 + return 1;
8549 + break;
8550 +
8551 + default:
8552 + errnum = ERR_NEED_MB_KERNEL;
8553 + return 1;
8554 + }
8555 +
8556 + return 0;
8557 +}
8558 +
8559 +static struct builtin builtin_module =
8560 +{
8561 + "module",
8562 + module_func,
8563 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
8564 + "module FILE [ARG ...]",
8565 + "Load a boot module FILE for a Multiboot format boot image (no"
8566 + " interpretation of the file contents is made, so users of this"
8567 + " command must know what the kernel in question expects). The"
8568 + " rest of the line is passed as the \"module command line\", like"
8569 + " the `kernel' command."
8570 +};
8571 +
8572 +\f
8573 +/* modulenounzip */
8574 +static int
8575 +modulenounzip_func (char *arg, int flags)
8576 +{
8577 + int ret;
8578 +
8579 +#ifndef NO_DECOMPRESSION
8580 + no_decompression = 1;
8581 +#endif
8582 +
8583 + ret = module_func (arg, flags);
8584 +
8585 +#ifndef NO_DECOMPRESSION
8586 + no_decompression = 0;
8587 +#endif
8588 +
8589 + return ret;
8590 +}
8591 +
8592 +static struct builtin builtin_modulenounzip =
8593 +{
8594 + "modulenounzip",
8595 + modulenounzip_func,
8596 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
8597 + "modulenounzip FILE [ARG ...]",
8598 + "The same as `module', except that automatic decompression is"
8599 + " disabled."
8600 +};
8601 +
8602 +\f
8603 +/* pager [on|off] */
8604 +static int
8605 +pager_func (char *arg, int flags)
8606 +{
8607 + /* If ARG is empty, toggle the flag. */
8608 + if (! *arg)
8609 + use_pager = ! use_pager;
8610 + else if (grub_memcmp (arg, "on", 2) == 0)
8611 + use_pager = 1;
8612 + else if (grub_memcmp (arg, "off", 3) == 0)
8613 + use_pager = 0;
8614 + else
8615 + {
8616 + errnum = ERR_BAD_ARGUMENT;
8617 + return 1;
8618 + }
8619 +
8620 + grub_printf (" Internal pager is now %s\n", use_pager ? "on" : "off");
8621 + return 0;
8622 +}
8623 +
8624 +static struct builtin builtin_pager =
8625 +{
8626 + "pager",
8627 + pager_func,
8628 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
8629 + "pager [FLAG]",
8630 + "Toggle pager mode with no argument. If FLAG is given and its value"
8631 + " is `on', turn on the mode. If FLAG is `off', turn off the mode."
8632 +};
8633 +
8634 +\f
8635 +/* partnew PART TYPE START LEN */
8636 +static int
8637 +partnew_func (char *arg, int flags)
8638 +{
8639 + int new_type, new_start, new_len;
8640 + int start_cl, start_ch, start_dh;
8641 + int end_cl, end_ch, end_dh;
8642 + int entry;
8643 + char mbr[512];
8644 +
8645 + /* Convert a LBA address to a CHS address in the INT 13 format. */
8646 + auto void lba_to_chs (int lba, int *cl, int *ch, int *dh);
8647 + void lba_to_chs (int lba, int *cl, int *ch, int *dh)
8648 + {
8649 + int cylinder, head, sector;
8650 +
8651 + sector = lba % buf_geom.sectors + 1;
8652 + head = (lba / buf_geom.sectors) % buf_geom.heads;
8653 + cylinder = lba / (buf_geom.sectors * buf_geom.heads);
8654 +
8655 + if (cylinder >= buf_geom.cylinders)
8656 + cylinder = buf_geom.cylinders - 1;
8657 +
8658 + *cl = sector | ((cylinder & 0x300) >> 2);
8659 + *ch = cylinder & 0xFF;
8660 + *dh = head;
8661 + }
8662 +
8663 + /* Get the drive and the partition. */
8664 + if (! set_device (arg))
8665 + return 1;
8666 +
8667 + /* The drive must be a hard disk. */
8668 + if (! (current_drive & 0x80))
8669 + {
8670 + errnum = ERR_BAD_ARGUMENT;
8671 + return 1;
8672 + }
8673 +
8674 + /* The partition must a primary partition. */
8675 + if ((current_partition >> 16) > 3
8676 + || (current_partition & 0xFFFF) != 0xFFFF)
8677 + {
8678 + errnum = ERR_BAD_ARGUMENT;
8679 + return 1;
8680 + }
8681 +
8682 + entry = current_partition >> 16;
8683 +
8684 + /* Get the new partition type. */
8685 + arg = skip_to (0, arg);
8686 + if (! safe_parse_maxint (&arg, &new_type))
8687 + return 1;
8688 +
8689 + /* The partition type is unsigned char. */
8690 + if (new_type > 0xFF)
8691 + {
8692 + errnum = ERR_BAD_ARGUMENT;
8693 + return 1;
8694 + }
8695 +
8696 + /* Get the new partition start. */
8697 + arg = skip_to (0, arg);
8698 + if (! safe_parse_maxint (&arg, &new_start))
8699 + return 1;
8700 +
8701 + /* Get the new partition length. */
8702 + arg = skip_to (0, arg);
8703 + if (! safe_parse_maxint (&arg, &new_len))
8704 + return 1;
8705 +
8706 + /* Read the MBR. */
8707 + if (! rawread (current_drive, 0, 0, SECTOR_SIZE, mbr))
8708 + return 1;
8709 +
8710 + /* Check if the new partition will fit in the disk. */
8711 + if (new_start + new_len > buf_geom.total_sectors)
8712 + {
8713 + errnum = ERR_GEOM;
8714 + return 1;
8715 + }
8716 +
8717 + /* Store the partition information in the MBR. */
8718 + lba_to_chs (new_start, &start_cl, &start_ch, &start_dh);
8719 + lba_to_chs (new_start + new_len - 1, &end_cl, &end_ch, &end_dh);
8720 +
8721 + PC_SLICE_FLAG (mbr, entry) = 0;
8722 + PC_SLICE_HEAD (mbr, entry) = start_dh;
8723 + PC_SLICE_SEC (mbr, entry) = start_cl;
8724 + PC_SLICE_CYL (mbr, entry) = start_ch;
8725 + PC_SLICE_TYPE (mbr, entry) = new_type;
8726 + PC_SLICE_EHEAD (mbr, entry) = end_dh;
8727 + PC_SLICE_ESEC (mbr, entry) = end_cl;
8728 + PC_SLICE_ECYL (mbr, entry) = end_ch;
8729 + PC_SLICE_START (mbr, entry) = new_start;
8730 + PC_SLICE_LENGTH (mbr, entry) = new_len;
8731 +
8732 + /* Make sure that the MBR has a valid signature. */
8733 + PC_MBR_SIG (mbr) = PC_MBR_SIGNATURE;
8734 +
8735 + /* Write back the MBR to the disk. */
8736 + buf_track = -1;
8737 + if (! rawwrite (current_drive, 0, mbr))
8738 + return 1;
8739 +
8740 + return 0;
8741 +}
8742 +
8743 +static struct builtin builtin_partnew =
8744 +{
8745 + "partnew",
8746 + partnew_func,
8747 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
8748 + "partnew PART TYPE START LEN",
8749 + "Create a primary partition at the starting address START with the"
8750 + " length LEN, with the type TYPE. START and LEN are in sector units."
8751 +};
8752 +
8753 +\f
8754 +/* parttype PART TYPE */
8755 +static int
8756 +parttype_func (char *arg, int flags)
8757 +{
8758 + int new_type;
8759 + unsigned long part = 0xFFFFFF;
8760 + unsigned long start, len, offset, ext_offset;
8761 + int entry, type;
8762 + char mbr[512];
8763 +
8764 + /* Get the drive and the partition. */
8765 + if (! set_device (arg))
8766 + return 1;
8767 +
8768 + /* The drive must be a hard disk. */
8769 + if (! (current_drive & 0x80))
8770 + {
8771 + errnum = ERR_BAD_ARGUMENT;
8772 + return 1;
8773 + }
8774 +
8775 + /* The partition must be a PC slice. */
8776 + if ((current_partition >> 16) == 0xFF
8777 + || (current_partition & 0xFFFF) != 0xFFFF)
8778 + {
8779 + errnum = ERR_BAD_ARGUMENT;
8780 + return 1;
8781 + }
8782 +
8783 + /* Get the new partition type. */
8784 + arg = skip_to (0, arg);
8785 + if (! safe_parse_maxint (&arg, &new_type))
8786 + return 1;
8787 +
8788 + /* The partition type is unsigned char. */
8789 + if (new_type > 0xFF)
8790 + {
8791 + errnum = ERR_BAD_ARGUMENT;
8792 + return 1;
8793 + }
8794 +
8795 + /* Look for the partition. */
8796 + while (next_partition (current_drive, 0xFFFFFF, &part, &type,
8797 + &start, &len, &offset, &entry,
8798 + &ext_offset, mbr))
8799 + {
8800 + if (part == current_partition)
8801 + {
8802 + /* Found. */
8803 +
8804 + /* Set the type to NEW_TYPE. */
8805 + PC_SLICE_TYPE (mbr, entry) = new_type;
8806 +
8807 + /* Write back the MBR to the disk. */
8808 + buf_track = -1;
8809 + if (! rawwrite (current_drive, offset, mbr))
8810 + return 1;
8811 +
8812 + /* Succeed. */
8813 + return 0;
8814 + }
8815 + }
8816 +
8817 + /* The partition was not found. ERRNUM was set by next_partition. */
8818 + return 1;
8819 +}
8820 +
8821 +static struct builtin builtin_parttype =
8822 +{
8823 + "parttype",
8824 + parttype_func,
8825 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
8826 + "parttype PART TYPE",
8827 + "Change the type of the partition PART to TYPE."
8828 +};
8829 +
8830 +\f
8831 +/* password */
8832 +static int
8833 +password_func (char *arg, int flags)
8834 +{
8835 + int len;
8836 + password_t type = PASSWORD_PLAIN;
8837 +
8838 +#ifdef USE_MD5_PASSWORDS
8839 + if (grub_memcmp (arg, "--md5", 5) == 0)
8840 + {
8841 + type = PASSWORD_MD5;
8842 + arg = skip_to (0, arg);
8843 + }
8844 +#endif
8845 + if (grub_memcmp (arg, "--", 2) == 0)
8846 + {
8847 + type = PASSWORD_UNSUPPORTED;
8848 + arg = skip_to (0, arg);
8849 + }
8850 +
8851 + if ((flags & (BUILTIN_CMDLINE | BUILTIN_SCRIPT)) != 0)
8852 + {
8853 + /* Do password check! */
8854 + char entered[32];
8855 +
8856 + /* Wipe out any previously entered password */
8857 + entered[0] = 0;
8858 + get_cmdline ("Password: ", entered, 31, '*', 0);
8859 +
8860 + nul_terminate (arg);
8861 + if (check_password (entered, arg, type) != 0)
8862 + {
8863 + errnum = ERR_PRIVILEGED;
8864 + return 1;
8865 + }
8866 + }
8867 + else
8868 + {
8869 + len = grub_strlen (arg);
8870 +
8871 + /* PASSWORD NUL NUL ... */
8872 + if (len + 2 > PASSWORD_BUFLEN)
8873 + {
8874 + errnum = ERR_WONT_FIT;
8875 + return 1;
8876 + }
8877 +
8878 + /* Copy the password and clear the rest of the buffer. */
8879 + password = (char *) PASSWORD_BUF;
8880 + grub_memmove (password, arg, len);
8881 + grub_memset (password + len, 0, PASSWORD_BUFLEN - len);
8882 + password_type = type;
8883 + }
8884 + return 0;
8885 +}
8886 +
8887 +static struct builtin builtin_password =
8888 +{
8889 + "password",
8890 + password_func,
8891 + BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_NO_ECHO,
8892 + "password [--md5] PASSWD [FILE]",
8893 + "If used in the first section of a menu file, disable all"
8894 + " interactive editing control (menu entry editor and"
8895 + " command line). If the password PASSWD is entered, it loads the"
8896 + " FILE as a new config file and restarts the GRUB Stage 2. If you"
8897 + " omit the argument FILE, then GRUB just unlocks privileged"
8898 + " instructions. You can also use it in the script section, in"
8899 + " which case it will ask for the password, before continueing."
8900 + " The option --md5 tells GRUB that PASSWD is encrypted with"
8901 + " md5crypt."
8902 +};
8903 +
8904 +\f
8905 +/* pause */
8906 +static int
8907 +pause_func (char *arg, int flags)
8908 +{
8909 + printf("%s\n", arg);
8910 +
8911 + /* If ESC is returned, then abort this entry. */
8912 + if (ASCII_CHAR (getkey ()) == 27)
8913 + return 1;
8914 +
8915 + return 0;
8916 +}
8917 +
8918 +static struct builtin builtin_pause =
8919 +{
8920 + "pause",
8921 + pause_func,
8922 + BUILTIN_CMDLINE | BUILTIN_NO_ECHO,
8923 + "pause [MESSAGE ...]",
8924 + "Print MESSAGE, then wait until a key is pressed."
8925 +};
8926 +
8927 +\f
8928 +#ifdef GRUB_UTIL
8929 +/* quit */
8930 +static int
8931 +quit_func (char *arg, int flags)
8932 +{
8933 + stop ();
8934 +
8935 + /* Never reach here. */
8936 + return 0;
8937 +}
8938 +
8939 +static struct builtin builtin_quit =
8940 +{
8941 + "quit",
8942 + quit_func,
8943 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
8944 + "quit",
8945 + "Exit from the GRUB shell."
8946 +};
8947 +#endif /* GRUB_UTIL */
8948 +
8949 +\f
8950 +#ifdef SUPPORT_NETBOOT
8951 +/* rarp */
8952 +static int
8953 +rarp_func (char *arg, int flags)
8954 +{
8955 + if (! rarp ())
8956 + {
8957 + if (errnum == ERR_NONE)
8958 + errnum = ERR_DEV_VALUES;
8959 +
8960 + return 1;
8961 + }
8962 +
8963 + /* Notify the configuration. */
8964 + print_network_configuration ();
8965 + return 0;
8966 +}
8967 +
8968 +static struct builtin builtin_rarp =
8969 +{
8970 + "rarp",
8971 + rarp_func,
8972 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
8973 + "rarp",
8974 + "Initialize a network device via RARP."
8975 +};
8976 +#endif /* SUPPORT_NETBOOT */
8977 +
8978 +\f
8979 +static int
8980 +read_func (char *arg, int flags)
8981 +{
8982 + int addr;
8983 +
8984 + if (! safe_parse_maxint (&arg, &addr))
8985 + return 1;
8986 +
8987 + grub_printf ("Address 0x%x: Value 0x%x\n",
8988 + addr, *((unsigned *) RAW_ADDR (addr)));
8989 + return 0;
8990 +}
8991 +
8992 +static struct builtin builtin_read =
8993 +{
8994 + "read",
8995 + read_func,
8996 + BUILTIN_CMDLINE,
8997 + "read ADDR",
8998 + "Read a 32-bit value from memory at address ADDR and"
8999 + " display it in hex format."
9000 +};
9001 +
9002 +\f
9003 +/* reboot */
9004 +static int
9005 +reboot_func (char *arg, int flags)
9006 +{
9007 + grub_reboot ();
9008 +
9009 + /* Never reach here. */
9010 + return 1;
9011 +}
9012 +
9013 +static struct builtin builtin_reboot =
9014 +{
9015 + "reboot",
9016 + reboot_func,
9017 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
9018 + "reboot",
9019 + "Reboot your system."
9020 +};
9021 +
9022 +\f
9023 +/* Print the root device information. */
9024 +static void
9025 +print_root_device (void)
9026 +{
9027 + if (saved_drive == NETWORK_DRIVE)
9028 + {
9029 + /* Network drive. */
9030 + grub_printf (" (nd):");
9031 + }
9032 + else if (saved_drive & 0x80)
9033 + {
9034 + /* Hard disk drive. */
9035 + grub_printf (" (hd%d", saved_drive - 0x80);
9036 +
9037 + if ((saved_partition & 0xFF0000) != 0xFF0000)
9038 + grub_printf (",%d", saved_partition >> 16);
9039 +
9040 + if ((saved_partition & 0x00FF00) != 0x00FF00)
9041 + grub_printf (",%c", ((saved_partition >> 8) & 0xFF) + 'a');
9042 +
9043 + grub_printf ("):");
9044 + }
9045 + else
9046 + {
9047 + /* Floppy disk drive. */
9048 + grub_printf (" (fd%d):", saved_drive);
9049 + }
9050 +
9051 + /* Print the filesystem information. */
9052 + current_partition = saved_partition;
9053 + current_drive = saved_drive;
9054 + print_fsys_type ();
9055 +}
9056 +
9057 +static int
9058 +real_root_func (char *arg, int attempt_mount)
9059 +{
9060 + int hdbias = 0;
9061 + char *biasptr;
9062 + char *next;
9063 +
9064 + /* If ARG is empty, just print the current root device. */
9065 + if (! *arg)
9066 + {
9067 + print_root_device ();
9068 + return 0;
9069 + }
9070 +
9071 + /* Call set_device to get the drive and the partition in ARG. */
9072 + next = set_device (arg);
9073 + if (! next)
9074 + return 1;
9075 +
9076 + /* Ignore ERR_FSYS_MOUNT. */
9077 + if (attempt_mount)
9078 + {
9079 + if (! open_device () && errnum != ERR_FSYS_MOUNT)
9080 + return 1;
9081 + }
9082 + else
9083 + {
9084 + /* This is necessary, because the location of a partition table
9085 + must be set appropriately. */
9086 + if (open_partition ())
9087 + {
9088 + set_bootdev (0);
9089 + if (errnum)
9090 + return 1;
9091 + }
9092 + }
9093 +
9094 + /* Clear ERRNUM. */
9095 + errnum = 0;
9096 + saved_partition = current_partition;
9097 + saved_drive = current_drive;
9098 +
9099 + if (attempt_mount)
9100 + {
9101 + /* BSD and chainloading evil hacks !! */
9102 + biasptr = skip_to (0, next);
9103 + safe_parse_maxint (&biasptr, &hdbias);
9104 + errnum = 0;
9105 + bootdev = set_bootdev (hdbias);
9106 + if (errnum)
9107 + return 1;
9108 +
9109 + /* Print the type of the filesystem. */
9110 + print_fsys_type ();
9111 + }
9112 +
9113 + return 0;
9114 +}
9115 +
9116 +static int
9117 +root_func (char *arg, int flags)
9118 +{
9119 + return real_root_func (arg, 1);
9120 +}
9121 +
9122 +static struct builtin builtin_root =
9123 +{
9124 + "root",
9125 + root_func,
9126 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
9127 + "root [DEVICE [HDBIAS]]",
9128 + "Set the current \"root device\" to the device DEVICE, then"
9129 + " attempt to mount it to get the partition size (for passing the"
9130 + " partition descriptor in `ES:ESI', used by some chain-loaded"
9131 + " bootloaders), the BSD drive-type (for booting BSD kernels using"
9132 + " their native boot format), and correctly determine "
9133 + " the PC partition where a BSD sub-partition is located. The"
9134 + " optional HDBIAS parameter is a number to tell a BSD kernel"
9135 + " how many BIOS drive numbers are on controllers before the current"
9136 + " one. For example, if there is an IDE disk and a SCSI disk, and your"
9137 + " FreeBSD root partition is on the SCSI disk, then use a `1' for HDBIAS."
9138 +};
9139 +
9140 +\f
9141 +/* rootnoverify */
9142 +static int
9143 +rootnoverify_func (char *arg, int flags)
9144 +{
9145 + return real_root_func (arg, 0);
9146 +}
9147 +
9148 +static struct builtin builtin_rootnoverify =
9149 +{
9150 + "rootnoverify",
9151 + rootnoverify_func,
9152 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
9153 + "rootnoverify [DEVICE [HDBIAS]]",
9154 + "Similar to `root', but don't attempt to mount the partition. This"
9155 + " is useful for when an OS is outside of the area of the disk that"
9156 + " GRUB can read, but setting the correct root device is still"
9157 + " desired. Note that the items mentioned in `root' which"
9158 + " derived from attempting the mount will NOT work correctly."
9159 +};
9160 +
9161 +\f
9162 +/* savedefault */
9163 +static int
9164 +savedefault_func (char *arg, int flags)
9165 +{
9166 +#if !defined(SUPPORT_DISKLESS) && !defined(GRUB_UTIL)
9167 + unsigned long tmp_drive = saved_drive;
9168 + unsigned long tmp_partition = saved_partition;
9169 + char *default_file = (char *) DEFAULT_FILE_BUF;
9170 + char buf[10];
9171 + char sect[SECTOR_SIZE];
9172 + int entryno;
9173 + int sector_count = 0;
9174 + int saved_sectors[2];
9175 + int saved_offsets[2];
9176 + int saved_lengths[2];
9177 +
9178 + /* Save sector information about at most two sectors. */
9179 + auto void disk_read_savesect_func (int sector, int offset, int length);
9180 + void disk_read_savesect_func (int sector, int offset, int length)
9181 + {
9182 + if (sector_count < 2)
9183 + {
9184 + saved_sectors[sector_count] = sector;
9185 + saved_offsets[sector_count] = offset;
9186 + saved_lengths[sector_count] = length;
9187 + }
9188 + sector_count++;
9189 + }
9190 +
9191 + /* This command is only useful when you boot an entry from the menu
9192 + interface. */
9193 + if (! (flags & BUILTIN_SCRIPT))
9194 + {
9195 + errnum = ERR_UNRECOGNIZED;
9196 + return 1;
9197 + }
9198 +
9199 + /* Determine a saved entry number. */
9200 + if (*arg)
9201 + {
9202 + if (grub_memcmp (arg, "fallback", sizeof ("fallback") - 1) == 0)
9203 + {
9204 + int i;
9205 + int index = 0;
9206 +
9207 + for (i = 0; i < MAX_FALLBACK_ENTRIES; i++)
9208 + {
9209 + if (fallback_entries[i] < 0)
9210 + break;
9211 + if (fallback_entries[i] == current_entryno)
9212 + {
9213 + index = i + 1;
9214 + break;
9215 + }
9216 + }
9217 +
9218 + if (index >= MAX_FALLBACK_ENTRIES || fallback_entries[index] < 0)
9219 + {
9220 + /* This is the last. */
9221 + errnum = ERR_BAD_ARGUMENT;
9222 + return 1;
9223 + }
9224 +
9225 + entryno = fallback_entries[index];
9226 + }
9227 + else if (! safe_parse_maxint (&arg, &entryno))
9228 + return 1;
9229 + }
9230 + else
9231 + entryno = current_entryno;
9232 +
9233 + /* Open the default file. */
9234 + saved_drive = boot_drive;
9235 + saved_partition = install_partition;
9236 + if (grub_open (default_file))
9237 + {
9238 + int len;
9239 +
9240 + disk_read_hook = disk_read_savesect_func;
9241 + len = grub_read (buf, sizeof (buf));
9242 + disk_read_hook = 0;
9243 + grub_close ();
9244 +
9245 + if (len != sizeof (buf))
9246 + {
9247 + /* This is too small. Do not modify the file manually, please! */
9248 + errnum = ERR_READ;
9249 + goto fail;
9250 + }
9251 +
9252 + if (sector_count > 2)
9253 + {
9254 + /* Is this possible?! Too fragmented! */
9255 + errnum = ERR_FSYS_CORRUPT;
9256 + goto fail;
9257 + }
9258 +
9259 + /* Set up a string to be written. */
9260 + grub_memset (buf, '\n', sizeof (buf));
9261 + grub_sprintf (buf, "%d", entryno);
9262 +
9263 + if (saved_lengths[0] < sizeof (buf))
9264 + {
9265 + /* The file is anchored to another file and the first few bytes
9266 + are spanned in two sectors. Uggh... */
9267 + if (! rawread (current_drive, saved_sectors[0], 0, SECTOR_SIZE,
9268 + sect))
9269 + goto fail;
9270 + grub_memmove (sect + saved_offsets[0], buf, saved_lengths[0]);
9271 + if (! rawwrite (current_drive, saved_sectors[0], sect))
9272 + goto fail;
9273 +
9274 + if (! rawread (current_drive, saved_sectors[1], 0, SECTOR_SIZE,
9275 + sect))
9276 + goto fail;
9277 + grub_memmove (sect + saved_offsets[1],
9278 + buf + saved_lengths[0],
9279 + sizeof (buf) - saved_lengths[0]);
9280 + if (! rawwrite (current_drive, saved_sectors[1], sect))
9281 + goto fail;
9282 + }
9283 + else
9284 + {
9285 + /* This is a simple case. It fits into a single sector. */
9286 + if (! rawread (current_drive, saved_sectors[0], 0, SECTOR_SIZE,
9287 + sect))
9288 + goto fail;
9289 + grub_memmove (sect + saved_offsets[0], buf, sizeof (buf));
9290 + if (! rawwrite (current_drive, saved_sectors[0], sect))
9291 + goto fail;
9292 + }
9293 +
9294 + /* Clear the cache. */
9295 + buf_track = -1;
9296 + }
9297 +
9298 + fail:
9299 + saved_drive = tmp_drive;
9300 + saved_partition = tmp_partition;
9301 + return errnum;
9302 +#else /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */
9303 + errnum = ERR_UNRECOGNIZED;
9304 + return 1;
9305 +#endif /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */
9306 +}
9307 +
9308 +static struct builtin builtin_savedefault =
9309 +{
9310 + "savedefault",
9311 + savedefault_func,
9312 + BUILTIN_CMDLINE,
9313 + "savedefault [NUM | `fallback']",
9314 + "Save the current entry as the default boot entry if no argument is"
9315 + " specified. If a number is specified, this number is saved. If"
9316 + " `fallback' is used, next fallback entry is saved."
9317 +};
9318 +
9319 +\f
9320 +#ifdef SUPPORT_SERIAL
9321 +/* serial */
9322 +static int
9323 +serial_func (char *arg, int flags)
9324 +{
9325 + unsigned short port = serial_hw_get_port (0);
9326 + unsigned int speed = 9600;
9327 + int word_len = UART_8BITS_WORD;
9328 + int parity = UART_NO_PARITY;
9329 + int stop_bit_len = UART_1_STOP_BIT;
9330 +
9331 + /* Process GNU-style long options.
9332 + FIXME: We should implement a getopt-like function, to avoid
9333 + duplications. */
9334 + while (1)
9335 + {
9336 + if (grub_memcmp (arg, "--unit=", sizeof ("--unit=") - 1) == 0)
9337 + {
9338 + char *p = arg + sizeof ("--unit=") - 1;
9339 + int unit;
9340 +
9341 + if (! safe_parse_maxint (&p, &unit))
9342 + return 1;
9343 +
9344 + if (unit < 0 || unit > 3)
9345 + {
9346 + errnum = ERR_DEV_VALUES;
9347 + return 1;
9348 + }
9349 +
9350 + port = serial_hw_get_port (unit);
9351 + }
9352 + else if (grub_memcmp (arg, "--speed=", sizeof ("--speed=") - 1) == 0)
9353 + {
9354 + char *p = arg + sizeof ("--speed=") - 1;
9355 + int num;
9356 +
9357 + if (! safe_parse_maxint (&p, &num))
9358 + return 1;
9359 +
9360 + speed = (unsigned int) num;
9361 + }
9362 + else if (grub_memcmp (arg, "--port=", sizeof ("--port=") - 1) == 0)
9363 + {
9364 + char *p = arg + sizeof ("--port=") - 1;
9365 + int num;
9366 +
9367 + if (! safe_parse_maxint (&p, &num))
9368 + return 1;
9369 +
9370 + port = (unsigned short) num;
9371 + }
9372 + else if (grub_memcmp (arg, "--word=", sizeof ("--word=") - 1) == 0)
9373 + {
9374 + char *p = arg + sizeof ("--word=") - 1;
9375 + int len;
9376 +
9377 + if (! safe_parse_maxint (&p, &len))
9378 + return 1;
9379 +
9380 + switch (len)
9381 + {
9382 + case 5: word_len = UART_5BITS_WORD; break;
9383 + case 6: word_len = UART_6BITS_WORD; break;
9384 + case 7: word_len = UART_7BITS_WORD; break;
9385 + case 8: word_len = UART_8BITS_WORD; break;
9386 + default:
9387 + errnum = ERR_BAD_ARGUMENT;
9388 + return 1;
9389 + }
9390 + }
9391 + else if (grub_memcmp (arg, "--stop=", sizeof ("--stop=") - 1) == 0)
9392 + {
9393 + char *p = arg + sizeof ("--stop=") - 1;
9394 + int len;
9395 +
9396 + if (! safe_parse_maxint (&p, &len))
9397 + return 1;
9398 +
9399 + switch (len)
9400 + {
9401 + case 1: stop_bit_len = UART_1_STOP_BIT; break;
9402 + case 2: stop_bit_len = UART_2_STOP_BITS; break;
9403 + default:
9404 + errnum = ERR_BAD_ARGUMENT;
9405 + return 1;
9406 + }
9407 + }
9408 + else if (grub_memcmp (arg, "--parity=", sizeof ("--parity=") - 1) == 0)
9409 + {
9410 + char *p = arg + sizeof ("--parity=") - 1;
9411 +
9412 + if (grub_memcmp (p, "no", sizeof ("no") - 1) == 0)
9413 + parity = UART_NO_PARITY;
9414 + else if (grub_memcmp (p, "odd", sizeof ("odd") - 1) == 0)
9415 + parity = UART_ODD_PARITY;
9416 + else if (grub_memcmp (p, "even", sizeof ("even") - 1) == 0)
9417 + parity = UART_EVEN_PARITY;
9418 + else
9419 + {
9420 + errnum = ERR_BAD_ARGUMENT;
9421 + return 1;
9422 + }
9423 + }
9424 +# ifdef GRUB_UTIL
9425 + /* In the grub shell, don't use any port number but open a tty
9426 + device instead. */
9427 + else if (grub_memcmp (arg, "--device=", sizeof ("--device=") - 1) == 0)
9428 + {
9429 + char *p = arg + sizeof ("--device=") - 1;
9430 + char dev[256]; /* XXX */
9431 + char *q = dev;
9432 +
9433 + while (*p && ! grub_isspace (*p))
9434 + *q++ = *p++;
9435 +
9436 + *q = 0;
9437 + serial_set_device (dev);
9438 + }
9439 +# endif /* GRUB_UTIL */
9440 + else
9441 + break;
9442 +
9443 + arg = skip_to (0, arg);
9444 + }
9445 +
9446 + /* Initialize the serial unit. */
9447 + if (! serial_hw_init (port, speed, word_len, parity, stop_bit_len))
9448 + {
9449 + errnum = ERR_BAD_ARGUMENT;
9450 + return 1;
9451 + }
9452 +
9453 + return 0;
9454 +}
9455 +
9456 +static struct builtin builtin_serial =
9457 +{
9458 + "serial",
9459 + serial_func,
9460 + BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
9461 + "serial [--unit=UNIT] [--port=PORT] [--speed=SPEED] [--word=WORD] [--parity=PARITY] [--stop=STOP] [--device=DEV]",
9462 + "Initialize a serial device. UNIT is a digit that specifies which serial"
9463 + " device is used (e.g. 0 == COM1). If you need to specify the port number,"
9464 + " set it by --port. SPEED is the DTE-DTE speed. WORD is the word length,"
9465 + " PARITY is the type of parity, which is one of `no', `odd' and `even'."
9466 + " STOP is the length of stop bit(s). The option --device can be used only"
9467 + " in the grub shell, which specifies the file name of a tty device. The"
9468 + " default values are COM1, 9600, 8N1."
9469 +};
9470 +#endif /* SUPPORT_SERIAL */
9471 +
9472 +\f
9473 +/* setkey */
9474 +struct keysym
9475 +{
9476 + char *unshifted_name; /* the name in unshifted state */
9477 + char *shifted_name; /* the name in shifted state */
9478 + unsigned char unshifted_ascii; /* the ascii code in unshifted state */
9479 + unsigned char shifted_ascii; /* the ascii code in shifted state */
9480 + unsigned char keycode; /* keyboard scancode */
9481 +};
9482 +
9483 +/* The table for key symbols. If the "shifted" member of an entry is
9484 + NULL, the entry does not have shifted state. */
9485 +static struct keysym keysym_table[] =
9486 +{
9487 + {"escape", 0, 0x1b, 0, 0x01},
9488 + {"1", "exclam", '1', '!', 0x02},
9489 + {"2", "at", '2', '@', 0x03},
9490 + {"3", "numbersign", '3', '#', 0x04},
9491 + {"4", "dollar", '4', '$', 0x05},
9492 + {"5", "percent", '5', '%', 0x06},
9493 + {"6", "caret", '6', '^', 0x07},
9494 + {"7", "ampersand", '7', '&', 0x08},
9495 + {"8", "asterisk", '8', '*', 0x09},
9496 + {"9", "parenleft", '9', '(', 0x0a},
9497 + {"0", "parenright", '0', ')', 0x0b},
9498 + {"minus", "underscore", '-', '_', 0x0c},
9499 + {"equal", "plus", '=', '+', 0x0d},
9500 + {"backspace", 0, '\b', 0, 0x0e},
9501 + {"tab", 0, '\t', 0, 0x0f},
9502 + {"q", "Q", 'q', 'Q', 0x10},
9503 + {"w", "W", 'w', 'W', 0x11},
9504 + {"e", "E", 'e', 'E', 0x12},
9505 + {"r", "R", 'r', 'R', 0x13},
9506 + {"t", "T", 't', 'T', 0x14},
9507 + {"y", "Y", 'y', 'Y', 0x15},
9508 + {"u", "U", 'u', 'U', 0x16},
9509 + {"i", "I", 'i', 'I', 0x17},
9510 + {"o", "O", 'o', 'O', 0x18},
9511 + {"p", "P", 'p', 'P', 0x19},
9512 + {"bracketleft", "braceleft", '[', '{', 0x1a},
9513 + {"bracketright", "braceright", ']', '}', 0x1b},
9514 + {"enter", 0, '\n', 0, 0x1c},
9515 + {"control", 0, 0, 0, 0x1d},
9516 + {"a", "A", 'a', 'A', 0x1e},
9517 + {"s", "S", 's', 'S', 0x1f},
9518 + {"d", "D", 'd', 'D', 0x20},
9519 + {"f", "F", 'f', 'F', 0x21},
9520 + {"g", "G", 'g', 'G', 0x22},
9521 + {"h", "H", 'h', 'H', 0x23},
9522 + {"j", "J", 'j', 'J', 0x24},
9523 + {"k", "K", 'k', 'K', 0x25},
9524 + {"l", "L", 'l', 'L', 0x26},
9525 + {"semicolon", "colon", ';', ':', 0x27},
9526 + {"quote", "doublequote", '\'', '"', 0x28},
9527 + {"backquote", "tilde", '`', '~', 0x29},
9528 + {"shift", 0, 0, 0, 0x2a},
9529 + {"backslash", "bar", '\\', '|', 0x2b},
9530 + {"z", "Z", 'z', 'Z', 0x2c},
9531 + {"x", "X", 'x', 'X', 0x2d},
9532 + {"c", "C", 'c', 'C', 0x2e},
9533 + {"v", "V", 'v', 'V', 0x2f},
9534 + {"b", "B", 'b', 'B', 0x30},
9535 + {"n", "N", 'n', 'N', 0x31},
9536 + {"m", "M", 'm', 'M', 0x32},
9537 + {"comma", "less", ',', '<', 0x33},
9538 + {"period", "greater", '.', '>', 0x34},
9539 + {"slash", "question", '/', '?', 0x35},
9540 + {"alt", 0, 0, 0, 0x38},
9541 + {"space", 0, ' ', 0, 0x39},
9542 + {"capslock", 0, 0, 0, 0x3a},
9543 + {"F1", 0, 0, 0, 0x3b},
9544 + {"F2", 0, 0, 0, 0x3c},
9545 + {"F3", 0, 0, 0, 0x3d},
9546 + {"F4", 0, 0, 0, 0x3e},
9547 + {"F5", 0, 0, 0, 0x3f},
9548 + {"F6", 0, 0, 0, 0x40},
9549 + {"F7", 0, 0, 0, 0x41},
9550 + {"F8", 0, 0, 0, 0x42},
9551 + {"F9", 0, 0, 0, 0x43},
9552 + {"F10", 0, 0, 0, 0x44},
9553 + /* Caution: do not add NumLock here! we cannot deal with it properly. */
9554 + {"delete", 0, 0x7f, 0, 0x53}
9555 +};
9556 +
9557 +static int
9558 +setkey_func (char *arg, int flags)
9559 +{
9560 + char *to_key, *from_key;
9561 + int to_code, from_code;
9562 + int map_in_interrupt = 0;
9563 +
9564 + auto int find_key_code (char *key);
9565 + auto int find_ascii_code (char *key);
9566 +
9567 + auto int find_key_code (char *key)
9568 + {
9569 + int i;
9570 +
9571 + for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++)
9572 + {
9573 + if (keysym_table[i].unshifted_name &&
9574 + grub_strcmp (key, keysym_table[i].unshifted_name) == 0)
9575 + return keysym_table[i].keycode;
9576 + else if (keysym_table[i].shifted_name &&
9577 + grub_strcmp (key, keysym_table[i].shifted_name) == 0)
9578 + return keysym_table[i].keycode;
9579 + }
9580 +
9581 + return 0;
9582 + }
9583 +
9584 + auto int find_ascii_code (char *key)
9585 + {
9586 + int i;
9587 +
9588 + for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++)
9589 + {
9590 + if (keysym_table[i].unshifted_name &&
9591 + grub_strcmp (key, keysym_table[i].unshifted_name) == 0)
9592 + return keysym_table[i].unshifted_ascii;
9593 + else if (keysym_table[i].shifted_name &&
9594 + grub_strcmp (key, keysym_table[i].shifted_name) == 0)
9595 + return keysym_table[i].shifted_ascii;
9596 + }
9597 +
9598 + return 0;
9599 + }
9600 +
9601 + to_key = arg;
9602 + from_key = skip_to (0, to_key);
9603 +
9604 + if (! *to_key)
9605 + {
9606 + /* If the user specifies no argument, reset the key mappings. */
9607 + grub_memset (bios_key_map, 0, KEY_MAP_SIZE * sizeof (unsigned short));
9608 + grub_memset (ascii_key_map, 0, KEY_MAP_SIZE * sizeof (unsigned short));
9609 +
9610 + return 0;
9611 + }
9612 + else if (! *from_key)
9613 + {
9614 + /* The user must specify two arguments or zero argument. */
9615 + errnum = ERR_BAD_ARGUMENT;
9616 + return 1;
9617 + }
9618 +
9619 + nul_terminate (to_key);
9620 + nul_terminate (from_key);
9621 +
9622 + to_code = find_ascii_code (to_key);
9623 + from_code = find_ascii_code (from_key);
9624 + if (! to_code || ! from_code)
9625 + {
9626 + map_in_interrupt = 1;
9627 + to_code = find_key_code (to_key);
9628 + from_code = find_key_code (from_key);
9629 + if (! to_code || ! from_code)
9630 + {
9631 + errnum = ERR_BAD_ARGUMENT;
9632 + return 1;
9633 + }
9634 + }
9635 +
9636 + if (map_in_interrupt)
9637 + {
9638 + int i;
9639 +
9640 + /* Find an empty slot. */
9641 + for (i = 0; i < KEY_MAP_SIZE; i++)
9642 + {
9643 + if ((bios_key_map[i] & 0xff) == from_code)
9644 + /* Perhaps the user wants to overwrite the map. */
9645 + break;
9646 +
9647 + if (! bios_key_map[i])
9648 + break;
9649 + }
9650 +
9651 + if (i == KEY_MAP_SIZE)
9652 + {
9653 + errnum = ERR_WONT_FIT;
9654 + return 1;
9655 + }
9656 +
9657 + if (to_code == from_code)
9658 + /* If TO is equal to FROM, delete the entry. */
9659 + grub_memmove ((char *) &bios_key_map[i],
9660 + (char *) &bios_key_map[i + 1],
9661 + sizeof (unsigned short) * (KEY_MAP_SIZE - i));
9662 + else
9663 + bios_key_map[i] = (to_code << 8) | from_code;
9664 +
9665 + /* Ugly but should work. */
9666 + unset_int15_handler ();
9667 + set_int15_handler ();
9668 + }
9669 + else
9670 + {
9671 + int i;
9672 +
9673 + /* Find an empty slot. */
9674 + for (i = 0; i < KEY_MAP_SIZE; i++)
9675 + {
9676 + if ((ascii_key_map[i] & 0xff) == from_code)
9677 + /* Perhaps the user wants to overwrite the map. */
9678 + break;
9679 +
9680 + if (! ascii_key_map[i])
9681 + break;
9682 + }
9683 +
9684 + if (i == KEY_MAP_SIZE)
9685 + {
9686 + errnum = ERR_WONT_FIT;
9687 + return 1;
9688 + }
9689 +
9690 + if (to_code == from_code)
9691 + /* If TO is equal to FROM, delete the entry. */
9692 + grub_memmove ((char *) &ascii_key_map[i],
9693 + (char *) &ascii_key_map[i + 1],
9694 + sizeof (unsigned short) * (KEY_MAP_SIZE - i));
9695 + else
9696 + ascii_key_map[i] = (to_code << 8) | from_code;
9697 + }
9698 +
9699 + return 0;
9700 +}
9701 +
9702 +static struct builtin builtin_setkey =
9703 +{
9704 + "setkey",
9705 + setkey_func,
9706 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
9707 + "setkey [TO_KEY FROM_KEY]",
9708 + "Change the keyboard map. The key FROM_KEY is mapped to the key TO_KEY."
9709 + " A key must be an alphabet, a digit, or one of these: escape, exclam,"
9710 + " at, numbersign, dollar, percent, caret, ampersand, asterisk, parenleft,"
9711 + " parenright, minus, underscore, equal, plus, backspace, tab, bracketleft,"
9712 + " braceleft, bracketright, braceright, enter, control, semicolon, colon,"
9713 + " quote, doublequote, backquote, tilde, shift, backslash, bar, comma,"
9714 + " less, period, greater, slash, question, alt, space, capslock, FX (X"
9715 + " is a digit), and delete. If no argument is specified, reset key"
9716 + " mappings."
9717 +};
9718 +
9719 +\f
9720 +/* setup */
9721 +static int
9722 +setup_func (char *arg, int flags)
9723 +{
9724 + /* Point to the string of the installed drive/partition. */
9725 + char *install_ptr;
9726 + /* Point to the string of the drive/parition where the GRUB images
9727 + reside. */
9728 + char *image_ptr;
9729 + unsigned long installed_drive, installed_partition;
9730 + unsigned long image_drive, image_partition;
9731 + unsigned long tmp_drive, tmp_partition;
9732 + char stage1[64];
9733 + char stage2[64];
9734 + char config_filename[64];
9735 + char real_config_filename[64];
9736 + char cmd_arg[256];
9737 + char device[16];
9738 + char *buffer = (char *) RAW_ADDR (0x100000);
9739 + int is_force_lba = 0;
9740 + char *stage2_arg = 0;
9741 + char *prefix = 0;
9742 +
9743 + auto int check_file (char *file);
9744 + auto void sprint_device (int drive, int partition);
9745 + auto int embed_stage1_5 (char * stage1_5, int drive, int partition);
9746 +
9747 + /* Check if the file FILE exists like Autoconf. */
9748 + int check_file (char *file)
9749 + {
9750 + int ret;
9751 +
9752 + grub_printf (" Checking if \"%s\" exists... ", file);
9753 + ret = grub_open (file);
9754 + if (ret)
9755 + {
9756 + grub_close ();
9757 + grub_printf ("yes\n");
9758 + }
9759 + else
9760 + grub_printf ("no\n");
9761 +
9762 + return ret;
9763 + }
9764 +
9765 + /* Construct a device name in DEVICE. */
9766 + void sprint_device (int drive, int partition)
9767 + {
9768 + grub_sprintf (device, "(%cd%d",
9769 + (drive & 0x80) ? 'h' : 'f',
9770 + drive & ~0x80);
9771 + if ((partition & 0xFF0000) != 0xFF0000)
9772 + {
9773 + char tmp[16];
9774 + grub_sprintf (tmp, ",%d", (partition >> 16) & 0xFF);
9775 + grub_strncat (device, tmp, 256);
9776 + }
9777 + if ((partition & 0x00FF00) != 0x00FF00)
9778 + {
9779 + char tmp[16];
9780 + grub_sprintf (tmp, ",%c", 'a' + ((partition >> 8) & 0xFF));
9781 + grub_strncat (device, tmp, 256);
9782 + }
9783 + grub_strncat (device, ")", 256);
9784 + }
9785 +
9786 + int embed_stage1_5 (char *stage1_5, int drive, int partition)
9787 + {
9788 + /* We install GRUB into the MBR, so try to embed the
9789 + Stage 1.5 in the sectors right after the MBR. */
9790 + sprint_device (drive, partition);
9791 + grub_sprintf (cmd_arg, "%s %s", stage1_5, device);
9792 +
9793 + /* Notify what will be run. */
9794 + grub_printf (" Running \"embed %s\"... ", cmd_arg);
9795 +
9796 + embed_func (cmd_arg, flags);
9797 + if (! errnum)
9798 + {
9799 + /* Construct the blocklist representation. */
9800 + grub_sprintf (buffer, "%s%s", device, embed_info);
9801 + grub_printf ("succeeded\n");
9802 + return 1;
9803 + }
9804 + else
9805 + {
9806 + grub_printf ("failed (this is not fatal)\n");
9807 + return 0;
9808 + }
9809 + }
9810 +
9811 + struct stage1_5_map {
9812 + char *fsys;
9813 + char *name;
9814 + };
9815 + struct stage1_5_map stage1_5_map[] =
9816 + {
9817 + {"ext2fs", "/e2fs_stage1_5"},
9818 + {"fat", "/fat_stage1_5"},
9819 + {"ufs2", "/ufs2_stage1_5"},
9820 + {"ffs", "/ffs_stage1_5"},
9821 + {"iso9660", "/iso9660_stage1_5"},
9822 + {"jfs", "/jfs_stage1_5"},
9823 + {"minix", "/minix_stage1_5"},
9824 + {"reiserfs", "/reiserfs_stage1_5"},
9825 + {"vstafs", "/vstafs_stage1_5"},
9826 + {"xfs", "/xfs_stage1_5"}
9827 + };
9828 +
9829 + tmp_drive = saved_drive;
9830 + tmp_partition = saved_partition;
9831 +
9832 + /* Check if the user specifies --force-lba. */
9833 + while (1)
9834 + {
9835 + if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0)
9836 + {
9837 + is_force_lba = 1;
9838 + arg = skip_to (0, arg);
9839 + }
9840 + else if (grub_memcmp ("--prefix=", arg, sizeof ("--prefix=") - 1) == 0)
9841 + {
9842 + prefix = arg + sizeof ("--prefix=") - 1;
9843 + arg = skip_to (0, arg);
9844 + nul_terminate (prefix);
9845 + }
9846 +#ifdef GRUB_UTIL
9847 + else if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) == 0)
9848 + {
9849 + stage2_arg = arg;
9850 + arg = skip_to (0, arg);
9851 + nul_terminate (stage2_arg);
9852 + }
9853 +#endif /* GRUB_UTIL */
9854 + else
9855 + break;
9856 + }
9857 +
9858 + install_ptr = arg;
9859 + image_ptr = skip_to (0, install_ptr);
9860 +
9861 + /* Make sure that INSTALL_PTR is valid. */
9862 + set_device (install_ptr);
9863 + if (errnum)
9864 + return 1;
9865 +
9866 + installed_drive = current_drive;
9867 + installed_partition = current_partition;
9868 +
9869 + /* Mount the drive pointed by IMAGE_PTR. */
9870 + if (*image_ptr)
9871 + {
9872 + /* If the drive/partition where the images reside is specified,
9873 + get the drive and the partition. */
9874 + set_device (image_ptr);
9875 + if (errnum)
9876 + return 1;
9877 + }
9878 + else
9879 + {
9880 + /* If omitted, use SAVED_PARTITION and SAVED_DRIVE. */
9881 + current_drive = saved_drive;
9882 + current_partition = saved_partition;
9883 + }
9884 +
9885 + image_drive = saved_drive = current_drive;
9886 + image_partition = saved_partition = current_partition;
9887 +
9888 + /* Open it. */
9889 + if (! open_device ())
9890 + goto fail;
9891 +
9892 + /* Check if stage1 exists. If the user doesn't specify the option
9893 + `--prefix', attempt /boot/grub and /grub. */
9894 + /* NOTE: It is dangerous to run this command without `--prefix' in the
9895 + grub shell, since that affects `--stage2'. */
9896 + if (! prefix)
9897 + {
9898 + prefix = "/boot/grub";
9899 + grub_sprintf (stage1, "%s%s", prefix, "/stage1");
9900 + if (! check_file (stage1))
9901 + {
9902 + errnum = ERR_NONE;
9903 + prefix = "/grub";
9904 + grub_sprintf (stage1, "%s%s", prefix, "/stage1");
9905 + if (! check_file (stage1))
9906 + goto fail;
9907 + }
9908 + }
9909 + else
9910 + {
9911 + grub_sprintf (stage1, "%s%s", prefix, "/stage1");
9912 + if (! check_file (stage1))
9913 + goto fail;
9914 + }
9915 +
9916 + /* The prefix was determined. */
9917 + grub_sprintf (stage2, "%s%s", prefix, "/stage2");
9918 + grub_sprintf (config_filename, "%s%s", prefix, "/menu.lst");
9919 + *real_config_filename = 0;
9920 +
9921 + /* Check if stage2 exists. */
9922 + if (! check_file (stage2))
9923 + goto fail;
9924 +
9925 + {
9926 + char *fsys = fsys_table[fsys_type].name;
9927 + int i;
9928 + int size = sizeof (stage1_5_map) / sizeof (stage1_5_map[0]);
9929 +
9930 + /* Iterate finding the same filesystem name as FSYS. */
9931 + for (i = 0; i < size; i++)
9932 + if (grub_strcmp (fsys, stage1_5_map[i].fsys) == 0)
9933 + {
9934 + /* OK, check if the Stage 1.5 exists. */
9935 + char stage1_5[64];
9936 +
9937 + grub_sprintf (stage1_5, "%s%s", prefix, stage1_5_map[i].name);
9938 + if (check_file (stage1_5))
9939 + {
9940 + if (embed_stage1_5 (stage1_5,
9941 + installed_drive, installed_partition)
9942 + || embed_stage1_5 (stage1_5,
9943 + image_drive, image_partition))
9944 + {
9945 + grub_strcpy (real_config_filename, config_filename);
9946 + sprint_device (image_drive, image_partition);
9947 + grub_sprintf (config_filename, "%s%s", device, stage2);
9948 + grub_strcpy (stage2, buffer);
9949 + }
9950 + }
9951 + errnum = 0;
9952 + break;
9953 + }
9954 + }
9955 +
9956 + /* Construct a string that is used by the command "install" as its
9957 + arguments. */
9958 + sprint_device (installed_drive, installed_partition);
9959 +
9960 +#if 1
9961 + /* Don't embed a drive number unnecessarily. */
9962 + grub_sprintf (cmd_arg, "%s%s%s%s %s%s %s p %s %s",
9963 + is_force_lba? "--force-lba " : "",
9964 + stage2_arg? stage2_arg : "",
9965 + stage2_arg? " " : "",
9966 + stage1,
9967 + (installed_drive != image_drive) ? "d " : "",
9968 + device,
9969 + stage2,
9970 + config_filename,
9971 + real_config_filename);
9972 +#else /* NOT USED */
9973 + /* This code was used, because we belived some BIOSes had a problem
9974 + that they didn't pass a booting drive correctly. It turned out,
9975 + however, stage1 could trash a booting drive when checking LBA support,
9976 + because some BIOSes modified the register %dx in INT 13H, AH=48H.
9977 + So it becamed unclear whether GRUB should use a pre-defined booting
9978 + drive or not. If the problem still exists, it would be necessary to
9979 + switch back to this code. */
9980 + grub_sprintf (cmd_arg, "%s%s%s%s d %s %s p %s %s",
9981 + is_force_lba? "--force-lba " : "",
9982 + stage2_arg? stage2_arg : "",
9983 + stage2_arg? " " : "",
9984 + stage1,
9985 + device,
9986 + stage2,
9987 + config_filename,
9988 + real_config_filename);
9989 +#endif /* NOT USED */
9990 +
9991 + /* Notify what will be run. */
9992 + grub_printf (" Running \"install %s\"... ", cmd_arg);
9993 +
9994 + /* Make sure that SAVED_DRIVE and SAVED_PARTITION are identical
9995 + with IMAGE_DRIVE and IMAGE_PARTITION, respectively. */
9996 + saved_drive = image_drive;
9997 + saved_partition = image_partition;
9998 +
9999 + /* Run the command. */
10000 + if (! install_func (cmd_arg, flags))
10001 + grub_printf ("succeeded\nDone.\n");
10002 + else
10003 + grub_printf ("failed\n");
10004 +
10005 + fail:
10006 + saved_drive = tmp_drive;
10007 + saved_partition = tmp_partition;
10008 + return errnum;
10009 +}
10010 +
10011 +static struct builtin builtin_setup =
10012 +{
10013 + "setup",
10014 + setup_func,
10015 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
10016 + "setup [--prefix=DIR] [--stage2=STAGE2_FILE] [--force-lba] INSTALL_DEVICE [IMAGE_DEVICE]",
10017 + "Set up the installation of GRUB automatically. This command uses"
10018 + " the more flexible command \"install\" in the backend and installs"
10019 + " GRUB into the device INSTALL_DEVICE. If IMAGE_DEVICE is specified,"
10020 + " then find the GRUB images in the device IMAGE_DEVICE, otherwise"
10021 + " use the current \"root device\", which can be set by the command"
10022 + " \"root\". If you know that your BIOS should support LBA but GRUB"
10023 + " doesn't work in LBA mode, specify the option `--force-lba'."
10024 + " If you install GRUB under the grub shell and you cannot unmount the"
10025 + " partition where GRUB images reside, specify the option `--stage2'"
10026 + " to tell GRUB the file name under your OS."
10027 +};
10028 +
10029 +\f
10030 +#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
10031 +/* terminal */
10032 +static int
10033 +terminal_func (char *arg, int flags)
10034 +{
10035 + /* The index of the default terminal in TERM_TABLE. */
10036 + int default_term = -1;
10037 + struct term_entry *prev_term = current_term;
10038 + int to = -1;
10039 + int lines = 0;
10040 + int no_message = 0;
10041 + unsigned long term_flags = 0;
10042 + /* XXX: Assume less than 32 terminals. */
10043 + unsigned long term_bitmap = 0;
10044 +
10045 + /* Get GNU-style long options. */
10046 + while (1)
10047 + {
10048 + if (grub_memcmp (arg, "--dumb", sizeof ("--dumb") - 1) == 0)
10049 + term_flags |= TERM_DUMB;
10050 + else if (grub_memcmp (arg, "--no-echo", sizeof ("--no-echo") - 1) == 0)
10051 + /* ``--no-echo'' implies ``--no-edit''. */
10052 + term_flags |= (TERM_NO_ECHO | TERM_NO_EDIT);
10053 + else if (grub_memcmp (arg, "--no-edit", sizeof ("--no-edit") - 1) == 0)
10054 + term_flags |= TERM_NO_EDIT;
10055 + else if (grub_memcmp (arg, "--timeout=", sizeof ("--timeout=") - 1) == 0)
10056 + {
10057 + char *val = arg + sizeof ("--timeout=") - 1;
10058 +
10059 + if (! safe_parse_maxint (&val, &to))
10060 + return 1;
10061 + }
10062 + else if (grub_memcmp (arg, "--lines=", sizeof ("--lines=") - 1) == 0)
10063 + {
10064 + char *val = arg + sizeof ("--lines=") - 1;
10065 +
10066 + if (! safe_parse_maxint (&val, &lines))
10067 + return 1;
10068 +
10069 + /* Probably less than four is meaningless.... */
10070 + if (lines < 4)
10071 + {
10072 + errnum = ERR_BAD_ARGUMENT;
10073 + return 1;
10074 + }
10075 + }
10076 + else if (grub_memcmp (arg, "--silent", sizeof ("--silent") - 1) == 0)
10077 + no_message = 1;
10078 + else
10079 + break;
10080 +
10081 + arg = skip_to (0, arg);
10082 + }
10083 +
10084 + /* If no argument is specified, show current setting. */
10085 + if (! *arg)
10086 + {
10087 + grub_printf ("%s%s%s%s\n",
10088 + current_term->name,
10089 + current_term->flags & TERM_DUMB ? " (dumb)" : "",
10090 + current_term->flags & TERM_NO_EDIT ? " (no edit)" : "",
10091 + current_term->flags & TERM_NO_ECHO ? " (no echo)" : "");
10092 + return 0;
10093 + }
10094 +
10095 + while (*arg)
10096 + {
10097 + int i;
10098 + char *next = skip_to (0, arg);
10099 +
10100 + nul_terminate (arg);
10101 +
10102 + for (i = 0; term_table[i].name; i++)
10103 + {
10104 + if (grub_strcmp (arg, term_table[i].name) == 0)
10105 + {
10106 + if (term_table[i].flags & TERM_NEED_INIT)
10107 + {
10108 + errnum = ERR_DEV_NEED_INIT;
10109 + return 1;
10110 + }
10111 +
10112 + if (default_term < 0)
10113 + default_term = i;
10114 +
10115 + term_bitmap |= (1 << i);
10116 + break;
10117 + }
10118 + }
10119 +
10120 + if (! term_table[i].name)
10121 + {
10122 + errnum = ERR_BAD_ARGUMENT;
10123 + return 1;
10124 + }
10125 +
10126 + arg = next;
10127 + }
10128 +
10129 + /* If multiple terminals are specified, wait until the user pushes any
10130 + key on one of the terminals. */
10131 + if (term_bitmap & ~(1 << default_term))
10132 + {
10133 + int time1, time2 = -1;
10134 +
10135 + /* XXX: Disable the pager. */
10136 + count_lines = -1;
10137 +
10138 + /* Get current time. */
10139 + while ((time1 = getrtsecs ()) == 0xFF)
10140 + ;
10141 +
10142 + /* Wait for a key input. */
10143 + while (to)
10144 + {
10145 + int i;
10146 +
10147 + for (i = 0; term_table[i].name; i++)
10148 + {
10149 + if (term_bitmap & (1 << i))
10150 + {
10151 + if (term_table[i].checkkey () >= 0)
10152 + {
10153 + (void) term_table[i].getkey ();
10154 + default_term = i;
10155 +
10156 + goto end;
10157 + }
10158 + }
10159 + }
10160 +
10161 + /* Prompt the user, once per sec. */
10162 + if ((time1 = getrtsecs ()) != time2 && time1 != 0xFF)
10163 + {
10164 + if (! no_message)
10165 + {
10166 + /* Need to set CURRENT_TERM to each of selected
10167 + terminals. */
10168 + for (i = 0; term_table[i].name; i++)
10169 + if (term_bitmap & (1 << i))
10170 + {
10171 + current_term = term_table + i;
10172 + grub_printf ("\rPress any key to continue.\n");
10173 + }
10174 +
10175 + /* Restore CURRENT_TERM. */
10176 + current_term = prev_term;
10177 + }
10178 +
10179 + time2 = time1;
10180 + if (to > 0)
10181 + to--;
10182 + }
10183 + }
10184 + }
10185 +
10186 + end:
10187 + current_term = term_table + default_term;
10188 + current_term->flags = term_flags;
10189 +
10190 + if (lines)
10191 + max_lines = lines;
10192 + else
10193 + /* 24 would be a good default value. */
10194 + max_lines = 24;
10195 +
10196 + /* If the interface is currently the command-line,
10197 + restart it to repaint the screen. */
10198 + if (current_term != prev_term && (flags & BUILTIN_CMDLINE))
10199 + grub_longjmp (restart_cmdline_env, 0);
10200 +
10201 + return 0;
10202 +}
10203 +
10204 +static struct builtin builtin_terminal =
10205 +{
10206 + "terminal",
10207 + terminal_func,
10208 + BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
10209 + "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] [--silent] [console] [serial] [hercules]",
10210 + "Select a terminal. When multiple terminals are specified, wait until"
10211 + " you push any key to continue. If both console and serial are specified,"
10212 + " the terminal to which you input a key first will be selected. If no"
10213 + " argument is specified, print current setting. The option --dumb"
10214 + " specifies that your terminal is dumb, otherwise, vt100-compatibility"
10215 + " is assumed. If you specify --no-echo, input characters won't be echoed."
10216 + " If you specify --no-edit, the BASH-like editing feature will be disabled."
10217 + " If --timeout is present, this command will wait at most for SECS"
10218 + " seconds. The option --lines specifies the maximum number of lines."
10219 + " The option --silent is used to suppress messages."
10220 +};
10221 +#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
10222 +
10223 +\f
10224 +#ifdef SUPPORT_SERIAL
10225 +static int
10226 +terminfo_func (char *arg, int flags)
10227 +{
10228 + struct terminfo term;
10229 +
10230 + if (*arg)
10231 + {
10232 + struct
10233 + {
10234 + const char *name;
10235 + char *var;
10236 + }
10237 + options[] =
10238 + {
10239 + {"--name=", term.name},
10240 + {"--cursor-address=", term.cursor_address},
10241 + {"--clear-screen=", term.clear_screen},
10242 + {"--enter-standout-mode=", term.enter_standout_mode},
10243 + {"--exit-standout-mode=", term.exit_standout_mode}
10244 + };
10245 +
10246 + grub_memset (&term, 0, sizeof (term));
10247 +
10248 + while (*arg)
10249 + {
10250 + int i;
10251 + char *next = skip_to (0, arg);
10252 +
10253 + nul_terminate (arg);
10254 +
10255 + for (i = 0; i < sizeof (options) / sizeof (options[0]); i++)
10256 + {
10257 + const char *name = options[i].name;
10258 + int len = grub_strlen (name);
10259 +
10260 + if (! grub_memcmp (arg, name, len))
10261 + {
10262 + grub_strcpy (options[i].var, ti_unescape_string (arg + len));
10263 + break;
10264 + }
10265 + }
10266 +
10267 + if (i == sizeof (options) / sizeof (options[0]))
10268 + {
10269 + errnum = ERR_BAD_ARGUMENT;
10270 + return errnum;
10271 + }
10272 +
10273 + arg = next;
10274 + }
10275 +
10276 + if (term.name[0] == 0 || term.cursor_address[0] == 0)
10277 + {
10278 + errnum = ERR_BAD_ARGUMENT;
10279 + return errnum;
10280 + }
10281 +
10282 + ti_set_term (&term);
10283 + }
10284 + else
10285 + {
10286 + /* No option specifies printing out current settings. */
10287 + ti_get_term (&term);
10288 +
10289 + grub_printf ("name=%s\n",
10290 + ti_escape_string (term.name));
10291 + grub_printf ("cursor_address=%s\n",
10292 + ti_escape_string (term.cursor_address));
10293 + grub_printf ("clear_screen=%s\n",
10294 + ti_escape_string (term.clear_screen));
10295 + grub_printf ("enter_standout_mode=%s\n",
10296 + ti_escape_string (term.enter_standout_mode));
10297 + grub_printf ("exit_standout_mode=%s\n",
10298 + ti_escape_string (term.exit_standout_mode));
10299 + }
10300 +
10301 + return 0;
10302 +}
10303 +
10304 +static struct builtin builtin_terminfo =
10305 +{
10306 + "terminfo",
10307 + terminfo_func,
10308 + BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
10309 + "terminfo [--name=NAME --cursor-address=SEQ [--clear-screen=SEQ]"
10310 + " [--enter-standout-mode=SEQ] [--exit-standout-mode=SEQ]]",
10311 +
10312 + "Define the capabilities of your terminal. Use this command to"
10313 + " define escape sequences, if it is not vt100-compatible."
10314 + " You may use \\e for ESC and ^X for a control character."
10315 + " If no option is specified, the current settings are printed."
10316 +};
10317 +#endif /* SUPPORT_SERIAL */
10318 +
10319 +\f
10320 +/* testload */
10321 +static int
10322 +testload_func (char *arg, int flags)
10323 +{
10324 + int i;
10325 +
10326 + kernel_type = KERNEL_TYPE_NONE;
10327 +
10328 + if (! grub_open (arg))
10329 + return 1;
10330 +
10331 + disk_read_hook = disk_read_print_func;
10332 +
10333 + /* Perform filesystem test on the specified file. */
10334 + /* Read whole file first. */
10335 + grub_printf ("Whole file: ");
10336 +
10337 + grub_read ((char *) RAW_ADDR (0x100000), -1);
10338 +
10339 + /* Now compare two sections of the file read differently. */
10340 +
10341 + for (i = 0; i < 0x10ac0; i++)
10342 + {
10343 + *((unsigned char *) RAW_ADDR (0x200000 + i)) = 0;
10344 + *((unsigned char *) RAW_ADDR (0x300000 + i)) = 1;
10345 + }
10346 +
10347 + /* First partial read. */
10348 + grub_printf ("\nPartial read 1: ");
10349 +
10350 + grub_seek (0);
10351 + grub_read ((char *) RAW_ADDR (0x200000), 0x7);
10352 + grub_read ((char *) RAW_ADDR (0x200007), 0x100);
10353 + grub_read ((char *) RAW_ADDR (0x200107), 0x10);
10354 + grub_read ((char *) RAW_ADDR (0x200117), 0x999);
10355 + grub_read ((char *) RAW_ADDR (0x200ab0), 0x10);
10356 + grub_read ((char *) RAW_ADDR (0x200ac0), 0x10000);
10357 +
10358 + /* Second partial read. */
10359 + grub_printf ("\nPartial read 2: ");
10360 +
10361 + grub_seek (0);
10362 + grub_read ((char *) RAW_ADDR (0x300000), 0x10000);
10363 + grub_read ((char *) RAW_ADDR (0x310000), 0x10);
10364 + grub_read ((char *) RAW_ADDR (0x310010), 0x7);
10365 + grub_read ((char *) RAW_ADDR (0x310017), 0x10);
10366 + grub_read ((char *) RAW_ADDR (0x310027), 0x999);
10367 + grub_read ((char *) RAW_ADDR (0x3109c0), 0x100);
10368 +
10369 + grub_printf ("\nHeader1 = 0x%x, next = 0x%x, next = 0x%x, next = 0x%x\n",
10370 + *((int *) RAW_ADDR (0x200000)),
10371 + *((int *) RAW_ADDR (0x200004)),
10372 + *((int *) RAW_ADDR (0x200008)),
10373 + *((int *) RAW_ADDR (0x20000c)));
10374 +
10375 + grub_printf ("Header2 = 0x%x, next = 0x%x, next = 0x%x, next = 0x%x\n",
10376 + *((int *) RAW_ADDR (0x300000)),
10377 + *((int *) RAW_ADDR (0x300004)),
10378 + *((int *) RAW_ADDR (0x300008)),
10379 + *((int *) RAW_ADDR (0x30000c)));
10380 +
10381 + for (i = 0; i < 0x10ac0; i++)
10382 + if (*((unsigned char *) RAW_ADDR (0x200000 + i))
10383 + != *((unsigned char *) RAW_ADDR (0x300000 + i)))
10384 + break;
10385 +
10386 + grub_printf ("Max is 0x10ac0: i=0x%x, filepos=0x%x\n", i, filepos);
10387 + disk_read_hook = 0;
10388 + grub_close ();
10389 + return 0;
10390 +}
10391 +
10392 +static struct builtin builtin_testload =
10393 +{
10394 + "testload",
10395 + testload_func,
10396 + BUILTIN_CMDLINE,
10397 + "testload FILE",
10398 + "Read the entire contents of FILE in several different ways and"
10399 + " compares them, to test the filesystem code. The output is somewhat"
10400 + " cryptic, but if no errors are reported and the final `i=X,"
10401 + " filepos=Y' reading has X and Y equal, then it is definitely"
10402 + " consistent, and very likely works correctly subject to a"
10403 + " consistent offset error. If this test succeeds, then a good next"
10404 + " step is to try loading a kernel."
10405 +};
10406 +
10407 +\f
10408 +/* testvbe MODE */
10409 +static int
10410 +testvbe_func (char *arg, int flags)
10411 +{
10412 + int mode_number;
10413 + struct vbe_controller controller;
10414 + struct vbe_mode mode;
10415 +
10416 + if (! *arg)
10417 + {
10418 + errnum = ERR_BAD_ARGUMENT;
10419 + return 1;
10420 + }
10421 +
10422 + if (! safe_parse_maxint (&arg, &mode_number))
10423 + return 1;
10424 +
10425 + /* Preset `VBE2'. */
10426 + grub_memmove (controller.signature, "VBE2", 4);
10427 +
10428 + /* Detect VBE BIOS. */
10429 + if (get_vbe_controller_info (&controller) != 0x004F)
10430 + {
10431 + grub_printf (" VBE BIOS is not present.\n");
10432 + return 0;
10433 + }
10434 +
10435 + if (controller.version < 0x0200)
10436 + {
10437 + grub_printf (" VBE version %d.%d is not supported.\n",
10438 + (int) (controller.version >> 8),
10439 + (int) (controller.version & 0xFF));
10440 + return 0;
10441 + }
10442 +
10443 + if (get_vbe_mode_info (mode_number, &mode) != 0x004F
10444 + || (mode.mode_attributes & 0x0091) != 0x0091)
10445 + {
10446 + grub_printf (" Mode 0x%x is not supported.\n", mode_number);
10447 + return 0;
10448 + }
10449 +
10450 + /* Now trip to the graphics mode. */
10451 + if (set_vbe_mode (mode_number | (1 << 14)) != 0x004F)
10452 + {
10453 + grub_printf (" Switching to Mode 0x%x failed.\n", mode_number);
10454 + return 0;
10455 + }
10456 +
10457 + /* Draw something on the screen... */
10458 + {
10459 + unsigned char *base_buf = (unsigned char *) mode.phys_base;
10460 + int scanline = controller.version >= 0x0300
10461 + ? mode.linear_bytes_per_scanline : mode.bytes_per_scanline;
10462 + /* FIXME: this assumes that any depth is a modulo of 8. */
10463 + int bpp = mode.bits_per_pixel / 8;
10464 + int width = mode.x_resolution;
10465 + int height = mode.y_resolution;
10466 + int x, y;
10467 + unsigned color = 0;
10468 +
10469 + /* Iterate drawing on the screen, until the user hits any key. */
10470 + while (checkkey () == -1)
10471 + {
10472 + for (y = 0; y < height; y++)
10473 + {
10474 + unsigned char *line_buf = base_buf + scanline * y;
10475 +
10476 + for (x = 0; x < width; x++)
10477 + {
10478 + unsigned char *buf = line_buf + bpp * x;
10479 + int i;
10480 +
10481 + for (i = 0; i < bpp; i++, buf++)
10482 + *buf = (color >> (i * 8)) & 0xff;
10483 + }
10484 +
10485 + color++;
10486 + }
10487 + }
10488 +
10489 + /* Discard the input. */
10490 + getkey ();
10491 + }
10492 +
10493 + /* Back to the default text mode. */
10494 + if (set_vbe_mode (0x03) != 0x004F)
10495 + {
10496 + /* Why?! */
10497 + grub_reboot ();
10498 + }
10499 +
10500 + return 0;
10501 +}
10502 +
10503 +static struct builtin builtin_testvbe =
10504 +{
10505 + "testvbe",
10506 + testvbe_func,
10507 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
10508 + "testvbe MODE",
10509 + "Test the VBE mode MODE. Hit any key to return."
10510 +};
10511 +
10512 +\f
10513 +#ifdef SUPPORT_NETBOOT
10514 +/* tftpserver */
10515 +static int
10516 +tftpserver_func (char *arg, int flags)
10517 +{
10518 + if (! *arg || ! ifconfig (0, 0, 0, arg))
10519 + {
10520 + errnum = ERR_BAD_ARGUMENT;
10521 + return 1;
10522 + }
10523 +
10524 + print_network_configuration ();
10525 + return 0;
10526 +}
10527 +
10528 +static struct builtin builtin_tftpserver =
10529 +{
10530 + "tftpserver",
10531 + tftpserver_func,
10532 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
10533 + "tftpserver IPADDR",
10534 + "Override the TFTP server address."
10535 +};
10536 +#endif /* SUPPORT_NETBOOT */
10537 +
10538 +\f
10539 +/* timeout */
10540 +static int
10541 +timeout_func (char *arg, int flags)
10542 +{
10543 + if (! safe_parse_maxint (&arg, &grub_timeout))
10544 + return 1;
10545 +
10546 + return 0;
10547 +}
10548 +
10549 +static struct builtin builtin_timeout =
10550 +{
10551 + "timeout",
10552 + timeout_func,
10553 + BUILTIN_MENU,
10554 +#if 0
10555 + "timeout SEC",
10556 + "Set a timeout, in SEC seconds, before automatically booting the"
10557 + " default entry (normally the first entry defined)."
10558 +#endif
10559 +};
10560 +
10561 +\f
10562 +/* title */
10563 +static int
10564 +title_func (char *arg, int flags)
10565 +{
10566 + /* This function is not actually used at least currently. */
10567 + return 0;
10568 +}
10569 +
10570 +static struct builtin builtin_title =
10571 +{
10572 + "title",
10573 + title_func,
10574 + BUILTIN_TITLE,
10575 +#if 0
10576 + "title [NAME ...]",
10577 + "Start a new boot entry, and set its name to the contents of the"
10578 + " rest of the line, starting with the first non-space character."
10579 +#endif
10580 +};
10581 +
10582 +\f
10583 +/* unhide */
10584 +static int
10585 +unhide_func (char *arg, int flags)
10586 +{
10587 + if (! set_device (arg))
10588 + return 1;
10589 +
10590 + if (! set_partition_hidden_flag (0))
10591 + return 1;
10592 +
10593 + return 0;
10594 +}
10595 +
10596 +static struct builtin builtin_unhide =
10597 +{
10598 + "unhide",
10599 + unhide_func,
10600 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
10601 + "unhide PARTITION",
10602 + "Unhide PARTITION by clearing the \"hidden\" bit in its"
10603 + " partition type code."
10604 +};
10605 +
10606 +\f
10607 +/* uppermem */
10608 +static int
10609 +uppermem_func (char *arg, int flags)
10610 +{
10611 + if (! safe_parse_maxint (&arg, (int *) &mbi.mem_upper))
10612 + return 1;
10613 +
10614 + mbi.flags &= ~MB_INFO_MEM_MAP;
10615 + return 0;
10616 +}
10617 +
10618 +static struct builtin builtin_uppermem =
10619 +{
10620 + "uppermem",
10621 + uppermem_func,
10622 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
10623 + "uppermem KBYTES",
10624 + "Force GRUB to assume that only KBYTES kilobytes of upper memory are"
10625 + " installed. Any system address range maps are discarded."
10626 +};
10627 +
10628 +\f
10629 +/* vbeprobe */
10630 +static int
10631 +vbeprobe_func (char *arg, int flags)
10632 +{
10633 + struct vbe_controller controller;
10634 + unsigned short *mode_list;
10635 + int mode_number = -1;
10636 +
10637 + auto unsigned long vbe_far_ptr_to_linear (unsigned long);
10638 +
10639 + unsigned long vbe_far_ptr_to_linear (unsigned long ptr)
10640 + {
10641 + unsigned short seg = (ptr >> 16);
10642 + unsigned short off = (ptr & 0xFFFF);
10643 +
10644 + return (seg << 4) + off;
10645 + }
10646 +
10647 + if (*arg)
10648 + {
10649 + if (! safe_parse_maxint (&arg, &mode_number))
10650 + return 1;
10651 + }
10652 +
10653 + /* Set the signature to `VBE2', to obtain VBE 3.0 information. */
10654 + grub_memmove (controller.signature, "VBE2", 4);
10655 +
10656 + if (get_vbe_controller_info (&controller) != 0x004F)
10657 + {
10658 + grub_printf (" VBE BIOS is not present.\n");
10659 + return 0;
10660 + }
10661 +
10662 + /* Check the version. */
10663 + if (controller.version < 0x0200)
10664 + {
10665 + grub_printf (" VBE version %d.%d is not supported.\n",
10666 + (int) (controller.version >> 8),
10667 + (int) (controller.version & 0xFF));
10668 + return 0;
10669 + }
10670 +
10671 + /* Print some information. */
10672 + grub_printf (" VBE version %d.%d\n",
10673 + (int) (controller.version >> 8),
10674 + (int) (controller.version & 0xFF));
10675 +
10676 + /* Iterate probing modes. */
10677 + for (mode_list
10678 + = (unsigned short *) vbe_far_ptr_to_linear (controller.video_mode);
10679 + *mode_list != 0xFFFF;
10680 + mode_list++)
10681 + {
10682 + struct vbe_mode mode;
10683 +
10684 + if (get_vbe_mode_info (*mode_list, &mode) != 0x004F)
10685 + continue;
10686 +
10687 + /* Skip this, if this is not supported or linear frame buffer
10688 + mode is not support. */
10689 + if ((mode.mode_attributes & 0x0081) != 0x0081)
10690 + continue;
10691 +
10692 + if (mode_number == -1 || mode_number == *mode_list)
10693 + {
10694 + char *model;
10695 + switch (mode.memory_model)
10696 + {
10697 + case 0x00: model = "Text"; break;
10698 + case 0x01: model = "CGA graphics"; break;
10699 + case 0x02: model = "Hercules graphics"; break;
10700 + case 0x03: model = "Planar"; break;
10701 + case 0x04: model = "Packed pixel"; break;
10702 + case 0x05: model = "Non-chain 4, 256 color"; break;
10703 + case 0x06: model = "Direct Color"; break;
10704 + case 0x07: model = "YUV"; break;
10705 + default: model = "Unknown"; break;
10706 + }
10707 +
10708 + grub_printf (" 0x%x: %s, %ux%ux%u\n",
10709 + (unsigned) *mode_list,
10710 + model,
10711 + (unsigned) mode.x_resolution,
10712 + (unsigned) mode.y_resolution,
10713 + (unsigned) mode.bits_per_pixel);
10714 +
10715 + if (mode_number != -1)
10716 + break;
10717 + }
10718 + }
10719 +
10720 + if (mode_number != -1 && mode_number != *mode_list)
10721 + grub_printf (" Mode 0x%x is not found or supported.\n", mode_number);
10722 +
10723 + return 0;
10724 +}
10725 +
10726 +static struct builtin builtin_vbeprobe =
10727 +{
10728 + "vbeprobe",
10729 + vbeprobe_func,
10730 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
10731 + "vbeprobe [MODE]",
10732 + "Probe VBE information. If the mode number MODE is specified, show only"
10733 + " the information about only the mode."
10734 +};
10735 +
10736 +\f
10737 +/* The table of builtin commands. Sorted in dictionary order. */
10738 +struct builtin *builtin_table[] =
10739 +{
10740 + &builtin_blocklist,
10741 + &builtin_boot,
10742 +#ifdef SUPPORT_NETBOOT
10743 + &builtin_bootp,
10744 +#endif /* SUPPORT_NETBOOT */
10745 + &builtin_cat,
10746 + &builtin_chainloader,
10747 + &builtin_cmp,
10748 + &builtin_color,
10749 + &builtin_configfile,
10750 + &builtin_debug,
10751 + &builtin_default,
10752 +#ifdef GRUB_UTIL
10753 + &builtin_device,
10754 +#endif /* GRUB_UTIL */
10755 +#ifdef SUPPORT_NETBOOT
10756 + &builtin_dhcp,
10757 +#endif /* SUPPORT_NETBOOT */
10758 + &builtin_displayapm,
10759 + &builtin_displaymem,
10760 +#ifdef GRUB_UTIL
10761 + &builtin_dump,
10762 +#endif /* GRUB_UTIL */
10763 + &builtin_embed,
10764 + &builtin_fallback,
10765 + &builtin_find,
10766 + &builtin_fstest,
10767 + &builtin_geometry,
10768 + &builtin_halt,
10769 + &builtin_help,
10770 + &builtin_hiddenmenu,
10771 + &builtin_hide,
10772 +#ifdef SUPPORT_NETBOOT
10773 + &builtin_ifconfig,
10774 +#endif /* SUPPORT_NETBOOT */
10775 + &builtin_impsprobe,
10776 + &builtin_initrd,
10777 + &builtin_install,
10778 + &builtin_ioprobe,
10779 + &builtin_kernel,
10780 + &builtin_lock,
10781 + &builtin_makeactive,
10782 + &builtin_map,
10783 +#ifdef USE_MD5_PASSWORDS
10784 + &builtin_md5crypt,
10785 +#endif /* USE_MD5_PASSWORDS */
10786 + &builtin_module,
10787 + &builtin_modulenounzip,
10788 + &builtin_pager,
10789 + &builtin_partnew,
10790 + &builtin_parttype,
10791 + &builtin_password,
10792 + &builtin_pause,
10793 +#ifdef GRUB_UTIL
10794 + &builtin_quit,
10795 +#endif /* GRUB_UTIL */
10796 +#ifdef SUPPORT_NETBOOT
10797 + &builtin_rarp,
10798 +#endif /* SUPPORT_NETBOOT */
10799 + &builtin_read,
10800 + &builtin_reboot,
10801 + &builtin_root,
10802 + &builtin_rootnoverify,
10803 + &builtin_savedefault,
10804 +#ifdef SUPPORT_SERIAL
10805 + &builtin_serial,
10806 +#endif /* SUPPORT_SERIAL */
10807 + &builtin_setkey,
10808 + &builtin_setup,
10809 +#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
10810 + &builtin_terminal,
10811 +#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
10812 +#ifdef SUPPORT_SERIAL
10813 + &builtin_terminfo,
10814 +#endif /* SUPPORT_SERIAL */
10815 + &builtin_testload,
10816 + &builtin_testvbe,
10817 +#ifdef SUPPORT_NETBOOT
10818 + &builtin_tftpserver,
10819 +#endif /* SUPPORT_NETBOOT */
10820 + &builtin_timeout,
10821 + &builtin_title,
10822 + &builtin_unhide,
10823 + &builtin_uppermem,
10824 + &builtin_vbeprobe,
10825 + 0
10826 +};
10827 diff -Nur grub-0.97/stage2/char_io.c grub-0.97-patched/stage2/char_io.c
10828 --- grub-0.97/stage2/char_io.c 2005-02-01 21:51:23.000000000 +0100
10829 +++ grub-0.97-patched/stage2/char_io.c 2012-11-11 17:06:52.556085241 +0100
10830 @@ -35,6 +35,7 @@
10831 {
10832 "console",
10833 0,
10834 + 24,
10835 console_putchar,
10836 console_checkkey,
10837 console_getkey,
10838 @@ -43,13 +44,16 @@
10839 console_cls,
10840 console_setcolorstate,
10841 console_setcolor,
10842 - console_setcursor
10843 + console_setcursor,
10844 + 0,
10845 + 0
10846 },
10847 #ifdef SUPPORT_SERIAL
10848 {
10849 "serial",
10850 /* A serial device must be initialized. */
10851 TERM_NEED_INIT,
10852 + 24,
10853 serial_putchar,
10854 serial_checkkey,
10855 serial_getkey,
10856 @@ -58,6 +62,8 @@
10857 serial_cls,
10858 serial_setcolorstate,
10859 0,
10860 + 0,
10861 + 0,
10862 0
10863 },
10864 #endif /* SUPPORT_SERIAL */
10865 @@ -65,6 +71,7 @@
10866 {
10867 "hercules",
10868 0,
10869 + 24,
10870 hercules_putchar,
10871 console_checkkey,
10872 console_getkey,
10873 @@ -73,9 +80,28 @@
10874 hercules_cls,
10875 hercules_setcolorstate,
10876 hercules_setcolor,
10877 - hercules_setcursor
10878 + hercules_setcursor,
10879 + 0,
10880 + 0
10881 },
10882 #endif /* SUPPORT_HERCULES */
10883 +#ifdef SUPPORT_GRAPHICS
10884 + { "graphics",
10885 + TERM_NEED_INIT, /* flags */
10886 + 30, /* number of lines */
10887 + graphics_putchar, /* putchar */
10888 + console_checkkey, /* checkkey */
10889 + console_getkey, /* getkey */
10890 + graphics_getxy, /* getxy */
10891 + graphics_gotoxy, /* gotoxy */
10892 + graphics_cls, /* cls */
10893 + graphics_setcolorstate, /* setcolorstate */
10894 + graphics_setcolor, /* setcolor */
10895 + graphics_setcursor, /* nocursor */
10896 + graphics_init, /* initialize */
10897 + graphics_end /* shutdown */
10898 + },
10899 +#endif /* SUPPORT_GRAPHICS */
10900 /* This must be the last entry. */
10901 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
10902 };
10903 @@ -1046,13 +1072,15 @@
10904 the following grub_printf call will print newlines. */
10905 count_lines = -1;
10906
10907 + grub_printf("\n");
10908 if (current_term->setcolorstate)
10909 current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
10910
10911 - grub_printf ("\n[Hit return to continue]");
10912 + grub_printf ("[Hit return to continue]");
10913
10914 if (current_term->setcolorstate)
10915 current_term->setcolorstate (COLOR_STATE_NORMAL);
10916 +
10917
10918 do
10919 {
10920 @@ -1090,7 +1118,7 @@
10921 cls (void)
10922 {
10923 /* If the terminal is dumb, there is no way to clean the terminal. */
10924 - if (current_term->flags & TERM_DUMB)
10925 + if (current_term->flags & TERM_DUMB)
10926 grub_putchar ('\n');
10927 else
10928 current_term->cls ();
10929 @@ -1174,37 +1202,62 @@
10930 }
10931 #endif /* ! STAGE1_5 */
10932
10933 +#ifdef GRUB_UTIL
10934 +# ifdef __PIC__
10935 +# if defined(HAVE_START_SYMBOL) && defined(HAVE_END_SYMBOL)
10936 + extern char start[];
10937 + extern char end[];
10938 +# elif defined(HAVE_USCORE_START_SYMBOL) && defined (HAVE_USCORE_END_SYMBOL)
10939 + extern char _start[];
10940 + extern char _end[];
10941 +# endif
10942 +# endif
10943 +#endif
10944 int
10945 -memcheck (int addr, int len)
10946 +memcheck (unsigned long addr, unsigned long len)
10947 {
10948 #ifdef GRUB_UTIL
10949 - auto int start_addr (void);
10950 - auto int end_addr (void);
10951 +# ifdef __PIC__
10952 +# if defined(HAVE_START_SYMBOL) && defined(HAVE_END_SYMBOL)
10953 + if (start <= addr && end > addr + len)
10954 + return ! errnum;
10955 +# elif defined(HAVE_USCORE_START_SYMBOL) && defined (HAVE_USCORE_END_SYMBOL)
10956 + if (_start <= addr && _end > addr + len)
10957 + return ! errnum;
10958 +# endif
10959 +# else /* __PIC__ */
10960 + auto unsigned long start_addr (void);
10961 + auto unsigned long end_addr (void);
10962
10963 - auto int start_addr (void)
10964 + auto unsigned long start_addr (void)
10965 {
10966 - int ret;
10967 -# if defined(HAVE_START_SYMBOL)
10968 + unsigned long ret;
10969 +# if defined(HAVE_START_SYMBOL)
10970 asm volatile ("movl $start, %0" : "=a" (ret));
10971 -# elif defined(HAVE_USCORE_START_SYMBOL)
10972 +# elif defined(HAVE_USCORE_START_SYMBOL)
10973 asm volatile ("movl $_start, %0" : "=a" (ret));
10974 -# endif
10975 +# else
10976 + erk! /* function would return undefined data in this case - barf */
10977 +# endif
10978 return ret;
10979 }
10980
10981 - auto int end_addr (void)
10982 + auto unsigned long end_addr (void)
10983 {
10984 - int ret;
10985 -# if defined(HAVE_END_SYMBOL)
10986 + unsigned long ret;
10987 +# if defined(HAVE_END_SYMBOL)
10988 asm volatile ("movl $end, %0" : "=a" (ret));
10989 -# elif defined(HAVE_USCORE_END_SYMBOL)
10990 +# elif defined(HAVE_USCORE_END_SYMBOL)
10991 asm volatile ("movl $_end, %0" : "=a" (ret));
10992 -# endif
10993 +# else
10994 + erk! /* function would return undefined data in this case - barf */
10995 +# endif
10996 return ret;
10997 }
10998
10999 if (start_addr () <= addr && end_addr () > addr + len)
11000 return ! errnum;
11001 +# endif /* __PIC__ */
11002 #endif /* GRUB_UTIL */
11003
11004 if ((addr < RAW_ADDR (0x1000))
11005 @@ -1217,10 +1270,20 @@
11006 return ! errnum;
11007 }
11008
11009 +void
11010 +grub_memcpy(void *dest, const void *src, int len)
11011 +{
11012 + int i;
11013 + register char *d = (char*)dest, *s = (char*)src;
11014 +
11015 + for (i = 0; i < len; i++)
11016 + d[i] = s[i];
11017 +}
11018 +
11019 void *
11020 grub_memmove (void *to, const void *from, int len)
11021 {
11022 - if (memcheck ((int) to, len))
11023 + if (memcheck ((unsigned long) to, len))
11024 {
11025 /* This assembly code is stolen from
11026 linux-2.2.2/include/asm-i386/string.h. This is not very fast
11027 @@ -1258,7 +1321,7 @@
11028 {
11029 char *p = start;
11030
11031 - if (memcheck ((int) start, len))
11032 + if (memcheck ((unsigned long) start, len))
11033 {
11034 while (len -- > 0)
11035 *p ++ = c;
11036 diff -Nur grub-0.97/stage2/char_io.c.orig grub-0.97-patched/stage2/char_io.c.orig
11037 --- grub-0.97/stage2/char_io.c.orig 1970-01-01 01:00:00.000000000 +0100
11038 +++ grub-0.97-patched/stage2/char_io.c.orig 2005-02-01 21:51:23.000000000 +0100
11039 @@ -0,0 +1,1283 @@
11040 +/* char_io.c - basic console input and output */
11041 +/*
11042 + * GRUB -- GRand Unified Bootloader
11043 + * Copyright (C) 1999,2000,2001,2002,2004 Free Software Foundation, Inc.
11044 + *
11045 + * This program is free software; you can redistribute it and/or modify
11046 + * it under the terms of the GNU General Public License as published by
11047 + * the Free Software Foundation; either version 2 of the License, or
11048 + * (at your option) any later version.
11049 + *
11050 + * This program is distributed in the hope that it will be useful,
11051 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
11052 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11053 + * GNU General Public License for more details.
11054 + *
11055 + * You should have received a copy of the GNU General Public License
11056 + * along with this program; if not, write to the Free Software
11057 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
11058 + */
11059 +
11060 +#include <shared.h>
11061 +#include <term.h>
11062 +
11063 +#ifdef SUPPORT_HERCULES
11064 +# include <hercules.h>
11065 +#endif
11066 +
11067 +#ifdef SUPPORT_SERIAL
11068 +# include <serial.h>
11069 +#endif
11070 +
11071 +#ifndef STAGE1_5
11072 +struct term_entry term_table[] =
11073 + {
11074 + {
11075 + "console",
11076 + 0,
11077 + console_putchar,
11078 + console_checkkey,
11079 + console_getkey,
11080 + console_getxy,
11081 + console_gotoxy,
11082 + console_cls,
11083 + console_setcolorstate,
11084 + console_setcolor,
11085 + console_setcursor
11086 + },
11087 +#ifdef SUPPORT_SERIAL
11088 + {
11089 + "serial",
11090 + /* A serial device must be initialized. */
11091 + TERM_NEED_INIT,
11092 + serial_putchar,
11093 + serial_checkkey,
11094 + serial_getkey,
11095 + serial_getxy,
11096 + serial_gotoxy,
11097 + serial_cls,
11098 + serial_setcolorstate,
11099 + 0,
11100 + 0
11101 + },
11102 +#endif /* SUPPORT_SERIAL */
11103 +#ifdef SUPPORT_HERCULES
11104 + {
11105 + "hercules",
11106 + 0,
11107 + hercules_putchar,
11108 + console_checkkey,
11109 + console_getkey,
11110 + hercules_getxy,
11111 + hercules_gotoxy,
11112 + hercules_cls,
11113 + hercules_setcolorstate,
11114 + hercules_setcolor,
11115 + hercules_setcursor
11116 + },
11117 +#endif /* SUPPORT_HERCULES */
11118 + /* This must be the last entry. */
11119 + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
11120 + };
11121 +
11122 +/* This must be console. */
11123 +struct term_entry *current_term = term_table;
11124 +
11125 +int max_lines = 24;
11126 +int count_lines = -1;
11127 +int use_pager = 1;
11128 +#endif
11129 +
11130 +void
11131 +print_error (void)
11132 +{
11133 + if (errnum > ERR_NONE && errnum < MAX_ERR_NUM)
11134 +#ifndef STAGE1_5
11135 + /* printf("\7\n %s\n", err_list[errnum]); */
11136 + printf ("\nError %u: %s\n", errnum, err_list[errnum]);
11137 +#else /* STAGE1_5 */
11138 + printf ("Error %u\n", errnum);
11139 +#endif /* STAGE1_5 */
11140 +}
11141 +
11142 +char *
11143 +convert_to_ascii (char *buf, int c,...)
11144 +{
11145 + unsigned long num = *((&c) + 1), mult = 10;
11146 + char *ptr = buf;
11147 +
11148 +#ifndef STAGE1_5
11149 + if (c == 'x' || c == 'X')
11150 + mult = 16;
11151 +
11152 + if ((num & 0x80000000uL) && c == 'd')
11153 + {
11154 + num = (~num) + 1;
11155 + *(ptr++) = '-';
11156 + buf++;
11157 + }
11158 +#endif
11159 +
11160 + do
11161 + {
11162 + int dig = num % mult;
11163 + *(ptr++) = ((dig > 9) ? dig + 'a' - 10 : '0' + dig);
11164 + }
11165 + while (num /= mult);
11166 +
11167 + /* reorder to correct direction!! */
11168 + {
11169 + char *ptr1 = ptr - 1;
11170 + char *ptr2 = buf;
11171 + while (ptr1 > ptr2)
11172 + {
11173 + int tmp = *ptr1;
11174 + *ptr1 = *ptr2;
11175 + *ptr2 = tmp;
11176 + ptr1--;
11177 + ptr2++;
11178 + }
11179 + }
11180 +
11181 + return ptr;
11182 +}
11183 +
11184 +void
11185 +grub_putstr (const char *str)
11186 +{
11187 + while (*str)
11188 + grub_putchar (*str++);
11189 +}
11190 +
11191 +void
11192 +grub_printf (const char *format,...)
11193 +{
11194 + int *dataptr = (int *) &format;
11195 + char c, str[16];
11196 +
11197 + dataptr++;
11198 +
11199 + while ((c = *(format++)) != 0)
11200 + {
11201 + if (c != '%')
11202 + grub_putchar (c);
11203 + else
11204 + switch (c = *(format++))
11205 + {
11206 +#ifndef STAGE1_5
11207 + case 'd':
11208 + case 'x':
11209 + case 'X':
11210 +#endif
11211 + case 'u':
11212 + *convert_to_ascii (str, c, *((unsigned long *) dataptr++)) = 0;
11213 + grub_putstr (str);
11214 + break;
11215 +
11216 +#ifndef STAGE1_5
11217 + case 'c':
11218 + grub_putchar ((*(dataptr++)) & 0xff);
11219 + break;
11220 +
11221 + case 's':
11222 + grub_putstr ((char *) *(dataptr++));
11223 + break;
11224 +#endif
11225 + }
11226 + }
11227 +}
11228 +
11229 +#ifndef STAGE1_5
11230 +int
11231 +grub_sprintf (char *buffer, const char *format, ...)
11232 +{
11233 + /* XXX hohmuth
11234 + ugly hack -- should unify with printf() */
11235 + int *dataptr = (int *) &format;
11236 + char c, *ptr, str[16];
11237 + char *bp = buffer;
11238 +
11239 + dataptr++;
11240 +
11241 + while ((c = *format++) != 0)
11242 + {
11243 + if (c != '%')
11244 + *bp++ = c; /* putchar(c); */
11245 + else
11246 + switch (c = *(format++))
11247 + {
11248 + case 'd': case 'u': case 'x':
11249 + *convert_to_ascii (str, c, *((unsigned long *) dataptr++)) = 0;
11250 +
11251 + ptr = str;
11252 +
11253 + while (*ptr)
11254 + *bp++ = *(ptr++); /* putchar(*(ptr++)); */
11255 + break;
11256 +
11257 + case 'c': *bp++ = (*(dataptr++))&0xff;
11258 + /* putchar((*(dataptr++))&0xff); */
11259 + break;
11260 +
11261 + case 's':
11262 + ptr = (char *) (*(dataptr++));
11263 +
11264 + while ((c = *ptr++) != 0)
11265 + *bp++ = c; /* putchar(c); */
11266 + break;
11267 + }
11268 + }
11269 +
11270 + *bp = 0;
11271 + return bp - buffer;
11272 +}
11273 +
11274 +
11275 +void
11276 +init_page (void)
11277 +{
11278 + cls ();
11279 +
11280 + grub_printf ("\n GNU GRUB version %s (%dK lower / %dK upper memory)\n\n",
11281 + version_string, mbi.mem_lower, mbi.mem_upper);
11282 +}
11283 +
11284 +/* The number of the history entries. */
11285 +static int num_history = 0;
11286 +
11287 +/* Get the NOth history. If NO is less than zero or greater than or
11288 + equal to NUM_HISTORY, return NULL. Otherwise return a valid string. */
11289 +static char *
11290 +get_history (int no)
11291 +{
11292 + if (no < 0 || no >= num_history)
11293 + return 0;
11294 +
11295 + return (char *) HISTORY_BUF + MAX_CMDLINE * no;
11296 +}
11297 +
11298 +/* Add CMDLINE to the history buffer. */
11299 +static void
11300 +add_history (const char *cmdline, int no)
11301 +{
11302 + grub_memmove ((char *) HISTORY_BUF + MAX_CMDLINE * (no + 1),
11303 + (char *) HISTORY_BUF + MAX_CMDLINE * no,
11304 + MAX_CMDLINE * (num_history - no));
11305 + grub_strcpy ((char *) HISTORY_BUF + MAX_CMDLINE * no, cmdline);
11306 + if (num_history < HISTORY_SIZE)
11307 + num_history++;
11308 +}
11309 +
11310 +static int
11311 +real_get_cmdline (char *prompt, char *cmdline, int maxlen,
11312 + int echo_char, int readline)
11313 +{
11314 + /* This is a rather complicated function. So explain the concept.
11315 +
11316 + A command-line consists of ``section''s. A section is a part of the
11317 + line which may be displayed on the screen, but a section is never
11318 + displayed with another section simultaneously.
11319 +
11320 + Each section is basically 77 or less characters, but the exception
11321 + is the first section, which is 78 or less characters, because the
11322 + starting point is special. See below.
11323 +
11324 + The first section contains a prompt and a command-line (or the
11325 + first part of a command-line when it is too long to be fit in the
11326 + screen). So, in the first section, the number of command-line
11327 + characters displayed is 78 minus the length of the prompt (or
11328 + less). If the command-line has more characters, `>' is put at the
11329 + position 78 (zero-origin), to inform the user of the hidden
11330 + characters.
11331 +
11332 + Other sections always have `<' at the first position, since there
11333 + is absolutely a section before each section. If there is a section
11334 + after another section, this section consists of 77 characters and
11335 + `>' at the last position. The last section has 77 or less
11336 + characters and doesn't have `>'.
11337 +
11338 + Each section other than the last shares some characters with the
11339 + previous section. This region is called ``margin''. If the cursor
11340 + is put at the magin which is shared by the first section and the
11341 + second, the first section is displayed. Otherwise, a displayed
11342 + section is switched to another section, only if the cursor is put
11343 + outside that section. */
11344 +
11345 + /* XXX: These should be defined in shared.h, but I leave these here,
11346 + until this code is freezed. */
11347 +#define CMDLINE_WIDTH 78
11348 +#define CMDLINE_MARGIN 10
11349 +
11350 + int xpos, lpos, c, section;
11351 + /* The length of PROMPT. */
11352 + int plen;
11353 + /* The length of the command-line. */
11354 + int llen;
11355 + /* The index for the history. */
11356 + int history = -1;
11357 + /* The working buffer for the command-line. */
11358 + char *buf = (char *) CMDLINE_BUF;
11359 + /* The kill buffer. */
11360 + char *kill_buf = (char *) KILL_BUF;
11361 +
11362 + /* Nested function definitions for code simplicity. */
11363 +
11364 + /* The forward declarations of nested functions are prefixed
11365 + with `auto'. */
11366 + auto void cl_refresh (int full, int len);
11367 + auto void cl_backward (int count);
11368 + auto void cl_forward (int count);
11369 + auto void cl_insert (const char *str);
11370 + auto void cl_delete (int count);
11371 + auto void cl_init (void);
11372 +
11373 + /* Move the cursor backward. */
11374 + void cl_backward (int count)
11375 + {
11376 + lpos -= count;
11377 +
11378 + /* If the cursor is in the first section, display the first section
11379 + instead of the second. */
11380 + if (section == 1 && plen + lpos < CMDLINE_WIDTH)
11381 + cl_refresh (1, 0);
11382 + else if (xpos - count < 1)
11383 + cl_refresh (1, 0);
11384 + else
11385 + {
11386 + xpos -= count;
11387 +
11388 + if (current_term->flags & TERM_DUMB)
11389 + {
11390 + int i;
11391 +
11392 + for (i = 0; i < count; i++)
11393 + grub_putchar ('\b');
11394 + }
11395 + else
11396 + gotoxy (xpos, getxy () & 0xFF);
11397 + }
11398 + }
11399 +
11400 + /* Move the cursor forward. */
11401 + void cl_forward (int count)
11402 + {
11403 + lpos += count;
11404 +
11405 + /* If the cursor goes outside, scroll the screen to the right. */
11406 + if (xpos + count >= CMDLINE_WIDTH)
11407 + cl_refresh (1, 0);
11408 + else
11409 + {
11410 + xpos += count;
11411 +
11412 + if (current_term->flags & TERM_DUMB)
11413 + {
11414 + int i;
11415 +
11416 + for (i = lpos - count; i < lpos; i++)
11417 + {
11418 + if (! echo_char)
11419 + grub_putchar (buf[i]);
11420 + else
11421 + grub_putchar (echo_char);
11422 + }
11423 + }
11424 + else
11425 + gotoxy (xpos, getxy () & 0xFF);
11426 + }
11427 + }
11428 +
11429 + /* Refresh the screen. If FULL is true, redraw the full line, otherwise,
11430 + only LEN characters from LPOS. */
11431 + void cl_refresh (int full, int len)
11432 + {
11433 + int i;
11434 + int start;
11435 + int pos = xpos;
11436 +
11437 + if (full)
11438 + {
11439 + /* Recompute the section number. */
11440 + if (lpos + plen < CMDLINE_WIDTH)
11441 + section = 0;
11442 + else
11443 + section = ((lpos + plen - CMDLINE_WIDTH)
11444 + / (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN) + 1);
11445 +
11446 + /* From the start to the end. */
11447 + len = CMDLINE_WIDTH;
11448 + pos = 0;
11449 + grub_putchar ('\r');
11450 +
11451 + /* If SECTION is the first section, print the prompt, otherwise,
11452 + print `<'. */
11453 + if (section == 0)
11454 + {
11455 + grub_printf ("%s", prompt);
11456 + len -= plen;
11457 + pos += plen;
11458 + }
11459 + else
11460 + {
11461 + grub_putchar ('<');
11462 + len--;
11463 + pos++;
11464 + }
11465 + }
11466 +
11467 + /* Compute the index to start writing BUF and the resulting position
11468 + on the screen. */
11469 + if (section == 0)
11470 + {
11471 + int offset = 0;
11472 +
11473 + if (! full)
11474 + offset = xpos - plen;
11475 +
11476 + start = 0;
11477 + xpos = lpos + plen;
11478 + start += offset;
11479 + }
11480 + else
11481 + {
11482 + int offset = 0;
11483 +
11484 + if (! full)
11485 + offset = xpos - 1;
11486 +
11487 + start = ((section - 1) * (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN)
11488 + + CMDLINE_WIDTH - plen - CMDLINE_MARGIN);
11489 + xpos = lpos + 1 - start;
11490 + start += offset;
11491 + }
11492 +
11493 + /* Print BUF. If ECHO_CHAR is not zero, put it instead. */
11494 + for (i = start; i < start + len && i < llen; i++)
11495 + {
11496 + if (! echo_char)
11497 + grub_putchar (buf[i]);
11498 + else
11499 + grub_putchar (echo_char);
11500 +
11501 + pos++;
11502 + }
11503 +
11504 + /* Fill up the rest of the line with spaces. */
11505 + for (; i < start + len; i++)
11506 + {
11507 + grub_putchar (' ');
11508 + pos++;
11509 + }
11510 +
11511 + /* If the cursor is at the last position, put `>' or a space,
11512 + depending on if there are more characters in BUF. */
11513 + if (pos == CMDLINE_WIDTH)
11514 + {
11515 + if (start + len < llen)
11516 + grub_putchar ('>');
11517 + else
11518 + grub_putchar (' ');
11519 +
11520 + pos++;
11521 + }
11522 +
11523 + /* Back to XPOS. */
11524 + if (current_term->flags & TERM_DUMB)
11525 + {
11526 + for (i = 0; i < pos - xpos; i++)
11527 + grub_putchar ('\b');
11528 + }
11529 + else
11530 + gotoxy (xpos, getxy () & 0xFF);
11531 + }
11532 +
11533 + /* Initialize the command-line. */
11534 + void cl_init (void)
11535 + {
11536 + /* Distinguish us from other lines and error messages! */
11537 + grub_putchar ('\n');
11538 +
11539 + /* Print full line and set position here. */
11540 + cl_refresh (1, 0);
11541 + }
11542 +
11543 + /* Insert STR to BUF. */
11544 + void cl_insert (const char *str)
11545 + {
11546 + int l = grub_strlen (str);
11547 +
11548 + if (llen + l < maxlen)
11549 + {
11550 + if (lpos == llen)
11551 + grub_memmove (buf + lpos, str, l + 1);
11552 + else
11553 + {
11554 + grub_memmove (buf + lpos + l, buf + lpos, llen - lpos + 1);
11555 + grub_memmove (buf + lpos, str, l);
11556 + }
11557 +
11558 + llen += l;
11559 + lpos += l;
11560 + if (xpos + l >= CMDLINE_WIDTH)
11561 + cl_refresh (1, 0);
11562 + else if (xpos + l + llen - lpos > CMDLINE_WIDTH)
11563 + cl_refresh (0, CMDLINE_WIDTH - xpos);
11564 + else
11565 + cl_refresh (0, l + llen - lpos);
11566 + }
11567 + }
11568 +
11569 + /* Delete COUNT characters in BUF. */
11570 + void cl_delete (int count)
11571 + {
11572 + grub_memmove (buf + lpos, buf + lpos + count, llen - count + 1);
11573 + llen -= count;
11574 +
11575 + if (xpos + llen + count - lpos > CMDLINE_WIDTH)
11576 + cl_refresh (0, CMDLINE_WIDTH - xpos);
11577 + else
11578 + cl_refresh (0, llen + count - lpos);
11579 + }
11580 +
11581 + plen = grub_strlen (prompt);
11582 + llen = grub_strlen (cmdline);
11583 +
11584 + if (maxlen > MAX_CMDLINE)
11585 + {
11586 + maxlen = MAX_CMDLINE;
11587 + if (llen >= MAX_CMDLINE)
11588 + {
11589 + llen = MAX_CMDLINE - 1;
11590 + cmdline[MAX_CMDLINE] = 0;
11591 + }
11592 + }
11593 + lpos = llen;
11594 + grub_strcpy (buf, cmdline);
11595 +
11596 + cl_init ();
11597 +
11598 + while ((c = ASCII_CHAR (getkey ())) != '\n' && c != '\r')
11599 + {
11600 + /* If READLINE is non-zero, handle readline-like key bindings. */
11601 + if (readline)
11602 + {
11603 + switch (c)
11604 + {
11605 + case 9: /* TAB lists completions */
11606 + {
11607 + int i;
11608 + /* POS points to the first space after a command. */
11609 + int pos = 0;
11610 + int ret;
11611 + char *completion_buffer = (char *) COMPLETION_BUF;
11612 + int equal_pos = -1;
11613 + int is_filename;
11614 +
11615 + /* Find the first word. */
11616 + while (buf[pos] == ' ')
11617 + pos++;
11618 + while (buf[pos] && buf[pos] != '=' && buf[pos] != ' ')
11619 + pos++;
11620 +
11621 + is_filename = (lpos > pos);
11622 +
11623 + /* Find the position of the equal character after a
11624 + command, and replace it with a space. */
11625 + for (i = pos; buf[i] && buf[i] != ' '; i++)
11626 + if (buf[i] == '=')
11627 + {
11628 + equal_pos = i;
11629 + buf[i] = ' ';
11630 + break;
11631 + }
11632 +
11633 + /* Find the position of the first character in this
11634 + word. */
11635 + for (i = lpos; i > 0 && buf[i - 1] != ' '; i--)
11636 + ;
11637 +
11638 + /* Invalidate the cache, because the user may exchange
11639 + removable disks. */
11640 + buf_drive = -1;
11641 +
11642 + /* Copy this word to COMPLETION_BUFFER and do the
11643 + completion. */
11644 + grub_memmove (completion_buffer, buf + i, lpos - i);
11645 + completion_buffer[lpos - i] = 0;
11646 + ret = print_completions (is_filename, 1);
11647 + errnum = ERR_NONE;
11648 +
11649 + if (ret >= 0)
11650 + {
11651 + /* Found, so insert COMPLETION_BUFFER. */
11652 + cl_insert (completion_buffer + lpos - i);
11653 +
11654 + if (ret > 0)
11655 + {
11656 + /* There are more than one candidates, so print
11657 + the list. */
11658 + grub_putchar ('\n');
11659 + print_completions (is_filename, 0);
11660 + errnum = ERR_NONE;
11661 + }
11662 + }
11663 +
11664 + /* Restore the command-line. */
11665 + if (equal_pos >= 0)
11666 + buf[equal_pos] = '=';
11667 +
11668 + if (ret)
11669 + cl_init ();
11670 + }
11671 + break;
11672 + case 1: /* C-a go to beginning of line */
11673 + cl_backward (lpos);
11674 + break;
11675 + case 5: /* C-e go to end of line */
11676 + cl_forward (llen - lpos);
11677 + break;
11678 + case 6: /* C-f forward one character */
11679 + if (lpos < llen)
11680 + cl_forward (1);
11681 + break;
11682 + case 2: /* C-b backward one character */
11683 + if (lpos > 0)
11684 + cl_backward (1);
11685 + break;
11686 + case 21: /* C-u kill to beginning of line */
11687 + if (lpos == 0)
11688 + break;
11689 + /* Copy the string being deleted to KILL_BUF. */
11690 + grub_memmove (kill_buf, buf, lpos);
11691 + kill_buf[lpos] = 0;
11692 + {
11693 + /* XXX: Not very clever. */
11694 +
11695 + int count = lpos;
11696 +
11697 + cl_backward (lpos);
11698 + cl_delete (count);
11699 + }
11700 + break;
11701 + case 11: /* C-k kill to end of line */
11702 + if (lpos == llen)
11703 + break;
11704 + /* Copy the string being deleted to KILL_BUF. */
11705 + grub_memmove (kill_buf, buf + lpos, llen - lpos + 1);
11706 + cl_delete (llen - lpos);
11707 + break;
11708 + case 25: /* C-y yank the kill buffer */
11709 + cl_insert (kill_buf);
11710 + break;
11711 + case 16: /* C-p fetch the previous command */
11712 + {
11713 + char *p;
11714 +
11715 + if (history < 0)
11716 + /* Save the working buffer. */
11717 + grub_strcpy (cmdline, buf);
11718 + else if (grub_strcmp (get_history (history), buf) != 0)
11719 + /* If BUF is modified, add it into the history list. */
11720 + add_history (buf, history);
11721 +
11722 + history++;
11723 + p = get_history (history);
11724 + if (! p)
11725 + {
11726 + history--;
11727 + break;
11728 + }
11729 +
11730 + grub_strcpy (buf, p);
11731 + llen = grub_strlen (buf);
11732 + lpos = llen;
11733 + cl_refresh (1, 0);
11734 + }
11735 + break;
11736 + case 14: /* C-n fetch the next command */
11737 + {
11738 + char *p;
11739 +
11740 + if (history < 0)
11741 + {
11742 + break;
11743 + }
11744 + else if (grub_strcmp (get_history (history), buf) != 0)
11745 + /* If BUF is modified, add it into the history list. */
11746 + add_history (buf, history);
11747 +
11748 + history--;
11749 + p = get_history (history);
11750 + if (! p)
11751 + p = cmdline;
11752 +
11753 + grub_strcpy (buf, p);
11754 + llen = grub_strlen (buf);
11755 + lpos = llen;
11756 + cl_refresh (1, 0);
11757 + }
11758 + break;
11759 + }
11760 + }
11761 +
11762 + /* ESC, C-d and C-h are always handled. Actually C-d is not
11763 + functional if READLINE is zero, as the cursor cannot go
11764 + backward, but that's ok. */
11765 + switch (c)
11766 + {
11767 + case 27: /* ESC immediately return 1 */
11768 + return 1;
11769 + case 4: /* C-d delete character under cursor */
11770 + if (lpos == llen)
11771 + break;
11772 + cl_delete (1);
11773 + break;
11774 + case 8: /* C-h backspace */
11775 +# ifdef GRUB_UTIL
11776 + case 127: /* also backspace */
11777 +# endif
11778 + if (lpos > 0)
11779 + {
11780 + cl_backward (1);
11781 + cl_delete (1);
11782 + }
11783 + break;
11784 + default: /* insert printable character into line */
11785 + if (c >= ' ' && c <= '~')
11786 + {
11787 + char str[2];
11788 +
11789 + str[0] = c;
11790 + str[1] = 0;
11791 + cl_insert (str);
11792 + }
11793 + }
11794 + }
11795 +
11796 + grub_putchar ('\n');
11797 +
11798 + /* If ECHO_CHAR is NUL, remove the leading spaces. */
11799 + lpos = 0;
11800 + if (! echo_char)
11801 + while (buf[lpos] == ' ')
11802 + lpos++;
11803 +
11804 + /* Copy the working buffer to CMDLINE. */
11805 + grub_memmove (cmdline, buf + lpos, llen - lpos + 1);
11806 +
11807 + /* If the readline-like feature is turned on and CMDLINE is not
11808 + empty, add it into the history list. */
11809 + if (readline && lpos < llen)
11810 + add_history (cmdline, 0);
11811 +
11812 + return 0;
11813 +}
11814 +
11815 +/* Don't use this with a MAXLEN greater than 1600 or so! The problem
11816 + is that GET_CMDLINE depends on the everything fitting on the screen
11817 + at once. So, the whole screen is about 2000 characters, minus the
11818 + PROMPT, and space for error and status lines, etc. MAXLEN must be
11819 + at least 1, and PROMPT and CMDLINE must be valid strings (not NULL
11820 + or zero-length).
11821 +
11822 + If ECHO_CHAR is nonzero, echo it instead of the typed character. */
11823 +int
11824 +get_cmdline (char *prompt, char *cmdline, int maxlen,
11825 + int echo_char, int readline)
11826 +{
11827 + int old_cursor;
11828 + int ret;
11829 +
11830 + old_cursor = setcursor (1);
11831 +
11832 + /* Because it is hard to deal with different conditions simultaneously,
11833 + less functional cases are handled here. Assume that TERM_NO_ECHO
11834 + implies TERM_NO_EDIT. */
11835 + if (current_term->flags & (TERM_NO_ECHO | TERM_NO_EDIT))
11836 + {
11837 + char *p = cmdline;
11838 + int c;
11839 +
11840 + /* Make sure that MAXLEN is not too large. */
11841 + if (maxlen > MAX_CMDLINE)
11842 + maxlen = MAX_CMDLINE;
11843 +
11844 + /* Print only the prompt. The contents of CMDLINE is simply discarded,
11845 + even if it is not empty. */
11846 + grub_printf ("%s", prompt);
11847 +
11848 + /* Gather characters until a newline is gotten. */
11849 + while ((c = ASCII_CHAR (getkey ())) != '\n' && c != '\r')
11850 + {
11851 + /* Return immediately if ESC is pressed. */
11852 + if (c == 27)
11853 + {
11854 + setcursor (old_cursor);
11855 + return 1;
11856 + }
11857 +
11858 + /* Printable characters are added into CMDLINE. */
11859 + if (c >= ' ' && c <= '~')
11860 + {
11861 + if (! (current_term->flags & TERM_NO_ECHO))
11862 + grub_putchar (c);
11863 +
11864 + /* Preceding space characters must be ignored. */
11865 + if (c != ' ' || p != cmdline)
11866 + *p++ = c;
11867 + }
11868 + }
11869 +
11870 + *p = 0;
11871 +
11872 + if (! (current_term->flags & TERM_NO_ECHO))
11873 + grub_putchar ('\n');
11874 +
11875 + setcursor (old_cursor);
11876 + return 0;
11877 + }
11878 +
11879 + /* Complicated features are left to real_get_cmdline. */
11880 + ret = real_get_cmdline (prompt, cmdline, maxlen, echo_char, readline);
11881 + setcursor (old_cursor);
11882 + return ret;
11883 +}
11884 +
11885 +int
11886 +safe_parse_maxint (char **str_ptr, int *myint_ptr)
11887 +{
11888 + char *ptr = *str_ptr;
11889 + int myint = 0;
11890 + int mult = 10, found = 0;
11891 +
11892 + /*
11893 + * Is this a hex number?
11894 + */
11895 + if (*ptr == '0' && tolower (*(ptr + 1)) == 'x')
11896 + {
11897 + ptr += 2;
11898 + mult = 16;
11899 + }
11900 +
11901 + while (1)
11902 + {
11903 + /* A bit tricky. This below makes use of the equivalence:
11904 + (A >= B && A <= C) <=> ((A - B) <= (C - B))
11905 + when C > B and A is unsigned. */
11906 + unsigned int digit;
11907 +
11908 + digit = tolower (*ptr) - '0';
11909 + if (digit > 9)
11910 + {
11911 + digit -= 'a' - '0';
11912 + if (mult == 10 || digit > 5)
11913 + break;
11914 + digit += 10;
11915 + }
11916 +
11917 + found = 1;
11918 + if (myint > ((MAXINT - digit) / mult))
11919 + {
11920 + errnum = ERR_NUMBER_OVERFLOW;
11921 + return 0;
11922 + }
11923 + myint = (myint * mult) + digit;
11924 + ptr++;
11925 + }
11926 +
11927 + if (!found)
11928 + {
11929 + errnum = ERR_NUMBER_PARSING;
11930 + return 0;
11931 + }
11932 +
11933 + *str_ptr = ptr;
11934 + *myint_ptr = myint;
11935 +
11936 + return 1;
11937 +}
11938 +#endif /* STAGE1_5 */
11939 +
11940 +#if !defined(STAGE1_5) || defined(FSYS_FAT)
11941 +int
11942 +grub_tolower (int c)
11943 +{
11944 + if (c >= 'A' && c <= 'Z')
11945 + return (c + ('a' - 'A'));
11946 +
11947 + return c;
11948 +}
11949 +#endif /* ! STAGE1_5 || FSYS_FAT */
11950 +
11951 +int
11952 +grub_isspace (int c)
11953 +{
11954 + switch (c)
11955 + {
11956 + case ' ':
11957 + case '\t':
11958 + case '\r':
11959 + case '\n':
11960 + return 1;
11961 + default:
11962 + break;
11963 + }
11964 +
11965 + return 0;
11966 +}
11967 +
11968 +#if !defined(STAGE1_5) || defined(FSYS_ISO9660)
11969 +int
11970 +grub_memcmp (const char *s1, const char *s2, int n)
11971 +{
11972 + while (n)
11973 + {
11974 + if (*s1 < *s2)
11975 + return -1;
11976 + else if (*s1 > *s2)
11977 + return 1;
11978 + s1++;
11979 + s2++;
11980 + n--;
11981 + }
11982 +
11983 + return 0;
11984 +}
11985 +#endif /* ! STAGE1_5 || FSYS_ISO9660 */
11986 +
11987 +#ifndef STAGE1_5
11988 +int
11989 +grub_strncat (char *s1, const char *s2, int n)
11990 +{
11991 + int i = -1;
11992 +
11993 + while (++i < n && s1[i] != 0);
11994 +
11995 + while (i < n && (s1[i++] = *(s2++)) != 0);
11996 +
11997 + s1[n - 1] = 0;
11998 +
11999 + if (i >= n)
12000 + return 0;
12001 +
12002 + s1[i] = 0;
12003 +
12004 + return 1;
12005 +}
12006 +#endif /* ! STAGE1_5 */
12007 +
12008 +/* XXX: This below is an evil hack. Certainly, we should change the
12009 + strategy to determine what should be defined and what shouldn't be
12010 + defined for each image. For example, it would be better to create
12011 + a static library supporting minimal standard C functions and link
12012 + each image with the library. Complicated things should be left to
12013 + computer, definitely. -okuji */
12014 +#if !defined(STAGE1_5) || defined(FSYS_VSTAFS)
12015 +int
12016 +grub_strcmp (const char *s1, const char *s2)
12017 +{
12018 + while (*s1 || *s2)
12019 + {
12020 + if (*s1 < *s2)
12021 + return -1;
12022 + else if (*s1 > *s2)
12023 + return 1;
12024 + s1 ++;
12025 + s2 ++;
12026 + }
12027 +
12028 + return 0;
12029 +}
12030 +#endif /* ! STAGE1_5 || FSYS_VSTAFS */
12031 +
12032 +#ifndef STAGE1_5
12033 +/* Wait for a keypress and return its code. */
12034 +int
12035 +getkey (void)
12036 +{
12037 + return current_term->getkey ();
12038 +}
12039 +
12040 +/* Check if a key code is available. */
12041 +int
12042 +checkkey (void)
12043 +{
12044 + return current_term->checkkey ();
12045 +}
12046 +#endif /* ! STAGE1_5 */
12047 +
12048 +/* Display an ASCII character. */
12049 +void
12050 +grub_putchar (int c)
12051 +{
12052 + if (c == '\n')
12053 + grub_putchar ('\r');
12054 +#ifndef STAGE1_5
12055 + else if (c == '\t' && current_term->getxy)
12056 + {
12057 + int n;
12058 +
12059 + n = 8 - ((current_term->getxy () >> 8) & 3);
12060 + while (n--)
12061 + grub_putchar (' ');
12062 +
12063 + return;
12064 + }
12065 +#endif /* ! STAGE1_5 */
12066 +
12067 +#ifdef STAGE1_5
12068 +
12069 + /* In Stage 1.5, only the normal console is supported. */
12070 + console_putchar (c);
12071 +
12072 +#else /* ! STAGE1_5 */
12073 +
12074 + if (c == '\n')
12075 + {
12076 + /* Internal `more'-like feature. */
12077 + if (count_lines >= 0)
12078 + {
12079 + count_lines++;
12080 + if (count_lines >= max_lines - 2)
12081 + {
12082 + int tmp;
12083 +
12084 + /* It's important to disable the feature temporarily, because
12085 + the following grub_printf call will print newlines. */
12086 + count_lines = -1;
12087 +
12088 + if (current_term->setcolorstate)
12089 + current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
12090 +
12091 + grub_printf ("\n[Hit return to continue]");
12092 +
12093 + if (current_term->setcolorstate)
12094 + current_term->setcolorstate (COLOR_STATE_NORMAL);
12095 +
12096 + do
12097 + {
12098 + tmp = ASCII_CHAR (getkey ());
12099 + }
12100 + while (tmp != '\n' && tmp != '\r');
12101 + grub_printf ("\r \r");
12102 +
12103 + /* Restart to count lines. */
12104 + count_lines = 0;
12105 + return;
12106 + }
12107 + }
12108 + }
12109 +
12110 + current_term->putchar (c);
12111 +
12112 +#endif /* ! STAGE1_5 */
12113 +}
12114 +
12115 +#ifndef STAGE1_5
12116 +void
12117 +gotoxy (int x, int y)
12118 +{
12119 + current_term->gotoxy (x, y);
12120 +}
12121 +
12122 +int
12123 +getxy (void)
12124 +{
12125 + return current_term->getxy ();
12126 +}
12127 +
12128 +void
12129 +cls (void)
12130 +{
12131 + /* If the terminal is dumb, there is no way to clean the terminal. */
12132 + if (current_term->flags & TERM_DUMB)
12133 + grub_putchar ('\n');
12134 + else
12135 + current_term->cls ();
12136 +}
12137 +
12138 +int
12139 +setcursor (int on)
12140 +{
12141 + if (current_term->setcursor)
12142 + return current_term->setcursor (on);
12143 +
12144 + return 1;
12145 +}
12146 +#endif /* ! STAGE1_5 */
12147 +
12148 +int
12149 +substring (const char *s1, const char *s2)
12150 +{
12151 + while (*s1 == *s2)
12152 + {
12153 + /* The strings match exactly. */
12154 + if (! *(s1++))
12155 + return 0;
12156 + s2 ++;
12157 + }
12158 +
12159 + /* S1 is a substring of S2. */
12160 + if (*s1 == 0)
12161 + return -1;
12162 +
12163 + /* S1 isn't a substring. */
12164 + return 1;
12165 +}
12166 +
12167 +#ifndef STAGE1_5
12168 +/* Terminate the string STR with NUL. */
12169 +int
12170 +nul_terminate (char *str)
12171 +{
12172 + int ch;
12173 +
12174 + while (*str && ! grub_isspace (*str))
12175 + str++;
12176 +
12177 + ch = *str;
12178 + *str = 0;
12179 + return ch;
12180 +}
12181 +
12182 +char *
12183 +grub_strstr (const char *s1, const char *s2)
12184 +{
12185 + while (*s1)
12186 + {
12187 + const char *ptr, *tmp;
12188 +
12189 + ptr = s1;
12190 + tmp = s2;
12191 +
12192 + while (*tmp && *ptr == *tmp)
12193 + ptr++, tmp++;
12194 +
12195 + if (tmp > s2 && ! *tmp)
12196 + return (char *) s1;
12197 +
12198 + s1++;
12199 + }
12200 +
12201 + return 0;
12202 +}
12203 +
12204 +int
12205 +grub_strlen (const char *str)
12206 +{
12207 + int len = 0;
12208 +
12209 + while (*str++)
12210 + len++;
12211 +
12212 + return len;
12213 +}
12214 +#endif /* ! STAGE1_5 */
12215 +
12216 +int
12217 +memcheck (int addr, int len)
12218 +{
12219 +#ifdef GRUB_UTIL
12220 + auto int start_addr (void);
12221 + auto int end_addr (void);
12222 +
12223 + auto int start_addr (void)
12224 + {
12225 + int ret;
12226 +# if defined(HAVE_START_SYMBOL)
12227 + asm volatile ("movl $start, %0" : "=a" (ret));
12228 +# elif defined(HAVE_USCORE_START_SYMBOL)
12229 + asm volatile ("movl $_start, %0" : "=a" (ret));
12230 +# endif
12231 + return ret;
12232 + }
12233 +
12234 + auto int end_addr (void)
12235 + {
12236 + int ret;
12237 +# if defined(HAVE_END_SYMBOL)
12238 + asm volatile ("movl $end, %0" : "=a" (ret));
12239 +# elif defined(HAVE_USCORE_END_SYMBOL)
12240 + asm volatile ("movl $_end, %0" : "=a" (ret));
12241 +# endif
12242 + return ret;
12243 + }
12244 +
12245 + if (start_addr () <= addr && end_addr () > addr + len)
12246 + return ! errnum;
12247 +#endif /* GRUB_UTIL */
12248 +
12249 + if ((addr < RAW_ADDR (0x1000))
12250 + || (addr < RAW_ADDR (0x100000)
12251 + && RAW_ADDR (mbi.mem_lower * 1024) < (addr + len))
12252 + || (addr >= RAW_ADDR (0x100000)
12253 + && RAW_ADDR (mbi.mem_upper * 1024) < ((addr - 0x100000) + len)))
12254 + errnum = ERR_WONT_FIT;
12255 +
12256 + return ! errnum;
12257 +}
12258 +
12259 +void *
12260 +grub_memmove (void *to, const void *from, int len)
12261 +{
12262 + if (memcheck ((int) to, len))
12263 + {
12264 + /* This assembly code is stolen from
12265 + linux-2.2.2/include/asm-i386/string.h. This is not very fast
12266 + but compact. */
12267 + int d0, d1, d2;
12268 +
12269 + if (to < from)
12270 + {
12271 + asm volatile ("cld\n\t"
12272 + "rep\n\t"
12273 + "movsb"
12274 + : "=&c" (d0), "=&S" (d1), "=&D" (d2)
12275 + : "0" (len),"1" (from),"2" (to)
12276 + : "memory");
12277 + }
12278 + else
12279 + {
12280 + asm volatile ("std\n\t"
12281 + "rep\n\t"
12282 + "movsb\n\t"
12283 + "cld"
12284 + : "=&c" (d0), "=&S" (d1), "=&D" (d2)
12285 + : "0" (len),
12286 + "1" (len - 1 + (const char *) from),
12287 + "2" (len - 1 + (char *) to)
12288 + : "memory");
12289 + }
12290 + }
12291 +
12292 + return errnum ? NULL : to;
12293 +}
12294 +
12295 +void *
12296 +grub_memset (void *start, int c, int len)
12297 +{
12298 + char *p = start;
12299 +
12300 + if (memcheck ((int) start, len))
12301 + {
12302 + while (len -- > 0)
12303 + *p ++ = c;
12304 + }
12305 +
12306 + return errnum ? NULL : start;
12307 +}
12308 +
12309 +#ifndef STAGE1_5
12310 +char *
12311 +grub_strcpy (char *dest, const char *src)
12312 +{
12313 + grub_memmove (dest, src, grub_strlen (src) + 1);
12314 + return dest;
12315 +}
12316 +#endif /* ! STAGE1_5 */
12317 +
12318 +#ifndef GRUB_UTIL
12319 +# undef memcpy
12320 +/* GCC emits references to memcpy() for struct copies etc. */
12321 +void *memcpy (void *dest, const void *src, int n) __attribute__ ((alias ("grub_memmove")));
12322 +#endif
12323 diff -Nur grub-0.97/stage2/common.c grub-0.97-patched/stage2/common.c
12324 --- grub-0.97/stage2/common.c 2004-03-27 17:25:44.000000000 +0100
12325 +++ grub-0.97-patched/stage2/common.c 2012-11-11 17:06:52.558085305 +0100
12326 @@ -142,7 +142,8 @@
12327 init_bios_info (void)
12328 {
12329 #ifndef STAGE1_5
12330 - unsigned long cont, memtmp, addr;
12331 + unsigned long memtmp, addr;
12332 + volatile unsigned long cont;
12333 int drive;
12334 #endif
12335
12336 diff -Nur grub-0.97/stage2/disk_io.c grub-0.97-patched/stage2/disk_io.c
12337 --- grub-0.97/stage2/disk_io.c 2004-05-23 18:35:24.000000000 +0200
12338 +++ grub-0.97-patched/stage2/disk_io.c 2012-11-11 17:07:12.740730013 +0100
12339 @@ -21,6 +21,7 @@
12340
12341 #include <shared.h>
12342 #include <filesys.h>
12343 +#include <gpt.h>
12344
12345 #ifdef SUPPORT_NETBOOT
12346 # define GRUB 1
12347 @@ -137,7 +138,7 @@
12348 }
12349
12350 int
12351 -rawread (int drive, int sector, int byte_offset, int byte_len, char *buf)
12352 +rawread (int drive, unsigned int sector, int byte_offset, int byte_len, char *buf)
12353 {
12354 int slen, sectors_per_vtrack;
12355 int sector_size_bits = log2 (buf_geom.sector_size);
12356 @@ -261,7 +262,7 @@
12357 */
12358 if (disk_read_func)
12359 {
12360 - int sector_num = sector;
12361 + unsigned int sector_num = sector;
12362 int length = buf_geom.sector_size - byte_offset;
12363 if (length > size)
12364 length = size;
12365 @@ -291,7 +292,7 @@
12366
12367
12368 int
12369 -devread (int sector, int byte_offset, int byte_len, char *buf)
12370 +devread (unsigned int sector, int byte_offset, int byte_len, char *buf)
12371 {
12372 /*
12373 * Check partition boundaries
12374 @@ -330,7 +331,7 @@
12375
12376 #ifndef STAGE1_5
12377 int
12378 -rawwrite (int drive, int sector, char *buf)
12379 +rawwrite (int drive, unsigned int sector, char *buf)
12380 {
12381 if (sector == 0)
12382 {
12383 @@ -363,7 +364,7 @@
12384 }
12385
12386 int
12387 -devwrite (int sector, int sector_count, char *buf)
12388 +devwrite (unsigned int sector, int sector_count, char *buf)
12389 {
12390 #if defined(GRUB_UTIL) && defined(__linux__)
12391 if (current_partition != 0xFFFFFF
12392 @@ -502,8 +503,8 @@
12393 set_partition_hidden_flag (int hidden)
12394 {
12395 unsigned long part = 0xFFFFFF;
12396 - unsigned long start, len, offset, ext_offset;
12397 - int entry, type;
12398 + unsigned long start, len, offset, ext_offset, gpt_offset;
12399 + int entry, type, gpt_count, gpt_size;
12400 char mbr[512];
12401
12402 /* The drive must be a hard disk. */
12403 @@ -524,8 +525,15 @@
12404 /* Look for the partition. */
12405 while (next_partition (current_drive, 0xFFFFFF, &part, &type,
12406 &start, &len, &offset, &entry,
12407 - &ext_offset, mbr))
12408 + &ext_offset, &gpt_offset, &gpt_count, &gpt_size, mbr))
12409 {
12410 + /* The partition may not be a GPT partition. */
12411 + if (gpt_offset != 0)
12412 + {
12413 + errnum = ERR_BAD_ARGUMENT;
12414 + return 1;
12415 + }
12416 +
12417 if (part == current_partition)
12418 {
12419 /* Found. */
12420 @@ -577,11 +585,14 @@
12421 unsigned long *partition, int *type,
12422 unsigned long *start, unsigned long *len,
12423 unsigned long *offset, int *entry,
12424 - unsigned long *ext_offset, char *buf)
12425 + unsigned long *ext_offset,
12426 + unsigned long *gpt_offset, int *gpt_count,
12427 + int *gpt_size, char *buf)
12428 {
12429 /* Forward declarations. */
12430 auto int next_bsd_partition (void);
12431 auto int next_pc_slice (void);
12432 + auto int next_gpt_slice(void);
12433
12434 /* Get next BSD partition in current PC slice. */
12435 int next_bsd_partition (void)
12436 @@ -666,6 +677,40 @@
12437 return 0;
12438 }
12439
12440 + /* If this is a GPT partition table, read it as such. */
12441 + if (*entry == -1 && *offset == 0 && PC_SLICE_TYPE (buf, 0) == PC_SLICE_TYPE_GPT)
12442 + {
12443 + struct grub_gpt_header *hdr = (struct grub_gpt_header *) buf;
12444 +
12445 + /* Read in the GPT Partition table header. */
12446 + if (! rawread (drive, 1, 0, SECTOR_SIZE, buf))
12447 + return 0;
12448 +
12449 + if (hdr->magic == GPT_HEADER_MAGIC && hdr->version == 0x10000)
12450 + {
12451 + /* Let gpt_offset point to the first entry in the GPT
12452 + partition table. This can also be used by callers of
12453 + next_partition to determine if a entry comes from a
12454 + GPT partition table or not. */
12455 + *gpt_offset = hdr->partitions;
12456 + *gpt_count = hdr->maxpart;
12457 + *gpt_size = hdr->partentry_size;
12458 +
12459 + return next_gpt_slice();
12460 + }
12461 + else
12462 + {
12463 + /* This is not a valid header for a GPT partition table.
12464 + Re-read the MBR or the boot sector of the extended
12465 + partition. */
12466 + if (! rawread (drive, *offset, 0, SECTOR_SIZE, buf))
12467 + return 0;
12468 + }
12469 + }
12470 +
12471 + /* Not a GPT partition. */
12472 + *gpt_offset = 0;
12473 +
12474 /* Increase the entry number. */
12475 (*entry)++;
12476
12477 @@ -710,6 +755,43 @@
12478 return 1;
12479 }
12480
12481 + /* Get the next GPT slice. */
12482 + int next_gpt_slice (void)
12483 + {
12484 + struct grub_gpt_partentry *gptentry = (struct grub_gpt_partentry *) buf;
12485 + /* Make GPT partitions show up as PC slices. */
12486 + int pc_slice_no = (*partition & 0xFF0000) >> 16;
12487 +
12488 + /* If this is the first time... */
12489 + if (pc_slice_no == 0xFF)
12490 + {
12491 + pc_slice_no = -1;
12492 + *entry = -1;
12493 + }
12494 +
12495 + do {
12496 + (*entry)++;
12497 +
12498 + if (*entry >= *gpt_count)
12499 + {
12500 + errnum = ERR_NO_PART;
12501 + return 0;
12502 + }
12503 + /* Read in the GPT Partition table entry. */
12504 + if (! rawread (drive, (*gpt_offset) + GPT_ENTRY_SECTOR (*gpt_size, *entry), GPT_ENTRY_INDEX (*gpt_size, *entry), *gpt_size, buf))
12505 + return 0;
12506 + } while (! (gptentry->type1 && gptentry->type2));
12507 +
12508 + pc_slice_no++;
12509 + *start = gptentry->start;
12510 + *len = gptentry->end - gptentry->start + 1;
12511 + *type = PC_SLICE_TYPE_EXT2FS;
12512 + *entry = pc_slice_no;
12513 + *partition = (*entry << 16) | 0xFFFF;
12514 +
12515 + return 1;
12516 + }
12517 +
12518 /* Start the body of this function. */
12519
12520 #ifndef STAGE1_5
12521 @@ -717,6 +799,9 @@
12522 return 0;
12523 #endif
12524
12525 + if (*partition != 0xFFFFFF && *gpt_offset != 0)
12526 + return next_gpt_slice ();
12527 +
12528 /* If previous partition is a BSD partition or a PC slice which
12529 contains BSD partitions... */
12530 if ((*partition != 0xFFFFFF && IS_PC_SLICE_TYPE_BSD (*type & 0xff))
12531 @@ -746,6 +831,8 @@
12532 #ifndef STAGE1_5
12533 static unsigned long cur_part_offset;
12534 static unsigned long cur_part_addr;
12535 +static unsigned long cur_part_start;
12536 +static int cur_part_entry;
12537 #endif
12538
12539 /* Open a partition. */
12540 @@ -755,6 +842,9 @@
12541 unsigned long dest_partition = current_partition;
12542 unsigned long part_offset;
12543 unsigned long ext_offset;
12544 + unsigned long gpt_offset;
12545 + int gpt_count;
12546 + int gpt_size;
12547 int entry;
12548 char buf[SECTOR_SIZE];
12549 int bsd_part, pc_slice;
12550 @@ -766,7 +856,8 @@
12551 int ret = next_partition (current_drive, dest_partition,
12552 &current_partition, &current_slice,
12553 &part_start, &part_length,
12554 - &part_offset, &entry, &ext_offset, buf);
12555 + &part_offset, &entry, &ext_offset,
12556 + &gpt_offset, &gpt_count, &gpt_size, buf);
12557 bsd_part = (current_partition >> 8) & 0xFF;
12558 pc_slice = current_partition >> 16;
12559 return ret;
12560 @@ -800,7 +891,12 @@
12561
12562 /* If this is the whole disk, return here. */
12563 if (! flags && current_partition == 0xFFFFFF)
12564 - return 1;
12565 + {
12566 +#ifndef STAGE1_5
12567 + cur_part_offset = 0;
12568 +#endif /* ! STAGE1_5 */
12569 + return 1;
12570 + }
12571
12572 if (flags)
12573 dest_partition = 0xFFFFFF;
12574 @@ -815,6 +911,8 @@
12575
12576 cur_part_offset = part_offset;
12577 cur_part_addr = BOOT_PART_TABLE + (entry << 4);
12578 + cur_part_start = part_start;
12579 + cur_part_entry = entry;
12580 #endif /* ! STAGE1_5 */
12581
12582 /* If this is a valid partition... */
12583 @@ -1142,6 +1240,7 @@
12584 src = (char *) SCRATCHADDR + BOOTSEC_PART_OFFSET;
12585 while (dst < (char *) BOOT_PART_TABLE + BOOTSEC_PART_LENGTH)
12586 *dst++ = *src++;
12587 + PC_SLICE_START (BOOT_PART_TABLE - PC_SLICE_OFFSET, cur_part_entry) = cur_part_start;
12588
12589 /* Set the active flag of the booted partition. */
12590 for (i = 0; i < 4; i++)
12591 diff -Nur grub-0.97/stage2/fsys_ext2fs.c grub-0.97-patched/stage2/fsys_ext2fs.c
12592 --- grub-0.97/stage2/fsys_ext2fs.c 2004-08-08 20:19:18.000000000 +0200
12593 +++ grub-0.97-patched/stage2/fsys_ext2fs.c 2012-11-11 17:07:12.750730331 +0100
12594 @@ -41,6 +41,7 @@
12595 typedef unsigned short __u16;
12596 typedef __signed__ int __s32;
12597 typedef unsigned int __u32;
12598 +typedef unsigned long long __u64;
12599
12600 /*
12601 * Constants relative to the data blocks, from ext2_fs.h
12602 @@ -61,9 +62,9 @@
12603 __u32 s_free_inodes_count; /* Free inodes count */
12604 __u32 s_first_data_block; /* First Data Block */
12605 __u32 s_log_block_size; /* Block size */
12606 - __s32 s_log_frag_size; /* Fragment size */
12607 + __s32 s_obso_log_frag_size; /* Obsoleted Fragment size */
12608 __u32 s_blocks_per_group; /* # Blocks per group */
12609 - __u32 s_frags_per_group; /* # Fragments per group */
12610 + __u32 s_obso_frags_per_group; /* Obsoleted Fragments per group */
12611 __u32 s_inodes_per_group; /* # Inodes per group */
12612 __u32 s_mtime; /* Mount time */
12613 __u32 s_wtime; /* Write time */
12614 @@ -72,17 +73,62 @@
12615 __u16 s_magic; /* Magic signature */
12616 __u16 s_state; /* File system state */
12617 __u16 s_errors; /* Behaviour when detecting errors */
12618 - __u16 s_pad;
12619 + __u16 s_minor_rev_level; /* minor revision level */
12620 __u32 s_lastcheck; /* time of last check */
12621 __u32 s_checkinterval; /* max. time between checks */
12622 __u32 s_creator_os; /* OS */
12623 __u32 s_rev_level; /* Revision level */
12624 __u16 s_def_resuid; /* Default uid for reserved blocks */
12625 __u16 s_def_resgid; /* Default gid for reserved blocks */
12626 - __u32 s_reserved[235]; /* Padding to the end of the block */
12627 + /*
12628 + * These fields are for EXT2_DYNAMIC_REV superblocks only.
12629 + *
12630 + * Note: the difference between the compatible feature set and
12631 + * the incompatible feature set is that if there is a bit set
12632 + * in the incompatible feature set that the kernel doesn't
12633 + * know about, it should refuse to mount the filesystem.
12634 + *
12635 + * e2fsck's requirements are more strict; if it doesn't know
12636 + * about a feature in either the compatible or incompatible
12637 + * feature set, it must abort and not try to meddle with
12638 + * things it doesn't understand...
12639 + */
12640 + __u32 s_first_ino; /* First non-reserved inode */
12641 + __u16 s_inode_size; /* size of inode structure */
12642 + __u16 s_block_group_nr; /* block group # of this superblock */
12643 + __u32 s_feature_compat; /* compatible feature set */
12644 + __u32 s_feature_incompat; /* incompatible feature set */
12645 + __u32 s_feature_ro_compat; /* readonly-compatible feature set */
12646 + __u8 s_uuid[16]; /* 128-bit uuid for volume */
12647 + char s_volume_name[16]; /* volume name */
12648 + char s_last_mounted[64]; /* directory where last mounted */
12649 + __u32 s_algorithm_usage_bitmap; /* For compression */
12650 + /*
12651 + * Performance hints. Directory preallocation should only
12652 + * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
12653 + */
12654 + __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
12655 + __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
12656 + __u16 s_reserved_gdt_blocks;/* Per group table for online growth */
12657 + /*
12658 + * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
12659 + */
12660 + __u8 s_journal_uuid[16]; /* uuid of journal superblock */
12661 + __u32 s_journal_inum; /* inode number of journal file */
12662 + __u32 s_journal_dev; /* device number of journal file */
12663 + __u32 s_last_orphan; /* start of list of inodes to delete */
12664 + __u32 s_hash_seed[4]; /* HTREE hash seed */
12665 + __u8 s_def_hash_version; /* Default hash version to use */
12666 + __u8 s_jnl_backup_type; /* Default type of journal backup */
12667 + __u16 s_desc_size; /* size of group descriptor */
12668 + __u32 s_default_mount_opts;
12669 + __u32 s_first_meta_bg; /* First metablock group */
12670 + __u32 s_mkfs_time; /* When the filesystem was created */
12671 + __u32 s_jnl_blocks[17]; /* Backup of the journal inode */
12672 + __u32 s_reserved[172]; /* Padding to the end of the block */
12673 };
12674
12675 -struct ext2_group_desc
12676 +struct ext4_group_desc
12677 {
12678 __u32 bg_block_bitmap; /* Blocks bitmap block */
12679 __u32 bg_inode_bitmap; /* Inodes bitmap block */
12680 @@ -90,8 +136,18 @@
12681 __u16 bg_free_blocks_count; /* Free blocks count */
12682 __u16 bg_free_inodes_count; /* Free inodes count */
12683 __u16 bg_used_dirs_count; /* Directories count */
12684 - __u16 bg_pad;
12685 - __u32 bg_reserved[3];
12686 + __u16 bg_flags; /* EXT4_BG_flags (INODE_UNINIT, etc) */
12687 + __u32 bg_reserved[2]; /* Likely block/inode bitmap checksum */
12688 + __u16 bg_itable_unused; /* Unused inodes count */
12689 + __u16 bg_checksum; /* crc16(sb_uuid+group+desc) */
12690 + __u32 bg_block_bitmap_hi; /* Blocks bitmap block MSB */
12691 + __u32 bg_inode_bitmap_hi; /* Inodes bitmap block MSB */
12692 + __u32 bg_inode_table_hi; /* Inodes table block MSB */
12693 + __u16 bg_free_blocks_count_hi;/* Free blocks count MSB */
12694 + __u16 bg_free_inodes_count_hi;/* Free inodes count MSB */
12695 + __u16 bg_used_dirs_count_hi; /* Directories count MSB */
12696 + __u16 bg_itable_unused_hi; /* Unused inodes count MSB */
12697 + __u32 bg_reserved2[3];
12698 };
12699
12700 struct ext2_inode
12701 @@ -129,22 +185,22 @@
12702 __u32 i_block[EXT2_N_BLOCKS]; /* 40: Pointers to blocks */
12703 __u32 i_version; /* File version (for NFS) */
12704 __u32 i_file_acl; /* File ACL */
12705 - __u32 i_dir_acl; /* Directory ACL */
12706 - __u32 i_faddr; /* Fragment address */
12707 + __u32 i_size_high;
12708 + __u32 i_obso_faddr; /* Obsoleted fragment address */
12709 union
12710 {
12711 struct
12712 {
12713 - __u8 l_i_frag; /* Fragment number */
12714 - __u8 l_i_fsize; /* Fragment size */
12715 - __u16 i_pad1;
12716 - __u32 l_i_reserved2[2];
12717 + __u16 l_i_blocks_high; /* were l_i_reserved1 */
12718 + __u16 l_i_file_acl_high;
12719 + __u16 l_i_uid_high; /* these 2 fields */
12720 + __u16 l_i_gid_high; /* were reserved2[0] */
12721 + __u32 l_i_reserved2;
12722 }
12723 linux2;
12724 struct
12725 {
12726 - __u8 h_i_frag; /* Fragment number */
12727 - __u8 h_i_fsize; /* Fragment size */
12728 + __u16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
12729 __u16 h_i_mode_high;
12730 __u16 h_i_uid_high;
12731 __u16 h_i_gid_high;
12732 @@ -153,16 +209,36 @@
12733 hurd2;
12734 struct
12735 {
12736 - __u8 m_i_frag; /* Fragment number */
12737 - __u8 m_i_fsize; /* Fragment size */
12738 - __u16 m_pad1;
12739 + __u16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
12740 + __u16 m_i_file_acl_high;
12741 __u32 m_i_reserved2[2];
12742 }
12743 masix2;
12744 }
12745 osd2; /* OS dependent 2 */
12746 + __u16 i_extra_isize;
12747 + __u16 i_pad1;
12748 + __u32 i_ctime_extra; /* extra Change time (nsec << 2 | epoch) */
12749 + __u32 i_mtime_extra; /* extra Modification time(nsec << 2 | epoch) */
12750 + __u32 i_atime_extra; /* extra Access time (nsec << 2 | epoch) */
12751 + __u32 i_crtime; /* File Creation time */
12752 + __u32 i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */
12753 + __u32 i_version_hi; /* high 32 bits for 64-bit version */
12754 };
12755
12756 +#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
12757 +#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 /* grub not supported*/
12758 +#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
12759 +#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
12760 +
12761 +#define EXT4_HAS_INCOMPAT_FEATURE(sb,mask) \
12762 + ( sb->s_feature_incompat & mask )
12763 +
12764 +#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
12765 +#define EXT4_HUGE_FILE_FL 0x00040000 /* Set to each huge file */
12766 +
12767 +#define EXT4_MIN_DESC_SIZE 32
12768 +
12769 /* linux/limits.h */
12770 #define NAME_MAX 255 /* # chars in a file name */
12771
12772 @@ -180,6 +256,57 @@
12773 char name[EXT2_NAME_LEN]; /* File name */
12774 };
12775
12776 +/* linux/ext4_fs_extents.h */
12777 +/* This is the extent on-disk structure.
12778 + * It's used at the bottom of the tree.
12779 + */
12780 +struct ext4_extent
12781 + {
12782 + __u32 ee_block; /* first logical block extent covers */
12783 + __u16 ee_len; /* number of blocks covered by extent */
12784 + __u16 ee_start_hi; /* high 16 bits of physical block */
12785 + __u32 ee_start_lo; /* low 32 bits of physical block */
12786 + };
12787 +
12788 +/*
12789 + * This is index on-disk structure.
12790 + * It's used at all the levels except the bottom.
12791 + */
12792 +struct ext4_extent_idx
12793 + {
12794 + __u32 ei_block; /* index covers logical blocks from 'block' */
12795 + __u32 ei_leaf_lo; /* pointer to the physical block of the next *
12796 + * level. leaf or next index could be there */
12797 + __u16 ei_leaf_hi; /* high 16 bits of physical block */
12798 + __u16 ei_unused;
12799 + };
12800 +
12801 +/*
12802 + * Each block (leaves and indexes), even inode-stored has header.
12803 + */
12804 +struct ext4_extent_header
12805 + {
12806 + __u16 eh_magic; /* probably will support different formats */
12807 + __u16 eh_entries; /* number of valid entries */
12808 + __u16 eh_max; /* capacity of store in entries */
12809 + __u16 eh_depth; /* has tree real underlying blocks? */
12810 + __u32 eh_generation; /* generation of the tree */
12811 + };
12812 +
12813 +#define EXT4_EXT_MAGIC (0xf30a)
12814 +#define EXT_FIRST_EXTENT(__hdr__) \
12815 + ((struct ext4_extent *) (((char *) (__hdr__)) + \
12816 + sizeof(struct ext4_extent_header)))
12817 +#define EXT_FIRST_INDEX(__hdr__) \
12818 + ((struct ext4_extent_idx *) (((char *) (__hdr__)) + \
12819 + sizeof(struct ext4_extent_header)))
12820 +#define EXT_LAST_EXTENT(__hdr__) \
12821 + (EXT_FIRST_EXTENT((__hdr__)) + (__u16)((__hdr__)->eh_entries) - 1)
12822 +#define EXT_LAST_INDEX(__hdr__) \
12823 + (EXT_FIRST_INDEX((__hdr__)) + (__u16)((__hdr__)->eh_entries) - 1)
12824 +
12825 +
12826 +
12827 /* linux/ext2fs.h */
12828 /*
12829 * EXT2_DIR_PAD defines the directory entries boundaries
12830 @@ -218,13 +345,30 @@
12831 #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
12832 #define EXT2_ADDR_PER_BLOCK_BITS(s) (log2(EXT2_ADDR_PER_BLOCK(s)))
12833
12834 +#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
12835 +#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
12836 +#define EXT2_GOOD_OLD_INODE_SIZE 128
12837 +#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
12838 + EXT2_GOOD_OLD_INODE_SIZE : \
12839 + (s)->s_inode_size)
12840 +#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s))
12841 +
12842 /* linux/ext2_fs.h */
12843 #define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
12844 /* kind of from ext2/super.c */
12845 #define EXT2_BLOCK_SIZE(s) (1 << EXT2_BLOCK_SIZE_BITS(s))
12846 /* linux/ext2fs.h */
12847 +/* sizeof(struct ext2_group_desc) is changed in ext4
12848 + * in kernel code, ext2/3 uses sizeof(struct ext2_group_desc) to calculate
12849 + * number of desc per block, while ext4 uses superblock->s_desc_size in stead
12850 + * superblock->s_desc_size is not available in ext2/3
12851 + * */
12852 +#define EXT2_DESC_SIZE(s) \
12853 + (EXT4_HAS_INCOMPAT_FEATURE(s,EXT4_FEATURE_INCOMPAT_64BIT)? \
12854 + s->s_desc_size : EXT4_MIN_DESC_SIZE)
12855 #define EXT2_DESC_PER_BLOCK(s) \
12856 - (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
12857 + (EXT2_BLOCK_SIZE(s) / EXT2_DESC_SIZE(s))
12858 +
12859 /* linux/stat.h */
12860 #define S_IFMT 00170000
12861 #define S_IFLNK 0120000
12862 @@ -386,6 +530,122 @@
12863 [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
12864 }
12865
12866 +/* extent binary search index
12867 + * find closest index in the current level extent tree
12868 + * kind of from ext4_ext_binsearch_idx in ext4/extents.c
12869 + */
12870 +static struct ext4_extent_idx*
12871 +ext4_ext_binsearch_idx(struct ext4_extent_header* eh, int logical_block)
12872 +{
12873 + struct ext4_extent_idx *r, *l, *m;
12874 + l = EXT_FIRST_INDEX(eh) + 1;
12875 + r = EXT_LAST_INDEX(eh);
12876 + while (l <= r)
12877 + {
12878 + m = l + (r - l) / 2;
12879 + if (logical_block < m->ei_block)
12880 + r = m - 1;
12881 + else
12882 + l = m + 1;
12883 + }
12884 + return (struct ext4_extent_idx*)(l - 1);
12885 +}
12886 +
12887 +/* extent binary search
12888 + * find closest extent in the leaf level
12889 + * kind of from ext4_ext_binsearch in ext4/extents.c
12890 + */
12891 +static struct ext4_extent*
12892 +ext4_ext_binsearch(struct ext4_extent_header* eh, int logical_block)
12893 +{
12894 + struct ext4_extent *r, *l, *m;
12895 + l = EXT_FIRST_EXTENT(eh) + 1;
12896 + r = EXT_LAST_EXTENT(eh);
12897 + while (l <= r)
12898 + {
12899 + m = l + (r - l) / 2;
12900 + if (logical_block < m->ee_block)
12901 + r = m - 1;
12902 + else
12903 + l = m + 1;
12904 + }
12905 + return (struct ext4_extent*)(l - 1);
12906 +}
12907 +
12908 +/* Maps extents enabled logical block into physical block via an inode.
12909 + * EXT4_HUGE_FILE_FL should be checked before calling this.
12910 + */
12911 +static int
12912 +ext4fs_block_map (int logical_block)
12913 +{
12914 + struct ext4_extent_header *eh;
12915 + struct ext4_extent *ex, *extent;
12916 + struct ext4_extent_idx *ei, *index;
12917 + int depth;
12918 + int i;
12919 +
12920 +#ifdef E2DEBUG
12921 + unsigned char *i;
12922 + for (i = (unsigned char *) INODE;
12923 + i < ((unsigned char *) INODE + sizeof (struct ext2_inode));
12924 + i++)
12925 + {
12926 + printf ("%c", "0123456789abcdef"[*i >> 4]);
12927 + printf ("%c", "0123456789abcdef"[*i % 16]);
12928 + if (!((i + 1 - (unsigned char *) INODE) % 16))
12929 + {
12930 + printf ("\n");
12931 + }
12932 + else
12933 + {
12934 + printf (" ");
12935 + }
12936 + }
12937 + printf ("logical block %d\n", logical_block);
12938 +#endif /* E2DEBUG */
12939 + eh = (struct ext4_extent_header*)INODE->i_block;
12940 + if (eh->eh_magic != EXT4_EXT_MAGIC)
12941 + {
12942 + errnum = ERR_FSYS_CORRUPT;
12943 + return -1;
12944 + }
12945 + while((depth = eh->eh_depth) != 0)
12946 + { /* extent index */
12947 + if (eh->eh_magic != EXT4_EXT_MAGIC)
12948 + {
12949 + errnum = ERR_FSYS_CORRUPT;
12950 + return -1;
12951 + }
12952 + ei = ext4_ext_binsearch_idx(eh, logical_block);
12953 + if (ei->ei_leaf_hi)
12954 + {/* 64bit physical block number not supported */
12955 + errnum = ERR_FILELENGTH;
12956 + return -1;
12957 + }
12958 + if (!ext2_rdfsb(ei->ei_leaf_lo, DATABLOCK1))
12959 + {
12960 + errnum = ERR_FSYS_CORRUPT;
12961 + return -1;
12962 + }
12963 + eh = (struct ext4_extent_header*)DATABLOCK1;
12964 + }
12965 +
12966 + /* depth==0, we come to the leaf */
12967 + ex = ext4_ext_binsearch(eh, logical_block);
12968 + if (ex->ee_start_hi)
12969 + {/* 64bit physical block number not supported */
12970 + errnum = ERR_FILELENGTH;
12971 + return -1;
12972 + }
12973 + if ((ex->ee_block + ex->ee_len) < logical_block)
12974 + {
12975 + errnum = ERR_FSYS_CORRUPT;
12976 + return -1;
12977 + }
12978 + return ex->ee_start_lo + logical_block - ex->ee_block;
12979 +
12980 +}
12981 +
12982 /* preconditions: all preconds of ext2fs_block_map */
12983 int
12984 ext2fs_read (char *buf, int len)
12985 @@ -420,6 +680,11 @@
12986 /* find the (logical) block component of our location */
12987 logical_block = filepos >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
12988 offset = filepos & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1);
12989 + /* map extents enabled logical block number to physical fs on-dick block number */
12990 + if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK,EXT4_FEATURE_INCOMPAT_EXTENTS)
12991 + && INODE->i_flags & EXT4_EXTENTS_FL)
12992 + map = ext4fs_block_map (logical_block);
12993 + else
12994 map = ext2fs_block_map (logical_block);
12995 #ifdef E2DEBUG
12996 printf ("map=%d\n", map);
12997 @@ -504,7 +769,7 @@
12998 int desc; /* index within that group */
12999 int ino_blk; /* fs pointer of the inode's information */
13000 int str_chk = 0; /* used to hold the results of a string compare */
13001 - struct ext2_group_desc *gdp;
13002 + struct ext4_group_desc *ext4_gdp;
13003 struct ext2_inode *raw_inode; /* inode info corresponding to current_ino */
13004
13005 char linkbuf[PATH_MAX]; /* buffer for following symbolic links */
13006 @@ -550,10 +815,17 @@
13007 {
13008 return 0;
13009 }
13010 - gdp = GROUP_DESC;
13011 - ino_blk = gdp[desc].bg_inode_table +
13012 + ext4_gdp = (struct ext4_group_desc *)( (__u8*)GROUP_DESC +
13013 + desc * EXT2_DESC_SIZE(SUPERBLOCK));
13014 + if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK, EXT4_FEATURE_INCOMPAT_64BIT)
13015 + && (! ext4_gdp->bg_inode_table_hi))
13016 + {/* 64bit itable not supported */
13017 + errnum = ERR_FILELENGTH;
13018 + return -1;
13019 + }
13020 + ino_blk = ext4_gdp->bg_inode_table +
13021 (((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group))
13022 - >> log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)));
13023 + >> log2 (EXT2_INODES_PER_BLOCK (SUPERBLOCK)));
13024 #ifdef E2DEBUG
13025 printf ("inode table fsblock=%d\n", ino_blk);
13026 #endif /* E2DEBUG */
13027 @@ -565,13 +837,12 @@
13028 /* reset indirect blocks! */
13029 mapblock2 = mapblock1 = -1;
13030
13031 - raw_inode = INODE +
13032 - ((current_ino - 1)
13033 - & (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode) - 1));
13034 + raw_inode = (struct ext2_inode *)((char *)INODE +
13035 + ((current_ino - 1) & (EXT2_INODES_PER_BLOCK (SUPERBLOCK) - 1)) *
13036 + EXT2_INODE_SIZE (SUPERBLOCK));
13037 #ifdef E2DEBUG
13038 printf ("ipb=%d, sizeof(inode)=%d\n",
13039 - (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)),
13040 - sizeof (struct ext2_inode));
13041 + EXT2_INODES_PER_BLOCK (SUPERBLOCK), EXT2_INODE_SIZE (SUPERBLOCK));
13042 printf ("inode=%x, raw_inode=%x\n", INODE, raw_inode);
13043 printf ("offset into inode table block=%d\n", (int) raw_inode - (int) INODE);
13044 for (i = (unsigned char *) INODE; i <= (unsigned char *) raw_inode;
13045 @@ -629,7 +900,10 @@
13046 }
13047 linkbuf[filemax + len] = '\0';
13048
13049 - /* Read the symlink data. */
13050 + /* Read the symlink data.
13051 + * Slow symlink is extents enabled
13052 + * But since grub_read invokes ext2fs_read, nothing to change here
13053 + * */
13054 if (! ext2_is_fast_symlink ())
13055 {
13056 /* Read the necessary blocks, and reset the file pointer. */
13057 @@ -640,7 +914,9 @@
13058 }
13059 else
13060 {
13061 - /* Copy the data directly from the inode. */
13062 + /* Copy the data directly from the inode.
13063 + * Fast symlink is not extents enabled
13064 + * */
13065 len = filemax;
13066 memmove (linkbuf, (char *) INODE->i_block, len);
13067 }
13068 @@ -674,6 +950,13 @@
13069 errnum = ERR_BAD_FILETYPE;
13070 return 0;
13071 }
13072 + /* if file is too large, just stop and report an error*/
13073 + if ( (INODE->i_flags & EXT4_HUGE_FILE_FL) && !(INODE->i_size_high))
13074 + {
13075 + /* file too large, stop reading */
13076 + errnum = ERR_FILELENGTH;
13077 + return 0;
13078 + }
13079
13080 filemax = (INODE->i_size);
13081 return 1;
13082 @@ -728,17 +1011,28 @@
13083 }
13084
13085 /* else, find the (logical) block component of our location */
13086 + /* ext4 logical block number the same as ext2/3 */
13087 blk = loc >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
13088
13089 /* we know which logical block of the directory entry we are looking
13090 for, now we have to translate that to the physical (fs) block on
13091 the disk */
13092 + /* map extents enabled logical block number to physical fs on-dick block number */
13093 + if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK,EXT4_FEATURE_INCOMPAT_EXTENTS)
13094 + && INODE->i_flags & EXT4_EXTENTS_FL)
13095 + map = ext4fs_block_map (blk);
13096 + else
13097 map = ext2fs_block_map (blk);
13098 #ifdef E2DEBUG
13099 printf ("fs block=%d\n", map);
13100 #endif /* E2DEBUG */
13101 mapblock2 = -1;
13102 - if ((map < 0) || !ext2_rdfsb (map, DATABLOCK2))
13103 + if (map < 0)
13104 + {
13105 + *rest = ch;
13106 + return 0;
13107 + }
13108 + if (!ext2_rdfsb (map, DATABLOCK2))
13109 {
13110 errnum = ERR_FSYS_CORRUPT;
13111 *rest = ch;
13112 diff -Nur grub-0.97/stage2/gpt.h grub-0.97-patched/stage2/gpt.h
13113 --- grub-0.97/stage2/gpt.h 1970-01-01 01:00:00.000000000 +0100
13114 +++ grub-0.97-patched/stage2/gpt.h 2012-11-11 17:07:12.697728638 +0100
13115 @@ -0,0 +1,68 @@
13116 +/*
13117 + * GRUB -- GRand Unified Bootloader
13118 + * Copyright (C) 2002,2005,2006 Free Software Foundation, Inc.
13119 + *
13120 + * This program is free software; you can redistribute it and/or modify
13121 + * it under the terms of the GNU General Public License as published by
13122 + * the Free Software Foundation; either version 2 of the License, or
13123 + * (at your option) any later version.
13124 + *
13125 + * This program is distributed in the hope that it will be useful,
13126 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
13127 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13128 + * GNU General Public License for more details.
13129 + *
13130 + * You should have received a copy of the GNU General Public License
13131 + * along with this program; if not, write to the Free Software
13132 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
13133 + */
13134 +
13135 +#ifndef _GPT_H
13136 +#define _GPT_H
13137 +
13138 +typedef signed char grub_int8_t;
13139 +typedef signed short grub_int16_t;
13140 +typedef signed int grub_int32_t;
13141 +typedef signed long long int grub_int64_t;
13142 +typedef unsigned char grub_uint8_t;
13143 +typedef unsigned short grub_uint16_t;
13144 +typedef unsigned int grub_uint32_t;
13145 +typedef unsigned long long int grub_uint64_t;
13146 +
13147 +struct grub_gpt_header
13148 +{
13149 + grub_uint64_t magic;
13150 + grub_uint32_t version;
13151 + grub_uint32_t headersize;
13152 + grub_uint32_t crc32;
13153 + grub_uint32_t unused1;
13154 + grub_uint64_t primary;
13155 + grub_uint64_t backup;
13156 + grub_uint64_t start;
13157 + grub_uint64_t end;
13158 + grub_uint8_t guid[16];
13159 + grub_uint64_t partitions;
13160 + grub_uint32_t maxpart;
13161 + grub_uint32_t partentry_size;
13162 + grub_uint32_t partentry_crc32;
13163 +} __attribute__ ((packed));
13164 +
13165 +struct grub_gpt_partentry
13166 +{
13167 + grub_uint64_t type1;
13168 + grub_uint64_t type2;
13169 + grub_uint8_t guid[16];
13170 + grub_uint64_t start;
13171 + grub_uint64_t end;
13172 + grub_uint8_t attrib;
13173 + char name[72];
13174 +} __attribute__ ((packed));
13175 +
13176 +#define GPT_HEADER_MAGIC 0x5452415020494645UL
13177 +
13178 +#define GPT_ENTRY_SECTOR(size,entry) \
13179 + ((((entry) * (size) + 1) & ~(SECTOR_SIZE - 1)) >> SECTOR_BITS)
13180 +#define GPT_ENTRY_INDEX(size,entry) \
13181 + ((((entry) * (size) + 1) & (SECTOR_SIZE - 1)) - 1)
13182 +
13183 +#endif /* _GPT_H */
13184 diff -Nur grub-0.97/stage2/graphics.c grub-0.97-patched/stage2/graphics.c
13185 --- grub-0.97/stage2/graphics.c 1970-01-01 01:00:00.000000000 +0100
13186 +++ grub-0.97-patched/stage2/graphics.c 2012-11-11 17:06:33.320470847 +0100
13187 @@ -0,0 +1,563 @@
13188 +/* graphics.c - graphics mode support for GRUB */
13189 +/* Implemented as a terminal type by Jeremy Katz <katzj@redhat.com> based
13190 + * on a patch by Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
13191 + */
13192 +/*
13193 + * GRUB -- GRand Unified Bootloader
13194 + * Copyright (C) 2001,2002 Red Hat, Inc.
13195 + * Portions copyright (C) 2000 Conectiva, Inc.
13196 + *
13197 + * This program is free software; you can redistribute it and/or modify
13198 + * it under the terms of the GNU General Public License as published by
13199 + * the Free Software Foundation; either version 2 of the License, or
13200 + * (at your option) any later version.
13201 + *
13202 + * This program is distributed in the hope that it will be useful,
13203 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
13204 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13205 + * GNU General Public License for more details.
13206 + *
13207 + * You should have received a copy of the GNU General Public License
13208 + * along with this program; if not, write to the Free Software
13209 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
13210 + */
13211 +
13212 +
13213 +
13214 +#ifdef SUPPORT_GRAPHICS
13215 +
13216 +#include <term.h>
13217 +#include <shared.h>
13218 +#include <graphics.h>
13219 +
13220 +int saved_videomode;
13221 +unsigned char *font8x16;
13222 +
13223 +int graphics_inited = 0;
13224 +static char splashimage[64];
13225 +
13226 +#define VSHADOW VSHADOW1
13227 +unsigned char VSHADOW1[38400];
13228 +unsigned char VSHADOW2[38400];
13229 +unsigned char VSHADOW4[38400];
13230 +unsigned char VSHADOW8[38400];
13231 +
13232 +/* constants to define the viewable area */
13233 +const int x0 = 0;
13234 +const int x1 = 80;
13235 +const int y0 = 0;
13236 +const int y1 = 30;
13237 +
13238 +/* text buffer has to be kept around so that we can write things as we
13239 + * scroll and the like */
13240 +unsigned short text[80 * 30];
13241 +
13242 +/* why do these have to be kept here? */
13243 +int foreground = (63 << 16) | (63 << 8) | (63), background = 0, border = 0;
13244 +
13245 +/* current position */
13246 +static int fontx = 0;
13247 +static int fonty = 0;
13248 +
13249 +/* global state so that we don't try to recursively scroll or cursor */
13250 +static int no_scroll = 0;
13251 +
13252 +/* color state */
13253 +static int graphics_standard_color = A_NORMAL;
13254 +static int graphics_normal_color = A_NORMAL;
13255 +static int graphics_highlight_color = A_REVERSE;
13256 +static int graphics_current_color = A_NORMAL;
13257 +static color_state graphics_color_state = COLOR_STATE_STANDARD;
13258 +
13259 +
13260 +/* graphics local functions */
13261 +static void graphics_setxy(int col, int row);
13262 +static void graphics_scroll();
13263 +
13264 +/* FIXME: where do these really belong? */
13265 +static inline void outb(unsigned short port, unsigned char val)
13266 +{
13267 + __asm __volatile ("outb %0,%1"::"a" (val), "d" (port));
13268 +}
13269 +
13270 +static void MapMask(int value) {
13271 + outb(0x3c4, 2);
13272 + outb(0x3c5, value);
13273 +}
13274 +
13275 +/* bit mask register */
13276 +static void BitMask(int value) {
13277 + outb(0x3ce, 8);
13278 + outb(0x3cf, value);
13279 +}
13280 +
13281 +
13282 +
13283 +/* Set the splash image */
13284 +void graphics_set_splash(char *splashfile) {
13285 + grub_strcpy(splashimage, splashfile);
13286 +}
13287 +
13288 +/* Get the current splash image */
13289 +char *graphics_get_splash(void) {
13290 + return splashimage;
13291 +}
13292 +
13293 +/* Initialize a vga16 graphics display with the palette based off of
13294 + * the image in splashimage. If the image doesn't exist, leave graphics
13295 + * mode. */
13296 +int graphics_init()
13297 +{
13298 + if(!grub_file_exists(splashimage)) {
13299 + return 0;
13300 + }
13301 +
13302 + if (!graphics_inited) {
13303 + saved_videomode = set_videomode(0x12);
13304 + }
13305 +
13306 + if (!read_image(splashimage)) {
13307 + set_videomode(saved_videomode);
13308 + grub_printf("failed to read image\n");
13309 + return 0;
13310 + }
13311 +
13312 + font8x16 = (unsigned char*)graphics_get_font();
13313 +
13314 + graphics_inited = 1;
13315 +
13316 + /* make sure that the highlight color is set correctly */
13317 + graphics_highlight_color = ((graphics_normal_color >> 4) |
13318 + ((graphics_normal_color & 0xf) << 4));
13319 +
13320 + return 1;
13321 +}
13322 +
13323 +/* Leave graphics mode */
13324 +void graphics_end(void)
13325 +{
13326 + if (graphics_inited) {
13327 + set_videomode(saved_videomode);
13328 + graphics_inited = 0;
13329 + }
13330 +}
13331 +
13332 +/* Print ch on the screen. Handle any needed scrolling or the like */
13333 +void graphics_putchar(int ch) {
13334 + ch &= 0xff;
13335 +
13336 + graphics_cursor(0);
13337 +
13338 + if (ch == '\n') {
13339 + if (fonty + 1 < y1)
13340 + graphics_setxy(fontx, fonty + 1);
13341 + else
13342 + graphics_scroll();
13343 + graphics_cursor(1);
13344 + return;
13345 + } else if (ch == '\r') {
13346 + graphics_setxy(x0, fonty);
13347 + graphics_cursor(1);
13348 + return;
13349 + }
13350 +
13351 + graphics_cursor(0);
13352 +
13353 + text[fonty * 80 + fontx] = ch;
13354 + text[fonty * 80 + fontx] &= 0x00ff;
13355 + if (graphics_current_color & 0xf0)
13356 + text[fonty * 80 + fontx] |= 0x100;
13357 +
13358 + graphics_cursor(0);
13359 +
13360 + if ((fontx + 1) >= x1) {
13361 + graphics_setxy(x0, fonty);
13362 + if (fonty + 1 < y1)
13363 + graphics_setxy(x0, fonty + 1);
13364 + else
13365 + graphics_scroll();
13366 + } else {
13367 + graphics_setxy(fontx + 1, fonty);
13368 + }
13369 +
13370 + graphics_cursor(1);
13371 +}
13372 +
13373 +/* get the current location of the cursor */
13374 +int graphics_getxy(void) {
13375 + return (fontx << 8) | fonty;
13376 +}
13377 +
13378 +void graphics_gotoxy(int x, int y) {
13379 + graphics_cursor(0);
13380 +
13381 + graphics_setxy(x, y);
13382 +
13383 + graphics_cursor(1);
13384 +}
13385 +
13386 +void graphics_cls(void) {
13387 + int i;
13388 + unsigned char *mem, *s1, *s2, *s4, *s8;
13389 +
13390 + graphics_cursor(0);
13391 + graphics_gotoxy(x0, y0);
13392 +
13393 + mem = (unsigned char*)VIDEOMEM;
13394 + s1 = (unsigned char*)VSHADOW1;
13395 + s2 = (unsigned char*)VSHADOW2;
13396 + s4 = (unsigned char*)VSHADOW4;
13397 + s8 = (unsigned char*)VSHADOW8;
13398 +
13399 + for (i = 0; i < 80 * 30; i++)
13400 + text[i] = ' ';
13401 + graphics_cursor(1);
13402 +
13403 + BitMask(0xff);
13404 +
13405 + /* plano 1 */
13406 + MapMask(1);
13407 + grub_memcpy(mem, s1, 38400);
13408 +
13409 + /* plano 2 */
13410 + MapMask(2);
13411 + grub_memcpy(mem, s2, 38400);
13412 +
13413 + /* plano 3 */
13414 + MapMask(4);
13415 + grub_memcpy(mem, s4, 38400);
13416 +
13417 + /* plano 4 */
13418 + MapMask(8);
13419 + grub_memcpy(mem, s8, 38400);
13420 +
13421 + MapMask(15);
13422 +
13423 +}
13424 +
13425 +void graphics_setcolorstate (color_state state) {
13426 + switch (state) {
13427 + case COLOR_STATE_STANDARD:
13428 + graphics_current_color = graphics_standard_color;
13429 + break;
13430 + case COLOR_STATE_NORMAL:
13431 + graphics_current_color = graphics_normal_color;
13432 + break;
13433 + case COLOR_STATE_HIGHLIGHT:
13434 + graphics_current_color = graphics_highlight_color;
13435 + break;
13436 + default:
13437 + graphics_current_color = graphics_standard_color;
13438 + break;
13439 + }
13440 +
13441 + graphics_color_state = state;
13442 +}
13443 +
13444 +void graphics_setcolor (int normal_color, int highlight_color) {
13445 + graphics_normal_color = normal_color;
13446 + graphics_highlight_color = highlight_color;
13447 +
13448 + graphics_setcolorstate (graphics_color_state);
13449 +}
13450 +
13451 +void graphics_setcursor (int on) {
13452 + /* FIXME: we don't have a cursor in graphics */
13453 + return;
13454 +}
13455 +
13456 +/* Read in the splashscreen image and set the palette up appropriately.
13457 + * Format of splashscreen is an xpm (can be gzipped) with 16 colors and
13458 + * 640x480. */
13459 +int read_image(char *s)
13460 +{
13461 + char buf[32], pal[16];
13462 + unsigned char c, base, mask, *s1, *s2, *s4, *s8;
13463 + unsigned i, len, idx, colors, x, y, width, height;
13464 +
13465 + if (!grub_open(s))
13466 + return 0;
13467 +
13468 + /* read header */
13469 + if (!grub_read((char*)&buf, 10) || grub_memcmp(buf, "/* XPM */\n", 10)) {
13470 + grub_close();
13471 + return 0;
13472 + }
13473 +
13474 + /* parse info */
13475 + while (grub_read(&c, 1)) {
13476 + if (c == '"')
13477 + break;
13478 + }
13479 +
13480 + while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
13481 + ;
13482 +
13483 + i = 0;
13484 + width = c - '0';
13485 + while (grub_read(&c, 1)) {
13486 + if (c >= '0' && c <= '9')
13487 + width = width * 10 + c - '0';
13488 + else
13489 + break;
13490 + }
13491 + while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
13492 + ;
13493 +
13494 + height = c - '0';
13495 + while (grub_read(&c, 1)) {
13496 + if (c >= '0' && c <= '9')
13497 + height = height * 10 + c - '0';
13498 + else
13499 + break;
13500 + }
13501 + while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
13502 + ;
13503 +
13504 + colors = c - '0';
13505 + while (grub_read(&c, 1)) {
13506 + if (c >= '0' && c <= '9')
13507 + colors = colors * 10 + c - '0';
13508 + else
13509 + break;
13510 + }
13511 +
13512 + base = 0;
13513 + while (grub_read(&c, 1) && c != '"')
13514 + ;
13515 +
13516 + /* palette */
13517 + for (i = 0, idx = 1; i < colors; i++) {
13518 + len = 0;
13519 +
13520 + while (grub_read(&c, 1) && c != '"')
13521 + ;
13522 + grub_read(&c, 1); /* char */
13523 + base = c;
13524 + grub_read(buf, 4); /* \t c # */
13525 +
13526 + while (grub_read(&c, 1) && c != '"') {
13527 + if (len < sizeof(buf))
13528 + buf[len++] = c;
13529 + }
13530 +
13531 + if (len == 6 && idx < 15) {
13532 + int r = ((hex(buf[0]) << 4) | hex(buf[1])) >> 2;
13533 + int g = ((hex(buf[2]) << 4) | hex(buf[3])) >> 2;
13534 + int b = ((hex(buf[4]) << 4) | hex(buf[5])) >> 2;
13535 +
13536 + pal[idx] = base;
13537 + graphics_set_palette(idx, r, g, b);
13538 + ++idx;
13539 + }
13540 + }
13541 +
13542 + x = y = len = 0;
13543 +
13544 + s1 = (unsigned char*)VSHADOW1;
13545 + s2 = (unsigned char*)VSHADOW2;
13546 + s4 = (unsigned char*)VSHADOW4;
13547 + s8 = (unsigned char*)VSHADOW8;
13548 +
13549 + for (i = 0; i < 38400; i++)
13550 + s1[i] = s2[i] = s4[i] = s8[i] = 0;
13551 +
13552 + /* parse xpm data */
13553 + while (y < height) {
13554 + while (1) {
13555 + if (!grub_read(&c, 1)) {
13556 + grub_close();
13557 + return 0;
13558 + }
13559 + if (c == '"')
13560 + break;
13561 + }
13562 +
13563 + while (grub_read(&c, 1) && c != '"') {
13564 + for (i = 1; i < 15; i++)
13565 + if (pal[i] == c) {
13566 + c = i;
13567 + break;
13568 + }
13569 +
13570 + mask = 0x80 >> (x & 7);
13571 + if (c & 1)
13572 + s1[len + (x >> 3)] |= mask;
13573 + if (c & 2)
13574 + s2[len + (x >> 3)] |= mask;
13575 + if (c & 4)
13576 + s4[len + (x >> 3)] |= mask;
13577 + if (c & 8)
13578 + s8[len + (x >> 3)] |= mask;
13579 +
13580 + if (++x >= 640) {
13581 + x = 0;
13582 +
13583 + if (y < 480)
13584 + len += 80;
13585 + ++y;
13586 + }
13587 + }
13588 + }
13589 +
13590 + grub_close();
13591 +
13592 + graphics_set_palette(0, (background >> 16), (background >> 8) & 63,
13593 + background & 63);
13594 + graphics_set_palette(15, (foreground >> 16), (foreground >> 8) & 63,
13595 + foreground & 63);
13596 + graphics_set_palette(0x11, (border >> 16), (border >> 8) & 63,
13597 + border & 63);
13598 +
13599 + return 1;
13600 +}
13601 +
13602 +
13603 +/* Convert a character which is a hex digit to the appropriate integer */
13604 +int hex(int v)
13605 +{
13606 + if (v >= 'A' && v <= 'F')
13607 + return (v - 'A' + 10);
13608 + if (v >= 'a' && v <= 'f')
13609 + return (v - 'a' + 10);
13610 + return (v - '0');
13611 +}
13612 +
13613 +
13614 +/* move the graphics cursor location to col, row */
13615 +static void graphics_setxy(int col, int row) {
13616 + if (col >= x0 && col < x1) {
13617 + fontx = col;
13618 + cursorX = col << 3;
13619 + }
13620 + if (row >= y0 && row < y1) {
13621 + fonty = row;
13622 + cursorY = row << 4;
13623 + }
13624 +}
13625 +
13626 +/* scroll the screen */
13627 +static void graphics_scroll() {
13628 + int i, j;
13629 +
13630 + /* we don't want to scroll recursively... that would be bad */
13631 + if (no_scroll)
13632 + return;
13633 + no_scroll = 1;
13634 +
13635 + /* move everything up a line */
13636 + for (j = y0 + 1; j < y1; j++) {
13637 + graphics_gotoxy(x0, j - 1);
13638 + for (i = x0; i < x1; i++) {
13639 + graphics_putchar(text[j * 80 + i]);
13640 + }
13641 + }
13642 +
13643 + /* last line should be blank */
13644 + graphics_gotoxy(x0, y1 - 1);
13645 + for (i = x0; i < x1; i++)
13646 + graphics_putchar(' ');
13647 + graphics_setxy(x0, y1 - 1);
13648 +
13649 + no_scroll = 0;
13650 +}
13651 +
13652 +
13653 +void graphics_cursor(int set) {
13654 + unsigned char *pat, *mem, *ptr, chr[16 << 2];
13655 + int i, ch, invert, offset;
13656 +
13657 + if (set && no_scroll)
13658 + return;
13659 +
13660 + offset = cursorY * 80 + fontx;
13661 + ch = text[fonty * 80 + fontx] & 0xff;
13662 + invert = (text[fonty * 80 + fontx] & 0xff00) != 0;
13663 + pat = font8x16 + (ch << 4);
13664 +
13665 + mem = (unsigned char*)VIDEOMEM + offset;
13666 +
13667 + if (!set) {
13668 + for (i = 0; i < 16; i++) {
13669 + unsigned char mask = pat[i];
13670 +
13671 + if (!invert) {
13672 + chr[i ] = ((unsigned char*)VSHADOW1)[offset];
13673 + chr[16 + i] = ((unsigned char*)VSHADOW2)[offset];
13674 + chr[32 + i] = ((unsigned char*)VSHADOW4)[offset];
13675 + chr[48 + i] = ((unsigned char*)VSHADOW8)[offset];
13676 +
13677 + /* FIXME: if (shade) */
13678 + if (1) {
13679 + if (ch == DISP_VERT || ch == DISP_LL ||
13680 + ch == DISP_UR || ch == DISP_LR) {
13681 + unsigned char pmask = ~(pat[i] >> 1);
13682 +
13683 + chr[i ] &= pmask;
13684 + chr[16 + i] &= pmask;
13685 + chr[32 + i] &= pmask;
13686 + chr[48 + i] &= pmask;
13687 + }
13688 + if (i > 0 && ch != DISP_VERT) {
13689 + unsigned char pmask = ~(pat[i - 1] >> 1);
13690 +
13691 + chr[i ] &= pmask;
13692 + chr[16 + i] &= pmask;
13693 + chr[32 + i] &= pmask;
13694 + chr[48 + i] &= pmask;
13695 + if (ch == DISP_HORIZ || ch == DISP_UR || ch == DISP_LR) {
13696 + pmask = ~pat[i - 1];
13697 +
13698 + chr[i ] &= pmask;
13699 + chr[16 + i] &= pmask;
13700 + chr[32 + i] &= pmask;
13701 + chr[48 + i] &= pmask;
13702 + }
13703 + }
13704 + }
13705 + chr[i ] |= mask;
13706 + chr[16 + i] |= mask;
13707 + chr[32 + i] |= mask;
13708 + chr[48 + i] |= mask;
13709 +
13710 + offset += 80;
13711 + }
13712 + else {
13713 + chr[i ] = mask;
13714 + chr[16 + i] = mask;
13715 + chr[32 + i] = mask;
13716 + chr[48 + i] = mask;
13717 + }
13718 + }
13719 + }
13720 + else {
13721 + MapMask(15);
13722 + ptr = mem;
13723 + for (i = 0; i < 16; i++, ptr += 80) {
13724 + cursorBuf[i] = pat[i];
13725 + *ptr = ~pat[i];
13726 + }
13727 + return;
13728 + }
13729 +
13730 + offset = 0;
13731 + for (i = 1; i < 16; i <<= 1, offset += 16) {
13732 + int j;
13733 +
13734 + MapMask(i);
13735 + ptr = mem;
13736 + for (j = 0; j < 16; j++, ptr += 80)
13737 + *ptr = chr[j + offset];
13738 + }
13739 +
13740 + MapMask(15);
13741 +}
13742 +
13743 +int grub_file_exists(char *s) {
13744 + if (!grub_open(s))
13745 + return 0;
13746 + grub_close();
13747 + return 1;
13748 +}
13749 +
13750 +#endif /* SUPPORT_GRAPHICS */
13751 diff -Nur grub-0.97/stage2/graphics.h grub-0.97-patched/stage2/graphics.h
13752 --- grub-0.97/stage2/graphics.h 1970-01-01 01:00:00.000000000 +0100
13753 +++ grub-0.97-patched/stage2/graphics.h 2012-11-11 17:06:33.321470879 +0100
13754 @@ -0,0 +1,45 @@
13755 +/* graphics.h - graphics console interface */
13756 +/*
13757 + * GRUB -- GRand Unified Bootloader
13758 + * Copyright (C) 2002 Free Software Foundation, Inc.
13759 + *
13760 + * This program is free software; you can redistribute it and/or modify
13761 + * it under the terms of the GNU General Public License as published by
13762 + * the Free Software Foundation; either version 2 of the License, or
13763 + * (at your option) any later version.
13764 + *
13765 + * This program is distributed in the hope that it will be useful,
13766 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
13767 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13768 + * GNU General Public License for more details.
13769 + *
13770 + * You should have received a copy of the GNU General Public License
13771 + * along with this program; if not, write to the Free Software
13772 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
13773 + */
13774 +
13775 +#ifndef GRAPHICS_H
13776 +#define GRAPHICS_H
13777 +
13778 +/* magic constant */
13779 +#define VIDEOMEM 0xA0000
13780 +
13781 +/* function prototypes */
13782 +char *graphics_get_splash(void);
13783 +
13784 +int read_image(char *s);
13785 +void graphics_cursor(int set);
13786 +
13787 +/* function prototypes for asm functions */
13788 +void * graphics_get_font();
13789 +void graphics_set_palette(int idx, int red, int green, int blue);
13790 +void set_int1c_handler();
13791 +void unset_int1c_handler();
13792 +
13793 +/* Only to check for safe opening before we start */
13794 +int grub_file_exists(char *s);
13795 +
13796 +extern short cursorX, cursorY;
13797 +extern char cursorBuf[16];
13798 +
13799 +#endif /* GRAPHICS_H */
13800 diff -Nur grub-0.97/stage2/iso9660.h grub-0.97-patched/stage2/iso9660.h
13801 --- grub-0.97/stage2/iso9660.h 2004-03-27 17:02:38.000000000 +0100
13802 +++ grub-0.97-patched/stage2/iso9660.h 2012-11-11 17:07:12.740730013 +0100
13803 @@ -73,11 +73,11 @@
13804
13805 typedef struct __iso_16bit {
13806 u_int16_t l, b;
13807 -} iso_16bit_t __attribute__ ((packed));
13808 +} iso_16bit_t;
13809
13810 typedef struct __iso_32bit {
13811 u_int32_t l, b;
13812 -} iso_32bit_t __attribute__ ((packed));
13813 +} iso_32bit_t;
13814
13815 typedef u_int8_t iso_date_t[7];
13816
13817 diff -Nur grub-0.97/stage2/Makefile.am grub-0.97-patched/stage2/Makefile.am
13818 --- grub-0.97/stage2/Makefile.am 2005-02-02 21:37:35.000000000 +0100
13819 +++ grub-0.97-patched/stage2/Makefile.am 2012-11-11 17:07:12.747730236 +0100
13820 @@ -7,7 +7,7 @@
13821 fat.h filesys.h freebsd.h fs.h hercules.h i386-elf.h \
13822 imgact_aout.h iso9660.h jfs.h mb_header.h mb_info.h md5.h \
13823 nbi.h pc_slice.h serial.h shared.h smp-imps.h term.h \
13824 - terminfo.h tparm.h nbi.h ufs2.h vstafs.h xfs.h
13825 + terminfo.h tparm.h nbi.h ufs2.h vstafs.h xfs.h graphics.h
13826 EXTRA_DIST = setjmp.S apm.S $(noinst_SCRIPTS)
13827
13828 # For <stage1.h>.
13829 @@ -19,20 +19,20 @@
13830 disk_io.c fsys_ext2fs.c fsys_fat.c fsys_ffs.c fsys_iso9660.c \
13831 fsys_jfs.c fsys_minix.c fsys_reiserfs.c fsys_ufs2.c \
13832 fsys_vstafs.c fsys_xfs.c gunzip.c md5.c serial.c stage2.c \
13833 - terminfo.c tparm.c
13834 -libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \
13835 + terminfo.c tparm.c graphics.c
13836 +libgrub_a_CFLAGS = $(GRUB_CFLAGS) -fno-stack-protector -I$(top_srcdir)/lib \
13837 -DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 -DFSYS_FFS=1 \
13838 -DFSYS_ISO9660=1 -DFSYS_JFS=1 -DFSYS_MINIX=1 -DFSYS_REISERFS=1 \
13839 -DFSYS_UFS2=1 -DFSYS_VSTAFS=1 -DFSYS_XFS=1 \
13840 -DUSE_MD5_PASSWORDS=1 -DSUPPORT_SERIAL=1 -DSUPPORT_HERCULES=1
13841
13842 # Stage 2 and Stage 1.5's.
13843 -pkglibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
13844 +stagedir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
13845
13846 EXTRA_PROGRAMS = nbloader.exec pxeloader.exec diskless.exec
13847
13848 if DISKLESS_SUPPORT
13849 -pkglib_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
13850 +stage_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
13851 ffs_stage1_5 iso9660_stage1_5 jfs_stage1_5 minix_stage1_5 \
13852 reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5 \
13853 nbgrub pxegrub
13854 @@ -43,7 +43,7 @@
13855 reiserfs_stage1_5.exec ufs2_stage1_5.exec vstafs_stage1_5.exec \
13856 xfs_stage1_5.exec nbloader.exec pxeloader.exec diskless.exec
13857 else
13858 -pkglib_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
13859 +stage_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
13860 ffs_stage1_5 iso9660_stage1_5 jfs_stage1_5 minix_stage1_5 \
13861 reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5
13862 noinst_DATA = pre_stage2 start start_eltorito
13863 @@ -79,8 +79,14 @@
13864 HERCULES_FLAGS =
13865 endif
13866
13867 -STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
13868 - $(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS)
13869 +if GRAPHICS_SUPPORT
13870 +GRAPHICS_FLAGS = -DSUPPORT_GRAPHICS=1
13871 +else
13872 +GRAPHICS_FLAGS =
13873 +endif
13874 +
13875 +STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-reorder-functions -fno-builtin -nostdinc \
13876 + $(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS) $(GRAPHICS_FLAGS)
13877
13878 STAGE1_5_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,2000
13879 STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1
13880 @@ -90,7 +96,8 @@
13881 cmdline.c common.c console.c disk_io.c fsys_ext2fs.c \
13882 fsys_fat.c fsys_ffs.c fsys_iso9660.c fsys_jfs.c fsys_minix.c \
13883 fsys_reiserfs.c fsys_ufs2.c fsys_vstafs.c fsys_xfs.c gunzip.c \
13884 - hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c
13885 + hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c \
13886 + graphics.c
13887 pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
13888 pre_stage2_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
13889 pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK)
13890 @@ -105,7 +112,7 @@
13891 BUILT_SOURCES = stage2_size.h
13892 endif
13893
13894 -CLEANFILES = $(pkglib_DATA) $(noinst_DATA) $(BUILT_SOURCES)
13895 +CLEANFILES = $(stage_DATA) $(noinst_DATA) $(BUILT_SOURCES)
13896
13897 stage2_size.h: pre_stage2
13898 -rm -f stage2_size.h
13899 diff -Nur grub-0.97/stage2/Makefile.am.orig grub-0.97-patched/stage2/Makefile.am.orig
13900 --- grub-0.97/stage2/Makefile.am.orig 1970-01-01 01:00:00.000000000 +0100
13901 +++ grub-0.97-patched/stage2/Makefile.am.orig 2005-02-02 21:37:35.000000000 +0100
13902 @@ -0,0 +1,272 @@
13903 +# For test target.
13904 +TESTS = size_test
13905 +noinst_SCRIPTS = $(TESTS)
13906 +
13907 +# For dist target.
13908 +noinst_HEADERS = apic.h defs.h dir.h disk_inode.h disk_inode_ffs.h \
13909 + fat.h filesys.h freebsd.h fs.h hercules.h i386-elf.h \
13910 + imgact_aout.h iso9660.h jfs.h mb_header.h mb_info.h md5.h \
13911 + nbi.h pc_slice.h serial.h shared.h smp-imps.h term.h \
13912 + terminfo.h tparm.h nbi.h ufs2.h vstafs.h xfs.h
13913 +EXTRA_DIST = setjmp.S apm.S $(noinst_SCRIPTS)
13914 +
13915 +# For <stage1.h>.
13916 +INCLUDES = -I$(top_srcdir)/stage1
13917 +
13918 +# The library for /sbin/grub.
13919 +noinst_LIBRARIES = libgrub.a
13920 +libgrub_a_SOURCES = boot.c builtins.c char_io.c cmdline.c common.c \
13921 + disk_io.c fsys_ext2fs.c fsys_fat.c fsys_ffs.c fsys_iso9660.c \
13922 + fsys_jfs.c fsys_minix.c fsys_reiserfs.c fsys_ufs2.c \
13923 + fsys_vstafs.c fsys_xfs.c gunzip.c md5.c serial.c stage2.c \
13924 + terminfo.c tparm.c
13925 +libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \
13926 + -DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 -DFSYS_FFS=1 \
13927 + -DFSYS_ISO9660=1 -DFSYS_JFS=1 -DFSYS_MINIX=1 -DFSYS_REISERFS=1 \
13928 + -DFSYS_UFS2=1 -DFSYS_VSTAFS=1 -DFSYS_XFS=1 \
13929 + -DUSE_MD5_PASSWORDS=1 -DSUPPORT_SERIAL=1 -DSUPPORT_HERCULES=1
13930 +
13931 +# Stage 2 and Stage 1.5's.
13932 +pkglibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
13933 +
13934 +EXTRA_PROGRAMS = nbloader.exec pxeloader.exec diskless.exec
13935 +
13936 +if DISKLESS_SUPPORT
13937 +pkglib_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
13938 + ffs_stage1_5 iso9660_stage1_5 jfs_stage1_5 minix_stage1_5 \
13939 + reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5 \
13940 + nbgrub pxegrub
13941 +noinst_DATA = pre_stage2 start start_eltorito nbloader pxeloader diskless
13942 +noinst_PROGRAMS = pre_stage2.exec start.exec start_eltorito.exec \
13943 + e2fs_stage1_5.exec fat_stage1_5.exec ffs_stage1_5.exec \
13944 + iso9660_stage1_5.exec jfs_stage1_5.exec minix_stage1_5.exec \
13945 + reiserfs_stage1_5.exec ufs2_stage1_5.exec vstafs_stage1_5.exec \
13946 + xfs_stage1_5.exec nbloader.exec pxeloader.exec diskless.exec
13947 +else
13948 +pkglib_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
13949 + ffs_stage1_5 iso9660_stage1_5 jfs_stage1_5 minix_stage1_5 \
13950 + reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5
13951 +noinst_DATA = pre_stage2 start start_eltorito
13952 +noinst_PROGRAMS = pre_stage2.exec start.exec start_eltorito.exec \
13953 + e2fs_stage1_5.exec fat_stage1_5.exec ffs_stage1_5.exec \
13954 + iso9660_stage1_5.exec jfs_stage1_5.exec minix_stage1_5.exec \
13955 + reiserfs_stage1_5.exec ufs2_stage1_5.exec vstafs_stage1_5.exec \
13956 + xfs_stage1_5.exec
13957 +endif
13958 +MOSTLYCLEANFILES = $(noinst_PROGRAMS)
13959 +
13960 +PRE_STAGE2_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,8200
13961 +START_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,8000
13962 +NBLOADER_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,0
13963 +PXELOADER_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,7C00
13964 +START_ELTORITO_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,7C00
13965 +
13966 +if NETBOOT_SUPPORT
13967 +NETBOOT_FLAGS = -I$(top_srcdir)/netboot -DSUPPORT_NETBOOT=1
13968 +else
13969 +NETBOOT_FLAGS =
13970 +endif
13971 +
13972 +if SERIAL_SUPPORT
13973 +SERIAL_FLAGS = -DSUPPORT_SERIAL=1
13974 +else
13975 +SERIAL_FLAGS =
13976 +endif
13977 +
13978 +if HERCULES_SUPPORT
13979 +HERCULES_FLAGS = -DSUPPORT_HERCULES=1
13980 +else
13981 +HERCULES_FLAGS =
13982 +endif
13983 +
13984 +STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
13985 + $(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS)
13986 +
13987 +STAGE1_5_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,2000
13988 +STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1
13989 +
13990 +# For stage2 target.
13991 +pre_stage2_exec_SOURCES = asm.S bios.c boot.c builtins.c char_io.c \
13992 + cmdline.c common.c console.c disk_io.c fsys_ext2fs.c \
13993 + fsys_fat.c fsys_ffs.c fsys_iso9660.c fsys_jfs.c fsys_minix.c \
13994 + fsys_reiserfs.c fsys_ufs2.c fsys_vstafs.c fsys_xfs.c gunzip.c \
13995 + hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c
13996 +pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
13997 +pre_stage2_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
13998 +pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK)
13999 +
14000 +if NETBOOT_SUPPORT
14001 +pre_stage2_exec_LDADD = ../netboot/libdrivers.a
14002 +endif
14003 +
14004 +if DISKLESS_SUPPORT
14005 +BUILT_SOURCES = stage2_size.h diskless_size.h
14006 +else
14007 +BUILT_SOURCES = stage2_size.h
14008 +endif
14009 +
14010 +CLEANFILES = $(pkglib_DATA) $(noinst_DATA) $(BUILT_SOURCES)
14011 +
14012 +stage2_size.h: pre_stage2
14013 + -rm -f stage2_size.h
14014 + set dummy `ls -l pre_stage2`; \
14015 + echo "#define STAGE2_SIZE $$6" > stage2_size.h
14016 +
14017 +start_exec_SOURCES = start.S
14018 +start_exec_CCASFLAGS = $(STAGE2_COMPILE)
14019 +start_exec_LDFLAGS = $(START_LINK)
14020 +
14021 +# XXX: automake doesn't provide a way to specify dependencies for object
14022 +# files explicitly, so we must write this by a general Makefile scheme.
14023 +# If automake change the naming scheme for per-executable objects, this
14024 +# will be broken.
14025 +start_exec-start.$(OBJEXT): stage2_size.h
14026 +
14027 +stage2: pre_stage2 start
14028 + -rm -f stage2
14029 + cat start pre_stage2 > stage2
14030 +
14031 +start_eltorito_exec_SOURCES = start_eltorito.S
14032 +start_eltorito_exec_CCASFLAGS = $(STAGE2_COMPILE)
14033 +start_eltorito_exec_LDFLAGS = $(START_ELTORITO_LINK)
14034 +
14035 +start_eltorito_exec-start.$(OBJEXT): stage2_size.h
14036 +
14037 +stage2_eltorito: pre_stage2 start_eltorito
14038 + -rm -f stage2_eltorito
14039 + cat start_eltorito pre_stage2 > stage2_eltorito
14040 +
14041 +# For e2fs_stage1_5 target.
14042 +e2fs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c disk_io.c \
14043 + stage1_5.c fsys_ext2fs.c bios.c
14044 +e2fs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_EXT2FS=1 \
14045 + -DNO_BLOCK_FILES=1
14046 +e2fs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_EXT2FS=1 \
14047 + -DNO_BLOCK_FILES=1
14048 +e2fs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
14049 +
14050 +# For fat_stage1_5 target.
14051 +fat_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c disk_io.c \
14052 + stage1_5.c fsys_fat.c bios.c
14053 +fat_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_FAT=1 \
14054 + -DNO_BLOCK_FILES=1
14055 +fat_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_FAT=1 \
14056 + -DNO_BLOCK_FILES=1
14057 +fat_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
14058 +
14059 +# For ffs_stage1_5 target.
14060 +ffs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c disk_io.c \
14061 + stage1_5.c fsys_ffs.c bios.c
14062 +ffs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_FFS=1 \
14063 + -DNO_BLOCK_FILES=1
14064 +ffs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_FFS=1 \
14065 + -DNO_BLOCK_FILES=1
14066 +ffs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
14067 +
14068 +# For ufs2_stage1_5 target.
14069 +ufs2_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c disk_io.c \
14070 + stage1_5.c fsys_ufs2.c bios.c
14071 +ufs2_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_UFS2=1 \
14072 + -DNO_BLOCK_FILES=1
14073 +ufs2_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_UFS2=1 \
14074 + -DNO_BLOCK_FILES=1
14075 +ufs2_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
14076 +
14077 +# For minix_stage1_5 target.
14078 +minix_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c disk_io.c \
14079 + stage1_5.c fsys_minix.c bios.c
14080 +minix_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_MINIX=1 \
14081 + -DNO_BLOCK_FILES=1
14082 +minix_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_MINIX=1 \
14083 + -DNO_BLOCK_FILES=1
14084 +minix_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
14085 +
14086 +# For reiserfs_stage1_5 target.
14087 +reiserfs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c \
14088 + disk_io.c stage1_5.c fsys_reiserfs.c bios.c
14089 +reiserfs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_REISERFS=1 \
14090 + -DNO_BLOCK_FILES=1
14091 +reiserfs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_REISERFS=1 \
14092 + -DNO_BLOCK_FILES=1
14093 +reiserfs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
14094 +
14095 +# For vstafs_stage1_5 target.
14096 +vstafs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c \
14097 + disk_io.c stage1_5.c fsys_vstafs.c bios.c
14098 +vstafs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_VSTAFS=1 \
14099 + -DNO_BLOCK_FILES=1
14100 +vstafs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_VSTAFS=1 \
14101 + -DNO_BLOCK_FILES=1
14102 +vstafs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
14103 +
14104 +# For jfs_stage1_5 target.
14105 +jfs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c \
14106 + disk_io.c stage1_5.c fsys_jfs.c bios.c
14107 +jfs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_JFS=1 \
14108 + -DNO_BLOCK_FILES=1
14109 +jfs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_JFS=1 \
14110 + -DNO_BLOCK_FILES=1
14111 +jfs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
14112 +
14113 +# For xfs_stage1_5 target.
14114 +xfs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c \
14115 + disk_io.c stage1_5.c fsys_xfs.c bios.c
14116 +xfs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_XFS=1 \
14117 + -DNO_BLOCK_FILES=1
14118 +xfs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_XFS=1 \
14119 + -DNO_BLOCK_FILES=1
14120 +xfs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
14121 +
14122 +# For iso9660_stage1_5 target.
14123 +iso9660_stage1_5_exec_SOURCES = start_eltorito.S asm.S common.c char_io.c \
14124 + disk_io.c stage1_5.c fsys_iso9660.c bios.c
14125 +iso9660_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_ISO9660=1 \
14126 + -DNO_BLOCK_FILES=1
14127 +iso9660_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_ISO9660=1 \
14128 + -DNO_BLOCK_FILES=1
14129 +iso9660_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
14130 +
14131 +# For diskless target.
14132 +diskless_exec_SOURCES = $(pre_stage2_exec_SOURCES)
14133 +diskless_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) \
14134 + -DSUPPORT_DISKLESS=1
14135 +diskless_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) \
14136 + -DSUPPORT_DISKLESS=1
14137 +diskless_exec_LDFLAGS = $(PRE_STAGE2_LINK)
14138 +diskless_exec_LDADD = ../netboot/libdrivers.a
14139 +
14140 +diskless_size.h: diskless
14141 + -rm -f $@
14142 + set dummy `ls -l $^`; \
14143 + echo "#define DISKLESS_SIZE $$6" > $@
14144 +
14145 +# For nbloader target.
14146 +nbloader_exec_SOURCES = nbloader.S
14147 +nbloader_exec_CCASFLAGS = $(STAGE2_COMPILE)
14148 +nbloader_exec_LDFLAGS = $(NBLOADER_LINK)
14149 +
14150 +# XXX: See the comment for start_exec-start.o.
14151 +nbloader_exec-nbloader.$(OBJEXT): diskless_size.h
14152 +
14153 +# For nbgrub target.
14154 +nbgrub: nbloader diskless
14155 + -rm -f $@
14156 + cat $^ > $@
14157 +
14158 +# For pxeloader target.
14159 +pxeloader_exec_SOURCES = pxeloader.S
14160 +pxeloader_exec_CCASFLAGS = $(STAGE2_COMPILE)
14161 +pxeloader_exec_LDFLAGS = $(PXELOADER_LINK)
14162 +
14163 +# XXX: See the comment for start_exec-start.o.
14164 +pxeloader_exec-pxeloader.$(OBJEXT): diskless_size.h
14165 +
14166 +# For pxegrub target.
14167 +pxegrub: pxeloader diskless
14168 + -rm -f $@
14169 + cat $^ > $@
14170 +
14171 +# General rule for making a raw binary.
14172 +SUFFIXES = .exec
14173 +.exec:
14174 + $(OBJCOPY) -O binary $< $@
14175 diff -Nur grub-0.97/stage2/pc_slice.h grub-0.97-patched/stage2/pc_slice.h
14176 --- grub-0.97/stage2/pc_slice.h 2003-07-09 13:45:53.000000000 +0200
14177 +++ grub-0.97-patched/stage2/pc_slice.h 2012-11-11 17:07:12.698728671 +0100
14178 @@ -115,6 +115,7 @@
14179 #define PC_SLICE_TYPE_LINUX_EXTENDED 0x85
14180 #define PC_SLICE_TYPE_VSTAFS 0x9e
14181 #define PC_SLICE_TYPE_DELL_UTIL 0xde
14182 +#define PC_SLICE_TYPE_GPT 0xee
14183 #define PC_SLICE_TYPE_LINUX_RAID 0xfd
14184
14185
14186 diff -Nur grub-0.97/stage2/shared.h grub-0.97-patched/stage2/shared.h
14187 --- grub-0.97/stage2/shared.h 2004-06-19 18:40:09.000000000 +0200
14188 +++ grub-0.97-patched/stage2/shared.h 2012-11-11 17:07:12.741730044 +0100
14189 @@ -36,8 +36,8 @@
14190
14191 /* Maybe redirect memory requests through grub_scratch_mem. */
14192 #ifdef GRUB_UTIL
14193 -extern char *grub_scratch_mem;
14194 -# define RAW_ADDR(x) ((x) + (int) grub_scratch_mem)
14195 +extern void *grub_scratch_mem;
14196 +# define RAW_ADDR(x) ((x) + (unsigned long) grub_scratch_mem)
14197 # define RAW_SEG(x) (RAW_ADDR ((x) << 4) >> 4)
14198 #else
14199 # define RAW_ADDR(x) (x)
14200 @@ -161,7 +161,9 @@
14201
14202 #define LINUX_CL_OFFSET 0x9000
14203 #define LINUX_CL_END_OFFSET 0x90FF
14204 -#define LINUX_SETUP_MOVE_SIZE 0x9100
14205 +#define LINUX_CL_0202_PRM_OFFSET 0x9500
14206 +#define LINUX_CL_0202_PRM_END_OFFSET 0x9FFF
14207 +#define LINUX_SETUP_MOVE_SIZE 0xA000
14208 #define LINUX_CL_MAGIC 0xA33F
14209
14210 /*
14211 @@ -499,7 +501,11 @@
14212 unsigned char linear_reserved_field_position;
14213 unsigned long max_pixel_clock;
14214
14215 - unsigned char reserved3[189];
14216 + /* Reserved field to make structure to be 256 bytes long, VESA BIOS
14217 + Extension 3.0 Specification says to reserve 189 bytes here but
14218 + that doesn't make structure to be 256 bytes. So additional one is
14219 + added here. */
14220 + unsigned char reserved3[189 + 1];
14221 } __attribute__ ((packed));
14222
14223
14224 @@ -807,7 +813,7 @@
14225 /* Low-level disk I/O */
14226 int get_diskinfo (int drive, struct geometry *geometry);
14227 int biosdisk (int subfunc, int drive, struct geometry *geometry,
14228 - int sector, int nsec, int segment);
14229 + unsigned int sector, int nsec, int segment);
14230 void stop_floppy (void);
14231
14232 /* Command-line interface functions. */
14233 @@ -871,6 +877,7 @@
14234 int grub_tolower (int c);
14235 int grub_isspace (int c);
14236 int grub_strncat (char *s1, const char *s2, int n);
14237 +void grub_memcpy(void *dest, const void *src, int len);
14238 void *grub_memmove (void *to, const void *from, int len);
14239 void *grub_memset (void *start, int c, int len);
14240 int grub_strncat (char *s1, const char *s2, int n);
14241 @@ -911,7 +918,7 @@
14242 int nul_terminate (char *str);
14243 int get_based_digit (int c, int base);
14244 int safe_parse_maxint (char **str_ptr, int *myint_ptr);
14245 -int memcheck (int start, int len);
14246 +int memcheck (unsigned long start, unsigned long len);
14247 void grub_putstr (const char *str);
14248
14249 #ifndef NO_DECOMPRESSION
14250 @@ -920,10 +927,10 @@
14251 int gunzip_read (char *buf, int len);
14252 #endif /* NO_DECOMPRESSION */
14253
14254 -int rawread (int drive, int sector, int byte_offset, int byte_len, char *buf);
14255 -int devread (int sector, int byte_offset, int byte_len, char *buf);
14256 -int rawwrite (int drive, int sector, char *buf);
14257 -int devwrite (int sector, int sector_len, char *buf);
14258 +int rawread (int drive, unsigned int sector, int byte_offset, int byte_len, char *buf);
14259 +int devread (unsigned int sector, int byte_offset, int byte_len, char *buf);
14260 +int rawwrite (int drive, unsigned int sector, char *buf);
14261 +int devwrite (unsigned int sector, int sector_len, char *buf);
14262
14263 /* Parse a device string and initialize the global parameters. */
14264 char *set_device (char *device);
14265 @@ -934,7 +941,9 @@
14266 unsigned long *partition, int *type,
14267 unsigned long *start, unsigned long *len,
14268 unsigned long *offset, int *entry,
14269 - unsigned long *ext_offset, char *buf);
14270 + unsigned long *ext_offset,
14271 + unsigned long *gpt_offset, int *gpt_count,
14272 + int *gpt_size, char *buf);
14273
14274 /* Sets device to the one represented by the SAVED_* parameters. */
14275 int make_saved_active (void);
14276 diff -Nur grub-0.97/stage2/size_test grub-0.97-patched/stage2/size_test
14277 --- grub-0.97/stage2/size_test 2004-05-14 21:30:52.000000000 +0200
14278 +++ grub-0.97-patched/stage2/size_test 2012-11-11 17:06:52.554085177 +0100
14279 @@ -36,9 +36,9 @@
14280 }
14281
14282 # The bootloader area of a FFS partition is 14 sectors.
14283 -check ffs_stage1_5 7168
14284 -
14285 -check ufs2_stage1_5 7168
14286 +#check ffs_stage1_5 7168
14287 +#
14288 +#check ufs2_stage1_5 7168
14289
14290 # Stage 1.5 can be installed in the sectors immediately after MBR in the
14291 # first cylinder, so the size is (63 - 1) sectors.
14292 diff -Nur grub-0.97/stage2/stage2.c grub-0.97-patched/stage2/stage2.c
14293 --- grub-0.97/stage2/stage2.c 2005-03-19 18:51:57.000000000 +0100
14294 +++ grub-0.97-patched/stage2/stage2.c 2012-11-11 17:07:12.742730076 +0100
14295 @@ -233,6 +233,7 @@
14296 {
14297 int c, time1, time2 = -1, first_entry = 0;
14298 char *cur_entry = 0;
14299 + struct term_entry *prev_term = NULL;
14300
14301 /*
14302 * Main loop for menu UI.
14303 @@ -651,7 +652,10 @@
14304 *(new_heap++) = 0;
14305
14306 if (config_entries)
14307 - run_menu (heap, NULL, new_num_entries, new_heap, 0);
14308 + {
14309 + current_entryno = first_entry + entryno;
14310 + run_menu (heap, NULL, new_num_entries, new_heap, 0);
14311 + }
14312 else
14313 {
14314 cls ();
14315 @@ -714,6 +718,15 @@
14316
14317 cls ();
14318 setcursor (1);
14319 + /* if our terminal needed initialization, we should shut it down
14320 + * before booting the kernel, but we want to save what it was so
14321 + * we can come back if needed */
14322 + prev_term = current_term;
14323 + if (current_term->shutdown)
14324 + {
14325 + (*current_term->shutdown)();
14326 + current_term = term_table; /* assumption: console is first */
14327 + }
14328
14329 while (1)
14330 {
14331 @@ -727,7 +740,8 @@
14332 cur_entry = get_entry (config_entries, first_entry + entryno, 1);
14333
14334 /* Set CURRENT_ENTRYNO for the command "savedefault". */
14335 - current_entryno = first_entry + entryno;
14336 + if (config_entries)
14337 + current_entryno = first_entry + entryno;
14338
14339 if (run_script (cur_entry, heap))
14340 {
14341 @@ -748,6 +762,13 @@
14342 break;
14343 }
14344
14345 + /* if we get back here, we should go back to what our term was before */
14346 + current_term = prev_term;
14347 + if (current_term->startup)
14348 + /* if our terminal fails to initialize, fall back to console since
14349 + * it should always work */
14350 + if ((*current_term->startup)() == 0)
14351 + current_term = term_table; /* we know that console is first */
14352 show_menu = 1;
14353 goto restart;
14354 }
14355 @@ -1050,6 +1071,10 @@
14356 while (is_preset);
14357 }
14358
14359 + /* go ahead and make sure the terminal is setup */
14360 + if (current_term->startup)
14361 + (*current_term->startup)();
14362 +
14363 if (! num_entries)
14364 {
14365 /* If no acceptable config file, goto command-line, starting
14366 diff -Nur grub-0.97/stage2/stage2.c.orig grub-0.97-patched/stage2/stage2.c.orig
14367 --- grub-0.97/stage2/stage2.c.orig 1970-01-01 01:00:00.000000000 +0100
14368 +++ grub-0.97-patched/stage2/stage2.c.orig 2005-03-19 18:51:57.000000000 +0100
14369 @@ -0,0 +1,1067 @@
14370 +/*
14371 + * GRUB -- GRand Unified Bootloader
14372 + * Copyright (C) 2000,2001,2002,2004,2005 Free Software Foundation, Inc.
14373 + *
14374 + * This program is free software; you can redistribute it and/or modify
14375 + * it under the terms of the GNU General Public License as published by
14376 + * the Free Software Foundation; either version 2 of the License, or
14377 + * (at your option) any later version.
14378 + *
14379 + * This program is distributed in the hope that it will be useful,
14380 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
14381 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14382 + * GNU General Public License for more details.
14383 + *
14384 + * You should have received a copy of the GNU General Public License
14385 + * along with this program; if not, write to the Free Software
14386 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
14387 + */
14388 +
14389 +#include <shared.h>
14390 +#include <term.h>
14391 +
14392 +grub_jmp_buf restart_env;
14393 +
14394 +#if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS)
14395 +
14396 +# if defined(PRESET_MENU_STRING)
14397 +static const char *preset_menu = PRESET_MENU_STRING;
14398 +# elif defined(SUPPORT_DISKLESS)
14399 +/* Execute the command "bootp" automatically. */
14400 +static const char *preset_menu = "bootp\n";
14401 +# endif /* SUPPORT_DISKLESS */
14402 +
14403 +static int preset_menu_offset;
14404 +
14405 +static int
14406 +open_preset_menu (void)
14407 +{
14408 +#ifdef GRUB_UTIL
14409 + /* Unless the user explicitly requests to use the preset menu,
14410 + always opening the preset menu fails in the grub shell. */
14411 + if (! use_preset_menu)
14412 + return 0;
14413 +#endif /* GRUB_UTIL */
14414 +
14415 + preset_menu_offset = 0;
14416 + return preset_menu != 0;
14417 +}
14418 +
14419 +static int
14420 +read_from_preset_menu (char *buf, int maxlen)
14421 +{
14422 + int len = grub_strlen (preset_menu + preset_menu_offset);
14423 +
14424 + if (len > maxlen)
14425 + len = maxlen;
14426 +
14427 + grub_memmove (buf, preset_menu + preset_menu_offset, len);
14428 + preset_menu_offset += len;
14429 +
14430 + return len;
14431 +}
14432 +
14433 +static void
14434 +close_preset_menu (void)
14435 +{
14436 + /* Disable the preset menu. */
14437 + preset_menu = 0;
14438 +}
14439 +
14440 +#else /* ! PRESET_MENU_STRING && ! SUPPORT_DISKLESS */
14441 +
14442 +#define open_preset_menu() 0
14443 +#define read_from_preset_menu(buf, maxlen) 0
14444 +#define close_preset_menu()
14445 +
14446 +#endif /* ! PRESET_MENU_STRING && ! SUPPORT_DISKLESS */
14447 +
14448 +static char *
14449 +get_entry (char *list, int num, int nested)
14450 +{
14451 + int i;
14452 +
14453 + for (i = 0; i < num; i++)
14454 + {
14455 + do
14456 + {
14457 + while (*(list++));
14458 + }
14459 + while (nested && *(list++));
14460 + }
14461 +
14462 + return list;
14463 +}
14464 +
14465 +/* Print an entry in a line of the menu box. */
14466 +static void
14467 +print_entry (int y, int highlight, char *entry)
14468 +{
14469 + int x;
14470 +
14471 + if (current_term->setcolorstate)
14472 + current_term->setcolorstate (COLOR_STATE_NORMAL);
14473 +
14474 + if (highlight && current_term->setcolorstate)
14475 + current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
14476 +
14477 + gotoxy (2, y);
14478 + grub_putchar (' ');
14479 + for (x = 3; x < 75; x++)
14480 + {
14481 + if (*entry && x <= 72)
14482 + {
14483 + if (x == 72)
14484 + grub_putchar (DISP_RIGHT);
14485 + else
14486 + grub_putchar (*entry++);
14487 + }
14488 + else
14489 + grub_putchar (' ');
14490 + }
14491 + gotoxy (74, y);
14492 +
14493 + if (current_term->setcolorstate)
14494 + current_term->setcolorstate (COLOR_STATE_STANDARD);
14495 +}
14496 +
14497 +/* Print entries in the menu box. */
14498 +static void
14499 +print_entries (int y, int size, int first, int entryno, char *menu_entries)
14500 +{
14501 + int i;
14502 +
14503 + gotoxy (77, y + 1);
14504 +
14505 + if (first)
14506 + grub_putchar (DISP_UP);
14507 + else
14508 + grub_putchar (' ');
14509 +
14510 + menu_entries = get_entry (menu_entries, first, 0);
14511 +
14512 + for (i = 0; i < size; i++)
14513 + {
14514 + print_entry (y + i + 1, entryno == i, menu_entries);
14515 +
14516 + while (*menu_entries)
14517 + menu_entries++;
14518 +
14519 + if (*(menu_entries - 1))
14520 + menu_entries++;
14521 + }
14522 +
14523 + gotoxy (77, y + size);
14524 +
14525 + if (*menu_entries)
14526 + grub_putchar (DISP_DOWN);
14527 + else
14528 + grub_putchar (' ');
14529 +
14530 + gotoxy (74, y + entryno + 1);
14531 +}
14532 +
14533 +static void
14534 +print_entries_raw (int size, int first, char *menu_entries)
14535 +{
14536 + int i;
14537 +
14538 +#define LINE_LENGTH 67
14539 +
14540 + for (i = 0; i < LINE_LENGTH; i++)
14541 + grub_putchar ('-');
14542 + grub_putchar ('\n');
14543 +
14544 + for (i = first; i < size; i++)
14545 + {
14546 + /* grub's printf can't %02d so ... */
14547 + if (i < 10)
14548 + grub_putchar (' ');
14549 + grub_printf ("%d: %s\n", i, get_entry (menu_entries, i, 0));
14550 + }
14551 +
14552 + for (i = 0; i < LINE_LENGTH; i++)
14553 + grub_putchar ('-');
14554 + grub_putchar ('\n');
14555 +
14556 +#undef LINE_LENGTH
14557 +}
14558 +
14559 +
14560 +static void
14561 +print_border (int y, int size)
14562 +{
14563 + int i;
14564 +
14565 + if (current_term->setcolorstate)
14566 + current_term->setcolorstate (COLOR_STATE_NORMAL);
14567 +
14568 + gotoxy (1, y);
14569 +
14570 + grub_putchar (DISP_UL);
14571 + for (i = 0; i < 73; i++)
14572 + grub_putchar (DISP_HORIZ);
14573 + grub_putchar (DISP_UR);
14574 +
14575 + i = 1;
14576 + while (1)
14577 + {
14578 + gotoxy (1, y + i);
14579 +
14580 + if (i > size)
14581 + break;
14582 +
14583 + grub_putchar (DISP_VERT);
14584 + gotoxy (75, y + i);
14585 + grub_putchar (DISP_VERT);
14586 +
14587 + i++;
14588 + }
14589 +
14590 + grub_putchar (DISP_LL);
14591 + for (i = 0; i < 73; i++)
14592 + grub_putchar (DISP_HORIZ);
14593 + grub_putchar (DISP_LR);
14594 +
14595 + if (current_term->setcolorstate)
14596 + current_term->setcolorstate (COLOR_STATE_STANDARD);
14597 +}
14598 +
14599 +static void
14600 +run_menu (char *menu_entries, char *config_entries, int num_entries,
14601 + char *heap, int entryno)
14602 +{
14603 + int c, time1, time2 = -1, first_entry = 0;
14604 + char *cur_entry = 0;
14605 +
14606 + /*
14607 + * Main loop for menu UI.
14608 + */
14609 +
14610 +restart:
14611 + /* Dumb terminal always use all entries for display
14612 + invariant for TERM_DUMB: first_entry == 0 */
14613 + if (! (current_term->flags & TERM_DUMB))
14614 + {
14615 + while (entryno > 11)
14616 + {
14617 + first_entry++;
14618 + entryno--;
14619 + }
14620 + }
14621 +
14622 + /* If the timeout was expired or wasn't set, force to show the menu
14623 + interface. */
14624 + if (grub_timeout < 0)
14625 + show_menu = 1;
14626 +
14627 + /* If SHOW_MENU is false, don't display the menu until ESC is pressed. */
14628 + if (! show_menu)
14629 + {
14630 + /* Get current time. */
14631 + while ((time1 = getrtsecs ()) == 0xFF)
14632 + ;
14633 +
14634 + while (1)
14635 + {
14636 + /* Check if ESC is pressed. */
14637 + if (checkkey () != -1 && ASCII_CHAR (getkey ()) == '\e')
14638 + {
14639 + grub_timeout = -1;
14640 + show_menu = 1;
14641 + break;
14642 + }
14643 +
14644 + /* If GRUB_TIMEOUT is expired, boot the default entry. */
14645 + if (grub_timeout >=0
14646 + && (time1 = getrtsecs ()) != time2
14647 + && time1 != 0xFF)
14648 + {
14649 + if (grub_timeout <= 0)
14650 + {
14651 + grub_timeout = -1;
14652 + goto boot_entry;
14653 + }
14654 +
14655 + time2 = time1;
14656 + grub_timeout--;
14657 +
14658 + /* Print a message. */
14659 + grub_printf ("\rPress `ESC' to enter the menu... %d ",
14660 + grub_timeout);
14661 + }
14662 + }
14663 + }
14664 +
14665 + /* Only display the menu if the user wants to see it. */
14666 + if (show_menu)
14667 + {
14668 + init_page ();
14669 + setcursor (0);
14670 +
14671 + if (current_term->flags & TERM_DUMB)
14672 + print_entries_raw (num_entries, first_entry, menu_entries);
14673 + else
14674 + print_border (3, 12);
14675 +
14676 + grub_printf ("\n\
14677 + Use the %c and %c keys to select which entry is highlighted.\n",
14678 + DISP_UP, DISP_DOWN);
14679 +
14680 + if (! auth && password)
14681 + {
14682 + printf ("\
14683 + Press enter to boot the selected OS or \'p\' to enter a\n\
14684 + password to unlock the next set of features.");
14685 + }
14686 + else
14687 + {
14688 + if (config_entries)
14689 + printf ("\
14690 + Press enter to boot the selected OS, \'e\' to edit the\n\
14691 + commands before booting, or \'c\' for a command-line.");
14692 + else
14693 + printf ("\
14694 + Press \'b\' to boot, \'e\' to edit the selected command in the\n\
14695 + boot sequence, \'c\' for a command-line, \'o\' to open a new line\n\
14696 + after (\'O\' for before) the selected line, \'d\' to remove the\n\
14697 + selected line, or escape to go back to the main menu.");
14698 + }
14699 +
14700 + if (current_term->flags & TERM_DUMB)
14701 + grub_printf ("\n\nThe selected entry is %d ", entryno);
14702 + else
14703 + print_entries (3, 12, first_entry, entryno, menu_entries);
14704 + }
14705 +
14706 + /* XX using RT clock now, need to initialize value */
14707 + while ((time1 = getrtsecs()) == 0xFF);
14708 +
14709 + while (1)
14710 + {
14711 + /* Initialize to NULL just in case... */
14712 + cur_entry = NULL;
14713 +
14714 + if (grub_timeout >= 0 && (time1 = getrtsecs()) != time2 && time1 != 0xFF)
14715 + {
14716 + if (grub_timeout <= 0)
14717 + {
14718 + grub_timeout = -1;
14719 + break;
14720 + }
14721 +
14722 + /* else not booting yet! */
14723 + time2 = time1;
14724 +
14725 + if (current_term->flags & TERM_DUMB)
14726 + grub_printf ("\r Entry %d will be booted automatically in %d seconds. ",
14727 + entryno, grub_timeout);
14728 + else
14729 + {
14730 + gotoxy (3, 22);
14731 + grub_printf ("The highlighted entry will be booted automatically in %d seconds. ",
14732 + grub_timeout);
14733 + gotoxy (74, 4 + entryno);
14734 + }
14735 +
14736 + grub_timeout--;
14737 + }
14738 +
14739 + /* Check for a keypress, however if TIMEOUT has been expired
14740 + (GRUB_TIMEOUT == -1) relax in GETKEY even if no key has been
14741 + pressed.
14742 + This avoids polling (relevant in the grub-shell and later on
14743 + in grub if interrupt driven I/O is done). */
14744 + if (checkkey () >= 0 || grub_timeout < 0)
14745 + {
14746 + /* Key was pressed, show which entry is selected before GETKEY,
14747 + since we're comming in here also on GRUB_TIMEOUT == -1 and
14748 + hang in GETKEY */
14749 + if (current_term->flags & TERM_DUMB)
14750 + grub_printf ("\r Highlighted entry is %d: ", entryno);
14751 +
14752 + c = ASCII_CHAR (getkey ());
14753 +
14754 + if (grub_timeout >= 0)
14755 + {
14756 + if (current_term->flags & TERM_DUMB)
14757 + grub_putchar ('\r');
14758 + else
14759 + gotoxy (3, 22);
14760 + printf (" ");
14761 + grub_timeout = -1;
14762 + fallback_entryno = -1;
14763 + if (! (current_term->flags & TERM_DUMB))
14764 + gotoxy (74, 4 + entryno);
14765 + }
14766 +
14767 + /* We told them above (at least in SUPPORT_SERIAL) to use
14768 + '^' or 'v' so accept these keys. */
14769 + if (c == 16 || c == '^')
14770 + {
14771 + if (current_term->flags & TERM_DUMB)
14772 + {
14773 + if (entryno > 0)
14774 + entryno--;
14775 + }
14776 + else
14777 + {
14778 + if (entryno > 0)
14779 + {
14780 + print_entry (4 + entryno, 0,
14781 + get_entry (menu_entries,
14782 + first_entry + entryno,
14783 + 0));
14784 + entryno--;
14785 + print_entry (4 + entryno, 1,
14786 + get_entry (menu_entries,
14787 + first_entry + entryno,
14788 + 0));
14789 + }
14790 + else if (first_entry > 0)
14791 + {
14792 + first_entry--;
14793 + print_entries (3, 12, first_entry, entryno,
14794 + menu_entries);
14795 + }
14796 + }
14797 + }
14798 + else if ((c == 14 || c == 'v')
14799 + && first_entry + entryno + 1 < num_entries)
14800 + {
14801 + if (current_term->flags & TERM_DUMB)
14802 + entryno++;
14803 + else
14804 + {
14805 + if (entryno < 11)
14806 + {
14807 + print_entry (4 + entryno, 0,
14808 + get_entry (menu_entries,
14809 + first_entry + entryno,
14810 + 0));
14811 + entryno++;
14812 + print_entry (4 + entryno, 1,
14813 + get_entry (menu_entries,
14814 + first_entry + entryno,
14815 + 0));
14816 + }
14817 + else if (num_entries > 12 + first_entry)
14818 + {
14819 + first_entry++;
14820 + print_entries (3, 12, first_entry, entryno, menu_entries);
14821 + }
14822 + }
14823 + }
14824 + else if (c == 7)
14825 + {
14826 + /* Page Up */
14827 + first_entry -= 12;
14828 + if (first_entry < 0)
14829 + {
14830 + entryno += first_entry;
14831 + first_entry = 0;
14832 + if (entryno < 0)
14833 + entryno = 0;
14834 + }
14835 + print_entries (3, 12, first_entry, entryno, menu_entries);
14836 + }
14837 + else if (c == 3)
14838 + {
14839 + /* Page Down */
14840 + first_entry += 12;
14841 + if (first_entry + entryno + 1 >= num_entries)
14842 + {
14843 + first_entry = num_entries - 12;
14844 + if (first_entry < 0)
14845 + first_entry = 0;
14846 + entryno = num_entries - first_entry - 1;
14847 + }
14848 + print_entries (3, 12, first_entry, entryno, menu_entries);
14849 + }
14850 +
14851 + if (config_entries)
14852 + {
14853 + if ((c == '\n') || (c == '\r') || (c == 6))
14854 + break;
14855 + }
14856 + else
14857 + {
14858 + if ((c == 'd') || (c == 'o') || (c == 'O'))
14859 + {
14860 + if (! (current_term->flags & TERM_DUMB))
14861 + print_entry (4 + entryno, 0,
14862 + get_entry (menu_entries,
14863 + first_entry + entryno,
14864 + 0));
14865 +
14866 + /* insert after is almost exactly like insert before */
14867 + if (c == 'o')
14868 + {
14869 + /* But `o' differs from `O', since it may causes
14870 + the menu screen to scroll up. */
14871 + if (entryno < 11 || (current_term->flags & TERM_DUMB))
14872 + entryno++;
14873 + else
14874 + first_entry++;
14875 +
14876 + c = 'O';
14877 + }
14878 +
14879 + cur_entry = get_entry (menu_entries,
14880 + first_entry + entryno,
14881 + 0);
14882 +
14883 + if (c == 'O')
14884 + {
14885 + grub_memmove (cur_entry + 2, cur_entry,
14886 + ((int) heap) - ((int) cur_entry));
14887 +
14888 + cur_entry[0] = ' ';
14889 + cur_entry[1] = 0;
14890 +
14891 + heap += 2;
14892 +
14893 + num_entries++;
14894 + }
14895 + else if (num_entries > 0)
14896 + {
14897 + char *ptr = get_entry(menu_entries,
14898 + first_entry + entryno + 1,
14899 + 0);
14900 +
14901 + grub_memmove (cur_entry, ptr,
14902 + ((int) heap) - ((int) ptr));
14903 + heap -= (((int) ptr) - ((int) cur_entry));
14904 +
14905 + num_entries--;
14906 +
14907 + if (entryno >= num_entries)
14908 + entryno--;
14909 + if (first_entry && num_entries < 12 + first_entry)
14910 + first_entry--;
14911 + }
14912 +
14913 + if (current_term->flags & TERM_DUMB)
14914 + {
14915 + grub_printf ("\n\n");
14916 + print_entries_raw (num_entries, first_entry,
14917 + menu_entries);
14918 + grub_printf ("\n");
14919 + }
14920 + else
14921 + print_entries (3, 12, first_entry, entryno, menu_entries);
14922 + }
14923 +
14924 + cur_entry = menu_entries;
14925 + if (c == 27)
14926 + return;
14927 + if (c == 'b')
14928 + break;
14929 + }
14930 +
14931 + if (! auth && password)
14932 + {
14933 + if (c == 'p')
14934 + {
14935 + /* Do password check here! */
14936 + char entered[32];
14937 + char *pptr = password;
14938 +
14939 + if (current_term->flags & TERM_DUMB)
14940 + grub_printf ("\r ");
14941 + else
14942 + gotoxy (1, 21);
14943 +
14944 + /* Wipe out the previously entered password */
14945 + grub_memset (entered, 0, sizeof (entered));
14946 + get_cmdline (" Password: ", entered, 31, '*', 0);
14947 +
14948 + while (! isspace (*pptr) && *pptr)
14949 + pptr++;
14950 +
14951 + /* Make sure that PASSWORD is NUL-terminated. */
14952 + *pptr++ = 0;
14953 +
14954 + if (! check_password (entered, password, password_type))
14955 + {
14956 + char *new_file = config_file;
14957 + while (isspace (*pptr))
14958 + pptr++;
14959 +
14960 + /* If *PPTR is NUL, then allow the user to use
14961 + privileged instructions, otherwise, load
14962 + another configuration file. */
14963 + if (*pptr != 0)
14964 + {
14965 + while ((*(new_file++) = *(pptr++)) != 0)
14966 + ;
14967 +
14968 + /* Make sure that the user will not have
14969 + authority in the next configuration. */
14970 + auth = 0;
14971 + return;
14972 + }
14973 + else
14974 + {
14975 + /* Now the user is superhuman. */
14976 + auth = 1;
14977 + goto restart;
14978 + }
14979 + }
14980 + else
14981 + {
14982 + grub_printf ("Failed!\n Press any key to continue...");
14983 + getkey ();
14984 + goto restart;
14985 + }
14986 + }
14987 + }
14988 + else
14989 + {
14990 + if (c == 'e')
14991 + {
14992 + int new_num_entries = 0, i = 0;
14993 + char *new_heap;
14994 +
14995 + if (config_entries)
14996 + {
14997 + new_heap = heap;
14998 + cur_entry = get_entry (config_entries,
14999 + first_entry + entryno,
15000 + 1);
15001 + }
15002 + else
15003 + {
15004 + /* safe area! */
15005 + new_heap = heap + NEW_HEAPSIZE + 1;
15006 + cur_entry = get_entry (menu_entries,
15007 + first_entry + entryno,
15008 + 0);
15009 + }
15010 +
15011 + do
15012 + {
15013 + while ((*(new_heap++) = cur_entry[i++]) != 0);
15014 + new_num_entries++;
15015 + }
15016 + while (config_entries && cur_entry[i]);
15017 +
15018 + /* this only needs to be done if config_entries is non-NULL,
15019 + but it doesn't hurt to do it always */
15020 + *(new_heap++) = 0;
15021 +
15022 + if (config_entries)
15023 + run_menu (heap, NULL, new_num_entries, new_heap, 0);
15024 + else
15025 + {
15026 + cls ();
15027 + print_cmdline_message (0);
15028 +
15029 + new_heap = heap + NEW_HEAPSIZE + 1;
15030 +
15031 + saved_drive = boot_drive;
15032 + saved_partition = install_partition;
15033 + current_drive = GRUB_INVALID_DRIVE;
15034 +
15035 + if (! get_cmdline (PACKAGE " edit> ", new_heap,
15036 + NEW_HEAPSIZE + 1, 0, 1))
15037 + {
15038 + int j = 0;
15039 +
15040 + /* get length of new command */
15041 + while (new_heap[j++])
15042 + ;
15043 +
15044 + if (j < 2)
15045 + {
15046 + j = 2;
15047 + new_heap[0] = ' ';
15048 + new_heap[1] = 0;
15049 + }
15050 +
15051 + /* align rest of commands properly */
15052 + grub_memmove (cur_entry + j, cur_entry + i,
15053 + (int) heap - ((int) cur_entry + i));
15054 +
15055 + /* copy command to correct area */
15056 + grub_memmove (cur_entry, new_heap, j);
15057 +
15058 + heap += (j - i);
15059 + }
15060 + }
15061 +
15062 + goto restart;
15063 + }
15064 + if (c == 'c')
15065 + {
15066 + enter_cmdline (heap, 0);
15067 + goto restart;
15068 + }
15069 +#ifdef GRUB_UTIL
15070 + if (c == 'q')
15071 + {
15072 + /* The same as ``quit''. */
15073 + stop ();
15074 + }
15075 +#endif
15076 + }
15077 + }
15078 + }
15079 +
15080 + /* Attempt to boot an entry. */
15081 +
15082 + boot_entry:
15083 +
15084 + cls ();
15085 + setcursor (1);
15086 +
15087 + while (1)
15088 + {
15089 + if (config_entries)
15090 + printf (" Booting \'%s\'\n\n",
15091 + get_entry (menu_entries, first_entry + entryno, 0));
15092 + else
15093 + printf (" Booting command-list\n\n");
15094 +
15095 + if (! cur_entry)
15096 + cur_entry = get_entry (config_entries, first_entry + entryno, 1);
15097 +
15098 + /* Set CURRENT_ENTRYNO for the command "savedefault". */
15099 + current_entryno = first_entry + entryno;
15100 +
15101 + if (run_script (cur_entry, heap))
15102 + {
15103 + if (fallback_entryno >= 0)
15104 + {
15105 + cur_entry = NULL;
15106 + first_entry = 0;
15107 + entryno = fallback_entries[fallback_entryno];
15108 + fallback_entryno++;
15109 + if (fallback_entryno >= MAX_FALLBACK_ENTRIES
15110 + || fallback_entries[fallback_entryno] < 0)
15111 + fallback_entryno = -1;
15112 + }
15113 + else
15114 + break;
15115 + }
15116 + else
15117 + break;
15118 + }
15119 +
15120 + show_menu = 1;
15121 + goto restart;
15122 +}
15123 +
15124 +
15125 +static int
15126 +get_line_from_config (char *cmdline, int maxlen, int read_from_file)
15127 +{
15128 + int pos = 0, literal = 0, comment = 0;
15129 + char c; /* since we're loading it a byte at a time! */
15130 +
15131 + while (1)
15132 + {
15133 + if (read_from_file)
15134 + {
15135 + if (! grub_read (&c, 1))
15136 + break;
15137 + }
15138 + else
15139 + {
15140 + if (! read_from_preset_menu (&c, 1))
15141 + break;
15142 + }
15143 +
15144 + /* Skip all carriage returns. */
15145 + if (c == '\r')
15146 + continue;
15147 +
15148 + /* Replace tabs with spaces. */
15149 + if (c == '\t')
15150 + c = ' ';
15151 +
15152 + /* The previous is a backslash, then... */
15153 + if (literal)
15154 + {
15155 + /* If it is a newline, replace it with a space and continue. */
15156 + if (c == '\n')
15157 + {
15158 + c = ' ';
15159 +
15160 + /* Go back to overwrite a backslash. */
15161 + if (pos > 0)
15162 + pos--;
15163 + }
15164 +
15165 + literal = 0;
15166 + }
15167 +
15168 + /* translate characters first! */
15169 + if (c == '\\' && ! literal)
15170 + literal = 1;
15171 +
15172 + if (comment)
15173 + {
15174 + if (c == '\n')
15175 + comment = 0;
15176 + }
15177 + else if (! pos)
15178 + {
15179 + if (c == '#')
15180 + comment = 1;
15181 + else if ((c != ' ') && (c != '\n'))
15182 + cmdline[pos++] = c;
15183 + }
15184 + else
15185 + {
15186 + if (c == '\n')
15187 + break;
15188 +
15189 + if (pos < maxlen)
15190 + cmdline[pos++] = c;
15191 + }
15192 + }
15193 +
15194 + cmdline[pos] = 0;
15195 +
15196 + return pos;
15197 +}
15198 +
15199 +
15200 +/* This is the starting function in C. */
15201 +void
15202 +cmain (void)
15203 +{
15204 + int config_len, menu_len, num_entries;
15205 + char *config_entries, *menu_entries;
15206 + char *kill_buf = (char *) KILL_BUF;
15207 +
15208 + auto void reset (void);
15209 + void reset (void)
15210 + {
15211 + count_lines = -1;
15212 + config_len = 0;
15213 + menu_len = 0;
15214 + num_entries = 0;
15215 + config_entries = (char *) mbi.drives_addr + mbi.drives_length;
15216 + menu_entries = (char *) MENU_BUF;
15217 + init_config ();
15218 + }
15219 +
15220 + /* Initialize the environment for restarting Stage 2. */
15221 + grub_setjmp (restart_env);
15222 +
15223 + /* Initialize the kill buffer. */
15224 + *kill_buf = 0;
15225 +
15226 + /* Never return. */
15227 + for (;;)
15228 + {
15229 + int is_opened, is_preset;
15230 +
15231 + reset ();
15232 +
15233 + /* Here load the configuration file. */
15234 +
15235 +#ifdef GRUB_UTIL
15236 + if (use_config_file)
15237 +#endif /* GRUB_UTIL */
15238 + {
15239 + char *default_file = (char *) DEFAULT_FILE_BUF;
15240 + int i;
15241 +
15242 + /* Get a saved default entry if possible. */
15243 + saved_entryno = 0;
15244 + *default_file = 0;
15245 + grub_strncat (default_file, config_file, DEFAULT_FILE_BUFLEN);
15246 + for (i = grub_strlen(default_file); i >= 0; i--)
15247 + if (default_file[i] == '/')
15248 + {
15249 + i++;
15250 + break;
15251 + }
15252 + default_file[i] = 0;
15253 + grub_strncat (default_file + i, "default", DEFAULT_FILE_BUFLEN - i);
15254 + if (grub_open (default_file))
15255 + {
15256 + char buf[10]; /* This is good enough. */
15257 + char *p = buf;
15258 + int len;
15259 +
15260 + len = grub_read (buf, sizeof (buf));
15261 + if (len > 0)
15262 + {
15263 + buf[sizeof (buf) - 1] = 0;
15264 + safe_parse_maxint (&p, &saved_entryno);
15265 + }
15266 +
15267 + grub_close ();
15268 + }
15269 + errnum = ERR_NONE;
15270 +
15271 + do
15272 + {
15273 + /* STATE 0: Before any title command.
15274 + STATE 1: In a title command.
15275 + STATE >1: In a entry after a title command. */
15276 + int state = 0, prev_config_len = 0, prev_menu_len = 0;
15277 + char *cmdline;
15278 +
15279 + /* Try the preset menu first. This will succeed at most once,
15280 + because close_preset_menu disables the preset menu. */
15281 + is_opened = is_preset = open_preset_menu ();
15282 + if (! is_opened)
15283 + {
15284 + is_opened = grub_open (config_file);
15285 + errnum = ERR_NONE;
15286 + }
15287 +
15288 + if (! is_opened)
15289 + break;
15290 +
15291 + /* This is necessary, because the menu must be overrided. */
15292 + reset ();
15293 +
15294 + cmdline = (char *) CMDLINE_BUF;
15295 + while (get_line_from_config (cmdline, NEW_HEAPSIZE,
15296 + ! is_preset))
15297 + {
15298 + struct builtin *builtin;
15299 +
15300 + /* Get the pointer to the builtin structure. */
15301 + builtin = find_command (cmdline);
15302 + errnum = 0;
15303 + if (! builtin)
15304 + /* Unknown command. Just skip now. */
15305 + continue;
15306 +
15307 + if (builtin->flags & BUILTIN_TITLE)
15308 + {
15309 + char *ptr;
15310 +
15311 + /* the command "title" is specially treated. */
15312 + if (state > 1)
15313 + {
15314 + /* The next title is found. */
15315 + num_entries++;
15316 + config_entries[config_len++] = 0;
15317 + prev_menu_len = menu_len;
15318 + prev_config_len = config_len;
15319 + }
15320 + else
15321 + {
15322 + /* The first title is found. */
15323 + menu_len = prev_menu_len;
15324 + config_len = prev_config_len;
15325 + }
15326 +
15327 + /* Reset the state. */
15328 + state = 1;
15329 +
15330 + /* Copy title into menu area. */
15331 + ptr = skip_to (1, cmdline);
15332 + while ((menu_entries[menu_len++] = *(ptr++)) != 0)
15333 + ;
15334 + }
15335 + else if (! state)
15336 + {
15337 + /* Run a command found is possible. */
15338 + if (builtin->flags & BUILTIN_MENU)
15339 + {
15340 + char *arg = skip_to (1, cmdline);
15341 + (builtin->func) (arg, BUILTIN_MENU);
15342 + errnum = 0;
15343 + }
15344 + else
15345 + /* Ignored. */
15346 + continue;
15347 + }
15348 + else
15349 + {
15350 + char *ptr = cmdline;
15351 +
15352 + state++;
15353 + /* Copy config file data to config area. */
15354 + while ((config_entries[config_len++] = *ptr++) != 0)
15355 + ;
15356 + }
15357 + }
15358 +
15359 + if (state > 1)
15360 + {
15361 + /* Finish the last entry. */
15362 + num_entries++;
15363 + config_entries[config_len++] = 0;
15364 + }
15365 + else
15366 + {
15367 + menu_len = prev_menu_len;
15368 + config_len = prev_config_len;
15369 + }
15370 +
15371 + menu_entries[menu_len++] = 0;
15372 + config_entries[config_len++] = 0;
15373 + grub_memmove (config_entries + config_len, menu_entries,
15374 + menu_len);
15375 + menu_entries = config_entries + config_len;
15376 +
15377 + /* Make sure that all fallback entries are valid. */
15378 + if (fallback_entryno >= 0)
15379 + {
15380 + for (i = 0; i < MAX_FALLBACK_ENTRIES; i++)
15381 + {
15382 + if (fallback_entries[i] < 0)
15383 + break;
15384 + if (fallback_entries[i] >= num_entries)
15385 + {
15386 + grub_memmove (fallback_entries + i,
15387 + fallback_entries + i + 1,
15388 + ((MAX_FALLBACK_ENTRIES - i - 1)
15389 + * sizeof (int)));
15390 + i--;
15391 + }
15392 + }
15393 +
15394 + if (fallback_entries[0] < 0)
15395 + fallback_entryno = -1;
15396 + }
15397 + /* Check if the default entry is present. Otherwise reset
15398 + it to fallback if fallback is valid, or to DEFAULT_ENTRY
15399 + if not. */
15400 + if (default_entry >= num_entries)
15401 + {
15402 + if (fallback_entryno >= 0)
15403 + {
15404 + default_entry = fallback_entries[0];
15405 + fallback_entryno++;
15406 + if (fallback_entryno >= MAX_FALLBACK_ENTRIES
15407 + || fallback_entries[fallback_entryno] < 0)
15408 + fallback_entryno = -1;
15409 + }
15410 + else
15411 + default_entry = 0;
15412 + }
15413 +
15414 + if (is_preset)
15415 + close_preset_menu ();
15416 + else
15417 + grub_close ();
15418 + }
15419 + while (is_preset);
15420 + }
15421 +
15422 + if (! num_entries)
15423 + {
15424 + /* If no acceptable config file, goto command-line, starting
15425 + heap from where the config entries would have been stored
15426 + if there were any. */
15427 + enter_cmdline (config_entries, 1);
15428 + }
15429 + else
15430 + {
15431 + /* Run menu interface. */
15432 + run_menu (menu_entries, config_entries, num_entries,
15433 + menu_entries + menu_len, default_entry);
15434 + }
15435 + }
15436 +}
15437 diff -Nur grub-0.97/stage2/term.h grub-0.97-patched/stage2/term.h
15438 --- grub-0.97/stage2/term.h 2003-07-09 13:45:53.000000000 +0200
15439 +++ grub-0.97-patched/stage2/term.h 2012-11-11 17:06:33.311470556 +0100
15440 @@ -60,6 +60,8 @@
15441 const char *name;
15442 /* The feature flags defined above. */
15443 unsigned long flags;
15444 + /* Default for maximum number of lines if not specified */
15445 + unsigned short max_lines;
15446 /* Put a character. */
15447 void (*putchar) (int c);
15448 /* Check if any input character is available. */
15449 @@ -79,6 +81,11 @@
15450 void (*setcolor) (int normal_color, int highlight_color);
15451 /* Turn on/off the cursor. */
15452 int (*setcursor) (int on);
15453 +
15454 + /* function to start a terminal */
15455 + int (*startup) (void);
15456 + /* function to use to shutdown a terminal */
15457 + void (*shutdown) (void);
15458 };
15459
15460 /* This lists up available terminals. */
15461 @@ -124,4 +131,23 @@
15462 int hercules_setcursor (int on);
15463 #endif
15464
15465 +#ifdef SUPPORT_GRAPHICS
15466 +extern int foreground, background, border, graphics_inited;
15467 +
15468 +void graphics_set_splash(char *splashfile);
15469 +int set_videomode (int mode);
15470 +void graphics_putchar (int c);
15471 +int graphics_getxy(void);
15472 +void graphics_gotoxy(int x, int y);
15473 +void graphics_cls(void);
15474 +void graphics_setcolorstate (color_state state);
15475 +void graphics_setcolor (int normal_color, int highlight_color);
15476 +void graphics_setcursor (int on);
15477 +int graphics_init(void);
15478 +void graphics_end(void);
15479 +
15480 +int hex(int v);
15481 +void graphics_set_palette(int idx, int red, int green, int blue);
15482 +#endif /* SUPPORT_GRAPHICS */
15483 +
15484 #endif /* ! GRUB_TERM_HEADER */
15485 diff -Nur grub-0.97/THANKS grub-0.97-patched/THANKS
15486 --- grub-0.97/THANKS 2005-05-08 04:17:43.000000000 +0200
15487 +++ grub-0.97-patched/THANKS 2012-11-11 17:07:12.709729021 +0100
15488 @@ -121,3 +121,4 @@
15489 Yedidyah Bar-David <didi@post.tau.ac.il>
15490 Yury V. Umanets <umka@namesys.com>
15491 Yuri Zaporogets <yuriz@ukr.net>
15492 +Vitaly Fertman <vitaly@namesys.com>
15493 diff -Nur grub-0.97/util/grub-install.in grub-0.97-patched/util/grub-install.in
15494 --- grub-0.97/util/grub-install.in 2004-07-24 20:57:31.000000000 +0200
15495 +++ grub-0.97-patched/util/grub-install.in 2012-11-11 17:07:12.748730268 +0100
15496 @@ -96,24 +96,27 @@
15497 # Break the device name into the disk part and the partition part.
15498 case "$host_os" in
15499 linux*)
15500 - tmp_disk=`echo "$1" | sed -e 's%\([sh]d[a-z]\)[0-9]*$%\1%' \
15501 + tmp_disk=`echo "$1" | sed -e 's%\([shv]d[a-z]\)[0-9]*$%\1%' \
15502 -e 's%\(d[0-9]*\)p[0-9]*$%\1%' \
15503 -e 's%\(fd[0-9]*\)$%\1%' \
15504 -e 's%/part[0-9]*$%/disc%' \
15505 - -e 's%\(c[0-7]d[0-9]*\).*$%\1%'`
15506 - tmp_part=`echo "$1" | sed -e 's%.*/[sh]d[a-z]\([0-9]*\)$%\1%' \
15507 + -e 's%\(c[0-7]d[0-9]*\).*$%\1%' \
15508 + -e 's%\(e[0-9]\.[0-9]*\).*$%\1%'`
15509 + tmp_part=`echo "$1" | sed -e 's%.*/[shv]d[a-z]\([0-9]*\)$%\1%' \
15510 -e 's%.*d[0-9]*p%%' \
15511 -e 's%.*/fd[0-9]*$%%' \
15512 -e 's%.*/floppy/[0-9]*$%%' \
15513 -e 's%.*/\(disc\|part\([0-9]*\)\)$%\2%' \
15514 - -e 's%.*c[0-7]d[0-9]*p%%'`
15515 + -e 's%.*c[0-7]d[0-9]*p*%%' \
15516 + -e 's%.*e[0-9]\.[0-9]*p%%' \
15517 + -e 's%.*e[0-9]\.[0-9]*\$%%'`
15518 ;;
15519 gnu*)
15520 tmp_disk=`echo "$1" | sed 's%\([sh]d[0-9]*\).*%\1%'`
15521 tmp_part=`echo "$1" | sed "s%$tmp_disk%%"` ;;
15522 freebsd* | kfreebsd*-gnu)
15523 - tmp_disk=`echo "$1" | sed 's%r\{0,1\}\([saw]d[0-9]*\).*$%r\1%' \
15524 - | sed 's%r\{0,1\}\(da[0-9]*\).*$%r\1%'`
15525 + tmp_disk=`echo "$1" | sed 's%r\{0,1\}\([saw]d[0-9]*\).*$%\1%' \
15526 + | sed 's%r\{0,1\}\(da[0-9]*\).*$%\1%'`
15527 tmp_part=`echo "$1" \
15528 | sed "s%.*/r\{0,1\}[saw]d[0-9]\(s[0-9]*[a-h]\)%\1%" \
15529 | sed "s%.*/r\{0,1\}da[0-9]\(s[0-9]*[a-h]\)%\1%"`
15530 @@ -131,7 +134,7 @@
15531
15532 # Get the drive name.
15533 tmp_drive=`grep -v '^#' $device_map | grep "$tmp_disk *$" \
15534 - | sed 's%.*\(([hf]d[0-9][a-g0-9,]*)\).*%\1%'`
15535 + | sed 's%.*\(([hf]d[0-9][a-z0-9,]*)\).*%\1%'`
15536
15537 # If not found, print an error message and exit.
15538 if test "x$tmp_drive" = x; then
15539 @@ -148,13 +151,13 @@
15540 gnu*)
15541 if echo $tmp_part | grep "^s" >/dev/null; then
15542 tmp_pc_slice=`echo $tmp_part \
15543 - | sed "s%s\([0-9]*\)[a-g]*$%\1%"`
15544 + | sed "s%s\([0-9]*\)[a-z]*$%\1%"`
15545 tmp_drive=`echo "$tmp_drive" \
15546 | sed "s%)%,\`expr "$tmp_pc_slice" - 1\`)%"`
15547 fi
15548 - if echo $tmp_part | grep "[a-g]$" >/dev/null; then
15549 + if echo $tmp_part | grep "[a-z]$" >/dev/null; then
15550 tmp_bsd_partition=`echo "$tmp_part" \
15551 - | sed "s%[^a-g]*\([a-g]\)$%\1%"`
15552 + | sed "s%[^a-z]*\([a-z]\)$%\1%"`
15553 tmp_drive=`echo "$tmp_drive" \
15554 | sed "s%)%,$tmp_bsd_partition)%"`
15555 fi
15556 @@ -336,6 +339,10 @@
15557 # Create a safe temporary file.
15558 test -n "$mklog" && log_file=`$mklog`
15559
15560 + # Before all invocations of the grub shell, call sync to make sure
15561 + # the raw device is in sync with any bufferring in filesystems.
15562 + sync
15563 +
15564 $grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file
15565 quit
15566 EOF
15567 @@ -450,6 +457,10 @@
15568 # Create a safe temporary file.
15569 test -n "$mklog" && log_file=`$mklog`
15570
15571 +# Before all invocations of the grub shell, call sync to make sure
15572 +# the raw device is in sync with any bufferring in filesystems.
15573 +sync
15574 +
15575 # Now perform the installation.
15576 $grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file
15577 root $root_drive
15578 diff -Nur grub-0.97/util/grub-install.in.orig grub-0.97-patched/util/grub-install.in.orig
15579 --- grub-0.97/util/grub-install.in.orig 1970-01-01 01:00:00.000000000 +0100
15580 +++ grub-0.97-patched/util/grub-install.in.orig 2004-07-24 20:57:31.000000000 +0200
15581 @@ -0,0 +1,477 @@
15582 +#! /bin/sh
15583 +
15584 +# Install GRUB on your drive.
15585 +# Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
15586 +#
15587 +# This file is free software; you can redistribute it and/or modify it
15588 +# under the terms of the GNU General Public License as published by
15589 +# the Free Software Foundation; either version 2 of the License, or
15590 +# (at your option) any later version.
15591 +#
15592 +# This program is distributed in the hope that it will be useful, but
15593 +# WITHOUT ANY WARRANTY; without even the implied warranty of
15594 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15595 +# General Public License for more details.
15596 +#
15597 +# You should have received a copy of the GNU General Public License
15598 +# along with this program; if not, write to the Free Software
15599 +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15600 +
15601 +# Initialize some variables.
15602 +prefix=@prefix@
15603 +exec_prefix=@exec_prefix@
15604 +sbindir=@sbindir@
15605 +libdir=@libdir@
15606 +PACKAGE=@PACKAGE@
15607 +VERSION=@VERSION@
15608 +host_cpu=@host_cpu@
15609 +host_os=@host_os@
15610 +host_vendor=@host_vendor@
15611 +pkglibdir=${libdir}/${PACKAGE}/${host_cpu}-${host_vendor}
15612 +
15613 +grub_shell=${sbindir}/grub
15614 +grub_set_default=${sbindir}/grub-set-default
15615 +log_file=/tmp/grub-install.log.$$
15616 +img_file=/tmp/grub-install.img.$$
15617 +rootdir=
15618 +grub_prefix=/boot/grub
15619 +
15620 +install_device=
15621 +no_floppy=
15622 +force_lba=
15623 +recheck=no
15624 +debug=no
15625 +
15626 +# look for secure tempfile creation wrappers on this platform
15627 +if test -x /bin/tempfile; then
15628 + mklog="/bin/tempfile --prefix=grub"
15629 + mkimg="/bin/tempfile --prefix=grub"
15630 +elif test -x /bin/mktemp; then
15631 + mklog="/bin/mktemp /tmp/grub-install.log.XXXXXX"
15632 + mkimg="/bin/mktemp /tmp/grub-install.img.XXXXXX"
15633 +else
15634 + mklog=""
15635 + mkimg=""
15636 +fi
15637 +
15638 +# Usage: usage
15639 +# Print the usage.
15640 +usage () {
15641 + cat <<EOF
15642 +Usage: grub-install [OPTION] install_device
15643 +Install GRUB on your drive.
15644 +
15645 + -h, --help print this message and exit
15646 + -v, --version print the version information and exit
15647 + --root-directory=DIR install GRUB images under the directory DIR
15648 + instead of the root directory
15649 + --grub-shell=FILE use FILE as the grub shell
15650 + --no-floppy do not probe any floppy drive
15651 + --force-lba force GRUB to use LBA mode even for a buggy
15652 + BIOS
15653 + --recheck probe a device map even if it already exists
15654 +
15655 +INSTALL_DEVICE can be a GRUB device name or a system device filename.
15656 +
15657 +grub-install copies GRUB images into the DIR/boot directory specfied by
15658 +--root-directory, and uses the grub shell to install grub into the boot
15659 +sector.
15660 +
15661 +Report bugs to <bug-grub@gnu.org>.
15662 +EOF
15663 +}
15664 +
15665 +# Usage: convert os_device
15666 +# Convert an OS device to the corresponding GRUB drive.
15667 +# This part is OS-specific.
15668 +convert () {
15669 + # First, check if the device file exists.
15670 + if test -e "$1"; then
15671 + :
15672 + else
15673 + echo "$1: Not found or not a block device." 1>&2
15674 + exit 1
15675 + fi
15676 +
15677 + # Break the device name into the disk part and the partition part.
15678 + case "$host_os" in
15679 + linux*)
15680 + tmp_disk=`echo "$1" | sed -e 's%\([sh]d[a-z]\)[0-9]*$%\1%' \
15681 + -e 's%\(d[0-9]*\)p[0-9]*$%\1%' \
15682 + -e 's%\(fd[0-9]*\)$%\1%' \
15683 + -e 's%/part[0-9]*$%/disc%' \
15684 + -e 's%\(c[0-7]d[0-9]*\).*$%\1%'`
15685 + tmp_part=`echo "$1" | sed -e 's%.*/[sh]d[a-z]\([0-9]*\)$%\1%' \
15686 + -e 's%.*d[0-9]*p%%' \
15687 + -e 's%.*/fd[0-9]*$%%' \
15688 + -e 's%.*/floppy/[0-9]*$%%' \
15689 + -e 's%.*/\(disc\|part\([0-9]*\)\)$%\2%' \
15690 + -e 's%.*c[0-7]d[0-9]*p%%'`
15691 + ;;
15692 + gnu*)
15693 + tmp_disk=`echo "$1" | sed 's%\([sh]d[0-9]*\).*%\1%'`
15694 + tmp_part=`echo "$1" | sed "s%$tmp_disk%%"` ;;
15695 + freebsd* | kfreebsd*-gnu)
15696 + tmp_disk=`echo "$1" | sed 's%r\{0,1\}\([saw]d[0-9]*\).*$%r\1%' \
15697 + | sed 's%r\{0,1\}\(da[0-9]*\).*$%r\1%'`
15698 + tmp_part=`echo "$1" \
15699 + | sed "s%.*/r\{0,1\}[saw]d[0-9]\(s[0-9]*[a-h]\)%\1%" \
15700 + | sed "s%.*/r\{0,1\}da[0-9]\(s[0-9]*[a-h]\)%\1%"`
15701 + ;;
15702 + netbsd* | knetbsd*-gnu)
15703 + tmp_disk=`echo "$1" | sed 's%r\{0,1\}\([sw]d[0-9]*\).*$%r\1d%' \
15704 + | sed 's%r\{0,1\}\(fd[0-9]*\).*$%r\1a%'`
15705 + tmp_part=`echo "$1" \
15706 + | sed "s%.*/r\{0,1\}[sw]d[0-9]\([abe-p]\)%\1%"`
15707 + ;;
15708 + *)
15709 + echo "grub-install does not support your OS yet." 1>&2
15710 + exit 1 ;;
15711 + esac
15712 +
15713 + # Get the drive name.
15714 + tmp_drive=`grep -v '^#' $device_map | grep "$tmp_disk *$" \
15715 + | sed 's%.*\(([hf]d[0-9][a-g0-9,]*)\).*%\1%'`
15716 +
15717 + # If not found, print an error message and exit.
15718 + if test "x$tmp_drive" = x; then
15719 + echo "$1 does not have any corresponding BIOS drive." 1>&2
15720 + exit 1
15721 + fi
15722 +
15723 + if test "x$tmp_part" != x; then
15724 + # If a partition is specified, we need to translate it into the
15725 + # GRUB's syntax.
15726 + case "$host_os" in
15727 + linux*)
15728 + echo "$tmp_drive" | sed "s%)$%,`expr $tmp_part - 1`)%" ;;
15729 + gnu*)
15730 + if echo $tmp_part | grep "^s" >/dev/null; then
15731 + tmp_pc_slice=`echo $tmp_part \
15732 + | sed "s%s\([0-9]*\)[a-g]*$%\1%"`
15733 + tmp_drive=`echo "$tmp_drive" \
15734 + | sed "s%)%,\`expr "$tmp_pc_slice" - 1\`)%"`
15735 + fi
15736 + if echo $tmp_part | grep "[a-g]$" >/dev/null; then
15737 + tmp_bsd_partition=`echo "$tmp_part" \
15738 + | sed "s%[^a-g]*\([a-g]\)$%\1%"`
15739 + tmp_drive=`echo "$tmp_drive" \
15740 + | sed "s%)%,$tmp_bsd_partition)%"`
15741 + fi
15742 + echo "$tmp_drive" ;;
15743 + freebsd* | kfreebsd*-gnu)
15744 + if echo $tmp_part | grep "^s" >/dev/null; then
15745 + tmp_pc_slice=`echo $tmp_part \
15746 + | sed "s%s\([0-9]*\)[a-h]*$%\1%"`
15747 + tmp_drive=`echo "$tmp_drive" \
15748 + | sed "s%)%,\`expr "$tmp_pc_slice" - 1\`)%"`
15749 + fi
15750 + if echo $tmp_part | grep "[a-h]$" >/dev/null; then
15751 + tmp_bsd_partition=`echo "$tmp_part" \
15752 + | sed "s%s\{0,1\}[0-9]*\([a-h]\)$%\1%"`
15753 + tmp_drive=`echo "$tmp_drive" \
15754 + | sed "s%)%,$tmp_bsd_partition)%"`
15755 + fi
15756 + echo "$tmp_drive" ;;
15757 + netbsd* | knetbsd*-gnu)
15758 + if echo $tmp_part | grep "^[abe-p]$" >/dev/null; then
15759 + tmp_bsd_partition=`echo "$tmp_part" \
15760 + | sed "s%\([a-p]\)$%\1%"`
15761 + tmp_drive=`echo "$tmp_drive" \
15762 + | sed "s%)%,$tmp_bsd_partition)%"`
15763 + fi
15764 + echo "$tmp_drive" ;;
15765 + esac
15766 + else
15767 + # If no partition is specified, just print the drive name.
15768 + echo "$tmp_drive"
15769 + fi
15770 +}
15771 +
15772 +# Usage: resolve_symlink file
15773 +# Find the real file/device that file points at
15774 +resolve_symlink () {
15775 + tmp_fname=$1
15776 + # Resolve symlinks
15777 + while test -L $tmp_fname; do
15778 + tmp_new_fname=`ls -al $tmp_fname | sed -n 's%.*-> \(.*\)%\1%p'`
15779 + if test -z "$tmp_new_fname"; then
15780 + echo "Unrecognized ls output" 2>&1
15781 + exit 1
15782 + fi
15783 +
15784 + # Convert relative symlinks
15785 + case $tmp_new_fname in
15786 + /*) tmp_fname="$tmp_new_fname"
15787 + ;;
15788 + *) tmp_fname="`echo $tmp_fname | sed 's%/[^/]*$%%'`/$tmp_new_fname"
15789 + ;;
15790 + esac
15791 + done
15792 + echo "$tmp_fname"
15793 +}
15794 +
15795 +# Usage: find_device file
15796 +# Find block device on which the file resides.
15797 +find_device () {
15798 + # For now, this uses the program `df' to get the device name, but is
15799 + # this really portable?
15800 + tmp_fname=`df $1/ | sed -n 's%.*\(/dev/[^ ]*\).*%\1%p'`
15801 +
15802 + if test -z "$tmp_fname"; then
15803 + echo "Could not find device for $1" 2>&1
15804 + exit 1
15805 + fi
15806 +
15807 + tmp_fname=`resolve_symlink $tmp_fname`
15808 +
15809 + echo "$tmp_fname"
15810 +}
15811 +
15812 +# Check the arguments.
15813 +for option in "$@"; do
15814 + case "$option" in
15815 + -h | --help)
15816 + usage
15817 + exit 0 ;;
15818 + -v | --version)
15819 + echo "grub-install (GNU GRUB ${VERSION})"
15820 + exit 0 ;;
15821 + --root-directory=*)
15822 + rootdir=`echo "$option" | sed 's/--root-directory=//'` ;;
15823 + --grub-shell=*)
15824 + grub_shell=`echo "$option" | sed 's/--grub-shell=//'` ;;
15825 + --no-floppy)
15826 + no_floppy="--no-floppy" ;;
15827 + --force-lba)
15828 + force_lba="--force-lba" ;;
15829 + --recheck)
15830 + recheck=yes ;;
15831 + # This is an undocumented feature...
15832 + --debug)
15833 + debug=yes ;;
15834 + -*)
15835 + echo "Unrecognized option \`$option'" 1>&2
15836 + usage
15837 + exit 1
15838 + ;;
15839 + *)
15840 + if test "x$install_device" != x; then
15841 + echo "More than one install_devices?" 1>&2
15842 + usage
15843 + exit 1
15844 + fi
15845 + install_device="${option}" ;;
15846 + esac
15847 +done
15848 +
15849 +if test "x$install_device" = x; then
15850 + echo "install_device not specified." 1>&2
15851 + usage
15852 + exit 1
15853 +fi
15854 +
15855 +# If the debugging feature is enabled, print commands.
15856 +if test $debug = yes; then
15857 + set -x
15858 +fi
15859 +
15860 +# Initialize these directories here, since ROOTDIR was initialized.
15861 +case "$host_os" in
15862 +netbsd* | openbsd*)
15863 + # Because /boot is used for the boot block in NetBSD and OpenBSD, use /grub
15864 + # instead of /boot/grub.
15865 + grub_prefix=/grub
15866 + bootdir=${rootdir}
15867 + ;;
15868 +*)
15869 + # Use /boot/grub by default.
15870 + bootdir=${rootdir}/boot
15871 + ;;
15872 +esac
15873 +
15874 +grubdir=${bootdir}/grub
15875 +device_map=${grubdir}/device.map
15876 +
15877 +# Check if GRUB is installed.
15878 +# This is necessary, because the user can specify "grub --read-only".
15879 +set $grub_shell dummy
15880 +if test -f "$1"; then
15881 + :
15882 +else
15883 + echo "$1: Not found." 1>&2
15884 + exit 1
15885 +fi
15886 +
15887 +if test -f "$pkglibdir/stage1"; then
15888 + :
15889 +else
15890 + echo "${pkglibdir}/stage1: Not found." 1>&2
15891 + exit 1
15892 +fi
15893 +
15894 +if test -f "$pkglibdir/stage2"; then
15895 + :
15896 +else
15897 + echo "${pkglibdir}/stage2: Not found." 1>&2
15898 + exit 1
15899 +fi
15900 +
15901 +# Don't check for *stage1_5, because it is not fatal even if any
15902 +# Stage 1.5 does not exist.
15903 +
15904 +# Create the GRUB directory if it is not present.
15905 +test -d "$bootdir" || mkdir "$bootdir" || exit 1
15906 +test -d "$grubdir" || mkdir "$grubdir" || exit 1
15907 +
15908 +# If --recheck is specified, remove the device map, if present.
15909 +if test $recheck = yes; then
15910 + rm -f $device_map
15911 +fi
15912 +
15913 +# Create the device map file if it is not present.
15914 +if test -f "$device_map"; then
15915 + :
15916 +else
15917 + # Create a safe temporary file.
15918 + test -n "$mklog" && log_file=`$mklog`
15919 +
15920 + $grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file
15921 +quit
15922 +EOF
15923 + if grep "Error [0-9]*: " $log_file >/dev/null; then
15924 + cat $log_file 1>&2
15925 + exit 1
15926 + fi
15927 +
15928 + rm -f $log_file
15929 +fi
15930 +
15931 +# Make sure that there is no duplicated entry.
15932 +tmp=`sed -n '/^([fh]d[0-9]*)/s/\(^(.*)\).*/\1/p' $device_map \
15933 + | sort | uniq -d | sed -n 1p`
15934 +if test -n "$tmp"; then
15935 + echo "The drive $tmp is defined multiple times in the device map $device_map" 1>&2
15936 + exit 1
15937 +fi
15938 +
15939 +# Check for INSTALL_DEVICE.
15940 +case "$install_device" in
15941 +/dev/*)
15942 + install_device=`resolve_symlink "$install_device"`
15943 + install_drive=`convert "$install_device"`
15944 + # I don't know why, but some shells wouldn't die if exit is
15945 + # called in a function.
15946 + if test "x$install_drive" = x; then
15947 + exit 1
15948 + fi ;;
15949 +\([hf]d[0-9]*\))
15950 + install_drive="$install_device" ;;
15951 +[hf]d[0-9]*)
15952 + # The GRUB format with no parenthesis.
15953 + install_drive="($install_device)" ;;
15954 +*)
15955 + echo "Format of install_device not recognized." 1>&2
15956 + usage
15957 + exit 1 ;;
15958 +esac
15959 +
15960 +# Get the root drive.
15961 +root_device=`find_device ${rootdir}`
15962 +bootdir_device=`find_device ${bootdir}`
15963 +
15964 +# Check if the boot directory is in the same device as the root directory.
15965 +if test "x$root_device" != "x$bootdir_device"; then
15966 + # Perhaps the user has a separate boot partition.
15967 + root_device=$bootdir_device
15968 + grub_prefix="/grub"
15969 +fi
15970 +
15971 +# Convert the root device to a GRUB drive.
15972 +root_drive=`convert "$root_device"`
15973 +if test "x$root_drive" = x; then
15974 + exit 1
15975 +fi
15976 +
15977 +# Check if the root directory exists in the same device as the grub
15978 +# directory.
15979 +grubdir_device=`find_device ${grubdir}`
15980 +
15981 +if test "x$grubdir_device" != "x$root_device"; then
15982 + # For now, cannot deal with this situation.
15983 + cat <<EOF 1>&2
15984 +You must set the root directory by the option --root-directory, because
15985 +$grubdir does not exist in the root device $root_device.
15986 +EOF
15987 + exit 1
15988 +fi
15989 +
15990 +# Copy the GRUB images to the GRUB directory.
15991 +for file in ${grubdir}/stage1 ${grubdir}/stage2 ${grubdir}/*stage1_5; do
15992 + rm -f $file || exit 1
15993 +done
15994 +for file in \
15995 + ${pkglibdir}/stage1 ${pkglibdir}/stage2 ${pkglibdir}/*stage1_5; do
15996 + cp -f $file ${grubdir} || exit 1
15997 +done
15998 +
15999 +# Make a default file.
16000 +${grub_set_default} --root-directory=${rootdir} default
16001 +
16002 +# Make sure that GRUB reads the same images as the host OS.
16003 +test -n "$mkimg" && img_file=`$mkimg`
16004 +test -n "$mklog" && log_file=`$mklog`
16005 +
16006 +for file in ${grubdir}/stage1 ${grubdir}/stage2 ${grubdir}/*stage1_5; do
16007 + count=5
16008 + tmp=`echo $file | sed "s|^${grubdir}|${grub_prefix}|"`
16009 + while test $count -gt 0; do
16010 + $grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file
16011 +dump ${root_drive}${tmp} ${img_file}
16012 +quit
16013 +EOF
16014 + if grep "Error [0-9]*: " $log_file >/dev/null; then
16015 + :
16016 + elif cmp $file $img_file >/dev/null; then
16017 + break
16018 + fi
16019 + sleep 1
16020 + count=`expr $count - 1`
16021 + done
16022 + if test $count -eq 0; then
16023 + echo "The file $file not read correctly." 1>&2
16024 + exit 1
16025 + fi
16026 +done
16027 +
16028 +rm -f $img_file
16029 +rm -f $log_file
16030 +
16031 +# Create a safe temporary file.
16032 +test -n "$mklog" && log_file=`$mklog`
16033 +
16034 +# Now perform the installation.
16035 +$grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file
16036 +root $root_drive
16037 +setup $force_lba --stage2=$grubdir/stage2 --prefix=$grub_prefix $install_drive
16038 +quit
16039 +EOF
16040 +
16041 +if grep "Error [0-9]*: " $log_file >/dev/null || test $debug = yes; then
16042 + cat $log_file 1>&2
16043 + exit 1
16044 +fi
16045 +
16046 +rm -f $log_file
16047 +
16048 +# Prompt the user to check if the device map is correct.
16049 +echo "Installation finished. No error reported."
16050 +echo "This is the contents of the device map $device_map."
16051 +echo "Check if this is correct or not. If any of the lines is incorrect,"
16052 +echo "fix it and re-run the script \`grub-install'."
16053 +echo
16054 +
16055 +cat $device_map
16056 +
16057 +# Bye.
16058 +exit 0
16059 diff -Nur grub-0.97/util/mkbimage grub-0.97-patched/util/mkbimage
16060 --- grub-0.97/util/mkbimage 2004-07-24 20:57:31.000000000 +0200
16061 +++ grub-0.97-patched/util/mkbimage 2012-11-11 17:07:12.744730138 +0100
16062 @@ -1,7 +1,7 @@
16063 #!/bin/sh
16064 # MaKe a Bootable IMAGE --- 1.44, 2.88 and El Torito no-emulation mode
16065 # C) 2001,2002,2003 Thierry Laronde <tlaronde@polynum.org>
16066 -# C) 2001,2002,2003 Robert Millan <robertmh@gnu.org>
16067 +# C) 2001,2002,2003 Robert Millan <rmh@aybabtu.com>
16068
16069
16070 # This program is free software; you can redistribute it and/or modify
16071 @@ -94,15 +94,13 @@
16072 display Version information and exit
16073
16074 Copyright (c) 2001,2002,2003 Thierry Laronde <tlaronde@polynum.org>.
16075 -Copyright (c) 2001,2002 Robert Millan <zeratul2@wanadoo.es>.
16076 GPLed."
16077
16078 version="mkbimage $version_number
16079
16080 -Written by Thierry Laronde and Robert Millan.
16081 +Written by Thierry Laronde.
16082
16083 Copyright (c) 2001,2002,2003 Thierry Laronde <tlaronde@polynum.org>.
16084 -Copyright (c) 2001,2002,2003 Robert Millan <zeratul2@wanadoo.es>.
16085
16086 This is free software under the GPL version 2 or later; see the source for
16087 copying conditions. There is NO warranty, not even for MERCHANTABILITY or