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
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 :
11 AC_MSG_ERROR([${CC-cc} cannot link at address $link_addr])
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
17 +2008-05-20 Robert Millan <rmh@aybabtu.com>
19 + * netboot/cs89x0.c: Fix license violation.
20 + * netboot/cs89x0.h: Likewise.
22 +2008-04-10 Pavel Roskin <proski@gnu.org>
24 + * configure.ac: Always use "_cv_" in cache variables for
25 + compatibility with Autoconf 2.62.
27 +2008-03-28 Robert Millan <rmh@aybabtu.com>
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.
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
40 +2007-10-29 Pavel Roskin <proski@gnu.org>
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.
49 +2007-02-22 Pavel Roskin <proski@gnu.org>
51 + * stage2/iso9660.h: Remove unnecessary packed attributes.
53 +2007-02-22 Robert Millan <rmh@aybabtu.com>
55 + * util/mkbimage: Update my email address, and remove my name from
56 + some places where unnecessary credit is given.
58 +2006-09-10 Pavel Roskin <proski@gnu.org>
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.
64 +2006-09-08 Pavel Roskin <proski@gnu.org>
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
71 +2006-06-24 Yoshinori K. Okuji <okuji@enbug.org>
73 + * docs/grub.texi: Changed the license term to the GNU Free
74 + Documentation License 1.2.
76 + * docs/multiboot.texi: Reformatted to show the license term
77 + and the version number explicitly.
79 + * docs/fdl.texi: New file.
81 + * docs/Makefile.am (grub_TEXINFOS): Added fdl.texi.
83 +2006-06-24 Robert Millan <robertmh@gnu.org>
85 + * lib/device.c (write_to_partition): /dev/ataraid/ and /dev/rd/
86 + partitions have a "p" prefix. Add it.
88 +2006-06-24 Robert Millan <robertmh@gnu.org>
90 + * lib/device.c (get_i2o_disk_name): New function.
91 + (init_device_map) [__linux__]: Add support for I2O devices.
93 +2006-05-02 Pavel Roskin <proski@gnu.org>
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.
99 + * grub/main.c (main): Make sure the boot drive number doesn't
102 +2006-05-02 Vesa Jaaskelainen <chaac@nic.fi>
104 + * stage2/shared.h (vbe_mode): Back ported aligment fix from GRUB 2
105 + to GRUB Legacy. Problem reported by Gerardo Richarte.
107 +2006-04-23 Robert Millan <robertmh@gnu.org>
109 + * grub/asmstub.c (get_diskinfo): Optimize sysctl routine.
111 +2006-04-20 Robert Millan <robertmh@gnu.org>
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.
118 +2006-04-16 Yoshinori K. Okuji <okuji@enbug.org>
120 + * docs/multiboot.texi: Correct the offset of address
121 + fields. Reported by Jeroen Dekkers.
123 +2006-03-21 Yoshinori K. Okuji <okuji@enbug.org>
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>.
129 +2005-09-29 Yoshinori K. Okuji <okuji@enbug.org>
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.
135 +2005-09-28 Yoshinori K. Okuji <okuji@enbug.org>
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
141 2005-05-08 Yoshinori K. Okuji <okuji@enbug.org>
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
151 -i[[3456]]86) host_cpu=i386 ;;
152 -x86_64) host_cpu=x86_64 ;;
154 + STAGE_MARCH="-march=$host_cpu"
157 + STAGE_MARCH="-march=i686"
159 *) AC_MSG_ERROR([unsupported CPU type]) ;;
164 AC_CHECK_TOOL(CC, gcc)
166 -# We need this for older versions of Autoconf.
167 -_AM_DEPENDENCIES(CC)
169 -dnl Because recent automake complains about AS, set it here.
174 AC_ARG_WITH(binutils,
175 [ --with-binutils=DIR search the directory DIR to find binutils])
180 - AC_CACHE_CHECK([whether optimization for size works], size_flag, [
181 + AC_CACHE_CHECK([whether optimization for size works], grub_cv_cc_Os, [
184 - AC_TRY_COMPILE(, , size_flag=yes, size_flag=no)
185 + AC_TRY_COMPILE(, , grub_cv_cc_Os=yes, grub_cv_cc_Os=no)
188 - if test "x$size_flag" = xyes; then
189 + if test "x$grub_cv_cc_Os" = xyes; then
192 STAGE2_CFLAGS="-O2 -fno-strength-reduce -fno-unroll-loops"
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, [
200 CFLAGS="-fno-stack-protector"
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)
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"
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, [
216 + #if ! defined (__PIC__) || ! defined (__PIE__)
220 + grub_cv_cc_fpie=yes,
221 + grub_cv_cc_fpie=no)
223 + if test "x$grub_cv_cc_fpie" = xyes; then
224 + STAGE1_CFLAGS="$STAGE1_CFLAGS -nopie"
225 + STAGE2_CFLAGS="$STAGE2_CFLAGS -nopie"
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"
240 -AC_CACHE_CHECK([whether -Wundef works], undef_flag, [
241 +AC_CACHE_CHECK([whether -Wundef works], grub_cv_cc_Wundef, [
242 saved_CPPFLAGS="$CPPFLAGS"
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"
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"
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"
265 CPPFLAGS="$CPPFLAGS -malign-jumps=1 -malign-loops=1 -malign-functions=1"
268 -if test "x$undef_flag" = xyes; then
269 +if test "x$grub_cv_cc_Wundef" = xyes; then
270 CPPFLAGS="$CPPFLAGS -Wundef"
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"
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")
288 [ --enable-diskless enable diskless support])
289 AM_CONDITIONAL(DISKLESS_SUPPORT, test "x$enable_diskless" = xyes)
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)
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
304 +@node GNU Free Documentation License
305 +@appendixsec GNU Free Documentation License
307 +@cindex FDL, GNU Free Documentation License
308 +@center Version 1.2, November 2002
311 +Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc.
312 +51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
314 +Everyone is permitted to copy and distribute verbatim copies
315 +of this license document, but changing it is not allowed.
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.
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.
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.
344 +APPLICABILITY AND DEFINITIONS
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.
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.
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
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.
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.
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''.
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.
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.
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.
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.
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.
445 +You may also lend copies, under the same conditions stated above, and
446 +you may publicly display copies.
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.
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
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.
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.
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:
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.
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.
512 +State on the Title page the name of the publisher of the
513 +Modified Version, as the publisher.
516 +Preserve all the copyright notices of the Document.
519 +Add an appropriate copyright notice for your modifications
520 +adjacent to the other copyright notices.
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.
528 +Preserve in that license notice the full lists of Invariant Sections
529 +and required Cover Texts given in the Document's license notice.
532 +Include an unaltered copy of this License.
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.
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.
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.
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.
564 +Delete any section Entitled ``Endorsements''. Such a section
565 +may not be included in the Modified Version.
568 +Do not retitle any existing section to be Entitled ``Endorsements'' or
569 +to conflict in title with any Invariant Section.
572 +Preserve any Warranty Disclaimers.
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.
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
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.
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.
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.
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.
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.''
628 +COLLECTIONS OF DOCUMENTS
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.
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.
642 +AGGREGATION WITH INDEPENDENT WORKS
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.
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
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.
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
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.
694 +FUTURE REVISIONS OF THIS LICENSE
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/}.
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.
713 +@appendixsubsec ADDENDUM: How to use this License for your documents
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:
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''.
731 +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
732 +replace the ``with...Texts.'' line with this:
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
742 +If you have Invariant Sections without Cover Texts, or some other
743 +combination of the three, merge those two alternatives to suit the
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.
752 +@c ispell-local-pdict: "ispell-dict"
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
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
763 grub \- the grub shell
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
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
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
780 grub-install \- install GRUB on your drive
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
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
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
797 grub-md5-crypt \- Encrypt a password in MD5 format
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
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
807 grub-terminfo \- Generate a terminfo command from a terminfo name
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
814 @c %**start of header
815 @setfilename grub.info
816 -@settitle GRUB Manual
819 @include version.texi
821 +@settitle GNU GRUB Manual @value{VERSION}
822 @c Unify all our little indices for now.
830 @footnotestyle separate
835 +This manual is for GNU GRUB (version @value{VERSION},
838 +Copyright @copyright{} 1999,2000,2001,2002,2004,2006 Free Software Foundation, Inc.
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
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.''
857 * GRUB: (grub). The GRand Unified Bootloader
860 @setchapternewpage odd
863 -Copyright @copyright{} 1999,2000,2001,2002,2004 Free Software Foundation, Inc.
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.
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).
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.
882 -Permission is granted to copy and distribute translations of this manual
883 -into another language, under the above conditions for modified versions.
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.
895 @vskip 0pt plus 1filll
896 -Copyright @copyright{} 1999,2000,2001,2002,2004 Free Software Foundation, Inc.
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.
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.
913 @c Output the table of contents at the beginning.
919 +@top GNU GRUB manual
921 This is the documentation of GNU GRUB, the GRand Unified Bootloader,
922 a flexible and powerful boot loader program for @sc{pc}s.
924 This edition documents version @value{VERSION}.
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
938 @@ -3965,6 +3950,16 @@
939 @include internals.texi
942 +@node Copying This Manual
943 +@appendix Copying This Manual
946 +* GNU Free Documentation License:: License for copying this manual.
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
959 $include{$sect} .= <<EOT;
960 The full documentation for
962 -is maintained as a Texinfo manual. If the
963 +is maintained as a Texinfo manual in the
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
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
980 $(SHELL) $(srcdir)/$(SRC2TEXI) $(srcdir) $< $@
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=$@ $<
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
992 $(PERL) $(srcdir)/$(HELP2MAN) --name="install GRUB on your drive" \
993 - --section=8 --output=$@ $<
994 + --section=8 --include=$@.additions --output=$@ $<
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
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
1006 mbchk \- check the format of a Multiboot kernel
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
1012 # Fallback to the second entry.
1015 +# Splash image to show behind grub.
1016 +splashimage=(hd0,0)/boot/grub/splash.xpm.gz
1018 # For booting GNU/Hurd
1022 kernel /vmlinuz root=/dev/hdb1
1025 +# For booting Gentoo with the static rescue shell
1026 +title Gentoo (rescue shell)
1028 +kernel /vmlinuz root=/dev/hdb1 init=/bin/bb
1030 # For booting GNU/kFreeBSD
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
1038 +# Sample boot menu configuration file
1041 +# Boot automatically after 30 secs.
1044 +# By default, boot the first entry.
1047 +# Fallback to the second entry.
1050 +# For booting GNU/Hurd
1053 +kernel /boot/gnumach.gz root=hd0s1
1054 +module /boot/serverboot.gz
1056 +# For booting GNU/Linux
1059 +kernel /vmlinuz root=/dev/hdb1
1060 +#initrd /initrd.img
1062 +# For booting GNU/kFreeBSD
1065 +kernel /boot/loader.gz
1067 +# For booting GNU/kNetBSD
1070 +kernel --type=netbsd /boot/knetbsd.gz
1072 +# For booting Mach (getting kernel from floppy)
1073 +title Utah Mach4 multiboot
1075 +pause Insert the diskette now
\a!!
1076 +kernel (fd0)/boot/kernel root=hd0s3
1077 +module (fd0)/boot/bootstrap
1079 +# For booting FreeBSD
1082 +kernel /boot/loader
1084 +# For booting NetBSD
1087 +kernel --type=netbsd /netbsd
1089 +# For booting OpenBSD
1092 +kernel --type=netbsd /bsd
1098 +# chainload OS/2 bootloader from the first sector
1100 +# This is similar to "chainload", but loads a specific file
1101 +#chainloader /boot/chain.os2
1103 +# For booting Windows NT or Windows95
1104 +title Windows NT / Windows 95 boot menu
1105 +rootnoverify (hd0,0)
1108 +# For loading DOS if Windows NT is installed
1109 +# chainload /bootsect.dos
1111 +# For installing GRUB into the hard disk
1112 +title Install GRUB into the hard disk
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
1123 \input texinfo @c -*-texinfo-*-
1125 @c %**start of header
1126 @setfilename multiboot.info
1127 -@settitle Multiboot Specification
1128 -@c %**end of header
1130 +@set VERSION 0.6.95
1131 +@settitle Multiboot Specification version @value{VERSION}
1132 @c Unify all our little indices for now.
1138 +@c %**end of header
1140 @footnotestyle separate
1145 +Copyright @copyright{} 1995,96 Bryan Ford <baford@@cs.utah.edu>
1147 -@dircategory Kernel
1149 -* Multiboot Specification: (multiboot). Multiboot Specification.
1151 +Copyright @copyright{} 1995,96 Erich Stefan Boleyn <erich@@uruk.org>
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.
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.
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).
1170 Permission is granted to copy and distribute modified versions of this
1172 permission notice identical to this one.
1174 Permission is granted to copy and distribute translations of this manual
1175 -into another language, under the above conditions for modified versions.
1177 +into another language, under the above conditions for modified
1182 +@dircategory Kernel
1184 +* Multiboot Specification: (multiboot). Multiboot Specification.
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
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.
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.
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.
1208 -Permission is granted to copy and distribute translations of this manual
1209 -into another language, under the above conditions for modified versions.
1215 @top Multiboot Specification
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}.
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}
1237 +-------+-------+-------+-------+
1238 -| drive | part1 | part2 | part3 |
1239 +| part3 | part2 | part1 | drive |
1240 +-------+-------+-------+-------+
1243 @@ -1197,6 +1186,17 @@
1245 The maintainer changes to the GNU GRUB maintainer team
1246 @email{bug-grub@@gnu.org}, from Bryan Ford and Erich Stefan Boleyn.
1249 +The byte order of the @samp{boot_device} in Multiboot information is
1250 +reversed. This was a mistake.
1253 +The offset of the address fields were wrong.
1256 +The format is adapted to a newer Texinfo, and the version number is
1257 +specified more explicitly in the title.
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
1265 #include <sys/time.h>
1266 #include <termios.h>
1268 +#include <sys/mman.h>
1271 # include <sys/ioctl.h> /* ioctl */
1273 # endif /* ! BLKFLSBUF */
1274 #endif /* __linux__ */
1276 +#if defined(__FreeBSD_kernel__) || defined(__FreeBSD__)
1277 +# include <sys/sysctl.h>
1280 /* We want to prevent any circularararity in our stubs, as well as
1281 libc name clashes. */
1282 #define WITHOUT_LIBC_STUBS 1
1284 struct apm_info apm_bios_info;
1286 /* Emulation requirements. */
1287 -char *grub_scratch_mem = 0;
1288 +void *grub_scratch_mem = 0;
1290 struct geometry *disks = 0;
1292 @@ -103,14 +108,62 @@
1293 static unsigned int serial_speed;
1294 #endif /* SIMULATE_SLOWNESS_OF_SERIAL */
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)
1301 +grub_mmap_alloc(size_t len)
1303 + int mmap_flags = MAP_ANONYMOUS|MAP_PRIVATE;
1306 + mmap_flags |= MAP_32BIT;
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);
1312 +#else /* !defined(__linux__) */
1314 +grub_mmap_alloc(size_t len)
1316 + int fd = 0, offset = 0, ret = 0;
1317 + void *pa = MAP_FAILED;
1318 + char template[] = "/tmp/grub_mmap_alloc_XXXXXX";
1321 + fd = mkstemp(template);
1327 + ret = ftruncate(fd, len);
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);
1341 +#endif /* defined(__linux__) */
1343 /* The main entry point into this mess. */
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;
1356 auto void doit (void);
1357 @@ -142,9 +195,35 @@
1360 assert (grub_scratch_mem == 0);
1361 - scratch = malloc (0x100000 + EXTENDED_MEMSIZE + 15);
1363 - grub_scratch_mem = (char *) ((((int) scratch) >> 4) << 4);
1365 + /* Allocate enough pages for 0x100000 + EXTENDED_SIZE + 15, and
1366 + * make sure the memory is aligned to a multiple of the system's
1368 + page_size = sysconf (_SC_PAGESIZE);
1369 + simstack_size = ( 0x100000 + EXTENDED_MEMSIZE + 15);
1370 + if (simstack_size % page_size)
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;
1377 + /* Add one for a PROT_NONE boundary page at each end. */
1378 + simstack_size += 2 * page_size;
1380 + simstack_alloc_base = grub_mmap_alloc(simstack_size);
1381 + assert (simstack_alloc_base != MAP_FAILED);
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);
1392 + grub_scratch_mem = (void *)((unsigned long)simstack_alloc_base + page_size);
1394 /* FIXME: simulate the memory holes using mprot, if available. */
1401 + munmap(simstack_alloc_base, simstack_size);
1402 grub_scratch_mem = 0;
1405 @@ -777,7 +856,39 @@
1407 /* Open read/write, or read-only if that failed. */
1409 - disks[drive].flags = open (devname, O_RDWR);
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);
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));
1420 + if ((old_flags & 0x10) == 0)
1422 + /* "allow foot shooting", see geom(4) */
1423 + flags = old_flags | 0x10;
1425 + if (sysctlbyname (GEOM_SYSCTL, NULL, NULL, &flags, sizeof (int)) != 0)
1427 + flags = old_flags;
1428 + grub_printf ("failed to set " GEOM_SYSCTL "sysctl: %s\n", strerror (errno));
1432 + flags = old_flags;
1434 + disks[drive].flags = open (devname, O_RDWR);
1435 +#if defined(__FreeBSD_kernel__) || defined(__FreeBSD__)
1436 + if (flags != old_flags)
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));
1444 if (disks[drive].flags == -1)
1446 @@ -926,7 +1037,7 @@
1449 biosdisk (int subfunc, int drive, struct geometry *geometry,
1450 - int sector, int nsec, int segment)
1451 + unsigned int sector, int nsec, int segment)
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
1459 +/* asmstub.c - a version of shared_src/asm.S that works under Unix */
1461 + * GRUB -- GRand Unified Bootloader
1462 + * Copyright (C) 1999,2000,2001,2002,2004 Free Software Foundation, Inc.
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.
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.
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.
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
1484 +/* Simulator entry point. */
1485 +int grub_stage2 (void);
1487 +#include <stdlib.h>
1488 +#include <string.h>
1490 +#include <assert.h>
1492 +#include <sys/types.h>
1493 +#include <sys/stat.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>
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)) */
1512 +# define BLKFLSBUF _IO (0x12,97) /* flush buffer cache */
1513 +# endif /* ! BLKFLSBUF */
1514 +#endif /* __linux__ */
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>
1524 +/* Simulated memory sizes. */
1525 +#define EXTENDED_MEMSIZE (3 * 1024 * 1024) /* 3MB */
1526 +#define CONVENTIONAL_MEMSIZE (640 * 1024) /* 640kB */
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;
1539 +/* Emulation requirements. */
1540 +char *grub_scratch_mem = 0;
1542 +struct geometry *disks = 0;
1544 +/* The map between BIOS drives and UNIX device file names. */
1545 +char **device_map = 0;
1547 +/* The jump buffer for exiting correctly. */
1548 +static jmp_buf env_for_exit;
1550 +/* The current color for console. */
1551 +int console_current_color = A_NORMAL;
1553 +/* The file descriptor for a serial device. */
1554 +static int serial_fd = -1;
1556 +/* The file name of a serial device. */
1557 +static char *serial_device = 0;
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 */
1564 +/* The main entry point into this mess. */
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;
1574 + auto void doit (void);
1576 + /* We need a nested function so that we get a clean stack frame,
1577 + regardless of how the code is optimized. */
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));
1584 + /* Do a setjmp here for the stop command. */
1585 + if (! setjmp (env_for_exit))
1587 + /* Actually enter the generic stage2 code. */
1589 + init_bios_info ();
1593 + /* If ERRNUM is non-zero, then set STATUS to non-zero. */
1598 + /* Replace our stack before we use any local variables. */
1599 + asm volatile ("movl %0, %%esp\n" : : "r" (realstack));
1602 + assert (grub_scratch_mem == 0);
1603 + scratch = malloc (0x100000 + EXTENDED_MEMSIZE + 15);
1605 + grub_scratch_mem = (char *) ((((int) scratch) >> 4) << 4);
1607 + /* FIXME: simulate the memory holes using mprot, if available. */
1609 + assert (disks == 0);
1610 + disks = malloc (NUM_DISKS * sizeof (*disks));
1612 + /* Initialize DISKS. */
1613 + for (i = 0; i < NUM_DISKS; i++)
1614 + disks[i].flags = -1;
1616 + if (! init_device_map (&device_map, device_map_file, floppy_disks))
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);
1626 +#ifdef HAVE_LIBCURSES
1627 + /* Get into char-at-a-time mode. */
1634 + scrollok (stdscr, TRUE);
1635 + keypad (stdscr, TRUE);
1636 + wtimeout (stdscr, 100);
1637 + signal (SIGWINCH, SIG_IGN);
1641 + /* Make sure that actual writing is done. */
1644 + /* Set our stack, and go for it. */
1645 + simstack = (char *) PROTSTACKINIT;
1648 + /* I don't know if this is necessary really. */
1651 +#ifdef HAVE_LIBCURSES
1656 + /* Close off the file descriptors we used. */
1657 + for (i = 0; i < NUM_DISKS; i ++)
1658 + if (disks[i].flags != -1)
1661 + /* In Linux, invalidate the buffer cache. In other OSes, reboot
1662 + is one of the solutions... */
1663 + ioctl (disks[i].flags, BLKFLSBUF, 0);
1665 +# warning "In your operating system, the buffer cache will not be flushed."
1667 + close (disks[i].flags);
1670 + if (serial_fd >= 0)
1671 + close (serial_fd);
1673 + /* Release memory. */
1674 + restore_device_map (device_map);
1679 + grub_scratch_mem = 0;
1681 + if (serial_device)
1682 + free (serial_device);
1683 + serial_device = 0;
1685 + /* Ahh... at last we're ready to return to caller. */
1689 +/* Assign DRIVE to a device name DEVICE. */
1691 +assign_device_name (int drive, const char *device)
1693 + /* If DRIVE is already assigned, free it. */
1694 + if (device_map[drive])
1695 + free (device_map[drive]);
1697 + /* If the old one is already opened, close it. */
1698 + if (disks[drive].flags != -1)
1700 + close (disks[drive].flags);
1701 + disks[drive].flags = -1;
1704 + /* Assign DRIVE to DEVICE. */
1706 + device_map[drive] = 0;
1708 + device_map[drive] = strdup (device);
1714 +#ifdef HAVE_LIBCURSES
1719 + /* Jump to doit. */
1720 + longjmp (env_for_exit, 1);
1730 +grub_halt (int no_apm)
1735 +/* calls for direct boot-loader chaining */
1737 +chain_stage1 (unsigned long segment, unsigned long offset,
1738 + unsigned long part_table_addr)
1745 +chain_stage2 (unsigned long segment, unsigned long offset, int second_sector)
1751 +/* do some funky stuff, then boot linux */
1759 +/* For bzImage kernels. */
1761 +big_linux_boot (void)
1767 +/* booting a multiboot executable */
1769 +multi_boot (int start, int mb_info)
1774 +/* sets it to linear or wired A20 operation */
1776 +gateA20 (int linear)
1778 + /* Nothing to do in the simulator. */
1781 +/* Set up the int15 handler. */
1783 +set_int15_handler (void)
1785 + /* Nothing to do in the simulator. */
1788 +/* Restore the original int15 handler. */
1790 +unset_int15_handler (void)
1792 + /* Nothing to do in the simulator. */
1796 +unsigned short bios_key_map[KEY_MAP_SIZE + 1];
1797 +unsigned short ascii_key_map[KEY_MAP_SIZE + 1];
1799 +/* Copy MAP to the drive map and set up the int13 handler. */
1801 +set_int13_handler (unsigned short *map)
1803 + /* Nothing to do in the simulator. */
1807 +get_code_end (void)
1809 + /* Just return a little area for simulation. */
1810 + return BOOTSEC_LOCATION + (60 * 1024);
1814 +/* memory probe routines */
1816 +get_memsize (int type)
1819 + return CONVENTIONAL_MEMSIZE >> 10;
1821 + return EXTENDED_MEMSIZE >> 10;
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.
1830 +get_eisamemsize (void)
1832 + return (EXTENDED_MEMSIZE >> 10);
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 */
1841 +#define MMAR_DESC_LENGTH 20
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
1848 +get_mmap_entry (struct mmar_desc *desc, int cont)
1850 + /* Record the memory map statically. */
1851 + static struct mmar_desc desc_table[] =
1853 + /* The conventional memory. */
1857 + CONVENTIONAL_MEMSIZE,
1858 + MMAR_DESC_TYPE_AVAILABLE
1860 + /* BIOS RAM and ROM (such as video memory). */
1863 + CONVENTIONAL_MEMSIZE,
1864 + 0x100000 - CONVENTIONAL_MEMSIZE,
1865 + MMAR_DESC_TYPE_RESERVED
1867 + /* The extended memory. */
1872 + MMAR_DESC_TYPE_AVAILABLE
1876 + int num = sizeof (desc_table) / sizeof (*desc_table);
1878 + if (cont < 0 || cont >= num)
1880 + /* Should not happen. */
1881 + desc->desc_len = 0;
1885 + /* Copy the entry. */
1886 + *desc = desc_table[cont++];
1888 + /* If the next entry exists, return the index. */
1896 +/* Track the int13 handler. */
1898 +track_int13 (int drive)
1900 + /* Nothing to do in the simulator. */
1903 +/* Get the ROM configuration table. */
1905 +get_rom_config_table (void)
1910 +/* Get APM BIOS information. */
1912 +get_apm_info (void)
1914 + /* Nothing to do in the simulator. */
1917 +/* Get VBE controller information. */
1919 +get_vbe_controller_info (struct vbe_controller *controller)
1921 + /* Always fails. */
1925 +/* Get VBE mode information. */
1927 +get_vbe_mode_info (int mode_number, struct vbe_mode *mode)
1929 + /* Always fails. */
1933 +/* Set VBE mode. */
1935 +set_vbe_mode (int mode_number)
1937 + /* Always fails. */
1941 +/* low-level timing info */
1945 + /* FIXME: exact value is not important, so just return time_t for now. */
1952 + struct timeval tv;
1954 + int ticks_per_csec, ticks_per_usec;
1956 + /* Note: 18.2 ticks/sec. */
1958 + /* Get current time. */
1959 + gettimeofday (&tv, 0);
1961 + /* Compute centiseconds. */
1962 + csecs = tv.tv_sec / 10;
1964 + /* Ticks per centisecond. */
1965 + ticks_per_csec = csecs * 182;
1967 + /* Ticks per microsecond. */
1968 + ticks_per_usec = (((tv.tv_sec - csecs * 10) * 1000000 + tv.tv_usec)
1969 + * 182 / 10000000);
1972 + return ticks_per_csec + ticks_per_usec;
1975 +/* displays an ASCII character. IBM displays will translate some
1976 + characters to special graphical ones */
1978 +console_putchar (int c)
1980 + /* Curses doesn't have VGA fonts. */
2017 +#ifdef HAVE_LIBCURSES
2020 + /* In ncurses, a newline is treated badly, so we emulate it in our
2026 + getyx (stdscr, y, x);
2027 + if (y + 1 == LINES)
2032 + else if (isprint (c))
2036 + getyx (stdscr, y, x);
2037 + if (x + 1 == COLS)
2039 + console_putchar ('\r');
2040 + console_putchar ('\n');
2042 + addch (c | console_current_color);
2049 +#ifdef REFRESH_IMMEDIATELY
2056 + /* CR is not used in Unix. */
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;
2070 +console_translate_key (int c)
2084 + case KEY_BACKSPACE:
2101 +/* like 'getkey', but doesn't wait, returns -1 if nothing available */
2103 +console_checkkey (void)
2105 +#ifdef HAVE_LIBCURSES
2110 + /* Check for SAVE_CHAR. This should not be true, because this
2111 + means checkkey is called twice continuously. */
2112 + if (save_char != ERR)
2116 + /* If C is not ERR, then put it back in the input queue. */
2119 + return console_translate_key (c);
2123 + /* Just pretend they hit the space bar, then read the real key when
2124 + they call getkey. */
2128 +/* returns packed BIOS/ASCII code */
2130 +console_getkey (void)
2134 +#ifdef HAVE_LIBCURSES
2137 + /* If checkkey has already got a character, then return it. */
2138 + if (save_char != ERR)
2142 + return console_translate_key (c);
2145 + wtimeout (stdscr, -1);
2147 + wtimeout (stdscr, 100);
2153 + /* Quit if we get EOF. */
2157 + return console_translate_key (c);
2160 +/* returns packed values, LSB+1 is x, LSB is y */
2162 +console_getxy (void)
2165 +#ifdef HAVE_LIBCURSES
2167 + getyx (stdscr, y, x);
2171 + return (x << 8) | (y & 0xff);
2175 +console_gotoxy (int x, int y)
2177 +#ifdef HAVE_LIBCURSES
2183 +/* low-level character I/O */
2187 +#ifdef HAVE_LIBCURSES
2194 +console_setcolorstate (color_state state)
2196 + console_current_color =
2197 + (state == COLOR_STATE_HIGHLIGHT) ? A_REVERSE : A_NORMAL;
2201 +console_setcolor (int normal_color, int highlight_color)
2203 + /* Nothing to do. */
2207 +console_setcursor (int on)
2212 +/* Low-level disk I/O. Our stubbed version just returns a file
2213 + descriptor, not the actual geometry. */
2215 +get_diskinfo (int drive, struct geometry *geometry)
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 */
2222 + /* See if we have a cached device. */
2223 + if (disks[drive].flags == -1)
2225 + /* The unpartitioned device name: /dev/XdX */
2226 + char *devname = device_map[drive];
2233 + grub_printf ("Attempt to open drive 0x%x (%s)\n",
2236 + /* Open read/write, or read-only if that failed. */
2238 + disks[drive].flags = open (devname, O_RDWR);
2240 + if (disks[drive].flags == -1)
2242 + if (read_only || errno == EACCES || errno == EROFS || errno == EPERM)
2244 + disks[drive].flags = open (devname, O_RDONLY);
2245 + if (disks[drive].flags == -1)
2247 + assign_device_name (drive, 0);
2253 + assign_device_name (drive, 0);
2258 + /* Attempt to read the first sector. */
2259 + if (read (disks[drive].flags, buf, 512) != 512)
2261 + close (disks[drive].flags);
2262 + disks[drive].flags = -1;
2263 + assign_device_name (drive, 0);
2267 + if (disks[drive].flags != -1)
2268 + get_drive_geometry (&disks[drive], device_map, drive);
2271 + if (disks[drive].flags == -1)
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);
2280 + *geometry = disks[drive];
2284 +/* Read LEN bytes from FD in BUF. Return less than or equal to zero if an
2285 + error occurs, otherwise return LEN. */
2287 +nread (int fd, char *buf, size_t len)
2293 + int ret = read (fd, buf, len);
2297 + if (errno == EINTR)
2310 +/* Write LEN bytes from BUF to FD. Return less than or equal to zero if an
2311 + error occurs, otherwise return LEN. */
2313 +nwrite (int fd, char *buf, size_t len)
2319 + int ret = write (fd, buf, len);
2323 + if (errno == EINTR)
2336 +/* Dump BUF in the format of hexadecimal numbers. */
2338 +hex_dump (void *buf, size_t size)
2340 + /* FIXME: How to determine which length is readable? */
2341 +#define MAX_COLUMN 70
2343 + /* use unsigned char for numerical computations */
2344 + unsigned char *ptr = buf;
2345 + /* count the width of the line */
2347 + /* how many bytes written */
2353 + int hi = *ptr >> 4;
2355 + int low = *ptr & 0xf;
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);
2365 + /* Insert space or newline with the interval 4 bytes. */
2366 + if (size != 0 && (count % 4) == 0)
2368 + if (column < MAX_COLUMN)
2370 + grub_printf (" ");
2375 + grub_printf ("\n");
2381 + /* Add a newline at the end for readability. */
2382 + grub_printf ("\n");
2386 +biosdisk (int subfunc, int drive, struct geometry *geometry,
2387 + int sector, int nsec, int segment)
2390 + int fd = geometry->flags;
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;
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. */
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);
2407 + offset = (loff_t) sector * (loff_t) SECTOR_SIZE;
2408 + if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
2413 + off_t offset = (off_t) sector * (off_t) SECTOR_SIZE;
2415 + if (lseek (fd, offset, SEEK_SET) != offset)
2420 + buf = (char *) (segment << 4);
2424 + case BIOSDISK_READ:
2426 + if (sector == 0 && nsec > 1)
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
2432 + if (nread (fd, buf, SECTOR_SIZE) != SECTOR_SIZE)
2434 + buf += SECTOR_SIZE;
2438 + if (nread (fd, buf, nsec * SECTOR_SIZE) != nsec * SECTOR_SIZE)
2442 + case BIOSDISK_WRITE:
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);
2451 + if (nwrite (fd, buf, nsec * SECTOR_SIZE) != nsec * SECTOR_SIZE)
2456 + grub_printf ("unknown subfunc %d\n", subfunc);
2470 +/* Fetch a key from a serial device. */
2472 +serial_hw_fetch (void)
2475 + struct timeval to;
2478 + /* Wait only for the serial device. */
2480 + FD_SET (serial_fd, &fds);
2485 + if (select (serial_fd + 1, &fds, 0, 0, &to) > 0)
2487 + if (nread (serial_fd, &c, 1) != 1)
2496 +/* Put a character to a serial device. */
2498 +serial_hw_put (int c)
2500 + char ch = (char) c;
2502 + if (nwrite (serial_fd, &ch, 1) != 1)
2507 +serial_hw_delay (void)
2509 +#ifdef SIMULATE_SLOWNESS_OF_SERIAL
2510 + struct timeval otv, tv;
2512 + gettimeofday (&otv, 0);
2518 + gettimeofday (&tv, 0);
2519 + delta = tv.tv_usec - otv.tv_usec;
2523 + if (delta >= 1000000 / (serial_speed >> 3))
2526 +#endif /* SIMULATE_SLOWNESS_OF_SERIAL */
2530 +get_termios_speed (int speed)
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;
2540 + case 57600: return B57600;
2543 + case 115200: return B115200;
2550 +/* Get the port number of the unit UNIT. In the grub shell, this doesn't
2553 +serial_hw_get_port (int unit)
2558 +/* Initialize a serial device. In the grub shell, PORT is unused. */
2560 +serial_hw_init (unsigned short port, unsigned int speed,
2561 + int word_len, int parity, int stop_bit_len)
2563 + struct termios termios;
2564 + speed_t termios_speed;
2567 + /* Check if the file name is specified. */
2568 + if (! serial_device)
2571 + /* If a serial device is already opened, close it first. */
2572 + if (serial_fd >= 0)
2573 + close (serial_fd);
2575 + /* Open the device file. */
2576 + serial_fd = open (serial_device,
2578 +#if defined(O_SYNC)
2579 + /* O_SYNC is used in Linux (and some others?). */
2581 +#elif defined(O_FSYNC)
2582 + /* O_FSYNC is used in FreeBSD. */
2586 + if (serial_fd < 0)
2589 + /* Get the termios parameters. */
2590 + if (tcgetattr (serial_fd, &termios))
2594 + cfmakeraw (&termios);
2596 + /* Set the speed. */
2597 + termios_speed = get_termios_speed (speed);
2598 + if (termios_speed == B0)
2601 + cfsetispeed (&termios, termios_speed);
2602 + cfsetospeed (&termios, termios_speed);
2604 + /* Set the word length. */
2605 + termios.c_cflag &= ~CSIZE;
2608 + case UART_5BITS_WORD:
2609 + termios.c_cflag |= CS5;
2611 + case UART_6BITS_WORD:
2612 + termios.c_cflag |= CS6;
2614 + case UART_7BITS_WORD:
2615 + termios.c_cflag |= CS7;
2617 + case UART_8BITS_WORD:
2618 + termios.c_cflag |= CS8;
2624 + /* Set the parity. */
2627 + case UART_NO_PARITY:
2628 + termios.c_cflag &= ~PARENB;
2630 + case UART_ODD_PARITY:
2631 + termios.c_cflag |= PARENB;
2632 + termios.c_cflag |= PARODD;
2634 + case UART_EVEN_PARITY:
2635 + termios.c_cflag |= PARENB;
2636 + termios.c_cflag &= ~PARODD;
2642 + /* Set the length of stop bit. */
2643 + switch (stop_bit_len)
2645 + case UART_1_STOP_BIT:
2646 + termios.c_cflag &= ~CSTOPB;
2648 + case UART_2_STOP_BITS:
2649 + termios.c_cflag |= CSTOPB;
2655 + /* Set the parameters. */
2656 + if (tcsetattr (serial_fd, TCSANOW, &termios))
2659 +#ifdef SIMULATE_SLOWNESS_OF_SERIAL
2660 + serial_speed = speed;
2661 +#endif /* SIMUATE_SLOWNESS_OF_SERIAL */
2663 + /* Get rid of the flag TERM_NEED_INIT from the serial terminal. */
2664 + for (i = 0; term_table[i].name; i++)
2666 + if (strcmp (term_table[i].name, "serial") == 0)
2668 + term_table[i].flags &= ~(TERM_NEED_INIT);
2676 + close (serial_fd);
2681 +/* Set the file name of a serial device (or a pty device). This is a
2682 + function specific to the grub shell. */
2684 +serial_set_device (const char *device)
2686 + if (serial_device)
2687 + free (serial_device);
2689 + serial_device = strdup (device);
2692 +/* There is no difference between console and hercules in the grub shell. */
2694 +hercules_putchar (int c)
2696 + console_putchar (c);
2700 +hercules_getxy (void)
2702 + return console_getxy ();
2706 +hercules_gotoxy (int x, int y)
2708 + console_gotoxy (x, y);
2712 +hercules_cls (void)
2718 +hercules_setcolorstate (color_state state)
2720 + console_setcolorstate (state);
2724 +hercules_setcolor (int normal_color, int highlight_color)
2726 + console_setcolor (normal_color, highlight_color);
2730 +hercules_setcursor (int on)
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
2738 #define WITHOUT_LIBC_STUBS 1
2741 +#include <device.h>
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;
2750 - default_config_file = config_file;
2752 - default_config_file = "NONE";
2753 + default_config_file = config_file;
2755 /* Parse command-line options. */
2757 @@ -192,6 +190,12 @@
2761 + if (boot_drive >= NUM_DISKS)
2763 + fprintf (stderr, "boot_drive should be from 0 to %d\n",
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
2774 +/* main.c - experimental GRUB stage2 that runs under Unix */
2776 + * GRUB -- GRand Unified Bootloader
2777 + * Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc.
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.
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.
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.
2794 +/* Simulator entry point. */
2795 +int grub_stage2 (void);
2798 +#include <getopt.h>
2799 +#include <unistd.h>
2800 +#include <string.h>
2801 +#include <stdlib.h>
2802 +#include <limits.h>
2803 +#include <setjmp.h>
2805 +#define WITHOUT_LIBC_STUBS 1
2806 +#include <shared.h>
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;
2815 +int use_curses = 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;
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 ""
2843 +static struct option longopts[] =
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},
2869 + fprintf (stderr, "Try ``grub --help'' for more information.\n");
2872 +Usage: grub [OPTION]...\n\
2874 +Enter the GRand Unified Bootloader command shell.\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\
2893 +Report bugs to <bug-grub@gnu.org>.\n\
2895 + default_boot_drive, default_config_file,
2896 + default_install_partition);
2903 +main (int argc, char **argv)
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. */
2913 + program_name = argv[0];
2914 + default_boot_drive = boot_drive;
2915 + default_install_partition = install_partition;
2917 + default_config_file = config_file;
2919 + default_config_file = "NONE";
2921 + /* Parse command-line options. */
2924 + c = getopt_long (argc, argv, OPTSTRING, longopts, 0);
2928 + /* Fall through the bottom of the loop. */
2936 + printf ("grub (GNU GRUB " VERSION ")\n");
2944 + hold = atoi (optarg);
2947 + case OPT_CONFIG_FILE:
2948 + strncpy (config_file, optarg, 127); /* FIXME: arbitrary */
2949 + config_file[127] = '\0';
2952 + case OPT_INSTALL_PARTITION:
2953 + install_partition = strtoul (optarg, 0, 0);
2954 + if (install_partition == ULONG_MAX)
2956 + perror ("strtoul");
2961 + case OPT_BOOT_DRIVE:
2962 + boot_drive = strtoul (optarg, 0, 0);
2963 + if (boot_drive == ULONG_MAX)
2965 + perror ("strtoul");
2970 + case OPT_NO_CONFIG_FILE:
2971 + use_config_file = 0;
2974 + case OPT_NO_CURSES:
2978 + case OPT_NO_PAGER:
2983 + /* This is the same as "--no-config-file --no-curses --no-pager". */
2984 + use_config_file = 0;
2989 + case OPT_READ_ONLY:
2997 + case OPT_NO_FLOPPY:
3001 + case OPT_PROBE_SECOND_FLOPPY:
3005 + case OPT_DEVICE_MAP:
3006 + device_map_file = strdup (optarg);
3009 + case OPT_PRESET_MENU:
3010 + use_preset_menu = 1;
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 ());
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 */
3034 + current_term->flags = TERM_NO_EDIT | TERM_DUMB;
3036 + /* Transfer control to the stage2 simulator. */
3037 + exit (grub_stage2 ());
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
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__ */
3054 /* Use __FreeBSD_kernel__ instead of __FreeBSD__ for compatibility with
3055 @@ -131,6 +131,152 @@
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
3066 +static void get_kernel_geometry(int fd, long long *cyl, int *heads, int *sectors) {
3067 + struct hd_geometry hdg;
3069 + if (ioctl (fd, HDIO_GETGEO, &hdg))
3072 + *cyl = hdg.cylinders;
3073 + *heads = hdg.heads;
3074 + *sectors = hdg.sectors;
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 */
3090 +#define ALIGNMENT 2
3093 + unsigned char align[ALIGNMENT];
3094 + unsigned char b[SECTOR_SIZE];
3097 + unsigned char align[ALIGNMENT];
3098 + unsigned char buffer[0x1BE];
3099 + struct partition part[4];
3100 + unsigned char magicflag[2];
3104 +#define PART_TABLE_FLAG0 0x55
3105 +#define PART_TABLE_FLAG1 0xAA
3108 +get_partition_table_geometry(partition_table *bufp, long long *cyl, int *heads,
3110 + struct partition *p;
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);
3120 + fprintf(stderr, "Unknown partition table signature\n");
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);
3134 + } else if (hh != h || ss != s)
3139 + if (!first && !bad) {
3145 +static long long my_lseek (unsigned int fd, long long offset,
3146 + unsigned int origin)
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);
3157 + if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET) < 0)
3158 + return (long long) -1;
3161 + return lseek(fd, offset, SEEK_SET);
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;
3171 + buf_unaligned = malloc(sizeof(partition_table) + 4095);
3172 + buff = (char *) (((unsigned long)buf_unaligned + 4096 - 1) &
3175 + get_kernel_geometry(fd, &kern_cyl, &kern_head, &kern_sectors);
3177 + if (my_lseek (fd, 0*SECTOR_SIZE, SEEK_SET) < 0) {
3178 + fprintf(stderr, "Unable to seek");
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);
3185 + fprintf(stderr, "Unable to read partition table: %s\n", strerror(errno));
3188 + if (pt_head && pt_sectors) {
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;
3196 + geom->heads = kern_head;
3197 + geom->sectors = kern_sectors;
3198 + geom->cylinders = kern_cyl;
3205 /* Get the geometry of a drive DRIVE. */
3207 get_drive_geometry (struct geometry *geom, char **map, int drive)
3208 @@ -151,20 +297,16 @@
3209 #if defined(__linux__)
3212 - struct hd_geometry hdg;
3214 + unsigned long long nr;
3216 - if (ioctl (fd, HDIO_GETGEO, &hdg))
3219 - if (ioctl (fd, BLKGETSIZE, &nr))
3220 + if (ioctl (fd, BLKGETSIZE64, &nr))
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)
3231 + geom->total_sectors = nr / 512;
3235 @@ -403,10 +545,28 @@
3239 +get_cciss_disk_name (char *name, int controller, int drive)
3241 + sprintf (name, "/dev/cciss/c%dd%d", controller, drive);
3245 +get_ida_disk_name (char *name, int controller, int drive)
3247 + sprintf (name, "/dev/ida/c%dd%d", controller, drive);
3251 get_ataraid_disk_name (char *name, int unit)
3253 sprintf (name, "/dev/ataraid/d%c", unit + '0');
3257 +get_i2o_disk_name (char *name, char unit)
3259 + sprintf (name, "/dev/i2o/hd%c", unit);
3263 /* Check if DEVICE can be read. If an error occurs, return zero,
3264 @@ -801,6 +961,97 @@
3269 + /* This is for I2O - we have /dev/i2o/hd<logical drive><partition> */
3273 + for (unit = 'a'; unit < 'f'; unit++)
3277 + get_i2o_disk_name (name, unit);
3278 + if (check_device (name))
3280 + (*map)[num_hd + 0x80] = strdup (name);
3281 + assert ((*map)[num_hd + 0x80]);
3283 + /* If the device map file is opened, write the map. */
3285 + fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
3292 + /* This is for CCISS, its like the DAC960 - we have
3293 + /dev/cciss/<controller>d<logical drive>p<partition>
3295 + It currently supports up to 3 controllers, 10 logical volumes
3298 + Code gratuitously copied from DAC960 above.
3299 + Horms <horms@verge.net.au> 23rd July 2004
3302 + int controller, drive;
3304 + for (controller = 0; controller < 2; controller++)
3306 + for (drive = 0; drive < 9; drive++)
3310 + get_cciss_disk_name (name, controller, drive);
3311 + if (check_device (name))
3313 + (*map)[num_hd + 0x80] = strdup (name);
3314 + assert ((*map)[num_hd + 0x80]);
3316 + /* If the device map file is opened, write the map. */
3318 + fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
3326 + /* This is for Compaq Smart Array, its like the DAC960 - we have
3327 + /dev/ida/<controller>d<logical drive>p<partition>
3329 + It currently supports up to 3 controllers, 10 logical volumes
3332 + Code gratuitously copied from DAC960 above.
3333 + Piotr Roszatycki <dexter@debian.org>
3336 + int controller, drive;
3338 + for (controller = 0; controller < 2; controller++)
3340 + for (drive = 0; drive < 9; drive++)
3344 + get_ida_disk_name (name, controller, drive);
3345 + if (check_device (name))
3347 + (*map)[num_hd + 0x80] = strdup (name);
3348 + assert ((*map)[num_hd + 0x80]);
3350 + /* If the device map file is opened, write the map. */
3352 + fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
3359 #endif /* __linux__ */
3361 /* OK, close the device map file if opened. */
3362 @@ -844,6 +1095,7 @@
3364 char dev[PATH_MAX]; /* XXX */
3366 + off_t offset = (off_t) sector * (off_t) SECTOR_SIZE;
3368 if ((partition & 0x00FF00) != 0x00FF00)
3370 @@ -861,6 +1113,14 @@
3371 if (strcmp (dev + strlen(dev) - 5, "/disc") == 0)
3372 strcpy (dev + strlen(dev) - 5, "/part");
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");
3382 sprintf (dev + strlen(dev), "%d", ((partition >> 16) & 0xFF) + 1);
3384 /* Open the partition. */
3385 @@ -870,35 +1130,13 @@
3386 errnum = ERR_NO_PART;
3390 -#if defined(__linux__) && (!defined(__GLIBC__) || \
3391 - ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
3392 - /* Maybe libc doesn't have large file support. */
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);
3400 - offset = (loff_t) sector * (loff_t) SECTOR_SIZE;
3401 - if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
3403 - errnum = ERR_DEV_VALUES;
3409 - off_t offset = (off_t) sector * (off_t) SECTOR_SIZE;
3411 - if (lseek (fd, offset, SEEK_SET) != offset)
3413 - errnum = ERR_DEV_VALUES;
3418 + if (my_lseek(fd, offset, SEEK_SET) != offset)
3420 + errnum = ERR_DEV_VALUES;
3424 if (write (fd, buf, size * SECTOR_SIZE) != (size * SECTOR_SIZE))
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
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.
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.
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
3448 /* cs89x0.c: A Crystal Semiconductor CS89[02]0 driver for etherboot. */
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
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.
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.
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
3473 /* Copyright, 1988-1992, Russell Nelson, Crynwr Software
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
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;
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
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;
3498 +#define BOOTP_DATA_ADDR (&bootp_data)
3500 #ifndef NO_DHCP_SUPPORT
3501 #endif /* NO_DHCP_SUPPORT */
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',
3512 static const unsigned char dhcprequest[] =
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',
3521 #endif /* ! NO_DHCP_SUPPORT */
3523 "adcw %%ax,%0\n\t" /* add carry of previous iteration */
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)
3535 - end_of_rfc1533 = NULL;
3536 vendorext_isvalid = 0;
3538 if (grub_memcmp (p, rfc1533_cookie, 4))
3539 @@ -1021,7 +1025,7 @@
3541 else if (c == RFC1533_END)
3543 - end_of_rfc1533 = endp = p;
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
3552 const char *p) /* Packet */
3554 u32 status, to, nstype;
3556 + volatile u32 tx_status;
3558 /* Stop the transmitter */
3559 outl(TxOff, ioaddr + ChipCmd);
3562 to = currticks() + TX_TIMEOUT;
3564 - while ((((volatile u32) tx_status=txd.cmdsts) & OWN) && (currticks() < to))
3565 + while (((tx_status=txd.cmdsts) & OWN) && (currticks() < to))
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 @@
3576 + "pushl %%ebx\n\t" /* save %ebx */
3577 #ifdef ABSOLUTE_WITHOUT_ASTERISK
3579 + "lcall (%%edi)\n\t"
3582 + "lcall *(%%edi)\n\t"
3584 + "movl %%ebx, %1\n\t" /* capture what was in %ebx */
3585 + "popl %%ebx\n\t" /* restore %ebx */
3586 : "=a" (return_code),
3592 @@ -141,18 +144,21 @@
3596 + "pushl %%ebx\n\t" /* save %ebx */
3597 + "movl %3, %%ebx\n\t" /* put the value into ebx */
3598 #ifdef ABSOLUTE_WITHOUT_ASTERISK
3601 "lcall *(%%esi)\n\t"
3604 - "xor %%ah, %%ah\n"
3605 + "popl %%ebx\n\t" /* restore %ebx */
3606 + "xor %%ah, %%ah\n\t"
3610 : "1" (PCIBIOS_READ_CONFIG_BYTE),
3614 "S" (&pci_indirect));
3615 restore_flags(flags);
3616 @@ -168,18 +174,21 @@
3620 + "pushl %%ebx\n\t" /* save %ebx */
3621 + "movl %3, %%ebx\n\t" /* put the value into ebx */
3622 #ifdef ABSOLUTE_WITHOUT_ASTERISK
3625 "lcall *(%%esi)\n\t"
3628 - "xor %%ah, %%ah\n"
3629 + "popl %%ebx\n\t" /* restore %ebx */
3630 + "xor %%ah, %%ah\n\t"
3634 : "1" (PCIBIOS_READ_CONFIG_WORD),
3638 "S" (&pci_indirect));
3639 restore_flags(flags);
3640 @@ -195,18 +204,21 @@
3644 + "pushl %%ebx\n\t" /* save %ebx */
3645 + "movl %3, %%ebx\n\t" /* put the value into ebx */
3646 #ifdef ABSOLUTE_WITHOUT_ASTERISK
3649 "lcall *(%%esi)\n\t"
3652 - "xor %%ah, %%ah\n"
3653 + "popl %%ebx\n\t" /* restore %ebx */
3654 + "xor %%ah, %%ah\n\t"
3658 : "1" (PCIBIOS_READ_CONFIG_DWORD),
3662 "S" (&pci_indirect));
3663 restore_flags(flags);
3664 @@ -222,18 +234,21 @@
3666 save_flags(flags); cli();
3668 + "pushl %%ebx\n\t" /* save %ebx */
3669 + "movl %3, %%ebx\n\t" /* put the value into ebx */
3670 #ifdef ABSOLUTE_WITHOUT_ASTERISK
3673 "lcall *(%%esi)\n\t"
3676 - "xor %%ah, %%ah\n"
3677 + "popl %%ebx\n\t" /* restore %ebx */
3678 + "xor %%ah, %%ah\n\t"
3681 : "0" (PCIBIOS_WRITE_CONFIG_BYTE),
3686 "S" (&pci_indirect));
3687 restore_flags(flags);
3688 @@ -249,18 +264,21 @@
3690 save_flags(flags); cli();
3692 + "pushl %%ebx\n\t" /* save %ebx */
3693 + "movl %3, %%ebx\n\t" /* put the value into ebx */
3694 #ifdef ABSOLUTE_WITHOUT_ASTERISK
3697 "lcall *(%%esi)\n\t"
3700 - "xor %%ah, %%ah\n"
3701 + "popl %%ebx\n\t" /* restore %ebx */
3702 + "xor %%ah, %%ah\n\t"
3705 : "0" (PCIBIOS_WRITE_CONFIG_WORD),
3710 "S" (&pci_indirect));
3711 restore_flags(flags);
3712 @@ -276,18 +294,21 @@
3714 save_flags(flags); cli();
3716 + "pushl %%ebx\n\t" /* save %ebx */
3717 + "movl %3, %%ebx\n\t" /* put the value into ebx */
3718 #ifdef ABSOLUTE_WITHOUT_ASTERISK
3721 "lcall *(%%esi)\n\t"
3724 - "xor %%ah, %%ah\n"
3725 + "popl %%ebx\n\t" /* restore %ebx */
3726 + "xor %%ah, %%ah\n\t"
3729 : "0" (PCIBIOS_WRITE_CONFIG_DWORD),
3734 "S" (&pci_indirect));
3735 restore_flags(flags);
3736 @@ -308,20 +329,22 @@
3740 + "pushl %%ebx\n\t" /* save %ebx */
3741 #ifdef ABSOLUTE_WITHOUT_ASTERISK
3744 "lcall *(%%edi)\n\t"
3747 - "xor %%ah, %%ah\n"
3748 + "xor %%ah, %%ah\n\t"
3749 "1:\tshl $8, %%eax\n\t"
3751 + "movw %%bx, %%ax\n\t"
3752 + "popl %%ebx\n\t" /* restore %ebx */
3755 : "1" (PCIBIOS_PCI_BIOS_PRESENT),
3759 restore_flags(flags);
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
3766 const char *p) /* Packet */
3768 u32 status, to, nstype;
3770 + volatile u32 tx_status;
3772 /* Stop the transmitter */
3773 outl(TxDIS, ioaddr + cr);
3776 to = currticks() + TX_TIMEOUT;
3778 - while ((((volatile u32) tx_status=txd.cmdsts) & OWN) && (currticks() < to))
3779 + while (((tx_status=txd.cmdsts) & OWN) && (currticks() < to))
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
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
3792 -CLEANFILES = $(nodist_pkglib_DATA)
3793 +CLEANFILES = $(nodist_stage_DATA)
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
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 @@
3809 -3: /* use keyboard controller */
3811 + * try to switch gateA20 using PORT92, the "Fast A20 and Init"
3816 + /* skip the port92 code if it's unimplemented (read returns 0xff) */
3820 + /* set or clear bit1, the ALT_A20_GATE bit */
3828 + /* clear the INIT_NOW bit don't accidently reset the machine */
3832 +6: /* use keyboard controller */
3836 @@ -1661,9 +1683,12 @@
3842 andb $K_IBUF_FUL, %al
3846 movb $KB_OUTPUT_MASK, %al
3849 @@ -1684,6 +1709,8 @@
3855 andb $K_IBUF_FUL, %al
3858 @@ -1991,6 +2018,11 @@
3859 ENTRY(console_getkey)
3863 + call EXT_C(console_checkkey)
3867 call EXT_C(prot_to_real)
3870 @@ -2216,6 +2248,156 @@
3875 +/* graphics mode functions */
3876 +#ifdef SUPPORT_GRAPHICS
3881 +VARIABLE(cursorCount)
3883 +VARIABLE(cursorBuf)
3884 +.byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
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.
3894 +ENTRY(set_videomode)
3899 + movb 0x10(%esp), %cl
3901 + call EXT_C(prot_to_real)
3906 + int $0x10 /* Get Current Video mode */
3910 + int $0x10 /* Set Video mode */
3912 + DATA32 call EXT_C(real_to_prot)
3925 + * unsigned char * graphics_get_font()
3926 + * BIOS call "INT 10H Function 11h" to set font
3927 + * Call with %ah = 0x11
3929 +ENTRY(graphics_get_font)
3935 + call EXT_C(prot_to_real)
3939 + movb $6, %bh /* font 8x16 */
3944 + DATA32 call EXT_C(real_to_prot)
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)
3970 +ENTRY(graphics_set_palette)
3977 + movw $0x3c8, %bx /* address write mode register */
3979 + /* wait vertical retrace */
3982 +l1b: inb %dx, %al /* wait vertical active display */
3986 +l2b: inb %dx, %al /* wait vertical retrace */
3991 + movb 0x18(%esp), %al /* index */
3995 + movb 0x1c(%esp), %al /* red */
3998 + movb 0x20(%esp), %al /* green */
4001 + movb 0x24(%esp), %al /* blue */
4004 + movw 0x18(%esp), %bx
4006 + call EXT_C(prot_to_real)
4013 + DATA32 call EXT_C(real_to_prot)
4023 +#endif /* SUPPORT_GRAPHICS */
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
4031 return the error number. Otherwise, return 0. */
4033 biosdisk (int read, int drive, struct geometry *geometry,
4034 - int sector, int nsec, int segment)
4035 + unsigned int sector, int nsec, int segment)
4040 unsigned short blocks;
4041 unsigned long buffer;
4042 unsigned long long block;
4043 - } __attribute__ ((packed)) dap;
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
4049 + unsigned char dummy[16];
4050 + } __attribute__ ((packed)) *dap;
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
4055 + dap = (struct disk_address_packet *)0x580;
4057 /* XXX: Don't check the geometry by default, because some buggy
4058 BIOSes don't return the number of total sectors correctly,
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;
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
4073 - dap.buffer = segment << 16;
4074 + dap->buffer = segment << 16;
4076 - err = biosdisk_int13_extensions ((read + 0x42) << 8, drive, &dap);
4077 + err = biosdisk_int13_extensions ((read + 0x42) << 8, drive, dap);
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
4085 /* boot.c - load and bootstrap a kernel */
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.
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
4094 lh = (struct linux_kernel_header *) buffer;
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)
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;
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++);
4116 + char *src = skip_to (0, arg);
4117 + char *dest = linux_data_tmp_addr + LINUX_CL_0202_PRM_OFFSET;
4119 + while (dest < linux_data_tmp_addr + LINUX_CL_0202_PRM_END_OFFSET && *src)
4120 + *(dest++) = *(src++);
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;
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;
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
4145 +/* boot.c - load and bootstrap a kernel */
4147 + * GRUB -- GRand Unified Bootloader
4148 + * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
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.
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.
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.
4166 +#include "shared.h"
4168 +#include "freebsd.h"
4169 +#include "imgact_aout.h"
4170 +#include "i386-elf.h"
4172 +static int cur_addr;
4173 +entry_func entry_addr;
4174 +static struct mod_list mll[99];
4175 +static int linux_mem_size;
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.
4184 +load_image (char *kernel, char *arg, kernel_t suggested_type,
4185 + unsigned long load_flags)
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;
4195 + struct multiboot_header *mb;
4196 + struct exec *aout;
4200 + /* presuming that MULTIBOOT_SEARCH is large enough to encompass an
4201 + executable header */
4202 + unsigned char buffer[MULTIBOOT_SEARCH];
4204 + /* sets the header pointer to point to the beginning of the
4205 + buffer by default */
4206 + pu.aout = (struct exec *) buffer;
4208 + if (!grub_open (kernel))
4209 + return KERNEL_TYPE_NONE;
4211 + if (!(len = grub_read (buffer, MULTIBOOT_SEARCH)) || len < 32)
4216 + errnum = ERR_EXEC_FORMAT;
4218 + return KERNEL_TYPE_NONE;
4221 + for (i = 0; i < len; i++)
4223 + if (MULTIBOOT_FOUND ((int) (buffer + i), len - i))
4225 + flags = ((struct multiboot_header *) (buffer + i))->flags;
4226 + if (flags & MULTIBOOT_UNSUPPORTED)
4229 + errnum = ERR_BOOT_FEATURES;
4230 + return KERNEL_TYPE_NONE;
4232 + type = KERNEL_TYPE_MULTIBOOT;
4233 + str2 = "Multiboot";
4238 + /* Use BUFFER as a linux kernel header, if the image is Linux zImage
4240 + lh = (struct linux_kernel_header *) buffer;
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))))
4250 + if (type == KERNEL_TYPE_MULTIBOOT)
4251 + entry_addr = (entry_func) pu.elf->e_entry;
4253 + entry_addr = (entry_func) (pu.elf->e_entry & 0xFFFFFF);
4255 + if (entry_addr < (entry_func) 0x100000)
4256 + errnum = ERR_BELOW_1MB;
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))
4263 + errnum = ERR_EXEC_FORMAT;
4266 + if (type == KERNEL_TYPE_NONE)
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)
4273 + type = suggested_type;
4278 + type = KERNEL_TYPE_FREEBSD;
4282 + else if (flags & MULTIBOOT_AOUT_KLUDGE)
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));
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;
4294 + text_len = pu.mb->load_end_addr - cur_addr;
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;
4301 + bss_len = pu.mb->bss_end_addr - pu.mb->load_end_addr;
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;
4309 + if (cur_addr < 0x100000)
4310 + errnum = ERR_BELOW_1MB;
4312 + pu.aout = (struct exec *) buffer;
4316 + else if (len > sizeof (struct exec) && !N_BADMAG ((*(pu.aout))))
4318 + entry_addr = (entry_func) pu.aout->a_entry;
4320 + if (type == KERNEL_TYPE_NONE)
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.
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
4333 + entry_addr = (entry_func) ((int) entry_addr & 0xFFFFFF);
4335 + if (buffer[0] == 0xb && buffer[1] == 1)
4337 + type = KERNEL_TYPE_FREEBSD;
4338 + cur_addr = (int) entry_addr;
4343 + type = KERNEL_TYPE_NETBSD;
4344 + cur_addr = (int) entry_addr & 0xF00000;
4345 + if (N_GETMAGIC ((*(pu.aout))) != NMAGIC)
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;
4357 + if (cur_addr < 0x100000)
4358 + errnum = ERR_BELOW_1MB;
4363 + else if (lh->boot_flag == BOOTSEC_SIGNATURE
4364 + && lh->setup_sects <= LINUX_MAX_SETUP_SECTS)
4366 + int big_linux = 0;
4367 + int setup_sects = lh->setup_sects;
4369 + if (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0200)
4371 + big_linux = (lh->loadflags & LINUX_FLAG_BIG_KERNEL);
4372 + lh->type_of_loader = LINUX_BOOT_LOADER_TYPE;
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;
4381 + if (lh->version >= 0x0201)
4383 + lh->heap_end_ptr = LINUX_HEAP_END_OFFSET;
4384 + lh->loadflags |= LINUX_FLAG_CAN_USE_HEAP;
4387 + if (lh->version >= 0x0202)
4388 + lh->cmd_line_ptr = linux_data_real_addr + LINUX_CL_OFFSET;
4391 + lh->cl_magic = LINUX_CL_MAGIC;
4392 + lh->cl_offset = LINUX_CL_OFFSET;
4393 + lh->setup_move_size = LINUX_SETUP_MOVE_SIZE;
4398 + /* Your kernel is quite old... */
4399 + lh->cl_magic = LINUX_CL_MAGIC;
4400 + lh->cl_offset = LINUX_CL_OFFSET;
4402 + setup_sects = LINUX_DEFAULT_SETUP_SECTS;
4404 + linux_data_real_addr = (char *) LINUX_OLD_REAL_MODE_ADDR;
4407 + /* If SETUP_SECTS is not set, set it to the default (4). */
4408 + if (! setup_sects)
4409 + setup_sects = LINUX_DEFAULT_SETUP_SECTS;
4411 + data_len = setup_sects << 9;
4412 + text_len = filemax - data_len - SECTOR_SIZE;
4414 + linux_data_tmp_addr = (char *) LINUX_BZIMAGE_ADDR + text_len;
4417 + && text_len > linux_data_real_addr - (char *) LINUX_ZIMAGE_ADDR)
4419 + grub_printf (" linux 'zImage' kernel too big, try 'make bzImage'\n");
4420 + errnum = ERR_WONT_FIT;
4422 + else if (linux_data_real_addr + LINUX_SETUP_MOVE_SIZE
4423 + > RAW_ADDR ((char *) (mbi.mem_lower << 10)))
4424 + errnum = ERR_WONT_FIT;
4427 + grub_printf (" [Linux-%s, setup=0x%x, size=0x%x]\n",
4428 + (big_linux ? "bzImage" : "zImage"), data_len, text_len);
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 */
4438 + /* Find the substring "vga=". */
4439 + vga = grub_strstr (arg, "vga=");
4442 + char *value = vga + 4;
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))
4456 + /* ERRNUM is already set inside the function
4457 + safe_parse_maxint. */
4459 + return KERNEL_TYPE_NONE;
4462 + lh->vid_mode = vid_mode;
4466 + /* Check the mem= option to limit memory used for initrd. */
4470 + mem = grub_strstr (arg, "mem=");
4473 + char *value = mem + 4;
4475 + safe_parse_maxint (&value, &linux_mem_size);
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;
4490 + switch (grub_tolower (*value))
4502 + /* Check an overflow. */
4503 + if (linux_mem_size > (MAXINT >> shift))
4504 + linux_mem_size = LINUX_INITRD_MAX_ADDRESS;
4506 + linux_mem_size <<= shift;
4511 + linux_mem_size = 0;
4512 + errnum = ERR_NONE;
4517 + linux_mem_size = 0;
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);
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);
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),
4537 + (64 - setup_sects - 1) << 9);
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. */
4548 + char *src = skip_to (0, arg);
4549 + char *dest = linux_data_tmp_addr + LINUX_CL_OFFSET;
4551 + while (dest < linux_data_tmp_addr + LINUX_CL_END_OFFSET && *src)
4552 + *(dest++) = *(src++);
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)
4580 + dest = convert_to_ascii (dest, 'u', (extended_memory + 0x400));
4587 + /* offset into file */
4588 + grub_seek (data_len + SECTOR_SIZE);
4590 + cur_addr = (int) linux_data_tmp_addr + LINUX_SETUP_MOVE_SIZE;
4591 + grub_read ((char *) LINUX_BZIMAGE_ADDR, text_len);
4593 + if (errnum == ERR_NONE)
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)))
4602 + errnum = ERR_EXEC_FORMAT;
4603 + return KERNEL_TYPE_NONE;
4607 + linux_text_len = text_len;
4609 + return big_linux ? KERNEL_TYPE_BIG_LINUX : KERNEL_TYPE_LINUX;
4613 + else /* no recognizable format */
4614 + errnum = ERR_EXEC_FORMAT;
4616 + /* return if error */
4620 + return KERNEL_TYPE_NONE;
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;
4634 + printf (" [%s-%s", str2, str);
4638 + if (exec_type) /* can be loaded like a.out */
4640 + if (flags & MULTIBOOT_AOUT_KLUDGE)
4641 + str = "-and-data";
4643 + printf (", loadaddr=0x%x, text%s=0x%x", cur_addr, str, text_len);
4645 + /* read text, then read data */
4646 + if (grub_read ((char *) RAW_ADDR (cur_addr), text_len) == text_len)
4648 + cur_addr += text_len;
4650 + if (!(flags & MULTIBOOT_AOUT_KLUDGE))
4652 + /* we have to align to a 4K boundary */
4654 + cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
4658 + printf (", data=0x%x", data_len);
4660 + if ((grub_read ((char *) RAW_ADDR (cur_addr), data_len)
4663 + errnum = ERR_EXEC_FORMAT;
4664 + cur_addr += data_len;
4669 + memset ((char *) RAW_ADDR (cur_addr), 0, bss_len);
4670 + cur_addr += bss_len;
4672 + printf (", bss=0x%x", bss_len);
4676 + errnum = ERR_EXEC_FORMAT;
4678 + if (!errnum && pu.aout->a_syms
4679 + && pu.aout->a_syms < (filemax - filepos))
4681 + int symtab_err, orig_addr = cur_addr;
4683 + /* we should align to a 4K boundary here for good measure */
4685 + cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
4687 + mbi.syms.a.addr = cur_addr;
4689 + *((int *) RAW_ADDR (cur_addr)) = pu.aout->a_syms;
4690 + cur_addr += sizeof (int);
4692 + printf (", symtab=0x%x", pu.aout->a_syms);
4694 + if (grub_read ((char *) RAW_ADDR (cur_addr), pu.aout->a_syms)
4695 + == pu.aout->a_syms)
4697 + cur_addr += pu.aout->a_syms;
4698 + mbi.syms.a.tabsize = pu.aout->a_syms;
4700 + if (grub_read ((char *) &i, sizeof (int)) == sizeof (int))
4702 + *((int *) RAW_ADDR (cur_addr)) = i;
4703 + cur_addr += sizeof (int);
4705 + mbi.syms.a.strsize = i;
4707 + i -= sizeof (int);
4709 + printf (", strtab=0x%x", i);
4711 + symtab_err = (grub_read ((char *) RAW_ADDR (cur_addr), i)
4724 + cur_addr = orig_addr;
4725 + mbi.syms.a.tabsize = 0;
4726 + mbi.syms.a.strsize = 0;
4727 + mbi.syms.a.addr = 0;
4730 + mbi.flags |= MB_INFO_AOUT_SYMS;
4734 + /* ELF executable */
4736 + unsigned loaded = 0, memaddr, memsiz, filesiz;
4739 + /* reset this to zero for now */
4742 + /* scan for program segments */
4743 + for (i = 0; i < pu.elf->e_phnum; i++)
4745 + phdr = (Elf32_Phdr *)
4746 + (pu.elf->e_phoff + ((int) buffer)
4747 + + (pu.elf->e_phentsize * i));
4748 + if (phdr->p_type == PT_LOAD)
4750 + /* offset into file */
4751 + grub_seek (phdr->p_offset);
4752 + filesiz = phdr->p_filesz;
4754 + if (type == KERNEL_TYPE_FREEBSD || type == KERNEL_TYPE_NETBSD)
4755 + memaddr = RAW_ADDR (phdr->p_paddr & 0xFFFFFF);
4757 + memaddr = RAW_ADDR (phdr->p_paddr);
4759 + memsiz = phdr->p_memsz;
4760 + if (memaddr < RAW_ADDR (0x100000))
4761 + errnum = ERR_BELOW_1MB;
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);
4771 + /* make sure we only load what we're supposed to! */
4772 + if (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 */
4782 + /* load the segment */
4783 + if (memcheck (memaddr, memsiz)
4784 + && grub_read ((char *) memaddr, filesiz) == filesiz)
4786 + if (memsiz > filesiz)
4787 + memset ((char *) (memaddr + filesiz), 0, memsiz - filesiz);
4797 + errnum = ERR_EXEC_FORMAT;
4800 + /* Load ELF symbols. */
4801 + Elf32_Shdr *shdr = NULL;
4802 + int tab_size, sec_size;
4803 + int symtab_err = 0;
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;
4809 + /* We should align to a 4K boundary here for good measure. */
4811 + cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
4813 + tab_size = pu.elf->e_shentsize * pu.elf->e_shnum;
4815 + grub_seek (pu.elf->e_shoff);
4816 + if (grub_read ((char *) RAW_ADDR (cur_addr), tab_size)
4819 + mbi.syms.e.addr = cur_addr;
4820 + shdr = (Elf32_Shdr *) mbi.syms.e.addr;
4821 + cur_addr += tab_size;
4823 + printf (", shtab=0x%x", cur_addr);
4825 + for (i = 0; i < mbi.syms.e.num; i++)
4827 + /* This section is a loaded section,
4828 + so we don't care. */
4829 + if (shdr[i].sh_addr != 0)
4832 + /* This section is empty, so we don't care. */
4833 + if (shdr[i].sh_size == 0)
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);
4840 + grub_seek (shdr[i].sh_offset);
4842 + sec_size = shdr[i].sh_size;
4844 + if (! (memcheck (cur_addr, sec_size)
4845 + && (grub_read ((char *) RAW_ADDR (cur_addr),
4853 + shdr[i].sh_addr = cur_addr;
4854 + cur_addr += sec_size;
4860 + if (mbi.syms.e.addr < RAW_ADDR(0x10000))
4866 + mbi.syms.e.num = 0;
4867 + mbi.syms.e.size = 0;
4868 + mbi.syms.e.addr = 0;
4869 + mbi.syms.e.shndx = 0;
4873 + mbi.flags |= MB_INFO_ELF_SHDR;
4880 + grub_printf (", entry=0x%x]\n", (unsigned) entry_addr);
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;
4890 + type = KERNEL_TYPE_NONE;
4895 + /* Sanity check. */
4896 + if (suggested_type != KERNEL_TYPE_NONE && suggested_type != type)
4898 + errnum = ERR_EXEC_FORMAT;
4899 + return KERNEL_TYPE_NONE;
4906 +load_module (char *module, char *arg)
4910 + /* if we are supposed to load on 4K boundaries */
4911 + cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
4913 + if (!grub_open (module))
4916 + len = grub_read ((char *) cur_addr, -1);
4923 + printf (" [Multiboot-module @ 0x%x, 0x%x bytes]\n", cur_addr, len);
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;
4929 + mll[mbi.mods_count].cmdline = (int) arg;
4930 + mll[mbi.mods_count].mod_start = cur_addr;
4932 + mll[mbi.mods_count].mod_end = cur_addr;
4933 + mll[mbi.mods_count].pad = 0;
4935 + /* increment number of modules included */
4943 +load_initrd (char *initrd)
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);
4951 +#ifndef NO_DECOMPRESSION
4952 + no_decompression = 1;
4955 + if (! grub_open (initrd))
4958 + len = grub_read ((char *) cur_addr, -1);
4965 + if (linux_mem_size)
4966 + moveto = linux_mem_size;
4968 + moveto = (mbi.mem_upper + 0x400) << 10;
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;
4976 + /* XXX: Linux 2.3.xx has a bug in the memory range check, so avoid
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);
4983 + printf (" [Linux-initrd @ 0x%x, 0x%x bytes]\n", moveto, len);
4985 + /* FIXME: Should check if the kernel supports INITRD. */
4986 + lh->ramdisk_image = RAW_ADDR (moveto);
4987 + lh->ramdisk_size = len;
4993 +#ifndef NO_DECOMPRESSION
4994 + no_decompression = 0;
5002 +/* Dummy function to fake the *BSD boot. */
5004 +bsd_boot_entry (int flags, int bootdev, int sym_start, int sym_end,
5005 + int mem_upper, int mem_lower)
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'
5021 +bsd_boot (kernel_t type, int bootdev, char *arg)
5025 + struct bootinfo bi;
5028 + entry_addr = (entry_func) bsd_boot_entry;
5033 + while (*(++arg) && *arg != ' ');
5039 + while (*str && *str != ' ')
5042 + clval |= RB_CDROM;
5044 + clval |= RB_ASKNAME;
5048 + clval |= RB_CONFIG;
5052 + clval |= RB_MULTIPLE;
5056 + clval |= RB_SERIAL;
5060 + clval |= RB_DFLTROOT;
5062 + clval |= RB_SINGLE;
5064 + clval |= RB_VERBOSE;
5072 + if (type == KERNEL_TYPE_FREEBSD)
5074 + clval |= RB_BOOTINFO;
5076 + bi.bi_version = BOOTINFO_VERSION;
5079 + while ((--arg) > (char *) MB_CMDLINE_BUF && *arg != '/');
5081 + bi.bi_kernelname = arg + 1;
5083 + bi.bi_kernelname = 0;
5085 + bi.bi_nfs_diskless = 0;
5086 + bi.bi_n_bios_used = 0; /* this field is apparently unused */
5088 + for (i = 0; i < N_BIOS_GEOM; i++)
5090 + struct geometry geom;
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));
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;
5108 + if (mbi.flags & MB_INFO_AOUT_SYMS)
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;
5115 + else if (mbi.flags & MB_INFO_ELF_SHDR)
5117 + /* FIXME: Should check if a symbol table exists and, if exists,
5118 + pass the table to BI. */
5124 + bi.bi_esymtab = 0;
5127 + /* call entry point */
5128 + (*entry_addr) (clval, bootdev, 0, 0, 0, ((int) (&bi)));
5133 + * We now pass the various bootstrap parameters to the loaded
5134 + * image via the argument list.
5136 + * This is the official list:
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)
5148 + * ...in actuality, we just pass the parameters used by the kernel.
5151 + /* call entry point */
5152 + unsigned long end_mark;
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);
5158 + /* FIXME: it should be mbi.syms.e.size. */
5161 + (*entry_addr) (clval, bootdev, 0, end_mark,
5162 + extended_memory, mbi.mem_lower);
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 @@
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.
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.
5184 + * The documentation in GCC actually uses the words "all hell will break
5185 + * loose" to describe this scenario.
5187 + * Also, "start_sector" was also used uninitialized, but gcc doesn't warn
5188 + * about it (possibly because of the scoping madness?)
5196 +} blocklist_func_context = {
5197 + .start_sector = 0,
5203 +/* Collect contiguous blocks into one entry as many as possible,
5204 + and print the blocklist notation on the screen. */
5206 +blocklist_read_helper (int sector, int offset, int length)
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;
5213 + if (*num_sectors > 0)
5215 + if (*start_sector + *num_sectors == sector
5216 + && offset == 0 && *last_length == SECTOR_SIZE)
5219 + *last_length = length;
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,
5233 + grub_printf ("%s%d[0-%d]", *num_entries ? "," : "",
5234 + *start_sector - part_start, *last_length);
5242 + grub_printf("%s%d[%d-%d]", *num_entries ? "," : "",
5243 + sector-part_start, offset, offset+length);
5248 + *start_sector = sector;
5250 + *last_length = length;
5256 blocklist_func (char *arg, int flags)
5258 char *dummy = (char *) RAW_ADDR (0x100000);
5260 - int num_sectors = 0;
5261 - int num_entries = 0;
5262 - int last_length = 0;
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;
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)
5273 - if (num_sectors > 0)
5275 - if (start_sector + num_sectors == sector
5276 - && offset == 0 && last_length == SECTOR_SIZE)
5279 - last_length = length;
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,
5293 - grub_printf ("%s%d[0-%d]", num_entries ? "," : "",
5294 - start_sector - part_start, last_length);
5302 - grub_printf("%s%d[%d-%d]", num_entries ? "," : "",
5303 - sector-part_start, offset, offset+length);
5308 - start_sector = sector;
5310 - last_length = length;
5314 /* Open the file. */
5315 if (! grub_open (arg))
5317 @@ -206,15 +241,15 @@
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))
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);
5337 @@ -852,6 +887,138 @@
5339 #endif /* SUPPORT_NETBOOT */
5341 +static int terminal_func (char *arg, int flags);
5343 +#ifdef SUPPORT_GRAPHICS
5345 +static int splashimage_func(char *arg, int flags) {
5346 + char splashimage[64];
5349 + /* filename can only be 64 characters due to our buffer size */
5350 + if (strlen(arg) > 63)
5352 + if (flags == BUILTIN_CMDLINE) {
5353 + if (!grub_open(arg))
5358 + strcpy(splashimage, arg);
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;
5368 + graphics_set_splash(splashimage);
5370 + if (flags == BUILTIN_CMDLINE && graphics_inited) {
5376 + /* FIXME: should we be explicitly switching the terminal as a
5377 + * side effect here? */
5378 + terminal_func("graphics", flags);
5383 +static struct builtin builtin_splashimage =
5387 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
5388 + "splashimage FILE",
5389 + "Load FILE as the background image when in graphics mode."
5395 +foreground_func(char *arg, int flags)
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;
5402 + foreground = (r << 16) | (g << 8) | b;
5403 + if (graphics_inited)
5404 + graphics_set_palette(15, r, g, b);
5412 +static struct builtin builtin_foreground =
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."
5425 +background_func(char *arg, int flags)
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;
5432 + background = (r << 16) | (g << 8) | b;
5433 + if (graphics_inited)
5434 + graphics_set_palette(0, r, g, b);
5441 +static struct builtin builtin_background =
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."
5451 +#endif /* SUPPORT_GRAPHICS */
5458 + if (current_term->cls)
5459 + current_term->cls();
5464 +static struct builtin builtin_clear =
5468 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
5470 + "Clear the screen"
5476 @@ -1233,14 +1400,15 @@
5477 for (drive = 0x80; drive < 0x88; drive++)
5479 unsigned long part = 0xFFFFFF;
5480 - unsigned long start, len, offset, ext_offset;
5482 + unsigned long start, len, offset, ext_offset, gpt_offset;
5483 + int type, entry, gpt_count, gpt_size;
5484 char buf[SECTOR_SIZE];
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))
5493 if (type != PC_SLICE_TYPE_NONE
5494 && ! IS_PC_SLICE_TYPE_BSD (type)
5495 @@ -1740,6 +1908,77 @@
5503 + char *stage2_first_buffer;
5504 +} install_func_context = {
5505 + .saved_sector = 0,
5508 + .stage2_first_buffer = NULL,
5511 +/* Save the first sector of Stage2 in STAGE2_SECT. */
5512 +/* Formerly disk_read_savesect_func with local scope inside install_func */
5514 +install_savesect_helper(int sector, int offset, int length)
5517 + printf ("[%d]", sector);
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;
5525 + install_func_context.saved_sector = sector;
5528 +/* Write SECTOR to INSTALLLIST, and update INSTALLADDR and INSTALLSECT. */
5529 +/* Formerly disk_read_blocklist_func with local scope inside install_func */
5531 +install_blocklist_helper (int sector, int offset, int length)
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;
5540 + printf("[%d]", sector);
5542 + if (offset != 0 || last_length != SECTOR_SIZE)
5544 + /* We found a non-sector-aligned data block. */
5545 + errnum = ERR_UNALIGNED;
5549 + last_length = length;
5551 + if (*((unsigned long *) (*installlist - 4))
5552 + + *((unsigned short *) *installlist) != sector
5553 + || *installlist == (int) *stage2_first_buffer + SECTOR_SIZE + 4)
5555 + *installlist -= 8;
5557 + if (*((unsigned long *) (*installlist - 8)))
5558 + errnum = ERR_WONT_FIT;
5561 + *((unsigned short *) (*installlist + 2)) = (*installaddr >> 4);
5562 + *((unsigned long *) (*installlist - 4)) = sector;
5566 + *((unsigned short *) *installlist) += 1;
5567 + *installaddr += 512;
5571 install_func (char *arg, int flags)
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;
5591 struct geometry dest_geom, src_geom;
5593 + int *saved_sector = &install_func_context.saved_sector;
5594 int stage2_first_sector, stage2_second_sector;
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 @@
5604 /* If LBA is forced? */
5605 int is_force_lba = 0;
5606 - /* Was the last sector full? */
5607 - int last_length = SECTOR_SIZE;
5610 + *stage2_first_buffer = old_sect + SECTOR_SIZE;
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 */
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);
5620 - /* Save the first sector of Stage2 in STAGE2_SECT. */
5621 - auto void disk_read_savesect_func (int sector, int offset, int length)
5624 - printf ("[%d]", sector);
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;
5632 - saved_sector = sector;
5635 - /* Write SECTOR to INSTALLLIST, and update INSTALLADDR and
5637 - auto void disk_read_blocklist_func (int sector, int offset, int length)
5640 - printf("[%d]", sector);
5642 - if (offset != 0 || last_length != SECTOR_SIZE)
5644 - /* We found a non-sector-aligned data block. */
5645 - errnum = ERR_UNALIGNED;
5649 - last_length = length;
5651 - if (*((unsigned long *) (installlist - 4))
5652 - + *((unsigned short *) installlist) != sector
5653 - || installlist == (int) stage2_first_buffer + SECTOR_SIZE + 4)
5657 - if (*((unsigned long *) (installlist - 8)))
5658 - errnum = ERR_WONT_FIT;
5661 - *((unsigned short *) (installlist + 2)) = (installaddr >> 4);
5662 - *((unsigned long *) (installlist - 4)) = sector;
5666 - *((unsigned short *) installlist) += 1;
5667 - installaddr += 512;
5670 /* First, check the GNU-style long option. */
5672 @@ -1862,10 +2052,10 @@
5673 addr = skip_to (0, file);
5675 /* Get the installation address. */
5676 - if (! safe_parse_maxint (&addr, &installaddr))
5677 + if (! safe_parse_maxint (&addr, installaddr))
5679 /* ADDR is not specified. */
5685 @@ -1961,17 +2151,17 @@
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)
5695 - stage2_first_sector = saved_sector;
5696 + stage2_first_sector = *saved_sector;
5698 /* Read the second sector of Stage 2. */
5699 if (grub_read (stage2_second_buffer, SECTOR_SIZE) != SECTOR_SIZE)
5702 - stage2_second_sector = saved_sector;
5703 + stage2_second_sector = *saved_sector;
5705 /* Check for the version of Stage 2. */
5706 if (*((short *) (stage2_second_buffer + STAGE2_VER_MAJ_OFFS))
5707 @@ -1987,27 +2177,27 @@
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)
5716 - installaddr = 0x8000;
5717 + *installaddr = 0x8000;
5720 - installaddr = 0x2000;
5721 + *installaddr = 0x2000;
5724 *((unsigned long *) (stage1_buffer + STAGE1_STAGE2_SECTOR))
5725 = stage2_first_sector;
5726 *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_ADDRESS))
5729 *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_SEGMENT))
5730 - = installaddr >> 4;
5731 + = *installaddr >> 4;
5733 - i = (int) stage2_first_buffer + SECTOR_SIZE - 4;
5734 + i = (int) *stage2_first_buffer + SECTOR_SIZE - 4;
5735 while (*((unsigned long *) i))
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 @@
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;
5751 /* Read the whole of Stage2 except for the first sector. */
5752 grub_seek (SECTOR_SIZE);
5754 - disk_read_hook = disk_read_blocklist_func;
5755 + disk_read_hook = install_blocklist_helper;
5756 if (! grub_read (dummy, -1))
5759 @@ -2110,7 +2300,7 @@
5760 /* Skip the first sector. */
5761 grub_seek (SECTOR_SIZE);
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)
5768 @@ -2180,7 +2370,7 @@
5770 #endif /* GRUB_UTIL */
5772 - if (! devwrite (saved_sector - part_start, 1, stage2_buffer))
5773 + if (! devwrite (*saved_sector - part_start, 1, stage2_buffer))
5777 @@ -2202,7 +2392,7 @@
5781 - if (fwrite (stage2_first_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE)
5782 + if (fwrite (*stage2_first_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE)
5786 @@ -2229,7 +2419,7 @@
5789 if (! devwrite (stage2_first_sector - src_part_start, 1,
5790 - stage2_first_buffer))
5791 + *stage2_first_buffer))
5794 if (! devwrite (stage2_second_sector - src_part_start, 1,
5795 @@ -2815,8 +3005,8 @@
5798 unsigned long part = 0xFFFFFF;
5799 - unsigned long start, len, offset, ext_offset;
5801 + unsigned long start, len, offset, ext_offset, gpt_offset;
5802 + int entry, type, gpt_count, gpt_size;
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))
5813 + /* The partition may not be a GPT partition. */
5814 + if (gpt_offset != 0)
5816 + errnum = ERR_BAD_ARGUMENT;
5820 if (part == current_partition)
5823 @@ -3830,15 +4027,15 @@
5826 grub_sprintf (tmp, ",%d", (partition >> 16) & 0xFF);
5827 - grub_strncat (device, tmp, 256);
5828 + grub_strncat (device, tmp, sizeof (device));
5830 if ((partition & 0x00FF00) != 0x00FF00)
5833 grub_sprintf (tmp, ",%c", 'a' + ((partition >> 8) & 0xFF));
5834 - grub_strncat (device, tmp, 256);
5835 + grub_strncat (device, tmp, sizeof (device));
5837 - grub_strncat (device, ")", 256);
5838 + grub_strncat (device, ")", sizeof (device));
5841 int embed_stage1_5 (char *stage1_5, int drive, int partition)
5842 @@ -4085,7 +4282,7 @@
5846 -#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
5847 +#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS)
5850 terminal_func (char *arg, int flags)
5851 @@ -4244,17 +4441,21 @@
5853 current_term = term_table + default_term;
5854 current_term->flags = term_flags;
5860 - /* 24 would be a good default value. */
5863 + max_lines = current_term->max_lines;
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);
5878 @@ -4264,7 +4465,7 @@
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."
5891 -#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
5892 +#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */
5895 #ifdef SUPPORT_SERIAL
5896 @@ -4795,6 +4996,9 @@
5897 /* The table of builtin commands. Sorted in dictionary order. */
5898 struct builtin *builtin_table[] =
5900 +#ifdef SUPPORT_GRAPHICS
5901 + &builtin_background,
5905 #ifdef SUPPORT_NETBOOT
5906 @@ -4802,6 +5006,7 @@
5907 #endif /* SUPPORT_NETBOOT */
5909 &builtin_chainloader,
5913 &builtin_configfile,
5914 @@ -4821,6 +5026,9 @@
5918 +#ifdef SUPPORT_GRAPHICS
5919 + &builtin_foreground,
5924 @@ -4864,9 +5072,12 @@
5925 #endif /* SUPPORT_SERIAL */
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)
5934 -#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
5935 +#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */
5936 #ifdef SUPPORT_SERIAL
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
5943 +/* builtins.c - the GRUB builtin commands */
5945 + * GRUB -- GRand Unified Bootloader
5946 + * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
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.
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.
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.
5963 +/* Include stdio.h before shared.h, because we can't define
5964 + WITHOUT_LIBC_STUBS here. */
5966 +# include <stdio.h>
5969 +#include <shared.h>
5970 +#include <filesys.h>
5973 +#ifdef SUPPORT_NETBOOT
5975 +# include <etherboot.h>
5978 +#ifdef SUPPORT_SERIAL
5979 +# include <serial.h>
5980 +# include <terminfo.h>
5984 +# include <device.h>
5985 +#else /* ! GRUB_UTIL */
5987 +# include <smp-imps.h>
5988 +#endif /* ! GRUB_UTIL */
5990 +#ifdef USE_MD5_PASSWORDS
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. */
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. */
6012 +/* The password type. */
6013 +password_t password_type;
6014 +/* The flag for indicating that the user is authoritative. */
6017 +int grub_timeout = -1;
6018 +/* Whether to show the menu or not. */
6020 +/* The BIOS drive map. */
6021 +static unsigned short bios_drive_map[DRIVE_MAP_SIZE + 1];
6023 +/* Prototypes for allowing straightfoward calling of builtins functions
6024 + inside other functions. */
6025 +static int configfile_func (char *arg, int flags);
6027 +/* Initialize the data for builtins. */
6029 +init_builtins (void)
6031 + kernel_type = KERNEL_TYPE_NONE;
6032 + /* BSD and chainloading evil hacks! */
6033 + bootdev = set_bootdev (0);
6034 + mb_cmdline = (char *) MB_CMDLINE_BUF;
6037 +/* Initialize the data for the configuration file. */
6041 + default_entry = 0;
6043 + fallback_entryno = -1;
6044 + fallback_entries[0] = -1;
6045 + grub_timeout = -1;
6048 +/* Check a password for correctness. Returns 0 if password was
6049 + correct, and a value != 0 for error, similarly to strcmp. */
6051 +check_password (char *entered, char* expected, password_t type)
6055 + case PASSWORD_PLAIN:
6056 + return strcmp (entered, expected);
6058 +#ifdef USE_MD5_PASSWORDS
6059 + case PASSWORD_MD5:
6060 + return check_md5_password (entered, expected);
6063 + /* unsupported password type: be secure */
6068 +/* Print which sector is read when loading a file. */
6070 +disk_read_print_func (int sector, int offset, int length)
6072 + grub_printf ("[%d,%d,%d]", sector, offset, length);
6078 +blocklist_func (char *arg, int flags)
6080 + char *dummy = (char *) RAW_ADDR (0x100000);
6082 + int num_sectors = 0;
6083 + int num_entries = 0;
6084 + int last_length = 0;
6086 + auto void disk_read_blocklist_func (int sector, int offset, int length);
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)
6092 + if (num_sectors > 0)
6094 + if (start_sector + num_sectors == sector
6095 + && offset == 0 && last_length == SECTOR_SIZE)
6098 + last_length = length;
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,
6112 + grub_printf ("%s%d[0-%d]", num_entries ? "," : "",
6113 + start_sector - part_start, last_length);
6121 + grub_printf("%s%d[%d-%d]", num_entries ? "," : "",
6122 + sector-part_start, offset, offset+length);
6127 + start_sector = sector;
6129 + last_length = length;
6133 + /* Open the file. */
6134 + if (! grub_open (arg))
6137 + /* Print the device name. */
6138 + grub_printf ("(%cd%d",
6139 + (current_drive & 0x80) ? 'h' : 'f',
6140 + current_drive & ~0x80);
6142 + if ((current_partition & 0xFF0000) != 0xFF0000)
6143 + grub_printf (",%d", (current_partition >> 16) & 0xFF);
6145 + if ((current_partition & 0x00FF00) != 0x00FF00)
6146 + grub_printf (",%c", 'a' + ((current_partition >> 8) & 0xFF));
6148 + grub_printf (")");
6150 + /* Read in the whole file to DUMMY. */
6151 + disk_read_hook = disk_read_blocklist_func;
6152 + if (! grub_read (dummy, -1))
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);
6161 + grub_printf ("\n");
6164 + disk_read_hook = 0;
6169 +static struct builtin builtin_blocklist =
6173 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
6175 + "Print the blocklist notation of the file FILE."
6180 +boot_func (char *arg, int flags)
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 ();
6188 +#ifdef SUPPORT_NETBOOT
6189 + /* Shut down the networking. */
6193 + switch (kernel_type)
6195 + case KERNEL_TYPE_FREEBSD:
6196 + case KERNEL_TYPE_NETBSD:
6198 + bsd_boot (kernel_type, bootdev, (char *) mbi.cmdline);
6201 + case KERNEL_TYPE_LINUX:
6206 + case KERNEL_TYPE_BIG_LINUX:
6208 + big_linux_boot ();
6211 + case KERNEL_TYPE_CHAINLOADER:
6214 + /* Check if we should set the int13 handler. */
6215 + if (bios_drive_map[0] != 0)
6219 + /* Search for SAVED_DRIVE. */
6220 + for (i = 0; i < DRIVE_MAP_SIZE; i++)
6222 + if (! bios_drive_map[i])
6224 + else if ((bios_drive_map[i] & 0xFF) == saved_drive)
6226 + /* Exchage SAVED_DRIVE with the mapped drive. */
6227 + saved_drive = (bios_drive_map[i] >> 8) & 0xFF;
6232 + /* Set the handler. This is somewhat dangerous. */
6233 + set_int13_handler (bios_drive_map);
6237 + boot_drive = saved_drive;
6238 + chain_stage1 (0, BOOTSEC_LOCATION, boot_part_addr);
6241 + case KERNEL_TYPE_MULTIBOOT:
6243 + multi_boot ((int) entry_addr, (int) &mbi);
6247 + errnum = ERR_BOOT_COMMAND;
6254 +static struct builtin builtin_boot =
6258 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
6260 + "Boot the OS/chain-loader which has been loaded."
6264 +#ifdef SUPPORT_NETBOOT
6267 +bootp_func (char *arg, int flags)
6269 + int with_configfile = 0;
6271 + if (grub_memcmp (arg, "--with-configfile", sizeof ("--with-configfile") - 1)
6274 + with_configfile = 1;
6275 + arg = skip_to (0, arg);
6280 + if (errnum == ERR_NONE)
6281 + errnum = ERR_DEV_VALUES;
6286 + /* Notify the configuration. */
6287 + print_network_configuration ();
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);
6297 +static struct builtin builtin_bootp =
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"
6307 +#endif /* SUPPORT_NETBOOT */
6312 +cat_func (char *arg, int flags)
6316 + if (! grub_open (arg))
6319 + while (grub_read (&c, 1))
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 <= '~'))
6326 + grub_putchar ('?');
6333 +static struct builtin builtin_cat =
6337 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
6339 + "Print the contents of the file FILE."
6345 +chainloader_func (char *arg, int flags)
6350 + /* If the option `--force' is specified? */
6351 + if (substring ("--force", arg) <= 0)
6354 + file = skip_to (0, arg);
6357 + /* Open the file. */
6358 + if (! grub_open (file))
6360 + kernel_type = KERNEL_TYPE_NONE;
6364 + /* Read the first block. */
6365 + if (grub_read ((char *) BOOTSEC_LOCATION, SECTOR_SIZE) != SECTOR_SIZE)
6368 + kernel_type = KERNEL_TYPE_NONE;
6370 + /* This below happens, if a file whose size is less than 512 bytes
6372 + if (errnum == ERR_NONE)
6373 + errnum = ERR_EXEC_FORMAT;
6378 + /* If not loading it forcibly, check for the signature. */
6380 + && (*((unsigned short *) (BOOTSEC_LOCATION + BOOTSEC_SIG_OFFSET))
6381 + != BOOTSEC_SIGNATURE))
6384 + errnum = ERR_EXEC_FORMAT;
6385 + kernel_type = KERNEL_TYPE_NONE;
6390 + kernel_type = KERNEL_TYPE_CHAINLOADER;
6392 + /* XXX: Windows evil hack. For now, only the first five letters are
6394 + if (IS_PC_SLICE_TYPE_FAT (current_slice)
6395 + && ! grub_memcmp ((char *) BOOTSEC_LOCATION + BOOTSEC_BPB_SYSTEM_ID,
6397 + *((unsigned long *) (BOOTSEC_LOCATION + BOOTSEC_BPB_HIDDEN_SECTORS))
6400 + errnum = ERR_NONE;
6405 +static struct builtin builtin_chainloader =
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."
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 */
6422 +cmp_func (char *arg, int flags)
6424 + /* The filenames. */
6425 + char *file1, *file2;
6426 + /* The addresses. */
6427 + char *addr1, *addr2;
6429 + /* The size of the file. */
6432 + /* Get the filenames from ARG. */
6434 + file2 = skip_to (0, arg);
6435 + if (! *file1 || ! *file2)
6437 + errnum = ERR_BAD_ARGUMENT;
6441 + /* Terminate the filenames for convenience. */
6442 + nul_terminate (file1);
6443 + nul_terminate (file2);
6445 + /* Read the whole data from FILE1. */
6446 + addr1 = (char *) RAW_ADDR (0x100000);
6447 + if (! grub_open (file1))
6450 + /* Get the size. */
6452 + if (grub_read (addr1, -1) != size)
6460 + /* Read the whole data from FILE2. */
6461 + addr2 = addr1 + size;
6462 + if (! grub_open (file2))
6465 + /* Check if the size of FILE2 is equal to the one of FILE2. */
6466 + if (size != filemax)
6468 + grub_printf ("Differ in size: 0x%x [%s], 0x%x [%s]\n",
6469 + size, file1, filemax, file2);
6474 + if (! grub_read (addr2, -1))
6482 + /* Now compare ADDR1 with ADDR2. */
6483 + for (i = 0; i < size; i++)
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);
6494 +static struct builtin builtin_cmp =
6499 + "cmp FILE1 FILE2",
6500 + "Compare the file FILE1 with the FILE2 and inform the different values"
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". */
6510 +color_func (char *arg, int flags)
6514 + int new_normal_color;
6515 + int new_highlight_color;
6516 + static char *color_list[16] =
6536 + auto int color_number (char *str);
6538 + /* Convert the color name STR into the magical number. */
6539 + auto int color_number (char *str)
6545 + /* Find the separator. */
6546 + for (ptr = str; *ptr && *ptr != '/'; ptr++)
6549 + /* If not found, return -1. */
6553 + /* Terminate the string STR. */
6556 + /* If STR contains the prefix "blink-", then set the `blink' bit
6558 + if (substring ("blink-", str) <= 0)
6564 + /* Search for the color name. */
6565 + for (i = 0; i < 16; i++)
6566 + if (grub_strcmp (color_list[i], str) == 0)
6576 + nul_terminate (str);
6578 + /* Search for the color name. */
6579 + for (i = 0; i < 8; i++)
6580 + if (grub_strcmp (color_list[i], str) == 0)
6593 + highlight = skip_to (0, arg);
6595 + new_normal_color = color_number (normal);
6596 + if (new_normal_color < 0 && ! safe_parse_maxint (&normal, &new_normal_color))
6599 + /* The second argument is optional, so set highlight_color
6600 + to inverted NORMAL_COLOR. */
6602 + new_highlight_color = ((new_normal_color >> 4)
6603 + | ((new_normal_color & 0xf) << 4));
6606 + new_highlight_color = color_number (highlight);
6607 + if (new_highlight_color < 0
6608 + && ! safe_parse_maxint (&highlight, &new_highlight_color))
6612 + if (current_term->setcolor)
6613 + current_term->setcolor (new_normal_color, new_highlight_color);
6618 +static struct builtin builtin_color =
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."
6639 +configfile_func (char *arg, int flags)
6641 + char *new_config = config_file;
6643 + /* Check if the file ARG is present. */
6644 + if (! grub_open (arg))
6649 + /* Copy ARG to CONFIG_FILE. */
6650 + while ((*new_config++ = *arg++) != 0)
6654 + /* Force to load the configuration file. */
6655 + use_config_file = 1;
6658 + /* Make sure that the user will not be authoritative. */
6661 + /* Restart cmain. */
6662 + grub_longjmp (restart_env, 0);
6664 + /* Never reach here. */
6668 +static struct builtin builtin_configfile =
6672 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
6673 + "configfile FILE",
6674 + "Load FILE as the configuration file."
6680 +debug_func (char *arg, int flags)
6685 + grub_printf (" Debug mode is turned off\n");
6690 + grub_printf (" Debug mode is turned on\n");
6696 +static struct builtin builtin_debug =
6702 + "Turn on/off the debug mode."
6708 +default_func (char *arg, int flags)
6710 +#ifndef SUPPORT_DISKLESS
6711 + if (grub_strcmp (arg, "saved") == 0)
6713 + default_entry = saved_entryno;
6716 +#endif /* SUPPORT_DISKLESS */
6718 + if (! safe_parse_maxint (&arg, &default_entry))
6724 +static struct builtin builtin_default =
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."
6740 +device_func (char *arg, int flags)
6742 + char *drive = arg;
6745 + /* Get the drive number from DRIVE. */
6746 + if (! set_device (drive))
6749 + /* Get the device argument. */
6750 + device = skip_to (0, drive);
6752 + /* Terminate DEVICE. */
6753 + nul_terminate (device);
6755 + if (! *device || ! check_device (device))
6757 + errnum = ERR_FILE_NOT_FOUND;
6761 + assign_device_name (current_drive, device);
6766 +static struct builtin builtin_device =
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."
6775 +#endif /* GRUB_UTIL */
6778 +#ifdef SUPPORT_NETBOOT
6781 +dhcp_func (char *arg, int flags)
6783 + /* For now, this is an alias for bootp. */
6784 + return bootp_func (arg, flags);
6787 +static struct builtin builtin_dhcp =
6791 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
6793 + "Initialize a network device via DHCP."
6795 +#endif /* SUPPORT_NETBOOT */
6800 +displayapm_func (char *arg, int flags)
6802 + if (mbi.flags & MB_INFO_APM_TABLE)
6804 + grub_printf ("APM BIOS information:\n"
6805 + " Version: 0x%x\n"
6806 + " 32-bit CS: 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);
6824 + grub_printf ("No APM BIOS found or probe failed\n");
6830 +static struct builtin builtin_displayapm =
6834 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
6836 + "Display APM BIOS information."
6842 +displaymem_func (char *arg, int flags)
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");
6850 + grub_printf (" Lower memory: %uK, "
6851 + "Upper memory (to first chipset hole): %uK\n",
6852 + mbi.mem_lower, mbi.mem_upper);
6854 + if (mbi.flags & MB_INFO_MEM_MAP)
6856 + struct AddrRangeDesc *map = (struct AddrRangeDesc *) mbi.mmap_addr;
6857 + int end_addr = mbi.mmap_addr + mbi.mmap_length;
6859 + grub_printf (" [Address Range Descriptor entries "
6860 + "immediately follow (values are 64-bit)]\n");
6861 + while (end_addr > (int) map)
6865 + if (map->Type == MB_ARD_MEMORY)
6866 + str = "Usable RAM";
6869 + grub_printf (" %s: Base Address: 0x%x X 4GB + 0x%x,\n"
6870 + " Length: 0x%x X 4GB + 0x%x bytes\n",
6872 + (unsigned long) (map->BaseAddr >> 32),
6873 + (unsigned long) (map->BaseAddr & 0xFFFFFFFF),
6874 + (unsigned long) (map->Length >> 32),
6875 + (unsigned long) (map->Length & 0xFFFFFFFF));
6877 + map = ((struct AddrRangeDesc *) (((int) map) + 4 + map->size));
6884 +static struct builtin builtin_displaymem =
6888 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
6890 + "Display what GRUB thinks the system address space map of the"
6891 + " machine is, including all regions of physical RAM installed."
6898 +dump_func (char *arg, int flags)
6905 + to = skip_to (0, arg);
6906 + if (! *from || ! *to)
6908 + errnum = ERR_BAD_ARGUMENT;
6912 + nul_terminate (from);
6913 + nul_terminate (to);
6915 + if (! grub_open (from))
6918 + fp = fopen (to, "w");
6921 + errnum = ERR_WRITE;
6925 + while (grub_read (&c, 1))
6926 + if (fputc (c, fp) == EOF)
6928 + errnum = ERR_WRITE;
6933 + if (fclose (fp) == EOF)
6935 + errnum = ERR_WRITE;
6943 +static struct builtin builtin_dump =
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."
6952 +#endif /* GRUB_UTIL */
6955 +static char embed_info[32];
6957 +/* Embed a Stage 1.5 in the first cylinder after MBR or in the
6958 + bootloader block in a FFS. */
6960 +embed_func (char *arg, int flags)
6964 + char *stage1_5_buffer = (char *) RAW_ADDR (0x100000);
6969 + device = skip_to (0, stage1_5);
6971 + /* Open a Stage 1.5. */
6972 + if (! grub_open (stage1_5))
6975 + /* Read the whole of the Stage 1.5. */
6976 + len = grub_read (stage1_5_buffer, -1);
6982 + size = (len + SECTOR_SIZE - 1) / SECTOR_SIZE;
6984 + /* Get the device where the Stage 1.5 will be embedded. */
6985 + set_device (device);
6989 + if (current_partition == 0xFFFFFF)
6991 + /* Embed it after the MBR. */
6993 + char mbr[SECTOR_SIZE];
6994 + char ezbios_check[2*SECTOR_SIZE];
6997 + /* Open the partition. */
6998 + if (! open_partition ())
7001 + /* No floppy has MBR. */
7002 + if (! (current_drive & 0x80))
7004 + errnum = ERR_DEV_VALUES;
7008 + /* Read the MBR of CURRENT_DRIVE. */
7009 + if (! rawread (current_drive, PC_MBR_SECTOR, 0, SECTOR_SIZE, mbr))
7012 + /* Sanity check. */
7013 + if (! PC_MBR_CHECK_SIG (mbr))
7015 + errnum = ERR_BAD_PART_TABLE;
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)
7023 + errnum = ERR_NO_DISK_SPACE;
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.
7031 + if (! rawread (current_drive, 1, 0, 2 * SECTOR_SIZE, ezbios_check))
7034 + if (! memcmp (ezbios_check + 3, "AERMH", 5)
7035 + || ! memcmp (ezbios_check + 512 + 3, "AERMH", 5))
7037 + /* The space after the MBR is used by EZ-BIOS which we must
7040 + errnum = ERR_NO_DISK_SPACE;
7048 + /* Embed it in the bootloader block in the filesystem. */
7051 + /* Open the partition. */
7052 + if (! open_device ())
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))
7059 + errnum = ERR_DEV_VALUES;
7063 + sector = part_start + start_sector;
7066 + /* Clear the cache. */
7069 + /* Now perform the embedding. */
7070 + if (! devwrite (sector - part_start, size, stage1_5_buffer))
7073 + grub_printf (" %d sectors are embedded.\n", size);
7074 + grub_sprintf (embed_info, "%d+%d", sector - part_start, size);
7078 +static struct builtin builtin_embed =
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."
7092 +fallback_func (char *arg, int flags)
7101 + if (! safe_parse_maxint (&arg, &entry))
7104 + /* Remove duplications to prevent infinite looping. */
7105 + for (j = 0; j < i; j++)
7106 + if (entry == fallback_entries[j])
7111 + fallback_entries[i++] = entry;
7112 + if (i == MAX_FALLBACK_ENTRIES)
7115 + arg = skip_to (0, arg);
7118 + if (i < MAX_FALLBACK_ENTRIES)
7119 + fallback_entries[i] = -1;
7121 + fallback_entryno = (i == 0) ? -1 : 0;
7126 +static struct builtin builtin_fallback =
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."
7143 +/* Search for the filename ARG in all of partitions. */
7145 +find_func (char *arg, int flags)
7147 + char *filename = arg;
7148 + unsigned long drive;
7149 + unsigned long tmp_drive = saved_drive;
7150 + unsigned long tmp_partition = saved_partition;
7154 + for (drive = 0; drive < 8; drive++)
7156 + current_drive = drive;
7157 + current_partition = 0xFFFFFF;
7159 + if (open_device ())
7161 + saved_drive = current_drive;
7162 + saved_partition = current_partition;
7163 + if (grub_open (filename))
7166 + grub_printf (" (fd%d)\n", drive);
7171 + errnum = ERR_NONE;
7175 + for (drive = 0x80; drive < 0x88; drive++)
7177 + unsigned long part = 0xFFFFFF;
7178 + unsigned long start, len, offset, ext_offset;
7180 + char buf[SECTOR_SIZE];
7182 + current_drive = drive;
7183 + while (next_partition (drive, 0xFFFFFF, &part, &type,
7184 + &start, &len, &offset, &entry,
7185 + &ext_offset, buf))
7187 + if (type != PC_SLICE_TYPE_NONE
7188 + && ! IS_PC_SLICE_TYPE_BSD (type)
7189 + && ! IS_PC_SLICE_TYPE_EXTENDED (type))
7191 + current_partition = part;
7192 + if (open_device ())
7194 + saved_drive = current_drive;
7195 + saved_partition = current_partition;
7196 + if (grub_open (filename))
7198 + int bsd_part = (part >> 8) & 0xFF;
7199 + int pc_slice = part >> 16;
7203 + if (bsd_part == 0xFF)
7204 + grub_printf (" (hd%d,%d)\n",
7205 + drive - 0x80, pc_slice);
7207 + grub_printf (" (hd%d,%d,%c)\n",
7208 + drive - 0x80, pc_slice, bsd_part + 'a');
7215 + /* We want to ignore any error here. */
7216 + errnum = ERR_NONE;
7219 + /* next_partition always sets ERRNUM in the last call, so clear
7221 + errnum = ERR_NONE;
7224 + saved_drive = tmp_drive;
7225 + saved_partition = tmp_partition;
7229 + errnum = ERR_NONE;
7233 + errnum = ERR_FILE_NOT_FOUND;
7237 +static struct builtin builtin_find =
7241 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
7243 + "Search for the filename FILENAME in all of partitions and print the list of"
7244 + " the devices which contain the file."
7250 +fstest_func (char *arg, int flags)
7252 + if (disk_read_hook)
7254 + disk_read_hook = NULL;
7255 + printf (" Filesystem tracing is now off\n");
7259 + disk_read_hook = disk_read_print_func;
7260 + printf (" Filesystem tracing is now on\n");
7266 +static struct builtin builtin_fstest =
7272 + "Toggle filesystem test mode."
7278 +geometry_func (char *arg, int flags)
7280 + struct geometry geom;
7282 + char *device = arg;
7287 + /* Get the device number. */
7288 + set_device (device);
7292 + /* Check for the geometry. */
7293 + if (get_diskinfo (current_drive, &geom))
7295 + errnum = ERR_NO_DISK;
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))
7304 + errnum = ERR_READ;
7309 + ptr = skip_to (0, device);
7312 + char *cylinder, *head, *sector, *total_sector;
7313 + int num_cylinder, num_head, num_sector, num_total_sector;
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 (§or, &num_sector))
7324 + disks[current_drive].cylinders = num_cylinder;
7325 + disks[current_drive].heads = num_head;
7326 + disks[current_drive].sectors = num_sector;
7328 + if (safe_parse_maxint (&total_sector, &num_total_sector))
7329 + disks[current_drive].total_sectors = num_total_sector;
7331 + disks[current_drive].total_sectors
7332 + = num_cylinder * num_head * num_sector;
7335 + geom = disks[current_drive];
7338 +#endif /* GRUB_UTIL */
7341 + msg = device_map[current_drive];
7343 + if (geom.flags & BIOSDISK_FLAG_LBA_EXTENSION)
7349 + grub_printf ("drive 0x%x: C/H/S = %d/%d/%d, "
7350 + "The number of sectors = %d, %s\n",
7352 + geom.cylinders, geom.heads, geom.sectors,
7353 + geom.total_sectors, msg);
7354 + real_open_partition (1);
7359 +static struct builtin builtin_geometry =
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."
7376 +halt_func (char *arg, int flags)
7380 + no_apm = (grub_memcmp (arg, "--no-apm", 8) == 0);
7381 + grub_halt (no_apm);
7383 + /* Never reach here. */
7387 +static struct builtin builtin_halt =
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'."
7399 +#define MAX_SHORT_DOC_LEN 39
7400 +#define MAX_LONG_DOC_LEN 66
7403 +help_func (char *arg, int flags)
7407 + if (grub_memcmp (arg, "--all", sizeof ("--all") - 1) == 0)
7410 + arg = skip_to (0, arg);
7415 + /* Invoked with no argument. Print the list of the short docs. */
7416 + struct builtin **builtin;
7419 + for (builtin = builtin_table; *builtin != 0; builtin++)
7424 + /* If this cannot be used in the command-line interface,
7426 + if (! ((*builtin)->flags & BUILTIN_CMDLINE))
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))
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;
7439 + for (i = 0; i < len; i++)
7440 + grub_putchar ((*builtin)->short_doc[i]);
7442 + for (; i < MAX_SHORT_DOC_LEN; i++)
7443 + grub_putchar (' ');
7446 + grub_putchar ('\n');
7451 + /* If the last entry was at the left column, no newline was printed
7454 + grub_putchar ('\n');
7458 + /* Invoked with one or more patterns. */
7461 + struct builtin **builtin;
7464 + /* Get the next argument. */
7465 + next_arg = skip_to (0, arg);
7467 + /* Terminate ARG. */
7468 + nul_terminate (arg);
7470 + for (builtin = builtin_table; *builtin; builtin++)
7472 + /* Skip this if this is only for the configuration file. */
7473 + if (! ((*builtin)->flags & BUILTIN_CMDLINE))
7476 + if (substring (arg, (*builtin)->name) < 1)
7478 + char *doc = (*builtin)->long_doc;
7480 + /* At first, print the name and the short doc. */
7481 + grub_printf ("%s: %s\n",
7482 + (*builtin)->name, (*builtin)->short_doc);
7484 + /* Print the long doc. */
7487 + int len = grub_strlen (doc);
7490 + /* If LEN is too long, fold DOC. */
7491 + if (len > MAX_LONG_DOC_LEN)
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] == ' ')
7499 + grub_printf (" ");
7500 + for (i = 0; i < len; i++)
7501 + grub_putchar (*doc++);
7502 + grub_putchar ('\n');
7515 +static struct builtin builtin_help =
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'."
7528 +hiddenmenu_func (char *arg, int flags)
7534 +static struct builtin builtin_hiddenmenu =
7548 +hide_func (char *arg, int flags)
7550 + if (! set_device (arg))
7553 + if (! set_partition_hidden_flag (1))
7559 +static struct builtin builtin_hide =
7563 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
7565 + "Hide PARTITION by setting the \"hidden\" bit in"
7566 + " its partition type code."
7570 +#ifdef SUPPORT_NETBOOT
7573 +ifconfig_func (char *arg, int flags)
7575 + char *svr = 0, *ip = 0, *gw = 0, *sm = 0;
7577 + if (! eth_probe ())
7579 + grub_printf ("No ethernet card found.\n");
7580 + errnum = ERR_DEV_VALUES;
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;
7596 + errnum = ERR_BAD_ARGUMENT;
7600 + arg = skip_to (0, arg);
7603 + if (! ifconfig (ip, sm, gw, svr))
7605 + errnum = ERR_BAD_ARGUMENT;
7609 + print_network_configuration ();
7613 +static struct builtin builtin_ifconfig =
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."
7622 +#endif /* SUPPORT_NETBOOT */
7627 +impsprobe_func (char *arg, int flags)
7630 + /* In the grub shell, we cannot probe IMPS. */
7631 + errnum = ERR_UNRECOGNIZED;
7633 +#else /* ! GRUB_UTIL */
7634 + if (!imps_probe ())
7635 + printf (" No MPS information found or probe failed\n");
7638 +#endif /* ! GRUB_UTIL */
7641 +static struct builtin builtin_impsprobe =
7647 + "Probe the Intel Multiprocessor Specification 1.1 or 1.4"
7648 + " configuration table and boot the various CPUs which are found into"
7655 +initrd_func (char *arg, int flags)
7657 + switch (kernel_type)
7659 + case KERNEL_TYPE_LINUX:
7660 + case KERNEL_TYPE_BIG_LINUX:
7661 + if (! load_initrd (arg))
7666 + errnum = ERR_NEED_LX_KERNEL;
7673 +static struct builtin builtin_initrd =
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."
7686 +install_func (char *arg, int flags)
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;
7701 + struct geometry dest_geom, src_geom;
7703 + int stage2_first_sector, stage2_second_sector;
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? */
7712 + /* If LBA is forced? */
7713 + int is_force_lba = 0;
7714 + /* Was the last sector full? */
7715 + int last_length = SECTOR_SIZE;
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 */
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);
7726 + /* Save the first sector of Stage2 in STAGE2_SECT. */
7727 + auto void disk_read_savesect_func (int sector, int offset, int length)
7730 + printf ("[%d]", sector);
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;
7738 + saved_sector = sector;
7741 + /* Write SECTOR to INSTALLLIST, and update INSTALLADDR and
7743 + auto void disk_read_blocklist_func (int sector, int offset, int length)
7746 + printf("[%d]", sector);
7748 + if (offset != 0 || last_length != SECTOR_SIZE)
7750 + /* We found a non-sector-aligned data block. */
7751 + errnum = ERR_UNALIGNED;
7755 + last_length = length;
7757 + if (*((unsigned long *) (installlist - 4))
7758 + + *((unsigned short *) installlist) != sector
7759 + || installlist == (int) stage2_first_buffer + SECTOR_SIZE + 4)
7763 + if (*((unsigned long *) (installlist - 8)))
7764 + errnum = ERR_WONT_FIT;
7767 + *((unsigned short *) (installlist + 2)) = (installaddr >> 4);
7768 + *((unsigned long *) (installlist - 4)) = sector;
7772 + *((unsigned short *) installlist) += 1;
7773 + installaddr += 512;
7776 + /* First, check the GNU-style long option. */
7779 + if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0)
7782 + arg = skip_to (0, arg);
7785 + else if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) == 0)
7787 + stage2_os_file = arg + sizeof ("--stage2=") - 1;
7788 + arg = skip_to (0, arg);
7789 + nul_terminate (stage2_os_file);
7791 +#endif /* GRUB_UTIL */
7796 + stage1_file = arg;
7797 + dest_dev = skip_to (0, stage1_file);
7798 + if (*dest_dev == 'd')
7801 + dest_dev = skip_to (0, dest_dev);
7803 + file = skip_to (0, dest_dev);
7804 + addr = skip_to (0, file);
7806 + /* Get the installation address. */
7807 + if (! safe_parse_maxint (&addr, &installaddr))
7809 + /* ADDR is not specified. */
7815 + ptr = skip_to (0, addr);
7817 +#ifndef NO_DECOMPRESSION
7818 + /* Do not decompress Stage 1 or Stage 2. */
7819 + no_decompression = 1;
7822 + /* Read Stage 1. */
7823 + is_open = grub_open (stage1_file);
7825 + || ! grub_read (stage1_buffer, SECTOR_SIZE) == SECTOR_SIZE)
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))
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;
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);
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);
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))
7856 + errnum = ERR_BAD_VERSION;
7860 + /* This below is not true any longer. But should we leave this alone? */
7862 + /* If DEST_DRIVE is a floppy, Stage 2 must have the iteration probe
7864 + if (! (dest_drive & 0x80)
7865 + && (*((unsigned char *) (stage1_buffer + BOOTSEC_PART_OFFSET)) == 0x80
7866 + || stage1_buffer[BOOTSEC_PART_OFFSET] == 0))
7868 + errnum = ERR_BAD_VERSION;
7874 + /* Open Stage 2. */
7875 + is_open = grub_open (file);
7879 + src_drive = current_drive;
7880 + src_partition = current_partition;
7881 + src_part_start = part_start;
7882 + src_geom = buf_geom;
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");
7891 + /* Set the boot drive. */
7892 + *((unsigned char *) (stage1_buffer + STAGE1_BOOT_DRIVE)) = new_drive;
7894 + /* Set the "force LBA" flag. */
7895 + *((unsigned char *) (stage1_buffer + STAGE1_FORCE_LBA)) = is_force_lba;
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))
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)
7910 + stage2_first_sector = saved_sector;
7912 + /* Read the second sector of Stage 2. */
7913 + if (grub_read (stage2_second_buffer, SECTOR_SIZE) != SECTOR_SIZE)
7916 + stage2_second_sector = saved_sector;
7918 + /* Check for the version of Stage 2. */
7919 + if (*((short *) (stage2_second_buffer + STAGE2_VER_MAJ_OFFS))
7920 + != COMPAT_VERSION)
7922 + errnum = ERR_BAD_VERSION;
7926 + /* Check for the Stage 2 id. */
7927 + if (stage2_second_buffer[STAGE2_STAGE2_ID] != STAGE2_ID_STAGE2)
7930 + /* If INSTALLADDR is not specified explicitly in the command-line,
7931 + determine it by the Stage 2 id. */
7932 + if (! installaddr)
7934 + if (! is_stage1_5)
7936 + installaddr = 0x8000;
7939 + installaddr = 0x2000;
7942 + *((unsigned long *) (stage1_buffer + STAGE1_STAGE2_SECTOR))
7943 + = stage2_first_sector;
7944 + *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_ADDRESS))
7946 + *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_SEGMENT))
7947 + = installaddr >> 4;
7949 + i = (int) stage2_first_buffer + SECTOR_SIZE - 4;
7950 + while (*((unsigned long *) i))
7952 + if (i < (int) stage2_first_buffer
7953 + || (*((int *) (i - 4)) & 0x80000000)
7954 + || *((unsigned short *) i) >= 0xA00
7955 + || *((short *) (i + 2)) == 0)
7957 + errnum = ERR_BAD_VERSION;
7962 + *((int *) (i - 4)) = 0;
7966 + installlist = (int) stage2_first_buffer + SECTOR_SIZE + 4;
7967 + installaddr += SECTOR_SIZE;
7969 + /* Read the whole of Stage2 except for the first sector. */
7970 + grub_seek (SECTOR_SIZE);
7972 + disk_read_hook = disk_read_blocklist_func;
7973 + if (! grub_read (dummy, -1))
7976 + disk_read_hook = 0;
7978 + /* Find a string for the configuration filename. */
7979 + config_file_location = stage2_second_buffer + STAGE2_VER_STR_OFFS;
7980 + while (*(config_file_location++))
7983 + /* Set the "force LBA" flag for Stage2. */
7984 + *((unsigned char *) (stage2_second_buffer + STAGE2_FORCE_LBA))
7989 + *((long *) (stage2_second_buffer + STAGE2_INSTALLPART))
7993 + /* Reset the device information in FILE if it is a Stage 1.5. */
7994 + unsigned long device = 0xFFFFFFFF;
7996 + grub_memmove (config_file_location, (char *) &device,
8000 + ptr = skip_to (0, ptr);
8005 + grub_strcpy (config_filename, ptr);
8006 + nul_terminate (config_filename);
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);
8013 + char *real_config;
8014 + unsigned long device;
8016 + /* Translate the external device syntax to the internal device
8018 + if (! (real_config = set_device (ptr)))
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;
8028 + if (current_drive == src_drive)
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
8033 + current_drive = GRUB_INVALID_DRIVE;
8036 + device = (current_drive << 24) | current_partition;
8037 + grub_memmove (config_file_location, (char *) &device,
8039 + grub_strcpy (config_file_location + sizeof (device),
8043 + /* If a Stage 1.5 is used, then we need to modify the Stage2. */
8046 + char *real_config_filename = skip_to (0, ptr);
8048 + is_open = grub_open (config_filename);
8052 + /* Skip the first sector. */
8053 + grub_seek (SECTOR_SIZE);
8055 + disk_read_hook = disk_read_savesect_func;
8056 + if (grub_read (stage2_buffer, SECTOR_SIZE) != SECTOR_SIZE)
8059 + disk_read_hook = 0;
8063 + /* Sanity check. */
8064 + if (*(stage2_buffer + STAGE2_STAGE2_ID) != STAGE2_ID_STAGE2)
8066 + errnum = ERR_BAD_VERSION;
8070 + /* Set the "force LBA" flag for Stage2. */
8071 + *(stage2_buffer + STAGE2_FORCE_LBA) = is_force_lba;
8073 + /* If REAL_CONFIG_FILENAME is specified, copy it to the Stage2. */
8074 + if (*real_config_filename)
8079 + /* Find a string for the configuration filename. */
8080 + location = stage2_buffer + STAGE2_VER_STR_OFFS;
8081 + while (*(location++))
8084 + /* Copy the name. */
8085 + grub_strcpy (location, real_config_filename);
8088 + /* Write it to the disk. */
8092 + /* In the grub shell, access the Stage 2 via the OS filesystem
8093 + service, if possible. */
8094 + if (stage2_os_file)
8098 + fp = fopen (stage2_os_file, "r+");
8101 + errnum = ERR_FILE_NOT_FOUND;
8105 + if (fseek (fp, SECTOR_SIZE, SEEK_SET) != 0)
8108 + errnum = ERR_BAD_VERSION;
8112 + if (fwrite (stage2_buffer, 1, SECTOR_SIZE, fp)
8116 + errnum = ERR_WRITE;
8123 +#endif /* GRUB_UTIL */
8125 + if (! devwrite (saved_sector - part_start, 1, stage2_buffer))
8131 + /* Clear the cache. */
8134 + /* Write the modified sectors of Stage2 to the disk. */
8136 + if (! is_stage1_5 && stage2_os_file)
8140 + fp = fopen (stage2_os_file, "r+");
8143 + errnum = ERR_FILE_NOT_FOUND;
8147 + if (fwrite (stage2_first_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE)
8150 + errnum = ERR_WRITE;
8154 + if (fwrite (stage2_second_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE)
8157 + errnum = ERR_WRITE;
8164 +#endif /* GRUB_UTIL */
8167 + current_drive = src_drive;
8168 + current_partition = src_partition;
8170 + if (! open_partition ())
8173 + if (! devwrite (stage2_first_sector - src_part_start, 1,
8174 + stage2_first_buffer))
8177 + if (! devwrite (stage2_second_sector - src_part_start, 1,
8178 + stage2_second_buffer))
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 ())
8188 + devwrite (0, 1, stage1_buffer);
8194 + disk_read_hook = 0;
8196 +#ifndef NO_DECOMPRESSION
8197 + no_decompression = 0;
8203 +static struct builtin builtin_install =
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."
8228 +ioprobe_func (char *arg, int flags)
8232 + errnum = ERR_UNRECOGNIZED;
8235 +#else /* ! GRUB_UTIL */
8237 + unsigned short *port;
8239 + /* Get the drive number. */
8244 + /* Clean out IO_MAP. */
8245 + grub_memset ((char *) io_map, 0, IO_MAP_SIZE * sizeof (unsigned short));
8247 + /* Track the int13 handler. */
8248 + track_int13 (current_drive);
8250 + /* Print out the result. */
8251 + for (port = io_map; *port != 0; port++)
8252 + grub_printf (" 0x%x", (unsigned int) *port);
8256 +#endif /* ! GRUB_UTIL */
8259 +static struct builtin builtin_ioprobe =
8265 + "Probe I/O ports used for the drive DRIVE."
8271 +kernel_func (char *arg, int flags)
8274 + kernel_t suggested_type = KERNEL_TYPE_NONE;
8275 + unsigned long load_flags = 0;
8277 +#ifndef AUTO_LINUX_MEM_OPT
8278 + load_flags |= KERNEL_LOAD_NO_MEM_OPTION;
8281 + /* Deal with GNU-style long options. */
8284 + /* If the option `--type=TYPE' is specified, convert the string to
8286 + if (grub_memcmp (arg, "--type=", 7) == 0)
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
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;
8306 + errnum = ERR_BAD_ARGUMENT;
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
8313 + else if (grub_memcmp (arg, "--no-mem-option", 15) == 0)
8314 + load_flags |= KERNEL_LOAD_NO_MEM_OPTION;
8318 + /* Try the next. */
8319 + arg = skip_to (0, arg);
8322 + len = grub_strlen (arg);
8324 + /* Reset MB_CMDLINE. */
8325 + mb_cmdline = (char *) MB_CMDLINE_BUF;
8326 + if (len + 1 > MB_CMDLINE_BUFLEN)
8328 + errnum = ERR_WONT_FIT;
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)
8338 + mb_cmdline += len + 1;
8342 +static struct builtin builtin_kernel =
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."
8360 +lock_func (char *arg, int flags)
8362 + if (! auth && password)
8364 + errnum = ERR_PRIVILEGED;
8371 +static struct builtin builtin_lock =
8377 + "Break a command execution unless the user is authenticated."
8383 +makeactive_func (char *arg, int flags)
8385 + if (! make_saved_active ())
8391 +static struct builtin builtin_makeactive =
8395 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
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."
8403 +/* Map FROM_DRIVE to TO_DRIVE. */
8405 +map_func (char *arg, int flags)
8409 + unsigned long to, from;
8413 + from_drive = skip_to (0, arg);
8415 + /* Get the drive number for TO_DRIVE. */
8416 + set_device (to_drive);
8419 + to = current_drive;
8421 + /* Get the drive number for FROM_DRIVE. */
8422 + set_device (from_drive);
8425 + from = current_drive;
8427 + /* Search for an empty slot in BIOS_DRIVE_MAP. */
8428 + for (i = 0; i < DRIVE_MAP_SIZE; i++)
8430 + /* Perhaps the user wants to override the map. */
8431 + if ((bios_drive_map[i] & 0xff) == from)
8434 + if (! bios_drive_map[i])
8438 + if (i == DRIVE_MAP_SIZE)
8440 + errnum = ERR_WONT_FIT;
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));
8449 + bios_drive_map[i] = from | (to << 8);
8454 +static struct builtin builtin_map =
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."
8466 +#ifdef USE_MD5_PASSWORDS
8469 +md5crypt_func (char *arg, int flags)
8473 + unsigned int seed;
8475 + const char *const seedchars =
8476 + "./0123456789ABCDEFGHIJKLMNOPQRST"
8477 + "UVWXYZabcdefghijklmnopqrstuvwxyz";
8479 + /* First create a salt. */
8481 + /* The magical prefix. */
8482 + grub_memset (crypted, 0, sizeof (crypted));
8483 + grub_memmove (crypted, "$1$", 3);
8485 + /* Create the length of a salt. */
8486 + seed = currticks ();
8488 + /* Generate a salt. */
8489 + for (i = 0; i < 8 && seed; i++)
8491 + /* FIXME: This should be more random. */
8492 + crypted[3 + i] = seedchars[seed & 0x3f];
8496 + /* A salt must be terminated with `$', if it is less than 8 chars. */
8497 + crypted[3 + i] = '$';
8499 +#ifdef DEBUG_MD5CRYPT
8500 + grub_printf ("salt = %s\n", crypted);
8503 + /* Get a password. */
8504 + grub_memset (key, 0, sizeof (key));
8505 + get_cmdline ("Password: ", key, sizeof (key) - 1, '*', 0);
8507 + /* Crypt the key. */
8508 + make_md5_password (key, crypted);
8510 + grub_printf ("Encrypted: %s\n", crypted);
8514 +static struct builtin builtin_md5crypt =
8518 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
8520 + "Generate a password in MD5 format."
8522 +#endif /* USE_MD5_PASSWORDS */
8527 +module_func (char *arg, int flags)
8529 + int len = grub_strlen (arg);
8531 + switch (kernel_type)
8533 + case KERNEL_TYPE_MULTIBOOT:
8534 + if (mb_cmdline + len + 1 > (char *) MB_CMDLINE_BUF + MB_CMDLINE_BUFLEN)
8536 + errnum = ERR_WONT_FIT;
8539 + grub_memmove (mb_cmdline, arg, len + 1);
8540 + if (! load_module (arg, mb_cmdline))
8542 + mb_cmdline += len + 1;
8545 + case KERNEL_TYPE_LINUX:
8546 + case KERNEL_TYPE_BIG_LINUX:
8547 + if (! load_initrd (arg))
8552 + errnum = ERR_NEED_MB_KERNEL;
8559 +static struct builtin builtin_module =
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."
8573 +/* modulenounzip */
8575 +modulenounzip_func (char *arg, int flags)
8579 +#ifndef NO_DECOMPRESSION
8580 + no_decompression = 1;
8583 + ret = module_func (arg, flags);
8585 +#ifndef NO_DECOMPRESSION
8586 + no_decompression = 0;
8592 +static struct builtin builtin_modulenounzip =
8595 + modulenounzip_func,
8596 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
8597 + "modulenounzip FILE [ARG ...]",
8598 + "The same as `module', except that automatic decompression is"
8603 +/* pager [on|off] */
8605 +pager_func (char *arg, int flags)
8607 + /* If ARG is empty, toggle the flag. */
8609 + use_pager = ! use_pager;
8610 + else if (grub_memcmp (arg, "on", 2) == 0)
8612 + else if (grub_memcmp (arg, "off", 3) == 0)
8616 + errnum = ERR_BAD_ARGUMENT;
8620 + grub_printf (" Internal pager is now %s\n", use_pager ? "on" : "off");
8624 +static struct builtin builtin_pager =
8628 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
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."
8635 +/* partnew PART TYPE START LEN */
8637 +partnew_func (char *arg, int flags)
8639 + int new_type, new_start, new_len;
8640 + int start_cl, start_ch, start_dh;
8641 + int end_cl, end_ch, end_dh;
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)
8649 + int cylinder, head, sector;
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);
8655 + if (cylinder >= buf_geom.cylinders)
8656 + cylinder = buf_geom.cylinders - 1;
8658 + *cl = sector | ((cylinder & 0x300) >> 2);
8659 + *ch = cylinder & 0xFF;
8663 + /* Get the drive and the partition. */
8664 + if (! set_device (arg))
8667 + /* The drive must be a hard disk. */
8668 + if (! (current_drive & 0x80))
8670 + errnum = ERR_BAD_ARGUMENT;
8674 + /* The partition must a primary partition. */
8675 + if ((current_partition >> 16) > 3
8676 + || (current_partition & 0xFFFF) != 0xFFFF)
8678 + errnum = ERR_BAD_ARGUMENT;
8682 + entry = current_partition >> 16;
8684 + /* Get the new partition type. */
8685 + arg = skip_to (0, arg);
8686 + if (! safe_parse_maxint (&arg, &new_type))
8689 + /* The partition type is unsigned char. */
8690 + if (new_type > 0xFF)
8692 + errnum = ERR_BAD_ARGUMENT;
8696 + /* Get the new partition start. */
8697 + arg = skip_to (0, arg);
8698 + if (! safe_parse_maxint (&arg, &new_start))
8701 + /* Get the new partition length. */
8702 + arg = skip_to (0, arg);
8703 + if (! safe_parse_maxint (&arg, &new_len))
8706 + /* Read the MBR. */
8707 + if (! rawread (current_drive, 0, 0, SECTOR_SIZE, mbr))
8710 + /* Check if the new partition will fit in the disk. */
8711 + if (new_start + new_len > buf_geom.total_sectors)
8713 + errnum = ERR_GEOM;
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);
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;
8732 + /* Make sure that the MBR has a valid signature. */
8733 + PC_MBR_SIG (mbr) = PC_MBR_SIGNATURE;
8735 + /* Write back the MBR to the disk. */
8737 + if (! rawwrite (current_drive, 0, mbr))
8743 +static struct builtin builtin_partnew =
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."
8754 +/* parttype PART TYPE */
8756 +parttype_func (char *arg, int flags)
8759 + unsigned long part = 0xFFFFFF;
8760 + unsigned long start, len, offset, ext_offset;
8764 + /* Get the drive and the partition. */
8765 + if (! set_device (arg))
8768 + /* The drive must be a hard disk. */
8769 + if (! (current_drive & 0x80))
8771 + errnum = ERR_BAD_ARGUMENT;
8775 + /* The partition must be a PC slice. */
8776 + if ((current_partition >> 16) == 0xFF
8777 + || (current_partition & 0xFFFF) != 0xFFFF)
8779 + errnum = ERR_BAD_ARGUMENT;
8783 + /* Get the new partition type. */
8784 + arg = skip_to (0, arg);
8785 + if (! safe_parse_maxint (&arg, &new_type))
8788 + /* The partition type is unsigned char. */
8789 + if (new_type > 0xFF)
8791 + errnum = ERR_BAD_ARGUMENT;
8795 + /* Look for the partition. */
8796 + while (next_partition (current_drive, 0xFFFFFF, &part, &type,
8797 + &start, &len, &offset, &entry,
8798 + &ext_offset, mbr))
8800 + if (part == current_partition)
8804 + /* Set the type to NEW_TYPE. */
8805 + PC_SLICE_TYPE (mbr, entry) = new_type;
8807 + /* Write back the MBR to the disk. */
8809 + if (! rawwrite (current_drive, offset, mbr))
8817 + /* The partition was not found. ERRNUM was set by next_partition. */
8821 +static struct builtin builtin_parttype =
8825 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
8826 + "parttype PART TYPE",
8827 + "Change the type of the partition PART to TYPE."
8833 +password_func (char *arg, int flags)
8836 + password_t type = PASSWORD_PLAIN;
8838 +#ifdef USE_MD5_PASSWORDS
8839 + if (grub_memcmp (arg, "--md5", 5) == 0)
8841 + type = PASSWORD_MD5;
8842 + arg = skip_to (0, arg);
8845 + if (grub_memcmp (arg, "--", 2) == 0)
8847 + type = PASSWORD_UNSUPPORTED;
8848 + arg = skip_to (0, arg);
8851 + if ((flags & (BUILTIN_CMDLINE | BUILTIN_SCRIPT)) != 0)
8853 + /* Do password check! */
8856 + /* Wipe out any previously entered password */
8858 + get_cmdline ("Password: ", entered, 31, '*', 0);
8860 + nul_terminate (arg);
8861 + if (check_password (entered, arg, type) != 0)
8863 + errnum = ERR_PRIVILEGED;
8869 + len = grub_strlen (arg);
8871 + /* PASSWORD NUL NUL ... */
8872 + if (len + 2 > PASSWORD_BUFLEN)
8874 + errnum = ERR_WONT_FIT;
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;
8887 +static struct builtin builtin_password =
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"
8907 +pause_func (char *arg, int flags)
8909 + printf("%s\n", arg);
8911 + /* If ESC is returned, then abort this entry. */
8912 + if (ASCII_CHAR (getkey ()) == 27)
8918 +static struct builtin builtin_pause =
8922 + BUILTIN_CMDLINE | BUILTIN_NO_ECHO,
8923 + "pause [MESSAGE ...]",
8924 + "Print MESSAGE, then wait until a key is pressed."
8931 +quit_func (char *arg, int flags)
8935 + /* Never reach here. */
8939 +static struct builtin builtin_quit =
8943 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
8945 + "Exit from the GRUB shell."
8947 +#endif /* GRUB_UTIL */
8950 +#ifdef SUPPORT_NETBOOT
8953 +rarp_func (char *arg, int flags)
8957 + if (errnum == ERR_NONE)
8958 + errnum = ERR_DEV_VALUES;
8963 + /* Notify the configuration. */
8964 + print_network_configuration ();
8968 +static struct builtin builtin_rarp =
8972 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
8974 + "Initialize a network device via RARP."
8976 +#endif /* SUPPORT_NETBOOT */
8980 +read_func (char *arg, int flags)
8984 + if (! safe_parse_maxint (&arg, &addr))
8987 + grub_printf ("Address 0x%x: Value 0x%x\n",
8988 + addr, *((unsigned *) RAW_ADDR (addr)));
8992 +static struct builtin builtin_read =
8998 + "Read a 32-bit value from memory at address ADDR and"
8999 + " display it in hex format."
9005 +reboot_func (char *arg, int flags)
9009 + /* Never reach here. */
9013 +static struct builtin builtin_reboot =
9017 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
9019 + "Reboot your system."
9023 +/* Print the root device information. */
9025 +print_root_device (void)
9027 + if (saved_drive == NETWORK_DRIVE)
9029 + /* Network drive. */
9030 + grub_printf (" (nd):");
9032 + else if (saved_drive & 0x80)
9034 + /* Hard disk drive. */
9035 + grub_printf (" (hd%d", saved_drive - 0x80);
9037 + if ((saved_partition & 0xFF0000) != 0xFF0000)
9038 + grub_printf (",%d", saved_partition >> 16);
9040 + if ((saved_partition & 0x00FF00) != 0x00FF00)
9041 + grub_printf (",%c", ((saved_partition >> 8) & 0xFF) + 'a');
9043 + grub_printf ("):");
9047 + /* Floppy disk drive. */
9048 + grub_printf (" (fd%d):", saved_drive);
9051 + /* Print the filesystem information. */
9052 + current_partition = saved_partition;
9053 + current_drive = saved_drive;
9054 + print_fsys_type ();
9058 +real_root_func (char *arg, int attempt_mount)
9064 + /* If ARG is empty, just print the current root device. */
9067 + print_root_device ();
9071 + /* Call set_device to get the drive and the partition in ARG. */
9072 + next = set_device (arg);
9076 + /* Ignore ERR_FSYS_MOUNT. */
9077 + if (attempt_mount)
9079 + if (! open_device () && errnum != ERR_FSYS_MOUNT)
9084 + /* This is necessary, because the location of a partition table
9085 + must be set appropriately. */
9086 + if (open_partition ())
9094 + /* Clear ERRNUM. */
9096 + saved_partition = current_partition;
9097 + saved_drive = current_drive;
9099 + if (attempt_mount)
9101 + /* BSD and chainloading evil hacks !! */
9102 + biasptr = skip_to (0, next);
9103 + safe_parse_maxint (&biasptr, &hdbias);
9105 + bootdev = set_bootdev (hdbias);
9109 + /* Print the type of the filesystem. */
9110 + print_fsys_type ();
9117 +root_func (char *arg, int flags)
9119 + return real_root_func (arg, 1);
9122 +static struct builtin builtin_root =
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."
9143 +rootnoverify_func (char *arg, int flags)
9145 + return real_root_func (arg, 0);
9148 +static struct builtin builtin_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."
9164 +savedefault_func (char *arg, int flags)
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;
9171 + char sect[SECTOR_SIZE];
9173 + int sector_count = 0;
9174 + int saved_sectors[2];
9175 + int saved_offsets[2];
9176 + int saved_lengths[2];
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)
9182 + if (sector_count < 2)
9184 + saved_sectors[sector_count] = sector;
9185 + saved_offsets[sector_count] = offset;
9186 + saved_lengths[sector_count] = length;
9191 + /* This command is only useful when you boot an entry from the menu
9193 + if (! (flags & BUILTIN_SCRIPT))
9195 + errnum = ERR_UNRECOGNIZED;
9199 + /* Determine a saved entry number. */
9202 + if (grub_memcmp (arg, "fallback", sizeof ("fallback") - 1) == 0)
9207 + for (i = 0; i < MAX_FALLBACK_ENTRIES; i++)
9209 + if (fallback_entries[i] < 0)
9211 + if (fallback_entries[i] == current_entryno)
9218 + if (index >= MAX_FALLBACK_ENTRIES || fallback_entries[index] < 0)
9220 + /* This is the last. */
9221 + errnum = ERR_BAD_ARGUMENT;
9225 + entryno = fallback_entries[index];
9227 + else if (! safe_parse_maxint (&arg, &entryno))
9231 + entryno = current_entryno;
9233 + /* Open the default file. */
9234 + saved_drive = boot_drive;
9235 + saved_partition = install_partition;
9236 + if (grub_open (default_file))
9240 + disk_read_hook = disk_read_savesect_func;
9241 + len = grub_read (buf, sizeof (buf));
9242 + disk_read_hook = 0;
9245 + if (len != sizeof (buf))
9247 + /* This is too small. Do not modify the file manually, please! */
9248 + errnum = ERR_READ;
9252 + if (sector_count > 2)
9254 + /* Is this possible?! Too fragmented! */
9255 + errnum = ERR_FSYS_CORRUPT;
9259 + /* Set up a string to be written. */
9260 + grub_memset (buf, '\n', sizeof (buf));
9261 + grub_sprintf (buf, "%d", entryno);
9263 + if (saved_lengths[0] < sizeof (buf))
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,
9270 + grub_memmove (sect + saved_offsets[0], buf, saved_lengths[0]);
9271 + if (! rawwrite (current_drive, saved_sectors[0], sect))
9274 + if (! rawread (current_drive, saved_sectors[1], 0, SECTOR_SIZE,
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))
9285 + /* This is a simple case. It fits into a single sector. */
9286 + if (! rawread (current_drive, saved_sectors[0], 0, SECTOR_SIZE,
9289 + grub_memmove (sect + saved_offsets[0], buf, sizeof (buf));
9290 + if (! rawwrite (current_drive, saved_sectors[0], sect))
9294 + /* Clear the cache. */
9299 + saved_drive = tmp_drive;
9300 + saved_partition = tmp_partition;
9302 +#else /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */
9303 + errnum = ERR_UNRECOGNIZED;
9305 +#endif /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */
9308 +static struct builtin builtin_savedefault =
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."
9320 +#ifdef SUPPORT_SERIAL
9323 +serial_func (char *arg, int flags)
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;
9331 + /* Process GNU-style long options.
9332 + FIXME: We should implement a getopt-like function, to avoid
9336 + if (grub_memcmp (arg, "--unit=", sizeof ("--unit=") - 1) == 0)
9338 + char *p = arg + sizeof ("--unit=") - 1;
9341 + if (! safe_parse_maxint (&p, &unit))
9344 + if (unit < 0 || unit > 3)
9346 + errnum = ERR_DEV_VALUES;
9350 + port = serial_hw_get_port (unit);
9352 + else if (grub_memcmp (arg, "--speed=", sizeof ("--speed=") - 1) == 0)
9354 + char *p = arg + sizeof ("--speed=") - 1;
9357 + if (! safe_parse_maxint (&p, &num))
9360 + speed = (unsigned int) num;
9362 + else if (grub_memcmp (arg, "--port=", sizeof ("--port=") - 1) == 0)
9364 + char *p = arg + sizeof ("--port=") - 1;
9367 + if (! safe_parse_maxint (&p, &num))
9370 + port = (unsigned short) num;
9372 + else if (grub_memcmp (arg, "--word=", sizeof ("--word=") - 1) == 0)
9374 + char *p = arg + sizeof ("--word=") - 1;
9377 + if (! safe_parse_maxint (&p, &len))
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;
9387 + errnum = ERR_BAD_ARGUMENT;
9391 + else if (grub_memcmp (arg, "--stop=", sizeof ("--stop=") - 1) == 0)
9393 + char *p = arg + sizeof ("--stop=") - 1;
9396 + if (! safe_parse_maxint (&p, &len))
9401 + case 1: stop_bit_len = UART_1_STOP_BIT; break;
9402 + case 2: stop_bit_len = UART_2_STOP_BITS; break;
9404 + errnum = ERR_BAD_ARGUMENT;
9408 + else if (grub_memcmp (arg, "--parity=", sizeof ("--parity=") - 1) == 0)
9410 + char *p = arg + sizeof ("--parity=") - 1;
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;
9420 + errnum = ERR_BAD_ARGUMENT;
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)
9429 + char *p = arg + sizeof ("--device=") - 1;
9430 + char dev[256]; /* XXX */
9433 + while (*p && ! grub_isspace (*p))
9437 + serial_set_device (dev);
9439 +# endif /* GRUB_UTIL */
9443 + arg = skip_to (0, arg);
9446 + /* Initialize the serial unit. */
9447 + if (! serial_hw_init (port, speed, word_len, parity, stop_bit_len))
9449 + errnum = ERR_BAD_ARGUMENT;
9456 +static struct builtin builtin_serial =
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."
9470 +#endif /* SUPPORT_SERIAL */
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 */
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[] =
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}
9558 +setkey_func (char *arg, int flags)
9560 + char *to_key, *from_key;
9561 + int to_code, from_code;
9562 + int map_in_interrupt = 0;
9564 + auto int find_key_code (char *key);
9565 + auto int find_ascii_code (char *key);
9567 + auto int find_key_code (char *key)
9571 + for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++)
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;
9584 + auto int find_ascii_code (char *key)
9588 + for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++)
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;
9602 + from_key = skip_to (0, to_key);
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));
9612 + else if (! *from_key)
9614 + /* The user must specify two arguments or zero argument. */
9615 + errnum = ERR_BAD_ARGUMENT;
9619 + nul_terminate (to_key);
9620 + nul_terminate (from_key);
9622 + to_code = find_ascii_code (to_key);
9623 + from_code = find_ascii_code (from_key);
9624 + if (! to_code || ! from_code)
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)
9631 + errnum = ERR_BAD_ARGUMENT;
9636 + if (map_in_interrupt)
9640 + /* Find an empty slot. */
9641 + for (i = 0; i < KEY_MAP_SIZE; i++)
9643 + if ((bios_key_map[i] & 0xff) == from_code)
9644 + /* Perhaps the user wants to overwrite the map. */
9647 + if (! bios_key_map[i])
9651 + if (i == KEY_MAP_SIZE)
9653 + errnum = ERR_WONT_FIT;
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));
9663 + bios_key_map[i] = (to_code << 8) | from_code;
9665 + /* Ugly but should work. */
9666 + unset_int15_handler ();
9667 + set_int15_handler ();
9673 + /* Find an empty slot. */
9674 + for (i = 0; i < KEY_MAP_SIZE; i++)
9676 + if ((ascii_key_map[i] & 0xff) == from_code)
9677 + /* Perhaps the user wants to overwrite the map. */
9680 + if (! ascii_key_map[i])
9684 + if (i == KEY_MAP_SIZE)
9686 + errnum = ERR_WONT_FIT;
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));
9696 + ascii_key_map[i] = (to_code << 8) | from_code;
9702 +static struct builtin builtin_setkey =
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"
9722 +setup_func (char *arg, int flags)
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
9729 + unsigned long installed_drive, installed_partition;
9730 + unsigned long image_drive, image_partition;
9731 + unsigned long tmp_drive, tmp_partition;
9734 + char config_filename[64];
9735 + char real_config_filename[64];
9736 + char cmd_arg[256];
9738 + char *buffer = (char *) RAW_ADDR (0x100000);
9739 + int is_force_lba = 0;
9740 + char *stage2_arg = 0;
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);
9747 + /* Check if the file FILE exists like Autoconf. */
9748 + int check_file (char *file)
9752 + grub_printf (" Checking if \"%s\" exists... ", file);
9753 + ret = grub_open (file);
9757 + grub_printf ("yes\n");
9760 + grub_printf ("no\n");
9765 + /* Construct a device name in DEVICE. */
9766 + void sprint_device (int drive, int partition)
9768 + grub_sprintf (device, "(%cd%d",
9769 + (drive & 0x80) ? 'h' : 'f',
9771 + if ((partition & 0xFF0000) != 0xFF0000)
9774 + grub_sprintf (tmp, ",%d", (partition >> 16) & 0xFF);
9775 + grub_strncat (device, tmp, 256);
9777 + if ((partition & 0x00FF00) != 0x00FF00)
9780 + grub_sprintf (tmp, ",%c", 'a' + ((partition >> 8) & 0xFF));
9781 + grub_strncat (device, tmp, 256);
9783 + grub_strncat (device, ")", 256);
9786 + int embed_stage1_5 (char *stage1_5, int drive, int partition)
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);
9793 + /* Notify what will be run. */
9794 + grub_printf (" Running \"embed %s\"... ", cmd_arg);
9796 + embed_func (cmd_arg, flags);
9799 + /* Construct the blocklist representation. */
9800 + grub_sprintf (buffer, "%s%s", device, embed_info);
9801 + grub_printf ("succeeded\n");
9806 + grub_printf ("failed (this is not fatal)\n");
9811 + struct stage1_5_map {
9815 + struct stage1_5_map stage1_5_map[] =
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"}
9829 + tmp_drive = saved_drive;
9830 + tmp_partition = saved_partition;
9832 + /* Check if the user specifies --force-lba. */
9835 + if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0)
9838 + arg = skip_to (0, arg);
9840 + else if (grub_memcmp ("--prefix=", arg, sizeof ("--prefix=") - 1) == 0)
9842 + prefix = arg + sizeof ("--prefix=") - 1;
9843 + arg = skip_to (0, arg);
9844 + nul_terminate (prefix);
9847 + else if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) == 0)
9850 + arg = skip_to (0, arg);
9851 + nul_terminate (stage2_arg);
9853 +#endif /* GRUB_UTIL */
9858 + install_ptr = arg;
9859 + image_ptr = skip_to (0, install_ptr);
9861 + /* Make sure that INSTALL_PTR is valid. */
9862 + set_device (install_ptr);
9866 + installed_drive = current_drive;
9867 + installed_partition = current_partition;
9869 + /* Mount the drive pointed by IMAGE_PTR. */
9872 + /* If the drive/partition where the images reside is specified,
9873 + get the drive and the partition. */
9874 + set_device (image_ptr);
9880 + /* If omitted, use SAVED_PARTITION and SAVED_DRIVE. */
9881 + current_drive = saved_drive;
9882 + current_partition = saved_partition;
9885 + image_drive = saved_drive = current_drive;
9886 + image_partition = saved_partition = current_partition;
9889 + if (! open_device ())
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'. */
9898 + prefix = "/boot/grub";
9899 + grub_sprintf (stage1, "%s%s", prefix, "/stage1");
9900 + if (! check_file (stage1))
9902 + errnum = ERR_NONE;
9904 + grub_sprintf (stage1, "%s%s", prefix, "/stage1");
9905 + if (! check_file (stage1))
9911 + grub_sprintf (stage1, "%s%s", prefix, "/stage1");
9912 + if (! check_file (stage1))
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;
9921 + /* Check if stage2 exists. */
9922 + if (! check_file (stage2))
9926 + char *fsys = fsys_table[fsys_type].name;
9928 + int size = sizeof (stage1_5_map) / sizeof (stage1_5_map[0]);
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)
9934 + /* OK, check if the Stage 1.5 exists. */
9935 + char stage1_5[64];
9937 + grub_sprintf (stage1_5, "%s%s", prefix, stage1_5_map[i].name);
9938 + if (check_file (stage1_5))
9940 + if (embed_stage1_5 (stage1_5,
9941 + installed_drive, installed_partition)
9942 + || embed_stage1_5 (stage1_5,
9943 + image_drive, image_partition))
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);
9956 + /* Construct a string that is used by the command "install" as its
9958 + sprint_device (installed_drive, installed_partition);
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? " " : "",
9967 + (installed_drive != image_drive) ? "d " : "",
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? " " : "",
9988 + real_config_filename);
9989 +#endif /* NOT USED */
9991 + /* Notify what will be run. */
9992 + grub_printf (" Running \"install %s\"... ", cmd_arg);
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;
9999 + /* Run the command. */
10000 + if (! install_func (cmd_arg, flags))
10001 + grub_printf ("succeeded\nDone.\n");
10003 + grub_printf ("failed\n");
10006 + saved_drive = tmp_drive;
10007 + saved_partition = tmp_partition;
10011 +static struct builtin builtin_setup =
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."
10030 +#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
10033 +terminal_func (char *arg, int flags)
10035 + /* The index of the default terminal in TERM_TABLE. */
10036 + int default_term = -1;
10037 + struct term_entry *prev_term = current_term;
10040 + int no_message = 0;
10041 + unsigned long term_flags = 0;
10042 + /* XXX: Assume less than 32 terminals. */
10043 + unsigned long term_bitmap = 0;
10045 + /* Get GNU-style long options. */
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)
10057 + char *val = arg + sizeof ("--timeout=") - 1;
10059 + if (! safe_parse_maxint (&val, &to))
10062 + else if (grub_memcmp (arg, "--lines=", sizeof ("--lines=") - 1) == 0)
10064 + char *val = arg + sizeof ("--lines=") - 1;
10066 + if (! safe_parse_maxint (&val, &lines))
10069 + /* Probably less than four is meaningless.... */
10072 + errnum = ERR_BAD_ARGUMENT;
10076 + else if (grub_memcmp (arg, "--silent", sizeof ("--silent") - 1) == 0)
10081 + arg = skip_to (0, arg);
10084 + /* If no argument is specified, show current setting. */
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)" : "");
10098 + char *next = skip_to (0, arg);
10100 + nul_terminate (arg);
10102 + for (i = 0; term_table[i].name; i++)
10104 + if (grub_strcmp (arg, term_table[i].name) == 0)
10106 + if (term_table[i].flags & TERM_NEED_INIT)
10108 + errnum = ERR_DEV_NEED_INIT;
10112 + if (default_term < 0)
10113 + default_term = i;
10115 + term_bitmap |= (1 << i);
10120 + if (! term_table[i].name)
10122 + errnum = ERR_BAD_ARGUMENT;
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))
10133 + int time1, time2 = -1;
10135 + /* XXX: Disable the pager. */
10136 + count_lines = -1;
10138 + /* Get current time. */
10139 + while ((time1 = getrtsecs ()) == 0xFF)
10142 + /* Wait for a key input. */
10147 + for (i = 0; term_table[i].name; i++)
10149 + if (term_bitmap & (1 << i))
10151 + if (term_table[i].checkkey () >= 0)
10153 + (void) term_table[i].getkey ();
10154 + default_term = i;
10161 + /* Prompt the user, once per sec. */
10162 + if ((time1 = getrtsecs ()) != time2 && time1 != 0xFF)
10164 + if (! no_message)
10166 + /* Need to set CURRENT_TERM to each of selected
10168 + for (i = 0; term_table[i].name; i++)
10169 + if (term_bitmap & (1 << i))
10171 + current_term = term_table + i;
10172 + grub_printf ("\rPress any key to continue.\n");
10175 + /* Restore CURRENT_TERM. */
10176 + current_term = prev_term;
10187 + current_term = term_table + default_term;
10188 + current_term->flags = term_flags;
10191 + max_lines = lines;
10193 + /* 24 would be a good default value. */
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);
10204 +static struct builtin builtin_terminal =
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."
10221 +#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
10224 +#ifdef SUPPORT_SERIAL
10226 +terminfo_func (char *arg, int flags)
10228 + struct terminfo term;
10234 + const char *name;
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}
10246 + grub_memset (&term, 0, sizeof (term));
10251 + char *next = skip_to (0, arg);
10253 + nul_terminate (arg);
10255 + for (i = 0; i < sizeof (options) / sizeof (options[0]); i++)
10257 + const char *name = options[i].name;
10258 + int len = grub_strlen (name);
10260 + if (! grub_memcmp (arg, name, len))
10262 + grub_strcpy (options[i].var, ti_unescape_string (arg + len));
10267 + if (i == sizeof (options) / sizeof (options[0]))
10269 + errnum = ERR_BAD_ARGUMENT;
10276 + if (term.name[0] == 0 || term.cursor_address[0] == 0)
10278 + errnum = ERR_BAD_ARGUMENT;
10282 + ti_set_term (&term);
10286 + /* No option specifies printing out current settings. */
10287 + ti_get_term (&term);
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));
10304 +static struct builtin builtin_terminfo =
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]]",
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."
10317 +#endif /* SUPPORT_SERIAL */
10322 +testload_func (char *arg, int flags)
10326 + kernel_type = KERNEL_TYPE_NONE;
10328 + if (! grub_open (arg))
10331 + disk_read_hook = disk_read_print_func;
10333 + /* Perform filesystem test on the specified file. */
10334 + /* Read whole file first. */
10335 + grub_printf ("Whole file: ");
10337 + grub_read ((char *) RAW_ADDR (0x100000), -1);
10339 + /* Now compare two sections of the file read differently. */
10341 + for (i = 0; i < 0x10ac0; i++)
10343 + *((unsigned char *) RAW_ADDR (0x200000 + i)) = 0;
10344 + *((unsigned char *) RAW_ADDR (0x300000 + i)) = 1;
10347 + /* First partial read. */
10348 + grub_printf ("\nPartial read 1: ");
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);
10358 + /* Second partial read. */
10359 + grub_printf ("\nPartial read 2: ");
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);
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)));
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)));
10381 + for (i = 0; i < 0x10ac0; i++)
10382 + if (*((unsigned char *) RAW_ADDR (0x200000 + i))
10383 + != *((unsigned char *) RAW_ADDR (0x300000 + i)))
10386 + grub_printf ("Max is 0x10ac0: i=0x%x, filepos=0x%x\n", i, filepos);
10387 + disk_read_hook = 0;
10392 +static struct builtin builtin_testload =
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."
10408 +/* testvbe MODE */
10410 +testvbe_func (char *arg, int flags)
10413 + struct vbe_controller controller;
10414 + struct vbe_mode mode;
10418 + errnum = ERR_BAD_ARGUMENT;
10422 + if (! safe_parse_maxint (&arg, &mode_number))
10425 + /* Preset `VBE2'. */
10426 + grub_memmove (controller.signature, "VBE2", 4);
10428 + /* Detect VBE BIOS. */
10429 + if (get_vbe_controller_info (&controller) != 0x004F)
10431 + grub_printf (" VBE BIOS is not present.\n");
10435 + if (controller.version < 0x0200)
10437 + grub_printf (" VBE version %d.%d is not supported.\n",
10438 + (int) (controller.version >> 8),
10439 + (int) (controller.version & 0xFF));
10443 + if (get_vbe_mode_info (mode_number, &mode) != 0x004F
10444 + || (mode.mode_attributes & 0x0091) != 0x0091)
10446 + grub_printf (" Mode 0x%x is not supported.\n", mode_number);
10450 + /* Now trip to the graphics mode. */
10451 + if (set_vbe_mode (mode_number | (1 << 14)) != 0x004F)
10453 + grub_printf (" Switching to Mode 0x%x failed.\n", mode_number);
10457 + /* Draw something on the screen... */
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;
10467 + unsigned color = 0;
10469 + /* Iterate drawing on the screen, until the user hits any key. */
10470 + while (checkkey () == -1)
10472 + for (y = 0; y < height; y++)
10474 + unsigned char *line_buf = base_buf + scanline * y;
10476 + for (x = 0; x < width; x++)
10478 + unsigned char *buf = line_buf + bpp * x;
10481 + for (i = 0; i < bpp; i++, buf++)
10482 + *buf = (color >> (i * 8)) & 0xff;
10489 + /* Discard the input. */
10493 + /* Back to the default text mode. */
10494 + if (set_vbe_mode (0x03) != 0x004F)
10503 +static struct builtin builtin_testvbe =
10507 + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
10509 + "Test the VBE mode MODE. Hit any key to return."
10513 +#ifdef SUPPORT_NETBOOT
10516 +tftpserver_func (char *arg, int flags)
10518 + if (! *arg || ! ifconfig (0, 0, 0, arg))
10520 + errnum = ERR_BAD_ARGUMENT;
10524 + print_network_configuration ();
10528 +static struct builtin builtin_tftpserver =
10532 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
10533 + "tftpserver IPADDR",
10534 + "Override the TFTP server address."
10536 +#endif /* SUPPORT_NETBOOT */
10541 +timeout_func (char *arg, int flags)
10543 + if (! safe_parse_maxint (&arg, &grub_timeout))
10549 +static struct builtin builtin_timeout =
10556 + "Set a timeout, in SEC seconds, before automatically booting the"
10557 + " default entry (normally the first entry defined)."
10564 +title_func (char *arg, int flags)
10566 + /* This function is not actually used at least currently. */
10570 +static struct builtin builtin_title =
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."
10585 +unhide_func (char *arg, int flags)
10587 + if (! set_device (arg))
10590 + if (! set_partition_hidden_flag (0))
10596 +static struct builtin builtin_unhide =
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."
10609 +uppermem_func (char *arg, int flags)
10611 + if (! safe_parse_maxint (&arg, (int *) &mbi.mem_upper))
10614 + mbi.flags &= ~MB_INFO_MEM_MAP;
10618 +static struct builtin builtin_uppermem =
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."
10631 +vbeprobe_func (char *arg, int flags)
10633 + struct vbe_controller controller;
10634 + unsigned short *mode_list;
10635 + int mode_number = -1;
10637 + auto unsigned long vbe_far_ptr_to_linear (unsigned long);
10639 + unsigned long vbe_far_ptr_to_linear (unsigned long ptr)
10641 + unsigned short seg = (ptr >> 16);
10642 + unsigned short off = (ptr & 0xFFFF);
10644 + return (seg << 4) + off;
10649 + if (! safe_parse_maxint (&arg, &mode_number))
10653 + /* Set the signature to `VBE2', to obtain VBE 3.0 information. */
10654 + grub_memmove (controller.signature, "VBE2", 4);
10656 + if (get_vbe_controller_info (&controller) != 0x004F)
10658 + grub_printf (" VBE BIOS is not present.\n");
10662 + /* Check the version. */
10663 + if (controller.version < 0x0200)
10665 + grub_printf (" VBE version %d.%d is not supported.\n",
10666 + (int) (controller.version >> 8),
10667 + (int) (controller.version & 0xFF));
10671 + /* Print some information. */
10672 + grub_printf (" VBE version %d.%d\n",
10673 + (int) (controller.version >> 8),
10674 + (int) (controller.version & 0xFF));
10676 + /* Iterate probing modes. */
10678 + = (unsigned short *) vbe_far_ptr_to_linear (controller.video_mode);
10679 + *mode_list != 0xFFFF;
10682 + struct vbe_mode mode;
10684 + if (get_vbe_mode_info (*mode_list, &mode) != 0x004F)
10687 + /* Skip this, if this is not supported or linear frame buffer
10688 + mode is not support. */
10689 + if ((mode.mode_attributes & 0x0081) != 0x0081)
10692 + if (mode_number == -1 || mode_number == *mode_list)
10695 + switch (mode.memory_model)
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;
10708 + grub_printf (" 0x%x: %s, %ux%ux%u\n",
10709 + (unsigned) *mode_list,
10711 + (unsigned) mode.x_resolution,
10712 + (unsigned) mode.y_resolution,
10713 + (unsigned) mode.bits_per_pixel);
10715 + if (mode_number != -1)
10720 + if (mode_number != -1 && mode_number != *mode_list)
10721 + grub_printf (" Mode 0x%x is not found or supported.\n", mode_number);
10726 +static struct builtin builtin_vbeprobe =
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."
10737 +/* The table of builtin commands. Sorted in dictionary order. */
10738 +struct builtin *builtin_table[] =
10740 + &builtin_blocklist,
10742 +#ifdef SUPPORT_NETBOOT
10744 +#endif /* SUPPORT_NETBOOT */
10746 + &builtin_chainloader,
10749 + &builtin_configfile,
10751 + &builtin_default,
10754 +#endif /* GRUB_UTIL */
10755 +#ifdef SUPPORT_NETBOOT
10757 +#endif /* SUPPORT_NETBOOT */
10758 + &builtin_displayapm,
10759 + &builtin_displaymem,
10762 +#endif /* GRUB_UTIL */
10764 + &builtin_fallback,
10767 + &builtin_geometry,
10770 + &builtin_hiddenmenu,
10772 +#ifdef SUPPORT_NETBOOT
10773 + &builtin_ifconfig,
10774 +#endif /* SUPPORT_NETBOOT */
10775 + &builtin_impsprobe,
10777 + &builtin_install,
10778 + &builtin_ioprobe,
10781 + &builtin_makeactive,
10783 +#ifdef USE_MD5_PASSWORDS
10784 + &builtin_md5crypt,
10785 +#endif /* USE_MD5_PASSWORDS */
10787 + &builtin_modulenounzip,
10789 + &builtin_partnew,
10790 + &builtin_parttype,
10791 + &builtin_password,
10795 +#endif /* GRUB_UTIL */
10796 +#ifdef SUPPORT_NETBOOT
10798 +#endif /* SUPPORT_NETBOOT */
10802 + &builtin_rootnoverify,
10803 + &builtin_savedefault,
10804 +#ifdef SUPPORT_SERIAL
10806 +#endif /* SUPPORT_SERIAL */
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,
10823 + &builtin_uppermem,
10824 + &builtin_vbeprobe,
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
10838 @@ -43,13 +44,16 @@
10840 console_setcolorstate,
10842 - console_setcursor
10843 + console_setcursor,
10847 #ifdef SUPPORT_SERIAL
10850 /* A serial device must be initialized. */
10858 serial_setcolorstate,
10864 #endif /* SUPPORT_SERIAL */
10875 hercules_setcolorstate,
10877 - hercules_setcursor
10878 + hercules_setcursor,
10882 #endif /* SUPPORT_HERCULES */
10883 +#ifdef SUPPORT_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 */
10899 +#endif /* SUPPORT_GRAPHICS */
10900 /* This must be the last entry. */
10901 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
10903 @@ -1046,13 +1072,15 @@
10904 the following grub_printf call will print newlines. */
10907 + grub_printf("\n");
10908 if (current_term->setcolorstate)
10909 current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
10911 - grub_printf ("\n[Hit return to continue]");
10912 + grub_printf ("[Hit return to continue]");
10914 if (current_term->setcolorstate)
10915 current_term->setcolorstate (COLOR_STATE_NORMAL);
10920 @@ -1090,7 +1118,7 @@
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');
10928 current_term->cls ();
10929 @@ -1174,37 +1202,62 @@
10931 #endif /* ! STAGE1_5 */
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[];
10945 -memcheck (int addr, int len)
10946 +memcheck (unsigned long addr, unsigned long len)
10949 - auto int start_addr (void);
10950 - auto int end_addr (void);
10952 +# if defined(HAVE_START_SYMBOL) && defined(HAVE_END_SYMBOL)
10953 + if (start <= addr && end > addr + len)
10955 +# elif defined(HAVE_USCORE_START_SYMBOL) && defined (HAVE_USCORE_END_SYMBOL)
10956 + if (_start <= addr && _end > addr + len)
10959 +# else /* __PIC__ */
10960 + auto unsigned long start_addr (void);
10961 + auto unsigned long end_addr (void);
10963 - auto int start_addr (void)
10964 + auto unsigned long start_addr (void)
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));
10976 + erk! /* function would return undefined data in this case - barf */
10981 - auto int end_addr (void)
10982 + auto unsigned long end_addr (void)
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));
10994 + erk! /* function would return undefined data in this case - barf */
10999 if (start_addr () <= addr && end_addr () > addr + len)
11001 +# endif /* __PIC__ */
11002 #endif /* GRUB_UTIL */
11004 if ((addr < RAW_ADDR (0x1000))
11005 @@ -1217,10 +1270,20 @@
11010 +grub_memcpy(void *dest, const void *src, int len)
11013 + register char *d = (char*)dest, *s = (char*)src;
11015 + for (i = 0; i < len; i++)
11020 grub_memmove (void *to, const void *from, int len)
11022 - if (memcheck ((int) to, len))
11023 + if (memcheck ((unsigned long) to, len))
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 @@
11031 - if (memcheck ((int) start, len))
11032 + if (memcheck ((unsigned long) start, len))
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
11040 +/* char_io.c - basic console input and output */
11042 + * GRUB -- GRand Unified Bootloader
11043 + * Copyright (C) 1999,2000,2001,2002,2004 Free Software Foundation, Inc.
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.
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.
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.
11060 +#include <shared.h>
11063 +#ifdef SUPPORT_HERCULES
11064 +# include <hercules.h>
11067 +#ifdef SUPPORT_SERIAL
11068 +# include <serial.h>
11072 +struct term_entry term_table[] =
11078 + console_checkkey,
11083 + console_setcolorstate,
11084 + console_setcolor,
11085 + console_setcursor
11087 +#ifdef SUPPORT_SERIAL
11090 + /* A serial device must be initialized. */
11098 + serial_setcolorstate,
11102 +#endif /* SUPPORT_SERIAL */
11103 +#ifdef SUPPORT_HERCULES
11107 + hercules_putchar,
11108 + console_checkkey,
11113 + hercules_setcolorstate,
11114 + hercules_setcolor,
11115 + hercules_setcursor
11117 +#endif /* SUPPORT_HERCULES */
11118 + /* This must be the last entry. */
11119 + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
11122 +/* This must be console. */
11123 +struct term_entry *current_term = term_table;
11125 +int max_lines = 24;
11126 +int count_lines = -1;
11127 +int use_pager = 1;
11131 +print_error (void)
11133 + if (errnum > ERR_NONE && errnum < MAX_ERR_NUM)
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 */
11143 +convert_to_ascii (char *buf, int c,...)
11145 + unsigned long num = *((&c) + 1), mult = 10;
11149 + if (c == 'x' || c == 'X')
11152 + if ((num & 0x80000000uL) && c == 'd')
11154 + num = (~num) + 1;
11162 + int dig = num % mult;
11163 + *(ptr++) = ((dig > 9) ? dig + 'a' - 10 : '0' + dig);
11165 + while (num /= mult);
11167 + /* reorder to correct direction!! */
11169 + char *ptr1 = ptr - 1;
11170 + char *ptr2 = buf;
11171 + while (ptr1 > ptr2)
11185 +grub_putstr (const char *str)
11188 + grub_putchar (*str++);
11192 +grub_printf (const char *format,...)
11194 + int *dataptr = (int *) &format;
11199 + while ((c = *(format++)) != 0)
11202 + grub_putchar (c);
11204 + switch (c = *(format++))
11212 + *convert_to_ascii (str, c, *((unsigned long *) dataptr++)) = 0;
11213 + grub_putstr (str);
11218 + grub_putchar ((*(dataptr++)) & 0xff);
11222 + grub_putstr ((char *) *(dataptr++));
11231 +grub_sprintf (char *buffer, const char *format, ...)
11234 + ugly hack -- should unify with printf() */
11235 + int *dataptr = (int *) &format;
11236 + char c, *ptr, str[16];
11237 + char *bp = buffer;
11241 + while ((c = *format++) != 0)
11244 + *bp++ = c; /* putchar(c); */
11246 + switch (c = *(format++))
11248 + case 'd': case 'u': case 'x':
11249 + *convert_to_ascii (str, c, *((unsigned long *) dataptr++)) = 0;
11254 + *bp++ = *(ptr++); /* putchar(*(ptr++)); */
11257 + case 'c': *bp++ = (*(dataptr++))&0xff;
11258 + /* putchar((*(dataptr++))&0xff); */
11262 + ptr = (char *) (*(dataptr++));
11264 + while ((c = *ptr++) != 0)
11265 + *bp++ = c; /* putchar(c); */
11271 + return bp - buffer;
11280 + grub_printf ("\n GNU GRUB version %s (%dK lower / %dK upper memory)\n\n",
11281 + version_string, mbi.mem_lower, mbi.mem_upper);
11284 +/* The number of the history entries. */
11285 +static int num_history = 0;
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. */
11290 +get_history (int no)
11292 + if (no < 0 || no >= num_history)
11295 + return (char *) HISTORY_BUF + MAX_CMDLINE * no;
11298 +/* Add CMDLINE to the history buffer. */
11300 +add_history (const char *cmdline, int no)
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)
11311 +real_get_cmdline (char *prompt, char *cmdline, int maxlen,
11312 + int echo_char, int readline)
11314 + /* This is a rather complicated function. So explain the concept.
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.
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.
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
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 `>'.
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. */
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
11350 + int xpos, lpos, c, section;
11351 + /* The length of PROMPT. */
11353 + /* The length of the command-line. */
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;
11362 + /* Nested function definitions for code simplicity. */
11364 + /* The forward declarations of nested functions are prefixed
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);
11373 + /* Move the cursor backward. */
11374 + void cl_backward (int count)
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);
11388 + if (current_term->flags & TERM_DUMB)
11392 + for (i = 0; i < count; i++)
11393 + grub_putchar ('\b');
11396 + gotoxy (xpos, getxy () & 0xFF);
11400 + /* Move the cursor forward. */
11401 + void cl_forward (int count)
11405 + /* If the cursor goes outside, scroll the screen to the right. */
11406 + if (xpos + count >= CMDLINE_WIDTH)
11407 + cl_refresh (1, 0);
11412 + if (current_term->flags & TERM_DUMB)
11416 + for (i = lpos - count; i < lpos; i++)
11419 + grub_putchar (buf[i]);
11421 + grub_putchar (echo_char);
11425 + gotoxy (xpos, getxy () & 0xFF);
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)
11439 + /* Recompute the section number. */
11440 + if (lpos + plen < CMDLINE_WIDTH)
11443 + section = ((lpos + plen - CMDLINE_WIDTH)
11444 + / (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN) + 1);
11446 + /* From the start to the end. */
11447 + len = CMDLINE_WIDTH;
11449 + grub_putchar ('\r');
11451 + /* If SECTION is the first section, print the prompt, otherwise,
11453 + if (section == 0)
11455 + grub_printf ("%s", prompt);
11461 + grub_putchar ('<');
11467 + /* Compute the index to start writing BUF and the resulting position
11468 + on the screen. */
11469 + if (section == 0)
11474 + offset = xpos - plen;
11477 + xpos = lpos + plen;
11485 + offset = xpos - 1;
11487 + start = ((section - 1) * (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN)
11488 + + CMDLINE_WIDTH - plen - CMDLINE_MARGIN);
11489 + xpos = lpos + 1 - start;
11493 + /* Print BUF. If ECHO_CHAR is not zero, put it instead. */
11494 + for (i = start; i < start + len && i < llen; i++)
11497 + grub_putchar (buf[i]);
11499 + grub_putchar (echo_char);
11504 + /* Fill up the rest of the line with spaces. */
11505 + for (; i < start + len; i++)
11507 + grub_putchar (' ');
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)
11515 + if (start + len < llen)
11516 + grub_putchar ('>');
11518 + grub_putchar (' ');
11523 + /* Back to XPOS. */
11524 + if (current_term->flags & TERM_DUMB)
11526 + for (i = 0; i < pos - xpos; i++)
11527 + grub_putchar ('\b');
11530 + gotoxy (xpos, getxy () & 0xFF);
11533 + /* Initialize the command-line. */
11534 + void cl_init (void)
11536 + /* Distinguish us from other lines and error messages! */
11537 + grub_putchar ('\n');
11539 + /* Print full line and set position here. */
11540 + cl_refresh (1, 0);
11543 + /* Insert STR to BUF. */
11544 + void cl_insert (const char *str)
11546 + int l = grub_strlen (str);
11548 + if (llen + l < maxlen)
11550 + if (lpos == llen)
11551 + grub_memmove (buf + lpos, str, l + 1);
11554 + grub_memmove (buf + lpos + l, buf + lpos, llen - lpos + 1);
11555 + grub_memmove (buf + lpos, str, 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);
11565 + cl_refresh (0, l + llen - lpos);
11569 + /* Delete COUNT characters in BUF. */
11570 + void cl_delete (int count)
11572 + grub_memmove (buf + lpos, buf + lpos + count, llen - count + 1);
11575 + if (xpos + llen + count - lpos > CMDLINE_WIDTH)
11576 + cl_refresh (0, CMDLINE_WIDTH - xpos);
11578 + cl_refresh (0, llen + count - lpos);
11581 + plen = grub_strlen (prompt);
11582 + llen = grub_strlen (cmdline);
11584 + if (maxlen > MAX_CMDLINE)
11586 + maxlen = MAX_CMDLINE;
11587 + if (llen >= MAX_CMDLINE)
11589 + llen = MAX_CMDLINE - 1;
11590 + cmdline[MAX_CMDLINE] = 0;
11594 + grub_strcpy (buf, cmdline);
11598 + while ((c = ASCII_CHAR (getkey ())) != '\n' && c != '\r')
11600 + /* If READLINE is non-zero, handle readline-like key bindings. */
11605 + case 9: /* TAB lists completions */
11608 + /* POS points to the first space after a command. */
11611 + char *completion_buffer = (char *) COMPLETION_BUF;
11612 + int equal_pos = -1;
11615 + /* Find the first word. */
11616 + while (buf[pos] == ' ')
11618 + while (buf[pos] && buf[pos] != '=' && buf[pos] != ' ')
11621 + is_filename = (lpos > pos);
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] == '=')
11633 + /* Find the position of the first character in this
11635 + for (i = lpos; i > 0 && buf[i - 1] != ' '; i--)
11638 + /* Invalidate the cache, because the user may exchange
11639 + removable disks. */
11642 + /* Copy this word to COMPLETION_BUFFER and do the
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;
11651 + /* Found, so insert COMPLETION_BUFFER. */
11652 + cl_insert (completion_buffer + lpos - i);
11656 + /* There are more than one candidates, so print
11658 + grub_putchar ('\n');
11659 + print_completions (is_filename, 0);
11660 + errnum = ERR_NONE;
11664 + /* Restore the command-line. */
11665 + if (equal_pos >= 0)
11666 + buf[equal_pos] = '=';
11672 + case 1: /* C-a go to beginning of line */
11673 + cl_backward (lpos);
11675 + case 5: /* C-e go to end of line */
11676 + cl_forward (llen - lpos);
11678 + case 6: /* C-f forward one character */
11682 + case 2: /* C-b backward one character */
11686 + case 21: /* C-u kill to beginning of line */
11689 + /* Copy the string being deleted to KILL_BUF. */
11690 + grub_memmove (kill_buf, buf, lpos);
11691 + kill_buf[lpos] = 0;
11693 + /* XXX: Not very clever. */
11695 + int count = lpos;
11697 + cl_backward (lpos);
11698 + cl_delete (count);
11701 + case 11: /* C-k kill to end of line */
11702 + if (lpos == llen)
11704 + /* Copy the string being deleted to KILL_BUF. */
11705 + grub_memmove (kill_buf, buf + lpos, llen - lpos + 1);
11706 + cl_delete (llen - lpos);
11708 + case 25: /* C-y yank the kill buffer */
11709 + cl_insert (kill_buf);
11711 + case 16: /* C-p fetch the previous command */
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);
11723 + p = get_history (history);
11730 + grub_strcpy (buf, p);
11731 + llen = grub_strlen (buf);
11733 + cl_refresh (1, 0);
11736 + case 14: /* C-n fetch the next command */
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);
11749 + p = get_history (history);
11753 + grub_strcpy (buf, p);
11754 + llen = grub_strlen (buf);
11756 + cl_refresh (1, 0);
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. */
11767 + case 27: /* ESC immediately return 1 */
11769 + case 4: /* C-d delete character under cursor */
11770 + if (lpos == llen)
11774 + case 8: /* C-h backspace */
11776 + case 127: /* also backspace */
11784 + default: /* insert printable character into line */
11785 + if (c >= ' ' && c <= '~')
11796 + grub_putchar ('\n');
11798 + /* If ECHO_CHAR is NUL, remove the leading spaces. */
11801 + while (buf[lpos] == ' ')
11804 + /* Copy the working buffer to CMDLINE. */
11805 + grub_memmove (cmdline, buf + lpos, llen - lpos + 1);
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);
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
11822 + If ECHO_CHAR is nonzero, echo it instead of the typed character. */
11824 +get_cmdline (char *prompt, char *cmdline, int maxlen,
11825 + int echo_char, int readline)
11830 + old_cursor = setcursor (1);
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))
11837 + char *p = cmdline;
11840 + /* Make sure that MAXLEN is not too large. */
11841 + if (maxlen > MAX_CMDLINE)
11842 + maxlen = MAX_CMDLINE;
11844 + /* Print only the prompt. The contents of CMDLINE is simply discarded,
11845 + even if it is not empty. */
11846 + grub_printf ("%s", prompt);
11848 + /* Gather characters until a newline is gotten. */
11849 + while ((c = ASCII_CHAR (getkey ())) != '\n' && c != '\r')
11851 + /* Return immediately if ESC is pressed. */
11854 + setcursor (old_cursor);
11858 + /* Printable characters are added into CMDLINE. */
11859 + if (c >= ' ' && c <= '~')
11861 + if (! (current_term->flags & TERM_NO_ECHO))
11862 + grub_putchar (c);
11864 + /* Preceding space characters must be ignored. */
11865 + if (c != ' ' || p != cmdline)
11872 + if (! (current_term->flags & TERM_NO_ECHO))
11873 + grub_putchar ('\n');
11875 + setcursor (old_cursor);
11879 + /* Complicated features are left to real_get_cmdline. */
11880 + ret = real_get_cmdline (prompt, cmdline, maxlen, echo_char, readline);
11881 + setcursor (old_cursor);
11886 +safe_parse_maxint (char **str_ptr, int *myint_ptr)
11888 + char *ptr = *str_ptr;
11890 + int mult = 10, found = 0;
11893 + * Is this a hex number?
11895 + if (*ptr == '0' && tolower (*(ptr + 1)) == 'x')
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;
11908 + digit = tolower (*ptr) - '0';
11911 + digit -= 'a' - '0';
11912 + if (mult == 10 || digit > 5)
11918 + if (myint > ((MAXINT - digit) / mult))
11920 + errnum = ERR_NUMBER_OVERFLOW;
11923 + myint = (myint * mult) + digit;
11929 + errnum = ERR_NUMBER_PARSING;
11934 + *myint_ptr = myint;
11938 +#endif /* STAGE1_5 */
11940 +#if !defined(STAGE1_5) || defined(FSYS_FAT)
11942 +grub_tolower (int c)
11944 + if (c >= 'A' && c <= 'Z')
11945 + return (c + ('a' - 'A'));
11949 +#endif /* ! STAGE1_5 || FSYS_FAT */
11952 +grub_isspace (int c)
11968 +#if !defined(STAGE1_5) || defined(FSYS_ISO9660)
11970 +grub_memcmp (const char *s1, const char *s2, int n)
11976 + else if (*s1 > *s2)
11985 +#endif /* ! STAGE1_5 || FSYS_ISO9660 */
11989 +grub_strncat (char *s1, const char *s2, int n)
11993 + while (++i < n && s1[i] != 0);
11995 + while (i < n && (s1[i++] = *(s2++)) != 0);
12006 +#endif /* ! STAGE1_5 */
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)
12016 +grub_strcmp (const char *s1, const char *s2)
12018 + while (*s1 || *s2)
12022 + else if (*s1 > *s2)
12030 +#endif /* ! STAGE1_5 || FSYS_VSTAFS */
12033 +/* Wait for a keypress and return its code. */
12037 + return current_term->getkey ();
12040 +/* Check if a key code is available. */
12044 + return current_term->checkkey ();
12046 +#endif /* ! STAGE1_5 */
12048 +/* Display an ASCII character. */
12050 +grub_putchar (int c)
12053 + grub_putchar ('\r');
12055 + else if (c == '\t' && current_term->getxy)
12059 + n = 8 - ((current_term->getxy () >> 8) & 3);
12061 + grub_putchar (' ');
12065 +#endif /* ! STAGE1_5 */
12069 + /* In Stage 1.5, only the normal console is supported. */
12070 + console_putchar (c);
12072 +#else /* ! STAGE1_5 */
12076 + /* Internal `more'-like feature. */
12077 + if (count_lines >= 0)
12080 + if (count_lines >= max_lines - 2)
12084 + /* It's important to disable the feature temporarily, because
12085 + the following grub_printf call will print newlines. */
12086 + count_lines = -1;
12088 + if (current_term->setcolorstate)
12089 + current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
12091 + grub_printf ("\n[Hit return to continue]");
12093 + if (current_term->setcolorstate)
12094 + current_term->setcolorstate (COLOR_STATE_NORMAL);
12098 + tmp = ASCII_CHAR (getkey ());
12100 + while (tmp != '\n' && tmp != '\r');
12101 + grub_printf ("\r \r");
12103 + /* Restart to count lines. */
12110 + current_term->putchar (c);
12112 +#endif /* ! STAGE1_5 */
12117 +gotoxy (int x, int y)
12119 + current_term->gotoxy (x, y);
12125 + return current_term->getxy ();
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');
12135 + current_term->cls ();
12139 +setcursor (int on)
12141 + if (current_term->setcursor)
12142 + return current_term->setcursor (on);
12146 +#endif /* ! STAGE1_5 */
12149 +substring (const char *s1, const char *s2)
12151 + while (*s1 == *s2)
12153 + /* The strings match exactly. */
12159 + /* S1 is a substring of S2. */
12163 + /* S1 isn't a substring. */
12168 +/* Terminate the string STR with NUL. */
12170 +nul_terminate (char *str)
12174 + while (*str && ! grub_isspace (*str))
12183 +grub_strstr (const char *s1, const char *s2)
12187 + const char *ptr, *tmp;
12192 + while (*tmp && *ptr == *tmp)
12195 + if (tmp > s2 && ! *tmp)
12196 + return (char *) s1;
12205 +grub_strlen (const char *str)
12214 +#endif /* ! STAGE1_5 */
12217 +memcheck (int addr, int len)
12220 + auto int start_addr (void);
12221 + auto int end_addr (void);
12223 + auto int start_addr (void)
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));
12234 + auto int end_addr (void)
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));
12245 + if (start_addr () <= addr && end_addr () > addr + len)
12247 +#endif /* GRUB_UTIL */
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;
12260 +grub_memmove (void *to, const void *from, int len)
12262 + if (memcheck ((int) to, len))
12264 + /* This assembly code is stolen from
12265 + linux-2.2.2/include/asm-i386/string.h. This is not very fast
12271 + asm volatile ("cld\n\t"
12274 + : "=&c" (d0), "=&S" (d1), "=&D" (d2)
12275 + : "0" (len),"1" (from),"2" (to)
12280 + asm volatile ("std\n\t"
12284 + : "=&c" (d0), "=&S" (d1), "=&D" (d2)
12286 + "1" (len - 1 + (const char *) from),
12287 + "2" (len - 1 + (char *) to)
12292 + return errnum ? NULL : to;
12296 +grub_memset (void *start, int c, int len)
12300 + if (memcheck ((int) start, len))
12302 + while (len -- > 0)
12306 + return errnum ? NULL : start;
12311 +grub_strcpy (char *dest, const char *src)
12313 + grub_memmove (dest, src, grub_strlen (src) + 1);
12316 +#endif /* ! STAGE1_5 */
12320 +/* GCC emits references to memcpy() for struct copies etc. */
12321 +void *memcpy (void *dest, const void *src, int n) __attribute__ ((alias ("grub_memmove")));
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)
12330 - unsigned long cont, memtmp, addr;
12331 + unsigned long memtmp, addr;
12332 + volatile unsigned long cont;
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
12341 #include <shared.h>
12342 #include <filesys.h>
12345 #ifdef SUPPORT_NETBOOT
12347 @@ -137,7 +138,7 @@
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)
12354 int slen, sectors_per_vtrack;
12355 int sector_size_bits = log2 (buf_geom.sector_size);
12356 @@ -261,7 +262,7 @@
12358 if (disk_read_func)
12360 - int sector_num = sector;
12361 + unsigned int sector_num = sector;
12362 int length = buf_geom.sector_size - byte_offset;
12365 @@ -291,7 +292,7 @@
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)
12373 * Check partition boundaries
12374 @@ -330,7 +331,7 @@
12378 -rawwrite (int drive, int sector, char *buf)
12379 +rawwrite (int drive, unsigned int sector, char *buf)
12383 @@ -363,7 +364,7 @@
12387 -devwrite (int sector, int sector_count, char *buf)
12388 +devwrite (unsigned int sector, int sector_count, char *buf)
12390 #if defined(GRUB_UTIL) && defined(__linux__)
12391 if (current_partition != 0xFFFFFF
12392 @@ -502,8 +503,8 @@
12393 set_partition_hidden_flag (int hidden)
12395 unsigned long part = 0xFFFFFF;
12396 - unsigned long start, len, offset, ext_offset;
12398 + unsigned long start, len, offset, ext_offset, gpt_offset;
12399 + int entry, type, gpt_count, gpt_size;
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))
12410 + /* The partition may not be a GPT partition. */
12411 + if (gpt_offset != 0)
12413 + errnum = ERR_BAD_ARGUMENT;
12417 if (part == current_partition)
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)
12429 /* Forward declarations. */
12430 auto int next_bsd_partition (void);
12431 auto int next_pc_slice (void);
12432 + auto int next_gpt_slice(void);
12434 /* Get next BSD partition in current PC slice. */
12435 int next_bsd_partition (void)
12436 @@ -666,6 +677,40 @@
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)
12443 + struct grub_gpt_header *hdr = (struct grub_gpt_header *) buf;
12445 + /* Read in the GPT Partition table header. */
12446 + if (! rawread (drive, 1, 0, SECTOR_SIZE, buf))
12449 + if (hdr->magic == GPT_HEADER_MAGIC && hdr->version == 0x10000)
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;
12459 + return next_gpt_slice();
12463 + /* This is not a valid header for a GPT partition table.
12464 + Re-read the MBR or the boot sector of the extended
12466 + if (! rawread (drive, *offset, 0, SECTOR_SIZE, buf))
12471 + /* Not a GPT partition. */
12474 /* Increase the entry number. */
12477 @@ -710,6 +755,43 @@
12481 + /* Get the next GPT slice. */
12482 + int next_gpt_slice (void)
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;
12488 + /* If this is the first time... */
12489 + if (pc_slice_no == 0xFF)
12491 + pc_slice_no = -1;
12498 + if (*entry >= *gpt_count)
12500 + errnum = ERR_NO_PART;
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))
12506 + } while (! (gptentry->type1 && gptentry->type2));
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;
12518 /* Start the body of this function. */
12521 @@ -717,6 +799,9 @@
12525 + if (*partition != 0xFFFFFF && *gpt_offset != 0)
12526 + return next_gpt_slice ();
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 @@
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;
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;
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 ¤t_partition, ¤t_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;
12560 @@ -800,7 +891,12 @@
12562 /* If this is the whole disk, return here. */
12563 if (! flags && current_partition == 0xFFFFFF)
12567 + cur_part_offset = 0;
12568 +#endif /* ! STAGE1_5 */
12573 dest_partition = 0xFFFFFF;
12574 @@ -815,6 +911,8 @@
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 */
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)
12587 + PC_SLICE_START (BOOT_PART_TABLE - PC_SLICE_OFFSET, cur_part_entry) = cur_part_start;
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
12595 typedef unsigned short __u16;
12596 typedef __signed__ int __s32;
12597 typedef unsigned int __u32;
12598 +typedef unsigned long long __u64;
12601 * Constants relative to the data blocks, from ext2_fs.h
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 */
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 */
12628 + * These fields are for EXT2_DYNAMIC_REV superblocks only.
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.
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...
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 */
12651 + * Performance hints. Directory preallocation should only
12652 + * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
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 */
12658 + * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
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 */
12675 -struct ext2_group_desc
12676 +struct ext4_group_desc
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 */
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];
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 */
12713 - __u8 l_i_frag; /* Fragment number */
12714 - __u8 l_i_fsize; /* Fragment size */
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;
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 @@
12736 - __u8 m_i_frag; /* Fragment number */
12737 - __u8 m_i_fsize; /* Fragment size */
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];
12745 osd2; /* OS dependent 2 */
12746 + __u16 i_extra_isize;
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 */
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
12761 +#define EXT4_HAS_INCOMPAT_FEATURE(sb,mask) \
12762 + ( sb->s_feature_incompat & mask )
12764 +#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
12765 +#define EXT4_HUGE_FILE_FL 0x00040000 /* Set to each huge file */
12767 +#define EXT4_MIN_DESC_SIZE 32
12769 /* linux/limits.h */
12770 #define NAME_MAX 255 /* # chars in a file name */
12772 @@ -180,6 +256,57 @@
12773 char name[EXT2_NAME_LEN]; /* File name */
12776 +/* linux/ext4_fs_extents.h */
12777 +/* This is the extent on-disk structure.
12778 + * It's used at the bottom of the tree.
12780 +struct ext4_extent
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 */
12789 + * This is index on-disk structure.
12790 + * It's used at all the levels except the bottom.
12792 +struct ext4_extent_idx
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 */
12802 + * Each block (leaves and indexes), even inode-stored has header.
12804 +struct ext4_extent_header
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 */
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)
12827 /* linux/ext2fs.h */
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)))
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))
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
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))
12860 #define S_IFMT 00170000
12861 #define S_IFLNK 0120000
12862 @@ -386,6 +530,122 @@
12863 [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
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
12870 +static struct ext4_extent_idx*
12871 +ext4_ext_binsearch_idx(struct ext4_extent_header* eh, int logical_block)
12873 + struct ext4_extent_idx *r, *l, *m;
12874 + l = EXT_FIRST_INDEX(eh) + 1;
12875 + r = EXT_LAST_INDEX(eh);
12878 + m = l + (r - l) / 2;
12879 + if (logical_block < m->ei_block)
12884 + return (struct ext4_extent_idx*)(l - 1);
12887 +/* extent binary search
12888 + * find closest extent in the leaf level
12889 + * kind of from ext4_ext_binsearch in ext4/extents.c
12891 +static struct ext4_extent*
12892 +ext4_ext_binsearch(struct ext4_extent_header* eh, int logical_block)
12894 + struct ext4_extent *r, *l, *m;
12895 + l = EXT_FIRST_EXTENT(eh) + 1;
12896 + r = EXT_LAST_EXTENT(eh);
12899 + m = l + (r - l) / 2;
12900 + if (logical_block < m->ee_block)
12905 + return (struct ext4_extent*)(l - 1);
12908 +/* Maps extents enabled logical block into physical block via an inode.
12909 + * EXT4_HUGE_FILE_FL should be checked before calling this.
12912 +ext4fs_block_map (int logical_block)
12914 + struct ext4_extent_header *eh;
12915 + struct ext4_extent *ex, *extent;
12916 + struct ext4_extent_idx *ei, *index;
12921 + unsigned char *i;
12922 + for (i = (unsigned char *) INODE;
12923 + i < ((unsigned char *) INODE + sizeof (struct ext2_inode));
12926 + printf ("%c", "0123456789abcdef"[*i >> 4]);
12927 + printf ("%c", "0123456789abcdef"[*i % 16]);
12928 + if (!((i + 1 - (unsigned char *) INODE) % 16))
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)
12942 + errnum = ERR_FSYS_CORRUPT;
12945 + while((depth = eh->eh_depth) != 0)
12946 + { /* extent index */
12947 + if (eh->eh_magic != EXT4_EXT_MAGIC)
12949 + errnum = ERR_FSYS_CORRUPT;
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;
12958 + if (!ext2_rdfsb(ei->ei_leaf_lo, DATABLOCK1))
12960 + errnum = ERR_FSYS_CORRUPT;
12963 + eh = (struct ext4_extent_header*)DATABLOCK1;
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;
12973 + if ((ex->ee_block + ex->ee_len) < logical_block)
12975 + errnum = ERR_FSYS_CORRUPT;
12978 + return ex->ee_start_lo + logical_block - ex->ee_block;
12982 /* preconditions: all preconds of ext2fs_block_map */
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);
12994 map = ext2fs_block_map (logical_block);
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 */
13005 char linkbuf[PATH_MAX]; /* buffer for following symbolic links */
13006 @@ -550,10 +815,17 @@
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;
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)));
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;
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));
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 @@
13047 linkbuf[filemax + len] = '\0';
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
13054 if (! ext2_is_fast_symlink ())
13056 /* Read the necessary blocks, and reset the file pointer. */
13057 @@ -640,7 +914,9 @@
13061 - /* Copy the data directly from the inode. */
13062 + /* Copy the data directly from the inode.
13063 + * Fast symlink is not extents enabled
13066 memmove (linkbuf, (char *) INODE->i_block, len);
13068 @@ -674,6 +950,13 @@
13069 errnum = ERR_BAD_FILETYPE;
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))
13075 + /* file too large, stop reading */
13076 + errnum = ERR_FILELENGTH;
13080 filemax = (INODE->i_size);
13082 @@ -728,17 +1011,28 @@
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);
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
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);
13097 map = ext2fs_block_map (blk);
13099 printf ("fs block=%d\n", map);
13100 #endif /* E2DEBUG */
13102 - if ((map < 0) || !ext2_rdfsb (map, DATABLOCK2))
13108 + if (!ext2_rdfsb (map, DATABLOCK2))
13110 errnum = ERR_FSYS_CORRUPT;
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
13117 + * GRUB -- GRand Unified Bootloader
13118 + * Copyright (C) 2002,2005,2006 Free Software Foundation, Inc.
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.
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.
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.
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;
13147 +struct grub_gpt_header
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));
13165 +struct grub_gpt_partentry
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;
13174 +} __attribute__ ((packed));
13176 +#define GPT_HEADER_MAGIC 0x5452415020494645UL
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)
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
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>
13193 + * GRUB -- GRand Unified Bootloader
13194 + * Copyright (C) 2001,2002 Red Hat, Inc.
13195 + * Portions copyright (C) 2000 Conectiva, Inc.
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.
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.
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.
13214 +#ifdef SUPPORT_GRAPHICS
13217 +#include <shared.h>
13218 +#include <graphics.h>
13220 +int saved_videomode;
13221 +unsigned char *font8x16;
13223 +int graphics_inited = 0;
13224 +static char splashimage[64];
13226 +#define VSHADOW VSHADOW1
13227 +unsigned char VSHADOW1[38400];
13228 +unsigned char VSHADOW2[38400];
13229 +unsigned char VSHADOW4[38400];
13230 +unsigned char VSHADOW8[38400];
13232 +/* constants to define the viewable area */
13234 +const int x1 = 80;
13236 +const int y1 = 30;
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];
13242 +/* why do these have to be kept here? */
13243 +int foreground = (63 << 16) | (63 << 8) | (63), background = 0, border = 0;
13245 +/* current position */
13246 +static int fontx = 0;
13247 +static int fonty = 0;
13249 +/* global state so that we don't try to recursively scroll or cursor */
13250 +static int no_scroll = 0;
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;
13260 +/* graphics local functions */
13261 +static void graphics_setxy(int col, int row);
13262 +static void graphics_scroll();
13264 +/* FIXME: where do these really belong? */
13265 +static inline void outb(unsigned short port, unsigned char val)
13267 + __asm __volatile ("outb %0,%1"::"a" (val), "d" (port));
13270 +static void MapMask(int value) {
13272 + outb(0x3c5, value);
13275 +/* bit mask register */
13276 +static void BitMask(int value) {
13278 + outb(0x3cf, value);
13283 +/* Set the splash image */
13284 +void graphics_set_splash(char *splashfile) {
13285 + grub_strcpy(splashimage, splashfile);
13288 +/* Get the current splash image */
13289 +char *graphics_get_splash(void) {
13290 + return splashimage;
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
13296 +int graphics_init()
13298 + if(!grub_file_exists(splashimage)) {
13302 + if (!graphics_inited) {
13303 + saved_videomode = set_videomode(0x12);
13306 + if (!read_image(splashimage)) {
13307 + set_videomode(saved_videomode);
13308 + grub_printf("failed to read image\n");
13312 + font8x16 = (unsigned char*)graphics_get_font();
13314 + graphics_inited = 1;
13316 + /* make sure that the highlight color is set correctly */
13317 + graphics_highlight_color = ((graphics_normal_color >> 4) |
13318 + ((graphics_normal_color & 0xf) << 4));
13323 +/* Leave graphics mode */
13324 +void graphics_end(void)
13326 + if (graphics_inited) {
13327 + set_videomode(saved_videomode);
13328 + graphics_inited = 0;
13332 +/* Print ch on the screen. Handle any needed scrolling or the like */
13333 +void graphics_putchar(int ch) {
13336 + graphics_cursor(0);
13338 + if (ch == '\n') {
13339 + if (fonty + 1 < y1)
13340 + graphics_setxy(fontx, fonty + 1);
13342 + graphics_scroll();
13343 + graphics_cursor(1);
13345 + } else if (ch == '\r') {
13346 + graphics_setxy(x0, fonty);
13347 + graphics_cursor(1);
13351 + graphics_cursor(0);
13353 + text[fonty * 80 + fontx] = ch;
13354 + text[fonty * 80 + fontx] &= 0x00ff;
13355 + if (graphics_current_color & 0xf0)
13356 + text[fonty * 80 + fontx] |= 0x100;
13358 + graphics_cursor(0);
13360 + if ((fontx + 1) >= x1) {
13361 + graphics_setxy(x0, fonty);
13362 + if (fonty + 1 < y1)
13363 + graphics_setxy(x0, fonty + 1);
13365 + graphics_scroll();
13367 + graphics_setxy(fontx + 1, fonty);
13370 + graphics_cursor(1);
13373 +/* get the current location of the cursor */
13374 +int graphics_getxy(void) {
13375 + return (fontx << 8) | fonty;
13378 +void graphics_gotoxy(int x, int y) {
13379 + graphics_cursor(0);
13381 + graphics_setxy(x, y);
13383 + graphics_cursor(1);
13386 +void graphics_cls(void) {
13388 + unsigned char *mem, *s1, *s2, *s4, *s8;
13390 + graphics_cursor(0);
13391 + graphics_gotoxy(x0, y0);
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;
13399 + for (i = 0; i < 80 * 30; i++)
13401 + graphics_cursor(1);
13407 + grub_memcpy(mem, s1, 38400);
13411 + grub_memcpy(mem, s2, 38400);
13415 + grub_memcpy(mem, s4, 38400);
13419 + grub_memcpy(mem, s8, 38400);
13425 +void graphics_setcolorstate (color_state state) {
13427 + case COLOR_STATE_STANDARD:
13428 + graphics_current_color = graphics_standard_color;
13430 + case COLOR_STATE_NORMAL:
13431 + graphics_current_color = graphics_normal_color;
13433 + case COLOR_STATE_HIGHLIGHT:
13434 + graphics_current_color = graphics_highlight_color;
13437 + graphics_current_color = graphics_standard_color;
13441 + graphics_color_state = state;
13444 +void graphics_setcolor (int normal_color, int highlight_color) {
13445 + graphics_normal_color = normal_color;
13446 + graphics_highlight_color = highlight_color;
13448 + graphics_setcolorstate (graphics_color_state);
13451 +void graphics_setcursor (int on) {
13452 + /* FIXME: we don't have a cursor in graphics */
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
13459 +int read_image(char *s)
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;
13465 + if (!grub_open(s))
13468 + /* read header */
13469 + if (!grub_read((char*)&buf, 10) || grub_memcmp(buf, "/* XPM */\n", 10)) {
13475 + while (grub_read(&c, 1)) {
13480 + while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
13485 + while (grub_read(&c, 1)) {
13486 + if (c >= '0' && c <= '9')
13487 + width = width * 10 + c - '0';
13491 + while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
13494 + height = c - '0';
13495 + while (grub_read(&c, 1)) {
13496 + if (c >= '0' && c <= '9')
13497 + height = height * 10 + c - '0';
13501 + while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
13504 + colors = c - '0';
13505 + while (grub_read(&c, 1)) {
13506 + if (c >= '0' && c <= '9')
13507 + colors = colors * 10 + c - '0';
13513 + while (grub_read(&c, 1) && c != '"')
13517 + for (i = 0, idx = 1; i < colors; i++) {
13520 + while (grub_read(&c, 1) && c != '"')
13522 + grub_read(&c, 1); /* char */
13524 + grub_read(buf, 4); /* \t c # */
13526 + while (grub_read(&c, 1) && c != '"') {
13527 + if (len < sizeof(buf))
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;
13537 + graphics_set_palette(idx, r, g, b);
13544 + s1 = (unsigned char*)VSHADOW1;
13545 + s2 = (unsigned char*)VSHADOW2;
13546 + s4 = (unsigned char*)VSHADOW4;
13547 + s8 = (unsigned char*)VSHADOW8;
13549 + for (i = 0; i < 38400; i++)
13550 + s1[i] = s2[i] = s4[i] = s8[i] = 0;
13552 + /* parse xpm data */
13553 + while (y < height) {
13555 + if (!grub_read(&c, 1)) {
13563 + while (grub_read(&c, 1) && c != '"') {
13564 + for (i = 1; i < 15; i++)
13565 + if (pal[i] == c) {
13570 + mask = 0x80 >> (x & 7);
13572 + s1[len + (x >> 3)] |= mask;
13574 + s2[len + (x >> 3)] |= mask;
13576 + s4[len + (x >> 3)] |= mask;
13578 + s8[len + (x >> 3)] |= mask;
13580 + if (++x >= 640) {
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,
13603 +/* Convert a character which is a hex digit to the appropriate integer */
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');
13614 +/* move the graphics cursor location to col, row */
13615 +static void graphics_setxy(int col, int row) {
13616 + if (col >= x0 && col < x1) {
13618 + cursorX = col << 3;
13620 + if (row >= y0 && row < y1) {
13622 + cursorY = row << 4;
13626 +/* scroll the screen */
13627 +static void graphics_scroll() {
13630 + /* we don't want to scroll recursively... that would be bad */
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]);
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);
13653 +void graphics_cursor(int set) {
13654 + unsigned char *pat, *mem, *ptr, chr[16 << 2];
13655 + int i, ch, invert, offset;
13657 + if (set && no_scroll)
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);
13665 + mem = (unsigned char*)VIDEOMEM + offset;
13668 + for (i = 0; i < 16; i++) {
13669 + unsigned char mask = pat[i];
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];
13677 + /* FIXME: if (shade) */
13679 + if (ch == DISP_VERT || ch == DISP_LL ||
13680 + ch == DISP_UR || ch == DISP_LR) {
13681 + unsigned char pmask = ~(pat[i] >> 1);
13683 + chr[i ] &= pmask;
13684 + chr[16 + i] &= pmask;
13685 + chr[32 + i] &= pmask;
13686 + chr[48 + i] &= pmask;
13688 + if (i > 0 && ch != DISP_VERT) {
13689 + unsigned char pmask = ~(pat[i - 1] >> 1);
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];
13698 + chr[i ] &= pmask;
13699 + chr[16 + i] &= pmask;
13700 + chr[32 + i] &= pmask;
13701 + chr[48 + i] &= pmask;
13706 + chr[16 + i] |= mask;
13707 + chr[32 + i] |= mask;
13708 + chr[48 + i] |= mask;
13714 + chr[16 + i] = mask;
13715 + chr[32 + i] = mask;
13716 + chr[48 + i] = mask;
13723 + for (i = 0; i < 16; i++, ptr += 80) {
13724 + cursorBuf[i] = pat[i];
13731 + for (i = 1; i < 16; i <<= 1, offset += 16) {
13736 + for (j = 0; j < 16; j++, ptr += 80)
13737 + *ptr = chr[j + offset];
13743 +int grub_file_exists(char *s) {
13744 + if (!grub_open(s))
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
13755 +/* graphics.h - graphics console interface */
13757 + * GRUB -- GRand Unified Bootloader
13758 + * Copyright (C) 2002 Free Software Foundation, Inc.
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.
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.
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.
13775 +#ifndef GRAPHICS_H
13776 +#define GRAPHICS_H
13778 +/* magic constant */
13779 +#define VIDEOMEM 0xA0000
13781 +/* function prototypes */
13782 +char *graphics_get_splash(void);
13784 +int read_image(char *s);
13785 +void graphics_cursor(int set);
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();
13793 +/* Only to check for safe opening before we start */
13794 +int grub_file_exists(char *s);
13796 +extern short cursorX, cursorY;
13797 +extern char cursorBuf[16];
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 @@
13805 typedef struct __iso_16bit {
13807 -} iso_16bit_t __attribute__ ((packed));
13810 typedef struct __iso_32bit {
13812 -} iso_32bit_t __attribute__ ((packed));
13815 typedef u_int8_t iso_date_t[7];
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
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)
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
13842 # Stage 2 and Stage 1.5's.
13843 -pkglibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
13844 +stagedir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
13846 EXTRA_PROGRAMS = nbloader.exec pxeloader.exec diskless.exec
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 \
13855 reiserfs_stage1_5.exec ufs2_stage1_5.exec vstafs_stage1_5.exec \
13856 xfs_stage1_5.exec nbloader.exec pxeloader.exec diskless.exec
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
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
13875 +STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-reorder-functions -fno-builtin -nostdinc \
13876 + $(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS) $(GRAPHICS_FLAGS)
13878 STAGE1_5_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,2000
13879 STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1
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 \
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
13894 -CLEANFILES = $(pkglib_DATA) $(noinst_DATA) $(BUILT_SOURCES)
13895 +CLEANFILES = $(stage_DATA) $(noinst_DATA) $(BUILT_SOURCES)
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
13903 +# For test target.
13905 +noinst_SCRIPTS = $(TESTS)
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)
13916 +INCLUDES = -I$(top_srcdir)/stage1
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
13931 +# Stage 2 and Stage 1.5's.
13932 +pkglibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
13934 +EXTRA_PROGRAMS = nbloader.exec pxeloader.exec diskless.exec
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 \
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
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
13958 +MOSTLYCLEANFILES = $(noinst_PROGRAMS)
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
13966 +if NETBOOT_SUPPORT
13967 +NETBOOT_FLAGS = -I$(top_srcdir)/netboot -DSUPPORT_NETBOOT=1
13973 +SERIAL_FLAGS = -DSUPPORT_SERIAL=1
13978 +if HERCULES_SUPPORT
13979 +HERCULES_FLAGS = -DSUPPORT_HERCULES=1
13984 +STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
13985 + $(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS)
13987 +STAGE1_5_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,2000
13988 +STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1
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)
14000 +if NETBOOT_SUPPORT
14001 +pre_stage2_exec_LDADD = ../netboot/libdrivers.a
14004 +if DISKLESS_SUPPORT
14005 +BUILT_SOURCES = stage2_size.h diskless_size.h
14007 +BUILT_SOURCES = stage2_size.h
14010 +CLEANFILES = $(pkglib_DATA) $(noinst_DATA) $(BUILT_SOURCES)
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
14017 +start_exec_SOURCES = start.S
14018 +start_exec_CCASFLAGS = $(STAGE2_COMPILE)
14019 +start_exec_LDFLAGS = $(START_LINK)
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
14025 +start_exec-start.$(OBJEXT): stage2_size.h
14027 +stage2: pre_stage2 start
14029 + cat start pre_stage2 > stage2
14031 +start_eltorito_exec_SOURCES = start_eltorito.S
14032 +start_eltorito_exec_CCASFLAGS = $(STAGE2_COMPILE)
14033 +start_eltorito_exec_LDFLAGS = $(START_ELTORITO_LINK)
14035 +start_eltorito_exec-start.$(OBJEXT): stage2_size.h
14037 +stage2_eltorito: pre_stage2 start_eltorito
14038 + -rm -f stage2_eltorito
14039 + cat start_eltorito pre_stage2 > stage2_eltorito
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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
14140 +diskless_size.h: diskless
14142 + set dummy `ls -l $^`; \
14143 + echo "#define DISKLESS_SIZE $$6" > $@
14145 +# For nbloader target.
14146 +nbloader_exec_SOURCES = nbloader.S
14147 +nbloader_exec_CCASFLAGS = $(STAGE2_COMPILE)
14148 +nbloader_exec_LDFLAGS = $(NBLOADER_LINK)
14150 +# XXX: See the comment for start_exec-start.o.
14151 +nbloader_exec-nbloader.$(OBJEXT): diskless_size.h
14153 +# For nbgrub target.
14154 +nbgrub: nbloader diskless
14158 +# For pxeloader target.
14159 +pxeloader_exec_SOURCES = pxeloader.S
14160 +pxeloader_exec_CCASFLAGS = $(STAGE2_COMPILE)
14161 +pxeloader_exec_LDFLAGS = $(PXELOADER_LINK)
14163 +# XXX: See the comment for start_exec-start.o.
14164 +pxeloader_exec-pxeloader.$(OBJEXT): diskless_size.h
14166 +# For pxegrub target.
14167 +pxegrub: pxeloader diskless
14171 +# General rule for making a raw binary.
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
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
14191 /* Maybe redirect memory requests through grub_scratch_mem. */
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)
14199 # define RAW_ADDR(x) (x)
14200 @@ -161,7 +161,9 @@
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
14211 @@ -499,7 +501,11 @@
14212 unsigned char linear_reserved_field_position;
14213 unsigned long max_pixel_clock;
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
14220 + unsigned char reserved3[189 + 1];
14221 } __attribute__ ((packed));
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);
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);
14249 #ifndef NO_DECOMPRESSION
14250 @@ -920,10 +927,10 @@
14251 int gunzip_read (char *buf, int len);
14252 #endif /* NO_DECOMPRESSION */
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);
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);
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
14282 # The bootloader area of a FFS partition is 14 sectors.
14283 -check ffs_stage1_5 7168
14285 -check ufs2_stage1_5 7168
14286 +#check ffs_stage1_5 7168
14288 +#check ufs2_stage1_5 7168
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 @@
14297 int c, time1, time2 = -1, first_entry = 0;
14298 char *cur_entry = 0;
14299 + struct term_entry *prev_term = NULL;
14302 * Main loop for menu UI.
14303 @@ -651,7 +652,10 @@
14306 if (config_entries)
14307 - run_menu (heap, NULL, new_num_entries, new_heap, 0);
14309 + current_entryno = first_entry + entryno;
14310 + run_menu (heap, NULL, new_num_entries, new_heap, 0);
14315 @@ -714,6 +718,15 @@
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)
14325 + (*current_term->shutdown)();
14326 + current_term = term_table; /* assumption: console is first */
14331 @@ -727,7 +740,8 @@
14332 cur_entry = get_entry (config_entries, first_entry + entryno, 1);
14334 /* Set CURRENT_ENTRYNO for the command "savedefault". */
14335 - current_entryno = first_entry + entryno;
14336 + if (config_entries)
14337 + current_entryno = first_entry + entryno;
14339 if (run_script (cur_entry, heap))
14341 @@ -748,6 +762,13 @@
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 */
14355 @@ -1050,6 +1071,10 @@
14359 + /* go ahead and make sure the terminal is setup */
14360 + if (current_term->startup)
14361 + (*current_term->startup)();
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
14371 + * GRUB -- GRand Unified Bootloader
14372 + * Copyright (C) 2000,2001,2002,2004,2005 Free Software Foundation, Inc.
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.
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.
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.
14389 +#include <shared.h>
14392 +grub_jmp_buf restart_env;
14394 +#if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS)
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 */
14403 +static int preset_menu_offset;
14406 +open_preset_menu (void)
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)
14413 +#endif /* GRUB_UTIL */
14415 + preset_menu_offset = 0;
14416 + return preset_menu != 0;
14420 +read_from_preset_menu (char *buf, int maxlen)
14422 + int len = grub_strlen (preset_menu + preset_menu_offset);
14424 + if (len > maxlen)
14427 + grub_memmove (buf, preset_menu + preset_menu_offset, len);
14428 + preset_menu_offset += len;
14434 +close_preset_menu (void)
14436 + /* Disable the preset menu. */
14440 +#else /* ! PRESET_MENU_STRING && ! SUPPORT_DISKLESS */
14442 +#define open_preset_menu() 0
14443 +#define read_from_preset_menu(buf, maxlen) 0
14444 +#define close_preset_menu()
14446 +#endif /* ! PRESET_MENU_STRING && ! SUPPORT_DISKLESS */
14449 +get_entry (char *list, int num, int nested)
14453 + for (i = 0; i < num; i++)
14457 + while (*(list++));
14459 + while (nested && *(list++));
14465 +/* Print an entry in a line of the menu box. */
14467 +print_entry (int y, int highlight, char *entry)
14471 + if (current_term->setcolorstate)
14472 + current_term->setcolorstate (COLOR_STATE_NORMAL);
14474 + if (highlight && current_term->setcolorstate)
14475 + current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
14478 + grub_putchar (' ');
14479 + for (x = 3; x < 75; x++)
14481 + if (*entry && x <= 72)
14484 + grub_putchar (DISP_RIGHT);
14486 + grub_putchar (*entry++);
14489 + grub_putchar (' ');
14493 + if (current_term->setcolorstate)
14494 + current_term->setcolorstate (COLOR_STATE_STANDARD);
14497 +/* Print entries in the menu box. */
14499 +print_entries (int y, int size, int first, int entryno, char *menu_entries)
14503 + gotoxy (77, y + 1);
14506 + grub_putchar (DISP_UP);
14508 + grub_putchar (' ');
14510 + menu_entries = get_entry (menu_entries, first, 0);
14512 + for (i = 0; i < size; i++)
14514 + print_entry (y + i + 1, entryno == i, menu_entries);
14516 + while (*menu_entries)
14519 + if (*(menu_entries - 1))
14523 + gotoxy (77, y + size);
14525 + if (*menu_entries)
14526 + grub_putchar (DISP_DOWN);
14528 + grub_putchar (' ');
14530 + gotoxy (74, y + entryno + 1);
14534 +print_entries_raw (int size, int first, char *menu_entries)
14538 +#define LINE_LENGTH 67
14540 + for (i = 0; i < LINE_LENGTH; i++)
14541 + grub_putchar ('-');
14542 + grub_putchar ('\n');
14544 + for (i = first; i < size; i++)
14546 + /* grub's printf can't %02d so ... */
14548 + grub_putchar (' ');
14549 + grub_printf ("%d: %s\n", i, get_entry (menu_entries, i, 0));
14552 + for (i = 0; i < LINE_LENGTH; i++)
14553 + grub_putchar ('-');
14554 + grub_putchar ('\n');
14556 +#undef LINE_LENGTH
14561 +print_border (int y, int size)
14565 + if (current_term->setcolorstate)
14566 + current_term->setcolorstate (COLOR_STATE_NORMAL);
14570 + grub_putchar (DISP_UL);
14571 + for (i = 0; i < 73; i++)
14572 + grub_putchar (DISP_HORIZ);
14573 + grub_putchar (DISP_UR);
14578 + gotoxy (1, y + i);
14583 + grub_putchar (DISP_VERT);
14584 + gotoxy (75, y + i);
14585 + grub_putchar (DISP_VERT);
14590 + grub_putchar (DISP_LL);
14591 + for (i = 0; i < 73; i++)
14592 + grub_putchar (DISP_HORIZ);
14593 + grub_putchar (DISP_LR);
14595 + if (current_term->setcolorstate)
14596 + current_term->setcolorstate (COLOR_STATE_STANDARD);
14600 +run_menu (char *menu_entries, char *config_entries, int num_entries,
14601 + char *heap, int entryno)
14603 + int c, time1, time2 = -1, first_entry = 0;
14604 + char *cur_entry = 0;
14607 + * Main loop for menu UI.
14611 + /* Dumb terminal always use all entries for display
14612 + invariant for TERM_DUMB: first_entry == 0 */
14613 + if (! (current_term->flags & TERM_DUMB))
14615 + while (entryno > 11)
14622 + /* If the timeout was expired or wasn't set, force to show the menu
14624 + if (grub_timeout < 0)
14627 + /* If SHOW_MENU is false, don't display the menu until ESC is pressed. */
14630 + /* Get current time. */
14631 + while ((time1 = getrtsecs ()) == 0xFF)
14636 + /* Check if ESC is pressed. */
14637 + if (checkkey () != -1 && ASCII_CHAR (getkey ()) == '\e')
14639 + grub_timeout = -1;
14644 + /* If GRUB_TIMEOUT is expired, boot the default entry. */
14645 + if (grub_timeout >=0
14646 + && (time1 = getrtsecs ()) != time2
14647 + && time1 != 0xFF)
14649 + if (grub_timeout <= 0)
14651 + grub_timeout = -1;
14658 + /* Print a message. */
14659 + grub_printf ("\rPress `ESC' to enter the menu... %d ",
14665 + /* Only display the menu if the user wants to see it. */
14671 + if (current_term->flags & TERM_DUMB)
14672 + print_entries_raw (num_entries, first_entry, menu_entries);
14674 + print_border (3, 12);
14676 + grub_printf ("\n\
14677 + Use the %c and %c keys to select which entry is highlighted.\n",
14678 + DISP_UP, DISP_DOWN);
14680 + if (! auth && password)
14683 + Press enter to boot the selected OS or \'p\' to enter a\n\
14684 + password to unlock the next set of features.");
14688 + if (config_entries)
14690 + Press enter to boot the selected OS, \'e\' to edit the\n\
14691 + commands before booting, or \'c\' for a command-line.");
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.");
14700 + if (current_term->flags & TERM_DUMB)
14701 + grub_printf ("\n\nThe selected entry is %d ", entryno);
14703 + print_entries (3, 12, first_entry, entryno, menu_entries);
14706 + /* XX using RT clock now, need to initialize value */
14707 + while ((time1 = getrtsecs()) == 0xFF);
14711 + /* Initialize to NULL just in case... */
14712 + cur_entry = NULL;
14714 + if (grub_timeout >= 0 && (time1 = getrtsecs()) != time2 && time1 != 0xFF)
14716 + if (grub_timeout <= 0)
14718 + grub_timeout = -1;
14722 + /* else not booting yet! */
14725 + if (current_term->flags & TERM_DUMB)
14726 + grub_printf ("\r Entry %d will be booted automatically in %d seconds. ",
14727 + entryno, grub_timeout);
14731 + grub_printf ("The highlighted entry will be booted automatically in %d seconds. ",
14733 + gotoxy (74, 4 + entryno);
14739 + /* Check for a keypress, however if TIMEOUT has been expired
14740 + (GRUB_TIMEOUT == -1) relax in GETKEY even if no key has been
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)
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);
14752 + c = ASCII_CHAR (getkey ());
14754 + if (grub_timeout >= 0)
14756 + if (current_term->flags & TERM_DUMB)
14757 + grub_putchar ('\r');
14761 + grub_timeout = -1;
14762 + fallback_entryno = -1;
14763 + if (! (current_term->flags & TERM_DUMB))
14764 + gotoxy (74, 4 + entryno);
14767 + /* We told them above (at least in SUPPORT_SERIAL) to use
14768 + '^' or 'v' so accept these keys. */
14769 + if (c == 16 || c == '^')
14771 + if (current_term->flags & TERM_DUMB)
14780 + print_entry (4 + entryno, 0,
14781 + get_entry (menu_entries,
14782 + first_entry + entryno,
14785 + print_entry (4 + entryno, 1,
14786 + get_entry (menu_entries,
14787 + first_entry + entryno,
14790 + else if (first_entry > 0)
14793 + print_entries (3, 12, first_entry, entryno,
14798 + else if ((c == 14 || c == 'v')
14799 + && first_entry + entryno + 1 < num_entries)
14801 + if (current_term->flags & TERM_DUMB)
14805 + if (entryno < 11)
14807 + print_entry (4 + entryno, 0,
14808 + get_entry (menu_entries,
14809 + first_entry + entryno,
14812 + print_entry (4 + entryno, 1,
14813 + get_entry (menu_entries,
14814 + first_entry + entryno,
14817 + else if (num_entries > 12 + first_entry)
14820 + print_entries (3, 12, first_entry, entryno, menu_entries);
14827 + first_entry -= 12;
14828 + if (first_entry < 0)
14830 + entryno += first_entry;
14835 + print_entries (3, 12, first_entry, entryno, menu_entries);
14840 + first_entry += 12;
14841 + if (first_entry + entryno + 1 >= num_entries)
14843 + first_entry = num_entries - 12;
14844 + if (first_entry < 0)
14846 + entryno = num_entries - first_entry - 1;
14848 + print_entries (3, 12, first_entry, entryno, menu_entries);
14851 + if (config_entries)
14853 + if ((c == '\n') || (c == '\r') || (c == 6))
14858 + if ((c == 'd') || (c == 'o') || (c == 'O'))
14860 + if (! (current_term->flags & TERM_DUMB))
14861 + print_entry (4 + entryno, 0,
14862 + get_entry (menu_entries,
14863 + first_entry + entryno,
14866 + /* insert after is almost exactly like insert before */
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))
14879 + cur_entry = get_entry (menu_entries,
14880 + first_entry + entryno,
14885 + grub_memmove (cur_entry + 2, cur_entry,
14886 + ((int) heap) - ((int) cur_entry));
14888 + cur_entry[0] = ' ';
14889 + cur_entry[1] = 0;
14895 + else if (num_entries > 0)
14897 + char *ptr = get_entry(menu_entries,
14898 + first_entry + entryno + 1,
14901 + grub_memmove (cur_entry, ptr,
14902 + ((int) heap) - ((int) ptr));
14903 + heap -= (((int) ptr) - ((int) cur_entry));
14907 + if (entryno >= num_entries)
14909 + if (first_entry && num_entries < 12 + first_entry)
14913 + if (current_term->flags & TERM_DUMB)
14915 + grub_printf ("\n\n");
14916 + print_entries_raw (num_entries, first_entry,
14918 + grub_printf ("\n");
14921 + print_entries (3, 12, first_entry, entryno, menu_entries);
14924 + cur_entry = menu_entries;
14931 + if (! auth && password)
14935 + /* Do password check here! */
14936 + char entered[32];
14937 + char *pptr = password;
14939 + if (current_term->flags & TERM_DUMB)
14940 + grub_printf ("\r ");
14944 + /* Wipe out the previously entered password */
14945 + grub_memset (entered, 0, sizeof (entered));
14946 + get_cmdline (" Password: ", entered, 31, '*', 0);
14948 + while (! isspace (*pptr) && *pptr)
14951 + /* Make sure that PASSWORD is NUL-terminated. */
14954 + if (! check_password (entered, password, password_type))
14956 + char *new_file = config_file;
14957 + while (isspace (*pptr))
14960 + /* If *PPTR is NUL, then allow the user to use
14961 + privileged instructions, otherwise, load
14962 + another configuration file. */
14965 + while ((*(new_file++) = *(pptr++)) != 0)
14968 + /* Make sure that the user will not have
14969 + authority in the next configuration. */
14975 + /* Now the user is superhuman. */
14982 + grub_printf ("Failed!\n Press any key to continue...");
14992 + int new_num_entries = 0, i = 0;
14995 + if (config_entries)
14998 + cur_entry = get_entry (config_entries,
14999 + first_entry + entryno,
15005 + new_heap = heap + NEW_HEAPSIZE + 1;
15006 + cur_entry = get_entry (menu_entries,
15007 + first_entry + entryno,
15013 + while ((*(new_heap++) = cur_entry[i++]) != 0);
15014 + new_num_entries++;
15016 + while (config_entries && cur_entry[i]);
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;
15022 + if (config_entries)
15023 + run_menu (heap, NULL, new_num_entries, new_heap, 0);
15027 + print_cmdline_message (0);
15029 + new_heap = heap + NEW_HEAPSIZE + 1;
15031 + saved_drive = boot_drive;
15032 + saved_partition = install_partition;
15033 + current_drive = GRUB_INVALID_DRIVE;
15035 + if (! get_cmdline (PACKAGE " edit> ", new_heap,
15036 + NEW_HEAPSIZE + 1, 0, 1))
15040 + /* get length of new command */
15041 + while (new_heap[j++])
15047 + new_heap[0] = ' ';
15051 + /* align rest of commands properly */
15052 + grub_memmove (cur_entry + j, cur_entry + i,
15053 + (int) heap - ((int) cur_entry + i));
15055 + /* copy command to correct area */
15056 + grub_memmove (cur_entry, new_heap, j);
15066 + enter_cmdline (heap, 0);
15072 + /* The same as ``quit''. */
15080 + /* Attempt to boot an entry. */
15089 + if (config_entries)
15090 + printf (" Booting \'%s\'\n\n",
15091 + get_entry (menu_entries, first_entry + entryno, 0));
15093 + printf (" Booting command-list\n\n");
15096 + cur_entry = get_entry (config_entries, first_entry + entryno, 1);
15098 + /* Set CURRENT_ENTRYNO for the command "savedefault". */
15099 + current_entryno = first_entry + entryno;
15101 + if (run_script (cur_entry, heap))
15103 + if (fallback_entryno >= 0)
15105 + cur_entry = NULL;
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;
15126 +get_line_from_config (char *cmdline, int maxlen, int read_from_file)
15128 + int pos = 0, literal = 0, comment = 0;
15129 + char c; /* since we're loading it a byte at a time! */
15133 + if (read_from_file)
15135 + if (! grub_read (&c, 1))
15140 + if (! read_from_preset_menu (&c, 1))
15144 + /* Skip all carriage returns. */
15148 + /* Replace tabs with spaces. */
15152 + /* The previous is a backslash, then... */
15155 + /* If it is a newline, replace it with a space and continue. */
15160 + /* Go back to overwrite a backslash. */
15168 + /* translate characters first! */
15169 + if (c == '\\' && ! literal)
15181 + else if ((c != ' ') && (c != '\n'))
15182 + cmdline[pos++] = c;
15189 + if (pos < maxlen)
15190 + cmdline[pos++] = c;
15194 + cmdline[pos] = 0;
15200 +/* This is the starting function in C. */
15204 + int config_len, menu_len, num_entries;
15205 + char *config_entries, *menu_entries;
15206 + char *kill_buf = (char *) KILL_BUF;
15208 + auto void reset (void);
15209 + void reset (void)
15211 + count_lines = -1;
15215 + config_entries = (char *) mbi.drives_addr + mbi.drives_length;
15216 + menu_entries = (char *) MENU_BUF;
15220 + /* Initialize the environment for restarting Stage 2. */
15221 + grub_setjmp (restart_env);
15223 + /* Initialize the kill buffer. */
15226 + /* Never return. */
15229 + int is_opened, is_preset;
15233 + /* Here load the configuration file. */
15236 + if (use_config_file)
15237 +#endif /* GRUB_UTIL */
15239 + char *default_file = (char *) DEFAULT_FILE_BUF;
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] == '/')
15252 + default_file[i] = 0;
15253 + grub_strncat (default_file + i, "default", DEFAULT_FILE_BUFLEN - i);
15254 + if (grub_open (default_file))
15256 + char buf[10]; /* This is good enough. */
15260 + len = grub_read (buf, sizeof (buf));
15263 + buf[sizeof (buf) - 1] = 0;
15264 + safe_parse_maxint (&p, &saved_entryno);
15269 + errnum = ERR_NONE;
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;
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 ();
15284 + is_opened = grub_open (config_file);
15285 + errnum = ERR_NONE;
15291 + /* This is necessary, because the menu must be overrided. */
15294 + cmdline = (char *) CMDLINE_BUF;
15295 + while (get_line_from_config (cmdline, NEW_HEAPSIZE,
15298 + struct builtin *builtin;
15300 + /* Get the pointer to the builtin structure. */
15301 + builtin = find_command (cmdline);
15304 + /* Unknown command. Just skip now. */
15307 + if (builtin->flags & BUILTIN_TITLE)
15311 + /* the command "title" is specially treated. */
15314 + /* The next title is found. */
15316 + config_entries[config_len++] = 0;
15317 + prev_menu_len = menu_len;
15318 + prev_config_len = config_len;
15322 + /* The first title is found. */
15323 + menu_len = prev_menu_len;
15324 + config_len = prev_config_len;
15327 + /* Reset the state. */
15330 + /* Copy title into menu area. */
15331 + ptr = skip_to (1, cmdline);
15332 + while ((menu_entries[menu_len++] = *(ptr++)) != 0)
15335 + else if (! state)
15337 + /* Run a command found is possible. */
15338 + if (builtin->flags & BUILTIN_MENU)
15340 + char *arg = skip_to (1, cmdline);
15341 + (builtin->func) (arg, BUILTIN_MENU);
15350 + char *ptr = cmdline;
15353 + /* Copy config file data to config area. */
15354 + while ((config_entries[config_len++] = *ptr++) != 0)
15361 + /* Finish the last entry. */
15363 + config_entries[config_len++] = 0;
15367 + menu_len = prev_menu_len;
15368 + config_len = prev_config_len;
15371 + menu_entries[menu_len++] = 0;
15372 + config_entries[config_len++] = 0;
15373 + grub_memmove (config_entries + config_len, menu_entries,
15375 + menu_entries = config_entries + config_len;
15377 + /* Make sure that all fallback entries are valid. */
15378 + if (fallback_entryno >= 0)
15380 + for (i = 0; i < MAX_FALLBACK_ENTRIES; i++)
15382 + if (fallback_entries[i] < 0)
15384 + if (fallback_entries[i] >= num_entries)
15386 + grub_memmove (fallback_entries + i,
15387 + fallback_entries + i + 1,
15388 + ((MAX_FALLBACK_ENTRIES - i - 1)
15389 + * sizeof (int)));
15394 + if (fallback_entries[0] < 0)
15395 + fallback_entryno = -1;
15397 + /* Check if the default entry is present. Otherwise reset
15398 + it to fallback if fallback is valid, or to DEFAULT_ENTRY
15400 + if (default_entry >= num_entries)
15402 + if (fallback_entryno >= 0)
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;
15411 + default_entry = 0;
15415 + close_preset_menu ();
15419 + while (is_preset);
15422 + if (! num_entries)
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);
15431 + /* Run menu interface. */
15432 + run_menu (menu_entries, config_entries, num_entries,
15433 + menu_entries + menu_len, default_entry);
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
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. */
15450 void (*setcolor) (int normal_color, int highlight_color);
15451 /* Turn on/off the cursor. */
15452 int (*setcursor) (int on);
15454 + /* function to start a terminal */
15455 + int (*startup) (void);
15456 + /* function to use to shutdown a terminal */
15457 + void (*shutdown) (void);
15460 /* This lists up available terminals. */
15461 @@ -124,4 +131,23 @@
15462 int hercules_setcursor (int on);
15465 +#ifdef SUPPORT_GRAPHICS
15466 +extern int foreground, background, border, graphics_inited;
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);
15481 +void graphics_set_palette(int idx, int red, int green, int blue);
15482 +#endif /* SUPPORT_GRAPHICS */
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.
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]*\$%%'`
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 @@
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%'`
15537 # If not found, print an error message and exit.
15538 if test "x$tmp_drive" = x; then
15539 @@ -148,13 +151,13 @@
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\`)%"`
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)%"`
15556 @@ -336,6 +339,10 @@
15557 # Create a safe temporary file.
15558 test -n "$mklog" && log_file=`$mklog`
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.
15564 $grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file
15567 @@ -450,6 +457,10 @@
15568 # Create a safe temporary file.
15569 test -n "$mklog" && log_file=`$mklog`
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.
15575 # Now perform the installation.
15576 $grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file
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
15584 +# Install GRUB on your drive.
15585 +# Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
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.
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.
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.
15601 +# Initialize some variables.
15603 +exec_prefix=@exec_prefix@
15608 +host_cpu=@host_cpu@
15610 +host_vendor=@host_vendor@
15611 +pkglibdir=${libdir}/${PACKAGE}/${host_cpu}-${host_vendor}
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.$$
15618 +grub_prefix=/boot/grub
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"
15639 +# Print the usage.
15642 +Usage: grub-install [OPTION] install_device
15643 +Install GRUB on your drive.
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
15653 + --recheck probe a device map even if it already exists
15655 +INSTALL_DEVICE can be a GRUB device name or a system device filename.
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
15661 +Report bugs to <bug-grub@gnu.org>.
15665 +# Usage: convert os_device
15666 +# Convert an OS device to the corresponding GRUB drive.
15667 +# This part is OS-specific.
15669 + # First, check if the device file exists.
15670 + if test -e "$1"; then
15673 + echo "$1: Not found or not a block device." 1>&2
15677 + # Break the device name into the disk part and the partition part.
15678 + case "$host_os" in
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%%'`
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%"`
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%"`
15709 + echo "grub-install does not support your OS yet." 1>&2
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%'`
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
15723 + if test "x$tmp_part" != x; then
15724 + # If a partition is specified, we need to translate it into the
15726 + case "$host_os" in
15728 + echo "$tmp_drive" | sed "s%)$%,`expr $tmp_part - 1`)%" ;;
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\`)%"`
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)%"`
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\`)%"`
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)%"`
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)%"`
15764 + echo "$tmp_drive" ;;
15767 + # If no partition is specified, just print the drive name.
15768 + echo "$tmp_drive"
15772 +# Usage: resolve_symlink file
15773 +# Find the real file/device that file points at
15774 +resolve_symlink () {
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
15784 + # Convert relative symlinks
15785 + case $tmp_new_fname in
15786 + /*) tmp_fname="$tmp_new_fname"
15788 + *) tmp_fname="`echo $tmp_fname | sed 's%/[^/]*$%%'`/$tmp_new_fname"
15792 + echo "$tmp_fname"
15795 +# Usage: find_device file
15796 +# Find block device on which the file resides.
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'`
15802 + if test -z "$tmp_fname"; then
15803 + echo "Could not find device for $1" 2>&1
15807 + tmp_fname=`resolve_symlink $tmp_fname`
15809 + echo "$tmp_fname"
15812 +# Check the arguments.
15813 +for option in "$@"; do
15814 + case "$option" in
15819 + echo "grub-install (GNU GRUB ${VERSION})"
15821 + --root-directory=*)
15822 + rootdir=`echo "$option" | sed 's/--root-directory=//'` ;;
15824 + grub_shell=`echo "$option" | sed 's/--grub-shell=//'` ;;
15826 + no_floppy="--no-floppy" ;;
15828 + force_lba="--force-lba" ;;
15831 + # This is an undocumented feature...
15835 + echo "Unrecognized option \`$option'" 1>&2
15840 + if test "x$install_device" != x; then
15841 + echo "More than one install_devices?" 1>&2
15845 + install_device="${option}" ;;
15849 +if test "x$install_device" = x; then
15850 + echo "install_device not specified." 1>&2
15855 +# If the debugging feature is enabled, print commands.
15856 +if test $debug = yes; then
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}
15869 + # Use /boot/grub by default.
15870 + bootdir=${rootdir}/boot
15874 +grubdir=${bootdir}/grub
15875 +device_map=${grubdir}/device.map
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
15883 + echo "$1: Not found." 1>&2
15887 +if test -f "$pkglibdir/stage1"; then
15890 + echo "${pkglibdir}/stage1: Not found." 1>&2
15894 +if test -f "$pkglibdir/stage2"; then
15897 + echo "${pkglibdir}/stage2: Not found." 1>&2
15901 +# Don't check for *stage1_5, because it is not fatal even if any
15902 +# Stage 1.5 does not exist.
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
15908 +# If --recheck is specified, remove the device map, if present.
15909 +if test $recheck = yes; then
15910 + rm -f $device_map
15913 +# Create the device map file if it is not present.
15914 +if test -f "$device_map"; then
15917 + # Create a safe temporary file.
15918 + test -n "$mklog" && log_file=`$mklog`
15920 + $grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file
15923 + if grep "Error [0-9]*: " $log_file >/dev/null; then
15924 + cat $log_file 1>&2
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
15939 +# Check for INSTALL_DEVICE.
15940 +case "$install_device" in
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
15950 + install_drive="$install_device" ;;
15952 + # The GRUB format with no parenthesis.
15953 + install_drive="($install_device)" ;;
15955 + echo "Format of install_device not recognized." 1>&2
15960 +# Get the root drive.
15961 +root_device=`find_device ${rootdir}`
15962 +bootdir_device=`find_device ${bootdir}`
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"
15971 +# Convert the root device to a GRUB drive.
15972 +root_drive=`convert "$root_device"`
15973 +if test "x$root_drive" = x; then
15977 +# Check if the root directory exists in the same device as the grub
15979 +grubdir_device=`find_device ${grubdir}`
15981 +if test "x$grubdir_device" != "x$root_device"; then
15982 + # For now, cannot deal with this situation.
15984 +You must set the root directory by the option --root-directory, because
15985 +$grubdir does not exist in the root device $root_device.
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
15995 + ${pkglibdir}/stage1 ${pkglibdir}/stage2 ${pkglibdir}/*stage1_5; do
15996 + cp -f $file ${grubdir} || exit 1
15999 +# Make a default file.
16000 +${grub_set_default} --root-directory=${rootdir} default
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`
16006 +for file in ${grubdir}/stage1 ${grubdir}/stage2 ${grubdir}/*stage1_5; do
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}
16014 + if grep "Error [0-9]*: " $log_file >/dev/null; then
16016 + elif cmp $file $img_file >/dev/null; then
16020 + count=`expr $count - 1`
16022 + if test $count -eq 0; then
16023 + echo "The file $file not read correctly." 1>&2
16031 +# Create a safe temporary file.
16032 +test -n "$mklog" && log_file=`$mklog`
16034 +# Now perform the installation.
16035 +$grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file
16037 +setup $force_lba --stage2=$grubdir/stage2 --prefix=$grub_prefix $install_drive
16041 +if grep "Error [0-9]*: " $log_file >/dev/null || test $debug = yes; then
16042 + cat $log_file 1>&2
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'."
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
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>
16070 # This program is free software; you can redistribute it and/or modify
16071 @@ -94,15 +94,13 @@
16072 display Version information and exit
16074 Copyright (c) 2001,2002,2003 Thierry Laronde <tlaronde@polynum.org>.
16075 -Copyright (c) 2001,2002 Robert Millan <zeratul2@wanadoo.es>.
16078 version="mkbimage $version_number
16080 -Written by Thierry Laronde and Robert Millan.
16081 +Written by Thierry Laronde.
16083 Copyright (c) 2001,2002,2003 Thierry Laronde <tlaronde@polynum.org>.
16084 -Copyright (c) 2001,2002,2003 Robert Millan <zeratul2@wanadoo.es>.
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