aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortjd21@arcadians.cl.cam.ac.uk <tjd21@arcadians.cl.cam.ac.uk>2005-03-29 10:01:06 +0000
committertjd21@arcadians.cl.cam.ac.uk <tjd21@arcadians.cl.cam.ac.uk>2005-03-29 10:01:06 +0000
commit4ceed52eee936e46559d85e08b07123fda1ba82d (patch)
treeeafd8bb5529bc266d52d67e6a08c2c458c4589f7
parentd3bd0aa333f314d098211dd51a439b69f1a400e0 (diff)
downloadxen-4ceed52eee936e46559d85e08b07123fda1ba82d.tar.gz
xen-4ceed52eee936e46559d85e08b07123fda1ba82d.tar.bz2
xen-4ceed52eee936e46559d85e08b07123fda1ba82d.zip
bitkeeper revision 1.1236.1.149 (42492762NRUXAIqtzpmd2lX5HSPVog)
Added the mbootpack tool, which packages multiboot boot files and disguises them as a linux bzImage. Useful for booting Xen using pxelinux, or another linux-only bootloader. Signed-off-by: Tim Deegan <Tim.Deegan@cl.cam.ac.uk>
-rw-r--r--.rootkeys11
-rw-r--r--BitKeeper/etc/logging_ok1
-rw-r--r--tools/misc/Makefile4
-rw-r--r--tools/misc/mbootpack/GPL340
-rw-r--r--tools/misc/mbootpack/Makefile97
-rw-r--r--tools/misc/mbootpack/README77
-rw-r--r--tools/misc/mbootpack/bin2c.c356
-rw-r--r--tools/misc/mbootpack/bootsect.S136
-rw-r--r--tools/misc/mbootpack/buildimage.c174
-rw-r--r--tools/misc/mbootpack/mb_header.h90
-rw-r--r--tools/misc/mbootpack/mb_info.h217
-rw-r--r--tools/misc/mbootpack/mbootpack.c703
-rw-r--r--tools/misc/mbootpack/mbootpack.h91
-rw-r--r--tools/misc/mbootpack/setup.S1064
14 files changed, 3361 insertions, 0 deletions
diff --git a/.rootkeys b/.rootkeys
index c93eea13ac..fac49380c5 100644
--- a/.rootkeys
+++ b/.rootkeys
@@ -696,6 +696,17 @@
41a216ca7mgVSnCBHPCLkGOIqPS1CQ tools/libxutil/util.h
3f776bd2Xd-dUcPKlPN2vG89VGtfvQ tools/misc/Makefile
40ab2cfawIw8tsYo0dQKtp83h4qfTQ tools/misc/fakei386xen
+4249273cDOw6_uLUPvvUwWU1ZrJxnQ tools/misc/mbootpack/GPL
+4249273cSmj2h8Fj3UpTg0g-k6CLsA tools/misc/mbootpack/Makefile
+4249273c8gKIttF1QPiczvGo5AEOeA tools/misc/mbootpack/README
+4249273c4N4PAkvt3trNlto4h76k8A tools/misc/mbootpack/bin2c.c
+4249273cISg5nhW1Pt7OJ0jFu343ig tools/misc/mbootpack/bootsect.S
+4249273cUiz8CgLqnG7XYFa8x5-MoQ tools/misc/mbootpack/buildimage.c
+4249273c_gZ2yI_h-ci66E1Y5oSEPA tools/misc/mbootpack/mb_header.h
+4249273cWnlW0-lOIYua1bkKirn6vA tools/misc/mbootpack/mb_info.h
+4249273cA8LI3IMaSuhLOjykuMeQJA tools/misc/mbootpack/mbootpack.c
+4249273cVTgyv2HYd-mC29IDaz0-mg tools/misc/mbootpack/mbootpack.h
+4249273cLXQbRWFp_v-FqcyOm0sYtg tools/misc/mbootpack/setup.S
3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/misc/miniterm/Makefile
3f6dc140C8tAeBfroAF24VrmCS4v_w tools/misc/miniterm/README
3f6dc142IHaf6XIcAYGmhV9nNSIHFQ tools/misc/miniterm/miniterm.c
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index a5cd08799d..fb88f12f88 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -81,6 +81,7 @@ smh22@uridium.cl.cam.ac.uk
sos22@donkeykong.cl.cam.ac.uk
sos22@douglas.cl.cam.ac.uk
sos22@labyrinth.cl.cam.ac.uk
+tjd21@arcadians.cl.cam.ac.uk
tlh20@elite.cl.cam.ac.uk
tlh20@labyrinth.cl.cam.ac.uk
tw275@labyrinth.cl.cam.ac.uk
diff --git a/tools/misc/Makefile b/tools/misc/Makefile
index b815072184..f12193eb6e 100644
--- a/tools/misc/Makefile
+++ b/tools/misc/Makefile
@@ -21,6 +21,7 @@ INSTALL_SBIN = netfix xm xend xensv xenperf
all: build
build: $(TARGETS)
$(MAKE) -C miniterm
+ $(MAKE) -C mbootpack
install: build
[ -d $(DESTDIR)/usr/bin ] || $(INSTALL_DIR) $(DESTDIR)/usr/bin
@@ -29,10 +30,13 @@ install: build
$(INSTALL_PROG) $(INSTALL_SBIN) $(DESTDIR)/usr/sbin
# No sense in installing miniterm on the Xen box.
# $(MAKE) -C miniterm install
+# Likewise mbootpack
+# $(MAKE) -C mbootpack install
clean:
$(RM) *.o $(TARGETS) *~
$(MAKE) -C miniterm clean
+ $(MAKE) -C mbootpack clean
%.o: %.c $(HDRS) Makefile
$(CC) -c $(CFLAGS) -o $@ $<
diff --git a/tools/misc/mbootpack/GPL b/tools/misc/mbootpack/GPL
new file mode 100644
index 0000000000..5b6e7c66c2
--- /dev/null
+++ b/tools/misc/mbootpack/GPL
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/tools/misc/mbootpack/Makefile b/tools/misc/mbootpack/Makefile
new file mode 100644
index 0000000000..c0bb60e28d
--- /dev/null
+++ b/tools/misc/mbootpack/Makefile
@@ -0,0 +1,97 @@
+#
+# Makefile for mbootpack
+#
+INSTALL = install
+INSTALL_PROG = $(INSTALL) -m0755
+INSTALL_DIR = $(INSTALL) -d -m0755
+
+XEN_ROOT=../../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+CFLAGS += -Wall -Werror -O3
+
+INCLUDES += -I $(XEN_XC)
+INCLUDES += -I $(XEN_LIBXC)
+CFLAGS += $(INCLUDES)
+
+HDRS = $(wildcard *.h)
+
+TARGETS = mbootpack
+
+INSTALL_BIN = mbootpack
+INSTALL_SBIN =
+
+all: build
+build: $(TARGETS)
+
+install: build
+ $(INSTALL_PROG) $(INSTALL_BIN) $(DESTDIR)/usr/bin
+
+#
+# What object files need building for the program
+#
+
+OBJS := mbootpack.o buildimage.o
+DEPS := mbootpack.d buildimage.d
+
+#
+# Tools etc.
+#
+
+RM := rm -f
+GDB := gdb
+INCS := -I. -I-
+DEFS :=
+LDFLAGS :=
+CC := gcc
+CFLAGS := -W -Wall -Wpointer-arith -Wcast-qual -Wno-unused -Wno-format
+CFLAGS += -Wmissing-prototypes
+#CFLAGS += -pipe -g -O0 -Wcast-align
+CFLAGS += -pipe -O3
+
+#
+# Rules
+#
+
+mbootpack: $(OBJS)
+ $(CC) -o $@ $(filter-out %.a, $^) $(LDFLAGS)
+
+clean: FRC
+ $(RM) mbootpack *.o *.d bootsect setup bzimage_header.c bin2c
+
+bootsect: bootsect.S
+ $(CC) $(CFLAGS) $(INCS) $(DEFS) -D__MB_ASM -c bootsect.S -o bootsect.o
+ $(LD) -m elf_i386 -Ttext 0x0 -s --oformat binary bootsect.o -o $@
+
+setup: setup.S
+ $(CC) $(CFLAGS) $(INCS) $(DEFS) -D__MB_ASM -c setup.S -o setup.o
+ $(LD) -m elf_i386 -Ttext 0x0 -s --oformat binary setup.o -o $@
+
+bin2c: bin2c.o
+ $(CC) -o $@ $^
+
+bzimage_header.c: bootsect setup bin2c
+ ./bin2c -n 8 -b1 -a bzimage_bootsect bootsect > bzimage_header.c
+ ./bin2c -n 8 -b1 -a bzimage_setup setup >> bzimage_header.c
+
+buildimage.c buildimage.d: bzimage_header.c
+
+%.o: %.S
+ $(CC) $(CFLAGS) $(INCS) $(DEFS) -c $< -o $@
+
+%.o: %.c
+ $(CC) $(CFLAGS) $(INCS) $(DEFS) -c $< -o $@
+
+%.d: %.c
+ $(CC) $(CFLAGS) $(INCS) $(DEFS) -M $< > $@
+
+FRC:
+.PHONY:: all FRC clean gdb
+.PRECIOUS: $(OBJS) $(OBJS:.o=.c) $(DEPS)
+.SUFFIXES:
+
+-include $(DEPS)
+
+#
+# EOF
+#
diff --git a/tools/misc/mbootpack/README b/tools/misc/mbootpack/README
new file mode 100644
index 0000000000..07516529b4
--- /dev/null
+++ b/tools/misc/mbootpack/README
@@ -0,0 +1,77 @@
+
+mbootpack
+---------
+
+This is a utility to take a multiboot kernel and modules and repackage
+them in a form that a standard linux bootloader will be able to load them.
+It statically allocates memory addresses based on a 'standard' PC memory
+layout, and then saves the image of the loaded system, along with an
+almost-standard linux bzImage header which takes care of the start-of-day
+requirements of a multiboot kernel (setting up 32-bit protected mode, etc.)
+
+Example invocation, to package a xen VMM and xenlinux guest and initrd:
+
+ mbootpack -o bzImage -m ./xenlinux -m ./initrd.img ./xen-image
+
+You can now boot the 'bzImage' file using your favourite linux bootloader.
+
+The kernel command line will be provided at boot time by the bootloader
+(you can specify a kernel command-line using the '-c' flag, but it will
+be overridden at boot time unledd the bootloder provides an entirely
+empty command line). If you wan to override the command line for the
+first module (i.e. domain 0 kernel in Xen) at boot time, append ' -- '
+and the module commadn line to the bootloader command line, e.g.:
+
+ boot: bzImage com1=9600,8n1 console=com1 dom0_mem=49152 -- root=/dev/sda3 ro console=ttyS0,9600n8
+
+Everything before the '--' is passed to the kernel (xen) as its command
+line; everything after is passed to the first module (xenlinux).
+
+This is ALPHA code: there are execution paths which have *not* been
+tested, though it works for loading the Xen hypervisor using GrUB, LILO
+or SYSLINUX. Bug reports and patches are very welcome.
+
+Possible features for future versions (all look possible, if there's any
+demand for them):
+
+ - support for kernels that load below 1MB
+ - zImage-style compressed images
+ - sane error messgaes for insane load addresses
+ - support for the MULTIBOOT_VIDEO_MODE bit
+ - proper support for passing E820h memory-maps from bzImage
+
+
+Tim Deegan <tjd21@cl.cam.ac.uk>, March 2005
+
+
+
+License and attributions
+------------------------
+
+The bzImage header block was originally taken from the Linux kernel.
+http://www.kernel.org/
+
+Some parts of the Multiboot loader code are based on GNU GRUB.
+mb_info.h and mb_header.h are taken from GNU GRUB.
+http://www.gnu.org/software/grub/
+
+Bin2C was written by Nicolas Doualot; I tidied it a bit for a clean compile.
+http://slubman.celeonet.fr/program.php?style=Default&project=bin2c
+
+All other code is copyright (C) 2003-2005 Tim Deegan (tjd21@cl.cam.ac.uk)
+
+mbootpack is distributed under the GNU General Public License: see "GPL"
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
diff --git a/tools/misc/mbootpack/bin2c.c b/tools/misc/mbootpack/bin2c.c
new file mode 100644
index 0000000000..609335da7d
--- /dev/null
+++ b/tools/misc/mbootpack/bin2c.c
@@ -0,0 +1,356 @@
+/***************************************************************************************
+ Project informations:
+ Project: bin2c
+ Version: 1.00
+ Plateforme: PC
+ Copyright: DNDD.INC
+ Date: 28/03/2004
+
+ File informations:
+ Name: bin2c.c
+ Description:Convert any file to a C array
+
+ Author informations:
+ Author: DOUALOT Nicolas
+ E-Mail: slubman@laposte.net
+ site: http://membres.lycos.fr/slubman/gp32
+***************************************************************************************/
+
+
+#include <stdio.h> /*perror */
+#include <sys/mman.h> /*PROT_READ,MAP_xxx */
+#include <fcntl.h> /*O_RDONLY */
+#include <sys/stat.h> /*stat */
+#include <stdlib.h> /*atoi */
+#include <string.h> /*strcmp */
+#include <ctype.h> /*toupper */
+
+#define VERSION "1.10"
+
+
+static void help(void)
+{
+ fprintf(stdout, "\nbin2c v"VERSION"\n");
+ fprintf(stdout, "Slubman DevSoft (c)2003-2004 slubman.dndd@laposte.net \n\n");
+
+ fprintf(stdout, "Usage: bin2c [flags] <infile>\n\n");
+
+ //fprintf(stdout, "\t-quiet :\tdon't output standard messages\n");
+ //fprintf(stdout, "\t-slash :\tappend backslash at end of line\n");
+ fprintf(stdout, "\t-n <count> :\tnumber of items per line\n");
+ fprintf(stdout, "\t-b1 :\tgenerate unsigned char array\n");
+ fprintf(stdout, "\t-b2 :\tgenerate unsigned short array\n");
+ fprintf(stdout, "\t-b4 :\tgenerate unsigned long array\n");
+ fprintf(stdout, "\t-a <name> :\tgenerate an array with given name\n");
+ fprintf(stdout, "\t-ss <nr> :\tskip number of bytes at begin of inputfile\n");
+ fprintf(stdout, "\t-se <nr> :\tskip number of bytes at end of inputfile\n");
+ fprintf(stdout, "\t-lb <nr> :\tinsert an additionally linebreak every nr line\n");
+ fprintf(stdout, "\t-h :\tproduce an header\n");
+ fprintf(stdout, "\tinfile :\tname of infile\n");
+ fprintf(stdout, "\toutfile :\tname of outfile (use \"-\" for stdout)\n\n");
+
+ fprintf(stdout, " \tconverts binary file to C array data\n");
+}
+
+static void UnknownFlag(char *flag)
+{
+ fprintf(stderr, "Error: unknown flag %s\n", flag);
+ help();
+ exit(EXIT_FAILURE);
+}
+
+static void WriteHeader(FILE * outFile, char *oFileName, char *iFileName)
+{
+ // File Header
+ fprintf(outFile, "/***************************************************************************************\n");
+ fprintf(outFile, "* File Name:\n");
+ fprintf(outFile, "* Name: %s\n", oFileName);
+ fprintf(outFile, "* From: %s\n", iFileName);
+ fprintf(outFile, "* Created by :bin2c v"VERSION"\n*\n");
+ fprintf(outFile, "* bin2c v"VERSION":\n");
+ fprintf(outFile, "* Author: DOUALOT Nicolas\n");
+ fprintf(outFile, "* E-Mail: slubman.dndd@laposte.net\n");
+ fprintf(outFile, "* site: http://www.slubman.linux-fan.com/\n");
+ fprintf(outFile, "***************************************************************************************/\n\n");
+}
+
+int main(int argc, char *argv[])
+{
+ FILE *inFile = stdin, *outFile = stdout;
+ int a, i, nbLine = 0;
+ unsigned char *memory;
+ struct stat st;
+
+ // Options
+ char arrayName[255] = "array"; // Array name
+ char *iFileName = NULL; // File to convert
+ char *oFileName = NULL; // File to write
+ int bpd = 1; // Array item length
+ int lb = 0; // Array blank line each lb line(s)
+ int nbCol = 15; // Nuber of items per line
+ int SkeepStart = 0; // Number of byte to skip at file begining
+ int SkeepEnd = 0; // Number of byte to skip at file end
+ int header = 0; // Produce an header
+
+ // Is there the good number of arguments
+ if (argc < 2)
+ {
+ help();
+ return 0;
+ }
+
+ // On récupère les arguments (Ready for more options)
+ for (a = 1; a < argc; a++)
+ {
+ // An option
+ if (argv[a][0] == '-')
+ {
+ // Wich flag is it ?
+ switch (argv[a][1])
+ {
+ // Writting on stdout
+ case 0:
+ printf("%s\n", argv[a]);
+ outFile = stdout;
+ break;
+
+ // ArrayName flag
+ case 'a':
+ strcpy(arrayName, argv[++a]);
+ break;
+
+ // Data type
+ case 'b':
+ switch (argv[a][2])
+ {
+ case '1':
+ bpd = 1;
+ break;
+
+ case '2':
+ bpd = 2;
+ break;
+
+ case '4':
+ bpd = 4;
+ break;
+
+ default:
+ UnknownFlag(argv[a]);
+ }
+ break;
+
+ // Produce an header
+ case 'h':
+ header = 1;
+ break;
+
+ // New line each n line
+ case 'l':
+ switch (argv[a][2])
+ {
+ case 'b':
+ lb = atoi(argv[++a]);
+ break;
+
+ default:
+ UnknownFlag(argv[a]);
+ }
+
+ // Number of bit per line
+ case 'n':
+ nbCol = atoi(argv[++a]);
+ break;
+
+ // Skip bytes
+ case 's':
+ switch (argv[a][2])
+ {
+ // Beginig of file
+ case 's':
+ SkeepStart = atoi(argv[++a]);
+ break;
+
+ // End of file
+ case 'e':
+ SkeepEnd = atoi(argv[++a]);
+ break;
+
+ // Flag inconnu
+ default:
+ UnknownFlag(argv[a]);
+ }
+
+ // Flag inconnu
+ default:
+ UnknownFlag(argv[a]);
+ }
+ }
+ // A filename
+ else
+ {
+ if (iFileName == NULL)
+ {
+ iFileName = argv[a];
+ if ((inFile = fopen(iFileName, "rb")) == NULL)
+ {
+ fprintf(stderr, "Error: can't open %s\n", iFileName);
+ exit(EXIT_FAILURE);
+ }
+ }
+ else
+ {
+ if (oFileName == NULL)
+ {
+ oFileName = argv[a];
+ if ((outFile = fopen(oFileName, "wb")) == NULL)
+ {
+ fprintf(stderr, "Error: can't open %s\n", oFileName);
+ exit(EXIT_FAILURE);
+ }
+ }
+ else
+ {
+ fprintf(stderr, "Error: Too many filesnames given!\n");
+ help();
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+ }
+
+ if (!iFileName)
+ exit(EXIT_FAILURE);
+
+ // Get file informations
+ if (stat(iFileName, &st) != 0)
+ {
+ fprintf(stderr, "Error: when scanning file %s\n", argv[1]);
+ exit(EXIT_FAILURE);
+ }
+
+ // Allocating memory
+ if (!(memory = malloc(st.st_size + 3)))
+ {
+ memset(memory, 0, st.st_size + 3);
+ fprintf(stderr, "Error: not enought memory\n");
+ exit(EXIT_FAILURE);
+ }
+
+ // Reading the file
+ if (fread(memory, 1, st.st_size, inFile) != (size_t)st.st_size)
+ {
+ fprintf(stderr, "Error: when reading file %s\n", argv[1]);
+ fclose(inFile);
+ exit(EXIT_FAILURE);
+ }
+ fclose(inFile);
+
+ // Must produce an header
+ if (header)
+ {
+ unsigned int i;
+ char hFileName[256], *def = NULL;
+ FILE *hFile = stdout;
+
+ if (oFileName)
+ {
+ strcpy(hFileName, oFileName);
+ hFileName[strlen(hFileName) - 1] = 'h';
+ hFile = fopen(hFileName, "wt");
+ }
+
+ WriteHeader(hFile, hFileName, iFileName);
+
+ // Replace all '.' by '_'
+ for (i = 0; i < strlen(hFileName); i++)
+ if (hFileName[i] == '.')
+ hFileName[i] = '_';
+ else
+ hFileName[i] = toupper(hFileName[i]);
+
+ // the #ifdef at the begining
+ def = strrchr(hFileName, '/');
+ def = def ? def + 1 : hFileName;
+ fprintf(hFile, "#ifndef __%s__\n#define __%s__\n\n", def, def);
+
+ // Define array size
+ fprintf(hFile, "#define _%s_size_ %u\n\n", arrayName, (unsigned int) (st.st_size - SkeepStart - SkeepEnd) / bpd);
+
+ // Begin the array
+ fprintf(hFile, "extern unsigned ");
+ fprintf(hFile, "%s ", bpd == 1 ? "char" : bpd == 2 ? "short" : "long");
+ fprintf(hFile, "%s[", arrayName);
+ fprintf(hFile, "%u];\n\n", (unsigned int) (st.st_size - SkeepStart - SkeepEnd) / bpd);
+
+ // the #endif at the end
+ fprintf(hFile, "#endif\n\n");
+
+ if (oFileName)
+ fclose(hFile);
+ }
+
+ WriteHeader(outFile, oFileName, iFileName);
+
+ // Define array size
+ if (!header)
+ fprintf(outFile, "#define _%s_size_ %u\n\n", arrayName, (unsigned int) (st.st_size - SkeepStart - SkeepEnd) / bpd);
+
+ // Begin the array
+ fprintf(outFile, "unsigned ");
+ fprintf(outFile, "%s ", bpd == 1 ? "char" : bpd == 2 ? "short" : "long");
+ fprintf(outFile, "%s[", arrayName);
+ fprintf(outFile, "%u] = {\n\t", (unsigned int) (st.st_size - SkeepStart - SkeepEnd) / bpd);
+
+ // Writing file elements
+ for (i = 0; i < (st.st_size - SkeepEnd - SkeepStart) / bpd; /*i+=bpd */ i++)
+ {
+ // We write an item of bpd byte(s)
+ switch (bpd)
+ {
+ case 1:
+ fprintf(outFile, "0x%02x", *(unsigned char *) &memory[SkeepStart + i]);
+ break;
+
+ case 2:
+ fprintf(outFile, "0x%04x", *(unsigned short *) &memory[SkeepStart + i]);
+ break;
+
+ case 4:
+ fprintf(outFile, "0x%08lx", *(unsigned long *) &memory[SkeepStart + i]);
+ break;
+ }
+
+ // Must put a coma ?
+ if (i != st.st_size - 1)
+ fprintf(outFile, ",");
+
+ // End of a line ?
+ if (i && !((i + 1) % nbCol))
+ {
+ // -lb option
+ if (lb && !((++nbLine) % lb))
+ fprintf(outFile, "\n");
+ fprintf(outFile, "\n\t");
+ }
+ // Add a space
+ else
+ fprintf(outFile, " ");
+ }
+
+ // The last line as nbCol elements
+ if (((st.st_size - SkeepStart - SkeepEnd) / bpd) % nbCol)
+ fprintf(outFile, "\n");
+
+ // Close the array
+ fprintf(outFile, "};\n");
+
+ // CLose the output file
+ if (outFile != stdout)
+ fclose(outFile);
+
+ // Free allocated memory
+ free(memory);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tools/misc/mbootpack/bootsect.S b/tools/misc/mbootpack/bootsect.S
new file mode 100644
index 0000000000..2cc9ee106c
--- /dev/null
+++ b/tools/misc/mbootpack/bootsect.S
@@ -0,0 +1,136 @@
+/*
+ * bootsect.S
+ *
+ * This is bootsect.S from the linux 2.6.9 sources,
+ * with minor changes for mbootpack.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * $Id: bootsect.S,v 1.2 2005/03/23 10:39:11 tjd21 Exp $
+ *
+ */
+
+#include "mbootpack.h"
+
+/*
+ * bootsect.S Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * modified by Drew Eckhardt
+ * modified by Bruce Evans (bde)
+ * modified by Chris Noe (May 1999) (as86 -> gas)
+ * gutted by H. Peter Anvin (Jan 2003)
+ *
+ * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment
+ * addresses must be multiplied by 16 to obtain their respective linear
+ * addresses. To avoid confusion, linear addresses are written using leading
+ * hex while segment addresses are written as segment:offset.
+ *
+ */
+
+/* #include <asm/boot.h> */
+/* Definitions we should have got from there */
+#define DEF_INITSEG 0x9000
+#define DEF_SYSSEG 0x1000
+#define DEF_SETUPSEG 0x9020
+#define DEF_SYSSIZE 0x7F00
+#define NORMAL_VGA 0xffff
+#define EXTENDED_VGA 0xfffe
+#define ASK_VGA 0xfffd
+
+
+/* SETUPSECTS = 4 */ /* default nr of setup-sectors */
+BOOTSEG = 0x07C0 /* original address of boot-sector */
+INITSEG = DEF_INITSEG /* we move boot here - out of the way */
+SETUPSEG = DEF_SETUPSEG /* setup starts here */
+SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */
+SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */
+ /* to be loaded */
+ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */
+SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */
+
+#ifndef SVGA_MODE
+/* #define SVGA_MODE ASK_VGA */
+#define SVGA_MODE NORMAL_VGA
+#endif
+
+#ifndef RAMDISK
+#define RAMDISK 0
+#endif
+
+#ifndef ROOT_RDONLY
+#define ROOT_RDONLY 1
+#endif
+
+.code16
+.text
+
+.global _start
+_start:
+
+ # Normalize the start address
+ jmpl $BOOTSEG, $start2
+
+start2:
+ movw %cs, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %ss
+ movw $0x7c00, %sp
+ sti
+ cld
+
+ movw $bugger_off_msg, %si
+
+msg_loop:
+ lodsb
+ andb %al, %al
+ jz die
+ movb $0xe, %ah
+ movw $7, %bx
+ int $0x10
+ jmp msg_loop
+
+die:
+ # Allow the user to press a key, then reboot
+ xorw %ax, %ax
+ int $0x16
+ int $0x19
+
+ # int 0x19 should never return. In case it does anyway,
+ # invoke the BIOS reset code...
+ ljmp $0xf000,$0xfff0
+
+
+bugger_off_msg:
+ .ascii "Direct booting from floppy is no longer supported.\r\n"
+ .ascii "Please use a boot loader program instead.\r\n"
+ .ascii "\n"
+ .ascii "Remove disk and press any key to reboot . . .\r\n"
+ .byte 0
+
+
+ # Kernel attributes; used by setupbegtext
+
+ .org 497
+setup_sects: .byte SETUPSECTS
+root_flags: .word ROOT_RDONLY
+syssize: .word SYSSIZE
+swap_dev: .word SWAP_DEV
+ram_size: .word RAMDISK
+vid_mode: .word SVGA_MODE
+root_dev: .word ROOT_DEV
+boot_flag: .word 0xAA55
diff --git a/tools/misc/mbootpack/buildimage.c b/tools/misc/mbootpack/buildimage.c
new file mode 100644
index 0000000000..223172803d
--- /dev/null
+++ b/tools/misc/mbootpack/buildimage.c
@@ -0,0 +1,174 @@
+/*
+ * buildimage.c
+ *
+ * Takes the memory image of a loaded kernel and modules and repackages
+ * it as a linux bzImage
+ *
+ * Copyright (C) 2003-2004 Tim Deegan (tjd21@cl.cam.ac.uk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * $Id: buildimage.c,v 1.2 2005/03/23 10:39:19 tjd21 Exp $
+ *
+ */
+
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <getopt.h>
+#include <elf.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <asm/page.h>
+
+#include "mbootpack.h"
+#include "mb_header.h"
+
+/* We will build an image that a bzImage-capable bootloader will load like
+ * this:
+ *
+ * ============== (0)
+ * (BIOS memory)
+ * --------------
+ * (Bootloader)
+ * --------------
+ * bzImage startup code
+ * MBI, command-lines, module info
+ * ============== (0xa0000)
+ * (memory hole)
+ * ============== (0x100000)
+ * Kernel and modules
+ * ==============
+ *
+ * The bzImage startup code is mostly taken straight from the linux kernel
+ * (see bootsect.S, startup.S). It does the usual unpleasant start-of-day
+ * tasks to get to 32-bit protected mode, then sets registers appropriately
+ * and jumps to the kernel's entry address.
+ *
+ * It also does some relocation to make sure the MBI is where we expect it,
+ * and parses the linux command line.
+ */
+
+#define BZ_SETUP_OFFSET (512 * (1 + SETUPSECTS))
+#define BZ_ENTRY_OFFSET 0x30
+#define BZ_MBI_OFFSET 0x34
+/* These *MUST* fit the offsets of entry_address and mbi_address in setup.S */
+
+/* Bring in the bzImage boot sector and setup code */
+#include "bzimage_header.c"
+
+address_t place_mbi(long int size)
+/* Find space at the top of *low* memory for the MBI and associated red tape */
+{
+ address_t start;
+ start = 0xa000 - size;
+ if (start < 0x9000 + sizeof(bzimage_bootsect) + sizeof(bzimage_setup)) {
+ printf("Fatal: command-lines too long: need %i, have %i bytes\n",
+ size,
+ 0x1000 - (sizeof(bzimage_bootsect) + sizeof(bzimage_setup)));
+ exit(1);
+ }
+ if (!quiet) {
+ printf("Placed MBI and strings (%p+%p)\n",
+ start, size);
+ }
+ return start;
+}
+
+void make_bzImage(section_t *sections,
+ address_t entry,
+ address_t mbi,
+ FILE *fp)
+/* Rework this list of sections into a bzImage and write it out to fp */
+{
+ int i;
+ size_t offset;
+ section_t *s;
+
+ /* Patch the kernel and mbi addresses into the setup code */
+ *(address_t *)(bzimage_setup + BZ_ENTRY_OFFSET) = entry;
+ *(address_t *)(bzimage_setup + BZ_MBI_OFFSET) = mbi;
+ if (!quiet) printf("Kernel entry is %p, MBI is %p.\n", entry, mbi);
+
+ /* Write out header and trampoline */
+ if (fseek(fp, 0, SEEK_SET) < 0) {
+ printf("Fatal: error seeking in output file: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ if (fwrite(bzimage_bootsect, sizeof(bzimage_bootsect), 1, fp) != 1) {
+ printf("Fatal: error writing to output file: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ if (fwrite(bzimage_setup, sizeof(bzimage_setup), 1, fp) != 1) {
+ printf("Fatal: error writing to output file: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+
+ if (!quiet) printf("Wrote bzImage header: %i + %i bytes.\n",
+ sizeof(bzimage_bootsect), sizeof(bzimage_setup));
+
+ /* Sorted list of sections below 1MB: write them out */
+ for (s = sections, i = 0; s; s = s->next) {
+ if (s->start >= HIGHMEM_START) continue;
+ offset = (s->start - 0x9000);
+ if (fseek(fp, offset, SEEK_SET) < 0) {
+ printf("Fatal: error seeking in output file: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ if (fwrite(s->buffer, s->size, 1, fp) != 1) {
+ printf("Fatal: error writing to output file: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ i++;
+ }
+
+ if (!quiet) printf("Wrote %i low-memory sections.\n", i);
+
+ /* Sorted list of sections higher than 1MB: write them out */
+ for (s = sections, i = 0; s; s = s->next) {
+ if (s->start < HIGHMEM_START) continue;
+ offset = (s->start - HIGHMEM_START) + BZ_SETUP_OFFSET;
+ if (fseek(fp, offset, SEEK_SET) < 0) {
+ printf("Fatal: error seeking in output file: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ if (fwrite(s->buffer, s->size, 1, fp) != 1) {
+ printf("Fatal: error writing to output file: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ i++;
+ }
+
+ if (!quiet) printf("Wrote %i high-memory sections.\n", i);
+}
+
+
+/*
+ * EOF(buildimage.c)
+ */
diff --git a/tools/misc/mbootpack/mb_header.h b/tools/misc/mbootpack/mb_header.h
new file mode 100644
index 0000000000..21934574f3
--- /dev/null
+++ b/tools/misc/mbootpack/mb_header.h
@@ -0,0 +1,90 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * MultiBoot Header description
+ */
+
+struct multiboot_header
+{
+ /* Must be MULTIBOOT_MAGIC - see below. */
+ unsigned magic;
+
+ /* Feature flags - see below. */
+ unsigned flags;
+
+ /*
+ * Checksum
+ *
+ * The above fields plus this one must equal 0 mod 2^32.
+ */
+ unsigned checksum;
+
+ /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */
+ unsigned header_addr;
+ unsigned load_addr;
+ unsigned load_end_addr;
+ unsigned bss_end_addr;
+ unsigned entry_addr;
+
+ /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */
+ unsigned mode_type;
+ unsigned width;
+ unsigned height;
+ unsigned depth;
+};
+
+/*
+ * The entire multiboot_header must be contained
+ * within the first MULTIBOOT_SEARCH bytes of the kernel image.
+ */
+#define MULTIBOOT_SEARCH 8192
+#define MULTIBOOT_FOUND(addr, len) \
+ (! ((addr) & 0x3) \
+ && (len) >= 12 \
+ && *((int *) (addr)) == MULTIBOOT_MAGIC \
+ && ! (*((unsigned *) (addr)) + *((unsigned *) (addr + 4)) \
+ + *((unsigned *) (addr + 8))) \
+ && (! (MULTIBOOT_AOUT_KLUDGE & *((int *) (addr + 4))) || (len) >= 32) \
+ && (! (MULTIBOOT_VIDEO_MODE & *((int *) (addr + 4))) || (len) >= 48))
+
+/* Magic value identifying the multiboot_header. */
+#define MULTIBOOT_MAGIC 0x1BADB002
+
+/*
+ * Features flags for 'flags'.
+ * If a boot loader sees a flag in MULTIBOOT_MUSTKNOW set
+ * and it doesn't understand it, it must fail.
+ */
+#define MULTIBOOT_MUSTKNOW 0x0000FFFF
+
+/* currently unsupported flags... this is a kind of version number. */
+#define MULTIBOOT_UNSUPPORTED 0x0000FFF8
+
+/* Align all boot modules on i386 page (4KB) boundaries. */
+#define MULTIBOOT_PAGE_ALIGN 0x00000001
+
+/* Must pass memory information to OS. */
+#define MULTIBOOT_MEMORY_INFO 0x00000002
+
+/* Must pass video information to OS. */
+#define MULTIBOOT_VIDEO_MODE 0x00000004
+
+/* This flag indicates the use of the address fields in the header. */
+#define MULTIBOOT_AOUT_KLUDGE 0x00010000
diff --git a/tools/misc/mbootpack/mb_info.h b/tools/misc/mbootpack/mb_info.h
new file mode 100644
index 0000000000..fb37f10ff0
--- /dev/null
+++ b/tools/misc/mbootpack/mb_info.h
@@ -0,0 +1,217 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * The structure type "mod_list" is used by the "multiboot_info" structure.
+ */
+
+struct mod_list
+{
+ /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
+ unsigned long mod_start;
+ unsigned long mod_end;
+
+ /* Module command line */
+ unsigned long cmdline;
+
+ /* padding to take it to 16 bytes (must be zero) */
+ unsigned long pad;
+};
+
+
+/*
+ * INT-15, AX=E820 style "AddressRangeDescriptor"
+ * ...with a "size" parameter on the front which is the structure size - 4,
+ * pointing to the next one, up until the full buffer length of the memory
+ * map has been reached.
+ */
+
+struct AddrRangeDesc
+{
+ unsigned long size;
+ unsigned long long BaseAddr;
+ unsigned long long Length;
+ unsigned long Type;
+
+ /* unspecified optional padding... */
+};
+
+/* usable memory "Type", all others are reserved. */
+#define MB_ARD_MEMORY 1
+
+
+/* Drive Info structure. */
+struct drive_info
+{
+ /* The size of this structure. */
+ unsigned long size;
+
+ /* The BIOS drive number. */
+ unsigned char drive_number;
+
+ /* The access mode (see below). */
+ unsigned char drive_mode;
+
+ /* The BIOS geometry. */
+ unsigned short drive_cylinders;
+ unsigned char drive_heads;
+ unsigned char drive_sectors;
+
+ /* The array of I/O ports used for the drive. */
+ unsigned short drive_ports[0];
+};
+
+/* Drive Mode. */
+#define MB_DI_CHS_MODE 0
+#define MB_DI_LBA_MODE 1
+
+
+/* APM BIOS info. */
+struct apm_info
+{
+ unsigned short version;
+ unsigned short cseg;
+ unsigned long offset;
+ unsigned short cseg_16;
+ unsigned short dseg_16;
+ unsigned short cseg_len;
+ unsigned short cseg_16_len;
+ unsigned short dseg_16_len;
+};
+
+
+/*
+ * MultiBoot Info description
+ *
+ * This is the struct passed to the boot image. This is done by placing
+ * its address in the EAX register.
+ */
+
+struct multiboot_info
+{
+ /* MultiBoot info version number */
+ unsigned long flags;
+
+ /* Available memory from BIOS */
+ unsigned long mem_lower;
+ unsigned long mem_upper;
+
+ /* "root" partition */
+ unsigned long boot_device;
+
+ /* Kernel command line */
+ unsigned long cmdline;
+
+ /* Boot-Module list */
+ unsigned long mods_count;
+ unsigned long mods_addr;
+
+ union
+ {
+ struct
+ {
+ /* (a.out) Kernel symbol table info */
+ unsigned long tabsize;
+ unsigned long strsize;
+ unsigned long addr;
+ unsigned long pad;
+ }
+ a;
+
+ struct
+ {
+ /* (ELF) Kernel section header table */
+ unsigned long num;
+ unsigned long size;
+ unsigned long addr;
+ unsigned long shndx;
+ }
+ e;
+ }
+ syms;
+
+ /* Memory Mapping buffer */
+ unsigned long mmap_length;
+ unsigned long mmap_addr;
+
+ /* Drive Info buffer */
+ unsigned long drives_length;
+ unsigned long drives_addr;
+
+ /* ROM configuration table */
+ unsigned long config_table;
+
+ /* Boot Loader Name */
+ unsigned long boot_loader_name;
+
+ /* APM table */
+ unsigned long apm_table;
+
+ /* Video */
+ unsigned long vbe_control_info;
+ unsigned long vbe_mode_info;
+ unsigned short vbe_mode;
+ unsigned short vbe_interface_seg;
+ unsigned short vbe_interface_off;
+ unsigned short vbe_interface_len;
+};
+
+/*
+ * Flags to be set in the 'flags' parameter above
+ */
+
+/* is there basic lower/upper memory information? */
+#define MB_INFO_MEMORY 0x00000001
+/* is there a boot device set? */
+#define MB_INFO_BOOTDEV 0x00000002
+/* is the command-line defined? */
+#define MB_INFO_CMDLINE 0x00000004
+/* are there modules to do something with? */
+#define MB_INFO_MODS 0x00000008
+
+/* These next two are mutually exclusive */
+
+/* is there a symbol table loaded? */
+#define MB_INFO_AOUT_SYMS 0x00000010
+/* is there an ELF section header table? */
+#define MB_INFO_ELF_SHDR 0x00000020
+
+/* is there a full memory map? */
+#define MB_INFO_MEM_MAP 0x00000040
+
+/* Is there drive info? */
+#define MB_INFO_DRIVE_INFO 0x00000080
+
+/* Is there a config table? */
+#define MB_INFO_CONFIG_TABLE 0x00000100
+
+/* Is there a boot loader name? */
+#define MB_INFO_BOOT_LOADER_NAME 0x00000200
+
+/* Is there a APM table? */
+#define MB_INFO_APM_TABLE 0x00000400
+
+/* Is there video information? */
+#define MB_INFO_VIDEO_INFO 0x00000800
+
+/*
+ * The following value must be present in the EAX register.
+ */
+
+#define MULTIBOOT_VALID 0x2BADB002
diff --git a/tools/misc/mbootpack/mbootpack.c b/tools/misc/mbootpack/mbootpack.c
new file mode 100644
index 0000000000..42a3151cd9
--- /dev/null
+++ b/tools/misc/mbootpack/mbootpack.c
@@ -0,0 +1,703 @@
+/*
+ * mbootpack.c
+ *
+ * Takes a multiboot image, command-line and modules, and repackages
+ * them as if they were a linux kernel. Only supports a subset of
+ * the multiboot info page options (enough to boot the Xen hypervisor).
+ *
+ * Copyright (C) 2003-2004 Tim Deegan (tjd21@cl.cam.ac.uk)
+ *
+ * Parts based on GNU GRUB, Copyright (C) 2000 Free Software Foundation, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * $Id: mbootpack.c,v 1.3 2005/03/23 10:38:36 tjd21 Exp tjd21 $
+ *
+ */
+
+#define _GNU_SOURCE
+#include "mbootpack.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <getopt.h>
+#include <elf.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <asm/page.h>
+
+/* From GNU GRUB */
+#include "mb_header.h"
+#include "mb_info.h"
+
+
+/*
+ * The plan: Marshal up the multiboot modules and strings as if we
+ * were loading them into memory on a fresh ix86 PC. Attach
+ * a linux bzImage header to the front, which sets up the machine
+ * appropriately and then jumps to the kernel entry address.
+ *
+ * The memory map will be made up roughly like so:
+ *
+ * =============
+ * multiboot information (mbi) struct
+ * -------
+ * kernel command line
+ * -------
+ * bootloader name
+ * -------
+ * module command lines
+ * -------
+ * module information structs
+ * =============
+ * (memory hole)
+ * =============
+ * kernel
+ * -------------
+ * module 1
+ * -------------
+ * module 2
+ * -------------
+ * .
+ * .
+ * .
+ *
+ * ==============
+ *
+ *
+ * For allocation of memory we assume that the target machine has 'low'
+ * memory from 0 to 640K and 'high' memory starting at 1M. We allocate
+ * the kernel first, wherever it wants to be. After that, sections
+ * are added at the next available aligned address, always in the order
+ * given above, and skipping the memory hole at 640K. Allocated sections
+ * are stored in a linked list of buffers.
+ *
+ * Re-packaging as a bzImage file happens in buildimage.c
+ *
+ */
+
+/* Version */
+static const char version_string[] = "mbootpack " MBOOTPACK_VERSION_STRING;
+
+/* Flags */
+int quiet = 0;
+
+/* How much of the start of a kernel we read looking for headers.
+ * Must be >= MULTIBOOT_SEARCH */
+#define HEADERBUF_SIZE MULTIBOOT_SEARCH
+
+
+/* Linked list of loaded sections, and a pointer to the next
+ * available space (i.e. just above the highest allocation so far). */
+static section_t *sections = NULL;
+static section_t *last_section = NULL;
+static address_t next_free_space = 0;
+
+static void usage(void)
+/* If we don't understand the command-line options */
+{
+ printf(
+"Usage: mbpack [OPTIONS] kernel-image\n\n"
+" -h --help Print this text.\n"
+" -q --quiet Only output errors and warnings.\n"
+" -o --output=filename Output to filename (default \"bzImage\").\n"
+" -M --multiboot-output Produce a multiboot kernel, not a bzImage\n"
+" (sets default output file to \"mbImage\").\n"
+" -c --command-line=STRING Set the kernel command line (DEPRECATED!).\n"
+" -m --module=\"MOD arg1 arg2...\" Load module MOD with arguments \"arg1...\"\n"
+" (can be used multiple times).\n"
+"\n");
+ exit(1);
+}
+
+
+static void place_kernel_section(address_t start, long int size)
+/* Place the kernel in memory, checking for the memory hole. */
+{
+ if (start >= MEM_HOLE_END) {
+ /* Above the memory hole: easy */
+ next_free_space = MAX(next_free_space, start + size);
+ if (!quiet) {
+ printf("Placed kernel section (%p+%p)\n", start, size);
+ }
+ return;
+ }
+
+ if (start >= MEM_HOLE_START) {
+ /* In the memory hole. Not so good */
+ printf("Fatal: kernel load address (%p) is in the memory hole.\n",
+ start);
+ exit(1);
+ }
+
+ if (start + size > MEM_HOLE_START) {
+ /* Too big for low memory */
+ printf("Fatal: kernel (%p+%p) runs into the memory hole.\n",
+ start, size);
+ exit(1);
+ }
+
+ /* Kernel loads below the memory hole */
+ next_free_space = MAX(next_free_space, start + size);
+
+ if (!quiet) {
+ printf("Placed kernel section (%p+%p)\n", start, size);
+ }
+}
+
+
+static address_t place_section(long int size, int align)
+/* Find the next available place for this section.
+ * "align" must be a power of 2 */
+{
+ address_t start;
+ assert(next_free_space != 0);
+ assert(((~align + 1) & align) == align);
+
+ start = ROUNDUP_P2(next_free_space, align);
+
+ /* Check that we don't hit the memory hole */
+ if (start < MEM_HOLE_END && (start + size) > MEM_HOLE_START)
+ start = ROUNDUP_P2(MEM_HOLE_END, align);
+
+ next_free_space = start + size;
+
+ if (!quiet) {
+ printf("Placed section (%p+%p), align=%p\n",
+ start, size, align);
+ }
+ return start;
+}
+
+
+
+
+static address_t load_kernel(const char *filename)
+/* Load an elf32/multiboot kernel from this file
+ * Returns the entry address for the kernel. */
+{
+ unsigned int i;
+ address_t start;
+ size_t len;
+ long int size, loadsize;
+ FILE *fp;
+ char *buffer;
+ section_t *sec, *s;
+ Elf32_Ehdr *ehdr;
+ Elf32_Phdr *phdr;
+ struct multiboot_header *mbh;
+ struct stat sb;
+
+ static char headerbuf[HEADERBUF_SIZE];
+
+ /* Stat and open the file */
+ if (stat(filename, &sb) != 0) {
+ printf("Fatal: cannot stat %s: %s\n", filename, strerror(errno));
+ exit(1);
+ }
+ if ((fp = fopen(filename, "r")) == NULL) {
+ printf("Fatal: cannot open %s: %s\n", filename, strerror(errno));
+ exit(1);
+ }
+
+ /* Load the first 8k of the file */
+ if (fseek(fp, 0, SEEK_SET) < 0) {
+ printf("Fatal: seek error in %s: %s\n", filename, strerror(errno));
+ exit(1);
+ }
+ if ((len = fread(headerbuf, 1, HEADERBUF_SIZE, fp))
+ < HEADERBUF_SIZE)
+ {
+ if (feof(fp)) /* Short file */
+ {
+ if (len < 12) {
+ printf("Fatal: %s is too short to be a multiboot file.",
+ filename);
+ exit(1);
+ }
+ } else {
+ printf("Fatal: read error in %s: %s\n", filename, strerror(errno));
+ exit(1);
+ }
+ }
+
+ /* Sanity-check: is this file compressed? */
+ if ((headerbuf[0] == '\037' &&
+ (headerbuf[1] == '\235' /* .Z */ ||
+ headerbuf[1] == '\213' /* .gz */)) ||
+ (headerbuf[0] == 'B' && headerbuf[1] == 'Z') /* .bz[2] */) {
+ printf("Warning: %s looks like a compressed file.\n"
+ " You should uncompress it first!\n", filename);
+ }
+
+ /* Now look for a multiboot header */
+ for (i = 0; i <= MIN(len - 12, MULTIBOOT_SEARCH - 12); i += 4)
+ {
+ mbh = (struct multiboot_header *)(headerbuf + i);
+ if (mbh->magic != MULTIBOOT_MAGIC
+ || ((mbh->magic+mbh->flags+mbh->checksum) & 0xffffffff))
+ {
+ /* Not a multiboot header */
+ continue;
+ }
+ if (mbh->flags & MULTIBOOT_UNSUPPORTED) {
+ /* Requires options we don't support */
+ printf("Fatal: found a multiboot header, but it "
+ "requires multiboot options that I\n"
+ "don't understand. Sorry.\n");
+ exit(1);
+ }
+ if (mbh->flags & MULTIBOOT_VIDEO_MODE) {
+ /* Asked for screen mode information */
+ /* XXX carry on regardless */
+ printf("Warning: found a multiboot header which asks "
+ "for screen mode information.\n"
+ " This kernel will NOT be given valid"
+ "screen mode information at boot time.\n");
+ }
+ /* This kernel will do: place and load it */
+
+ if (mbh->flags & MULTIBOOT_AOUT_KLUDGE) {
+
+ /* Load using the offsets in the multiboot header */
+ if(!quiet)
+ printf("Loading %s using multiboot header.\n", filename);
+
+ /* How much is there? */
+ start = mbh->load_addr;
+ if (mbh->load_end_addr != 0)
+ loadsize = mbh->load_end_addr - mbh->load_addr;
+ else
+ loadsize = sb.st_size;
+
+ /* How much memory will it take up? */
+ if (mbh->bss_end_addr != 0)
+ size = mbh->bss_end_addr - mbh->load_addr;
+ else
+ size = loadsize;
+
+ if (loadsize > size) {
+ printf("Fatal: can't load %i bytes of kernel into %i bytes "
+ "of memory.\n", loadsize, size);
+ exit(1);
+ }
+
+ /* Does it fit where it wants to be? */
+ place_kernel_section(start, size);
+
+ /* Load the kernel */
+ if ((buffer = malloc(size)) == NULL) {
+ printf("Fatal: malloc() for kernel load failed: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ if ((fread(buffer, loadsize, 1, fp)) != 1) {
+ printf("Fatal: cannot read %s: %s\n",
+ filename, strerror(errno));
+ exit(1);
+ }
+ fclose(fp);
+
+ /* Clear the kernel BSS */
+ memset(buffer + loadsize, 0, size - loadsize);
+
+ /* Start off the linked list of sections */
+ if ((sec = (section_t *)malloc(sizeof (section_t))) == NULL) {
+ printf("Fatal: malloc() for section_t failed: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ sec->buffer = buffer;
+ sec->start = start;
+ sec->size = size;
+ sec->next = NULL;
+ sec->prev = NULL;
+ sections = sec;
+ last_section = sec;
+
+ /* Done. */
+ if (!quiet) printf("Loaded kernel from %s\n", filename);
+ return mbh->entry_addr;
+
+ } else {
+
+ /* Now look for an ELF32 header */
+ ehdr = (Elf32_Ehdr *)headerbuf;
+ if (*(unsigned long *)ehdr != 0x464c457f
+ || ehdr->e_ident[EI_DATA] != ELFDATA2LSB
+ || ehdr->e_ident[EI_CLASS] != ELFCLASS32
+ || ehdr->e_machine != EM_386)
+ {
+ printf("Fatal: kernel has neither ELF32/x86 nor multiboot load"
+ " headers.\n");
+ exit(1);
+ }
+ if (ehdr->e_phoff + ehdr->e_phnum*sizeof(*phdr) > HEADERBUF_SIZE) {
+ /* Don't expect this will happen with sane kernels */
+ printf("Fatal: too much ELF for me. Try increasing "
+ "HEADERBUF_SIZE in mbootpack.\n");
+ exit(1);
+ }
+ if (ehdr->e_phoff + ehdr->e_phnum*sizeof (*phdr) > len) {
+ printf("Fatal: malformed ELF header overruns EOF.\n");
+ exit(1);
+ }
+ if (ehdr->e_phnum <= 0) {
+ printf("Fatal: ELF kernel has no program headers.\n");
+ exit(1);
+ }
+
+ if(!quiet)
+ printf("Loading %s using ELF header.\n", filename);
+
+ if (ehdr->e_type != ET_EXEC
+ || ehdr->e_version != EV_CURRENT
+ || ehdr->e_phentsize != sizeof (Elf32_Phdr)) {
+ printf("Warning: funny-looking ELF header.\n");
+ }
+ phdr = (Elf32_Phdr *)(headerbuf + ehdr->e_phoff);
+
+ /* Obey the program headers to load the kernel */
+ for(i = 0; i < ehdr->e_phnum; i++) {
+
+ start = phdr[i].p_paddr;
+ size = phdr[i].p_memsz;
+ if (phdr[i].p_type != PT_LOAD)
+ loadsize = 0;
+ else
+ loadsize = MIN((long int)phdr[i].p_filesz, size);
+
+ if ((buffer = malloc(size)) == NULL) {
+ printf("Fatal: malloc() for kernel load failed: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+
+ /* Place the section where it wants to be */
+ place_kernel_section(start, size);
+
+ /* Load section from file */
+ if (loadsize > 0) {
+ if (fseek(fp, phdr[i].p_offset, SEEK_SET) != 0) {
+ printf("Fatal: seek failed in %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ if ((fread(buffer, loadsize, 1, fp)) != 1) {
+ printf("Fatal: cannot read %s: %s\n",
+ filename, strerror(errno));
+ exit(1);
+ }
+ }
+
+ /* Clear the rest of the buffer */
+ memset(buffer + loadsize, 0, size - loadsize);
+
+ /* Add this section to the list (keeping it ordered) */
+ if ((sec = (section_t *)malloc(sizeof (section_t))) == NULL) {
+ printf("Fatal: malloc() for section_t failed: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ sec->buffer = buffer;
+ sec->start = start;
+ sec->size = size;
+
+ for(s = sections; s; s = s->next) {
+ if (s->start > start) {
+ sec->next = s;
+ if (s->prev == NULL) {
+ /* sec becomes the new first item */
+ s->prev = sec;
+ sections = sec;
+ } else {
+ /* sec goes between s->prev and s */
+ sec->prev = s->prev;
+ sec->prev->next = sec;
+ s->prev = sec;
+ }
+ break;
+ }
+ }
+ if (s == NULL) {
+ /* sec becomes the new last item */
+ sec->next = NULL;
+ sec->prev = last_section;
+ if (last_section) {
+ last_section->next = sec;
+ } else {
+ sections = sec;
+ }
+ last_section = sec;
+ }
+ }
+
+ /* Done! */
+ if (!quiet) printf("Loaded kernel from %s\n", filename);
+ return ehdr->e_entry;
+ }
+
+ }
+
+ /* This is not a multiboot kernel */
+ printf("Fatal: %s is not a multiboot kernel.\n", filename);
+ exit(1);
+}
+
+
+
+
+int main(int argc, char **argv)
+{
+ char *buffer, *imagename, *command_line, *p;
+ char *mod_filename, *mod_command_line, *mod_clp;
+ char *out_filename;
+ section_t *sec;
+ FILE *fp;
+ struct stat sb;
+ struct multiboot_info *mbi;
+ struct mod_list *modp;
+ address_t start, kernel_entry;
+ long int size, mod_command_line_space, command_line_len;
+ int modules, opt, mbi_reloc_offset, make_multiboot;
+
+ static const char short_options[] = "hc:m:o:qM";
+ static const struct option options[] = {
+ { "help", 0, 0, 'h' },
+ { "command-line", 1, 0, 'c' },
+ { "append", 1, 0, 'c' },
+ { "module", 1, 0, 'm' },
+ { "output", 1, 0, 'o' },
+ { "quiet", 0, 0, 'q' },
+ { 0, 0, 0, 0 },
+ };
+
+ /* Parse the command line */
+ out_filename = NULL;
+ command_line = "";
+ command_line_len = 0;
+ modules = 0;
+ mod_command_line_space = 0;
+ while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1)
+ {
+ switch(opt) {
+ case 'c':
+ command_line = optarg;
+ break;
+ case 'm':
+ modules++;
+ mod_command_line_space += strlen(optarg) + 1;
+ break;
+ case 'o':
+ out_filename = optarg;
+ break;
+ case 'q':
+ quiet = 1;
+ break;
+ case 'h':
+ case '?':
+ default:
+ usage();
+ }
+ }
+ imagename = argv[optind];
+ if (!imagename || strlen(imagename) == 0) usage();
+ command_line_len = strlen(command_line) + strlen(imagename) + 2;
+ /* Leave space to overwritethe command-line at boot time */
+ command_line_len = MAX(command_line_len, CMD_LINE_SPACE);
+ if (!out_filename) out_filename = "bzImage";
+
+ /* Place and load the kernel */
+ kernel_entry = load_kernel(imagename);
+ assert(sections != NULL);
+ assert(last_section != NULL);
+ assert(next_free_space != 0);
+
+ /* Next section is all the metadata between kernel and modules */
+ size = ((((sizeof (struct multiboot_info)
+ + command_line_len
+ + strlen(version_string) + 1
+ + mod_command_line_space)
+ + 3 ) & ~3)
+ + modules * sizeof (struct mod_list));
+ /* Locate this section after the setup sectors, in *low* memory */
+ start = place_mbi(size);
+
+ if ((buffer = malloc(size)) == NULL) {
+ printf("Fatal: malloc() for boot metadata failed: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+
+ if ((sec = (section_t *)malloc(sizeof (section_t))) == NULL) {
+ printf("Fatal: malloc() for section_t failed: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ sec->buffer = buffer;
+ sec->start = start;
+ sec->size = size;
+ sec->next = NULL;
+ sec->prev = last_section;
+ last_section->next = sec;
+ last_section = sec;
+
+ /* Multiboot info struct */
+ mbi = (struct multiboot_info *)buffer;
+ memset(buffer, 0, sizeof (struct multiboot_info));
+ mbi_reloc_offset = start - (address_t)buffer;
+
+ /* Command line */
+ p = (char *)(mbi + 1);
+ sprintf(p, "%s %s", imagename, command_line);
+ mbi->cmdline = ((address_t)p) + mbi_reloc_offset;
+ p += command_line_len;
+
+ /* Bootloader ID */
+ sprintf(p, version_string);
+ mbi->boot_loader_name = ((address_t)p) + mbi_reloc_offset;
+ p += strlen(version_string) + 1;
+
+ /* Next is space for the module command lines */
+ mod_clp = p;
+
+ /* Last come the module info structs */
+ modp = (struct mod_list *)
+ ((((address_t)p + mod_command_line_space) + 3) & ~3);
+ mbi->mods_count = modules;
+ mbi->mods_addr = ((address_t)modp) + mbi_reloc_offset;
+
+ /* Memory information will be added at boot time, by setup.S
+ * or trampoline.S. */
+ mbi->flags = MB_INFO_CMDLINE | MB_INFO_BOOT_LOADER_NAME;
+
+
+ /* Load the modules */
+ if (modules) {
+ mbi->flags |= MB_INFO_MODS;
+
+ /* Go back and parse the module command lines */
+ optind = opterr = 1;
+ while((opt = getopt_long(argc, argv,
+ short_options, options, 0)) != -1)
+ {
+ if (opt != 'm') continue;
+
+ /* Split module filename from command line */
+ mod_command_line = mod_filename = optarg;
+ if ((p = strchr(mod_filename, ' ')) != NULL) {
+ /* See as I discard the 'const' modifier */
+ *p = '\0';
+ }
+
+ /* Find space for it */
+ if (stat(mod_filename, &sb) != 0) {
+ printf("Fatal: cannot stat %s: %s\n",
+ mod_filename, strerror(errno));
+ exit(1);
+ }
+ size = sb.st_size;
+ start = place_section(size, X86_PAGE_SIZE);
+ /* XXX should be place_section(size, 4) if the MBH hasn't got
+ * XXX MULTIBOOT_PAGE_ALIGN set, but that breaks Xen */
+
+ /* Load it */
+ if ((buffer = malloc(sb.st_size)) == NULL) {
+ printf("Fatal: malloc failed for module load: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ if ((fp = fopen(mod_filename, "r")) == NULL) {
+ printf("Fatal: cannot open %s: %s\n",
+ mod_filename, strerror(errno));
+ exit(1);
+ }
+ if ((fread(buffer, sb.st_size, 1, fp)) != 1) {
+ printf("Fatal: cannot read %s: %s\n",
+ mod_filename, strerror(errno));
+ exit(1);
+ }
+ fclose(fp);
+
+ /* Sanity-check: is this file compressed? */
+ if ((buffer[0] == '\037' &&
+ (buffer[1] == '\235' /* .Z */ ||
+ buffer[1] == '\213' /* .gz */)) ||
+ (buffer[0] == 'B' && buffer[1] == 'Z') /* .bz[2] */) {
+ printf("Warning: %s looks like a compressed file.\n",
+ mod_filename);
+ }
+
+ if (!quiet) printf("Loaded module from %s\n", mod_filename);
+
+ /* Restore the command line to its former glory */
+ if (p != NULL) *p = ' ';
+
+ /* Fill in the module info struct */
+ modp->mod_start = start;
+ modp->mod_end = start + size;
+ modp->cmdline = (address_t)mod_clp + mbi_reloc_offset;
+ modp->pad = 0;
+ modp++;
+
+ /* Store the module command line */
+ sprintf(mod_clp, "%s", mod_command_line);
+ mod_clp += strlen(mod_clp) + 1;
+
+ /* Add the section to the list */
+ if ((sec = (section_t *)malloc(sizeof (section_t))) == NULL) {
+ printf("Fatal: malloc() for section_t failed: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ sec->buffer = buffer;
+ sec->start = start;
+ sec->size = size;
+ sec->next = NULL;
+ sec->prev = last_section;
+ last_section->next = sec;
+ last_section = sec;
+
+ }
+
+ }
+
+ /* Everything is placed and loaded. Now we package it all up
+ * as a bzImage */
+ if ((fp = fopen(out_filename, "w")) == NULL) {
+ printf("Fatal: cannot open %s: %s\n", out_filename, strerror(errno));
+ exit(1);
+ }
+ make_bzImage(sections,
+ kernel_entry,
+ ((address_t)mbi) + mbi_reloc_offset,
+ fp);
+ fclose(fp);
+
+ /* Success! */
+ if(!quiet) printf("Finished.\n");
+ return 0;
+}
+
+/*
+ * EOF (mbootpack.c)
+ */
+
diff --git a/tools/misc/mbootpack/mbootpack.h b/tools/misc/mbootpack/mbootpack.h
new file mode 100644
index 0000000000..b28718b88c
--- /dev/null
+++ b/tools/misc/mbootpack/mbootpack.h
@@ -0,0 +1,91 @@
+/*
+ * mbootpack.h
+ *
+ * Common definitions for mbootpack
+ *
+ * Copyright (C) 2003-2004 Tim Deegan (tjd21@cl.cam.ac.uk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * $Id: mbootpack.h,v 1.2 2005/03/23 10:38:37 tjd21 Exp $
+ *
+ */
+
+#ifndef __MBOOTPACK__H__
+#define __MBOOTPACK__H__
+
+#ifndef __MB_ASM
+
+#undef NDEBUG
+#include <stdio.h>
+
+/* Flags */
+extern int quiet;
+
+/* Types */
+typedef unsigned long address_t;
+
+typedef struct section_t {
+ char *buffer;
+ address_t start;
+ long int size;
+ struct section_t *prev;
+ struct section_t *next;
+} section_t;
+
+/* buildimage.c */
+extern void make_bzImage(section_t *sections,
+ address_t entry,
+ address_t mbi,
+ FILE *fp);
+
+address_t place_mbi(long int size);
+
+
+/* trampoline.S */
+extern unsigned char mb_trampoline[];
+extern unsigned char mb_trampoline_end[];
+extern volatile address_t mb_mbi_address, mb_entry_address;
+
+/* Macros */
+#define MIN(_x,_y) (((_x)<=(_y))?(_x):(_y))
+#define MAX(_x,_y) (((_x)<=(_y))?(_y):(_x))
+#define ROUNDUP_P2(_x, _a) (((_x)+((_a)-1))&(~((_a)-1)))
+
+#endif
+
+/* x86 memory: such fun */
+#define MEM_HOLE_START 0xa0000
+#define MEM_HOLE_END 0x100000
+#define HIGHMEM_START MEM_HOLE_END
+#define X86_PAGE_SIZE 0x1000
+
+/* How much command line we'll take from the bootloader. */
+#define CMD_LINE_SPACE 0x300
+
+/* Number of 512-byte sectors to load in low memory (max 7) */
+#define SETUPSECTS 7
+
+
+/* Who are we? */
+#define MBOOTPACK_VERSION_STRING "v0.2 (alpha)"
+
+#endif /* __MBOOTPACK__H__ */
+
+/*
+ * EOF (mbootpack.h)
+ */
+
diff --git a/tools/misc/mbootpack/setup.S b/tools/misc/mbootpack/setup.S
new file mode 100644
index 0000000000..f429312df6
--- /dev/null
+++ b/tools/misc/mbootpack/setup.S
@@ -0,0 +1,1064 @@
+/*
+ * bootsect.S
+ *
+ * This is setup.S from the linux 2.6.9 source code,
+ * with heavy cuts and changes for mbootpack
+ * November 2004 Tim Deegan <tjd21@cl.cam.ac.uk>
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * $Id: setup.S,v 1.4 2005/03/23 10:39:03 tjd21 Exp $
+ *
+ */
+
+#include "mbootpack.h"
+
+/*
+ * setup.S Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * setup.s is responsible for getting the system data from the BIOS,
+ * and putting them into the appropriate places in system memory.
+ * both setup.s and system has been loaded by the bootblock.
+ *
+ * This code asks the bios for memory/disk/other parameters, and
+ * puts them in a "safe" place: 0x90000-0x901FF, ie where the
+ * boot-block used to be. It is then up to the protected mode
+ * system to read them from there before the area is overwritten
+ * for buffer-blocks.
+ *
+ * Move PS/2 aux init code to psaux.c
+ * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92
+ *
+ * some changes and additional features by Christoph Niemann,
+ * March 1993/June 1994 (Christoph.Niemann@linux.org)
+ *
+ * add APM BIOS checking by Stephen Rothwell, May 1994
+ * (sfr@canb.auug.org.au)
+ *
+ * High load stuff, initrd support and position independency
+ * by Hans Lermen & Werner Almesberger, February 1996
+ * <lermen@elserv.ffm.fgan.de>, <almesber@lrc.epfl.ch>
+ *
+ * Video handling moved to video.S by Martin Mares, March 1996
+ * <mj@k332.feld.cvut.cz>
+ *
+ * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david
+ * parsons) to avoid loadlin confusion, July 1997
+ *
+ * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999.
+ * <stiker@northlink.com>
+ *
+ * Fix to work around buggy BIOSes which dont use carry bit correctly
+ * and/or report extended memory in CX/DX for e801h memory size detection
+ * call. As a result the kernel got wrong figures. The int15/e801h docs
+ * from Ralf Brown interrupt list seem to indicate AX/BX should be used
+ * anyway. So to avoid breaking many machines (presumably there was a reason
+ * to orginally use CX/DX instead of AX/BX), we do a kludge to see
+ * if CX/DX have been changed in the e801 call and if so use AX/BX .
+ * Michael Miller, April 2001 <michaelm@mjmm.org>
+ *
+ * New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes
+ * by Robert Schwebel, December 2001 <robert@schwebel.de>
+ */
+
+/*
+#include <linux/config.h>
+#include <asm/segment.h>
+#include <linux/version.h>
+#include <linux/compile.h>
+#include <asm/boot.h>
+#include <asm/e820.h>
+#include <asm/page.h>
+*/
+
+/* Definitions that should have come from these includes */
+#define DEF_INITSEG 0x9000
+#define DEF_SYSSEG 0x1000
+#define DEF_SETUPSEG 0x9020
+#define DEF_SYSSIZE 0x7F00
+#define NORMAL_VGA 0xffff
+#define EXTENDED_VGA 0xfffe
+#define ASK_VGA 0xfffd
+#define GDT_ENTRY_BOOT_CS 2
+#define __BOOT_CS (GDT_ENTRY_BOOT_CS * 8)
+#define GDT_ENTRY_BOOT_DS (GDT_ENTRY_BOOT_CS + 1)
+#define __BOOT_DS (GDT_ENTRY_BOOT_DS * 8)
+#define __PAGE_OFFSET (0xC0000000)
+#define E820MAP 0x2d0 /* our map */
+#define E820MAX 32 /* number of entries in E820MAP */
+#define E820NR 0x1e8 /* # entries in E820MAP */
+#define E820_RAM 1
+#define E820_RESERVED 2
+#define E820_ACPI 3 /* usable as RAM once ACPI tables have been read */
+#define E820_NVS 4
+#define __BIG_KERNEL__
+
+
+/* Signature words to ensure LILO loaded us right */
+#define SIG1 0xAA55
+#define SIG2 0x5A5A
+
+INITSEG = DEF_INITSEG # 0x9000, we move boot here, out of the way
+SYSSEG = DEF_SYSSEG # 0x1000, system loaded at 0x10000 (65536).
+SETUPSEG = DEF_SETUPSEG # 0x9020, this is the current segment
+ # ... and the former contents of CS
+
+DELTA_INITSEG = SETUPSEG - INITSEG # 0x0020
+
+.code16
+.globl _start, begtext, begdata, begbss, endtext, enddata, endbss
+
+.text
+begtext:
+.data
+begdata:
+.bss
+begbss:
+.text
+
+_start:
+start:
+ jmp trampoline
+
+# This is the setup header, and it must start at %cs:2 (old 0x9020:2)
+
+ .ascii "HdrS" # header signature
+ .word 0x0203 # header version number (>= 0x0105)
+ # or else old loadlin-1.5 will fail)
+realmode_swtch: .word 0, 0 # default_switch, SETUPSEG
+start_sys_seg: .word SYSSEG
+ .word kernel_version # pointing to kernel version string
+ # above section of header is compatible
+ # with loadlin-1.5 (header v1.5). Don't
+ # change it.
+
+type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin,
+ # Bootlin, SYSLX, bootsect...)
+ # See Documentation/i386/boot.txt for
+ # assigned ids
+
+# flags, unused bits must be zero (RFU) bit within loadflags
+loadflags:
+LOADED_HIGH = 1 # If set, the kernel is loaded high
+CAN_USE_HEAP = 0x80 # If set, the loader also has set
+ # heap_end_ptr to tell how much
+ # space behind setup.S can be used for
+ # heap purposes.
+ # Only the loader knows what is free
+#ifndef __BIG_KERNEL__
+ .byte 0
+#else
+ .byte LOADED_HIGH
+#endif
+
+setup_move_size: .word 0x8000 # size to move, when setup is not
+ # loaded at 0x90000. We will move setup
+ # to 0x90000 then just before jumping
+ # into the kernel. However, only the
+ # loader knows how much data behind
+ # us also needs to be loaded.
+
+/* N.B. these next addresses are entirely ignored by this code -- it
+ * assumes it was loaded with the 32bit code at 0x100000, and doesn't
+ * touch the ramdisk. */
+code32_start: # here loaders can put a different
+ # start address for 32-bit code.
+#ifndef __BIG_KERNEL__
+ .long 0x1000 # 0x1000 = default for zImage
+#else
+ .long 0x100000 # 0x100000 = default for big kernel
+#endif
+
+ramdisk_image: .long 0 # address of loaded ramdisk image
+ # Here the loader puts the 32-bit
+ # address where it loaded the image.
+ # This only will be read by the kernel.
+
+ramdisk_size: .long 0 # its size in bytes
+
+bootsect_kludge:
+ .long 0 # obsolete
+
+heap_end_ptr: .word modelist+1024 # (Header version 0x0201 or later)
+ # space from here (exclusive) down to
+ # end of setup code can be used by setup
+ # for local heap purposes.
+
+pad1: .word 0
+cmd_line_ptr: .long 0 # (Header version 0x0202 or later)
+ # If nonzero, a 32-bit pointer
+ # to the kernel command line.
+ # The command line should be
+ # located between the start of
+ # setup and the end of low
+ # memory (0xa0000), or it may
+ # get overwritten before it
+ # gets read. If this field is
+ # used, there is no longer
+ # anything magical about the
+ # 0x90000 segment; the setup
+ # can be located anywhere in
+ # low memory 0x10000 or higher.
+
+ramdisk_max: .long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff
+ # (Header version 0x0203 or later)
+ # The highest safe address for
+ # the contents of an initrd
+
+/* Add more known locations: the image builder will overwrite
+ * these with the entry point and MBI location for the multiboot kernel.
+ * These offsets *must* match the definitions in buildimage.c */
+
+entry_address: .long 0 # This will be offset 0x30 (0x230 from b'sect)
+mbi_address: .long 0 # This will be offset 0x34
+
+/* Storage space for the size of memory */
+highmem_size: .long 0
+
+trampoline: call start_of_setup
+ .space 1024
+# End of setup header #####################################################
+
+start_of_setup:
+# Bootlin depends on this being done early
+ movw $0x01500, %ax
+ movb $0x81, %dl
+ int $0x13
+
+#ifdef SAFE_RESET_DISK_CONTROLLER
+# Reset the disk controller.
+ movw $0x0000, %ax
+ movb $0x80, %dl
+ int $0x13
+#endif
+
+# Set %ds = %cs, we know that SETUPSEG = %cs at this point
+ movw %cs, %ax # aka SETUPSEG
+ movw %ax, %ds
+
+# Check signature at end of setup
+ cmpw $SIG1, setup_sig1
+ jne bad_sig
+
+ cmpw $SIG2, setup_sig2
+ jne bad_sig
+
+ jmp good_sig1
+
+# Routine to print asciiz string at ds:si
+prtstr:
+ lodsb
+ andb %al, %al
+ jz fin
+
+ call prtchr
+ jmp prtstr
+
+fin: ret
+
+# Space printing
+prtsp2: call prtspc # Print double space
+prtspc: movb $0x20, %al # Print single space (note: fall-thru)
+
+# Part of above routine, this one just prints ascii al
+prtchr: pushw %ax
+ pushw %cx
+ movw $7,%bx
+ movw $0x01, %cx
+ movb $0x0e, %ah
+ int $0x10
+ popw %cx
+ popw %ax
+ ret
+
+beep: movb $0x07, %al
+ jmp prtchr
+
+no_sig_mess: .string "No setup signature found ..."
+
+good_sig1:
+ jmp good_sig
+
+# We now have to find the rest of the setup code/data
+bad_sig:
+ movw %cs, %ax # SETUPSEG
+ subw $DELTA_INITSEG, %ax # INITSEG
+ movw %ax, %ds
+ xorb %bh, %bh
+ movb (497), %bl # get setup sect from bootsect
+ subw $4, %bx # LILO loads 4 sectors of setup
+ shlw $8, %bx # convert to words (1sect=2^8 words)
+ movw %bx, %cx
+ shrw $3, %bx # convert to segment
+ addw $SYSSEG, %bx
+ movw %bx, %cs:start_sys_seg
+# Move rest of setup code/data to here
+ movw $2048, %di # four sectors loaded by LILO
+ subw %si, %si
+ pushw %cs
+ popw %es
+ movw $SYSSEG, %ax
+ movw %ax, %ds
+ rep
+ movsw
+ movw %cs, %ax # aka SETUPSEG
+ movw %ax, %ds
+ cmpw $SIG1, setup_sig1
+ jne no_sig
+
+ cmpw $SIG2, setup_sig2
+ jne no_sig
+
+ jmp good_sig
+
+no_sig:
+ lea no_sig_mess, %si
+ call prtstr
+
+no_sig_loop:
+ hlt
+ jmp no_sig_loop
+
+mb_hello_mess1:
+ .string "mboot"
+
+good_sig:
+ lea mb_hello_mess1, %si
+ call prtstr
+
+ movw %cs, %ax # aka SETUPSEG
+ subw $DELTA_INITSEG, %ax # aka INITSEG
+ movw %ax, %ds
+# Check if an old loader tries to load a big-kernel
+ testb $LOADED_HIGH, %cs:loadflags # Do we have a big kernel?
+ jz loader_ok # No, no danger for old loaders.
+
+ cmpb $0, %cs:type_of_loader # Do we have a loader that
+ # can deal with us?
+ jnz loader_ok # Yes, continue.
+
+ pushw %cs # No, we have an old loader,
+ popw %ds # die.
+ lea loader_panic_mess, %si
+ call prtstr
+
+ jmp no_sig_loop
+
+loader_panic_mess: .string "Wrong loader, giving up..."
+
+loader_ok:
+
+# Get memory size (extended mem, kB)
+
+/* We'll be storing this in highmem_size, to be copied to the mbi */
+
+# Try three different memory detection schemes. First, try
+# e820h, which lets us assemble a memory map, then try e801h,
+# which returns a 32-bit memory size, and finally 88h, which
+# returns 0-64m
+
+ xorl %edx, %edx
+ xorl %eax, %eax
+ movl %eax, (0x1e0)
+ movl %eax, highmem_size
+ movb %al, (E820NR)
+
+# method E820H:
+# the memory map from hell. e820h returns memory classified into
+# a whole bunch of different types, and allows memory holes and
+# everything. We scan through this memory map and build a list
+# of the first 32 memory areas, which we return at [E820MAP].
+# This is documented at http://www.acpi.info/, in the ACPI 2.0 specification.
+
+#define SMAP 0x534d4150
+
+meme820:
+ xorl %ebx, %ebx # continuation counter
+ movw $E820MAP, %di # point into the whitelist
+ # so we can have the bios
+ # directly write into it.
+
+jmpe820:
+ movl $0x0000e820, %eax # e820, upper word zeroed
+ movl $SMAP, %edx # ascii 'SMAP'
+ movl $20, %ecx # size of the e820rec
+ pushw %ds # data record.
+ popw %es
+ int $0x15 # make the call
+ jc bail820 # fall to e801 if it fails
+
+ cmpl $SMAP, %eax # check the return is `SMAP'
+ jne bail820 # fall to e801 if it fails
+
+# cmpl $1, 16(%di) # is this usable memory?
+# jne again820
+
+ # If this is usable memory, we save it by simply advancing %di by
+ # sizeof(e820rec).
+ #
+good820:
+ movb (E820NR), %al # up to 32 entries
+ cmpb $E820MAX, %al
+ jnl bail820
+
+ incb (E820NR)
+ movw %di, %ax
+ addw $20, %ax
+ movw %ax, %di
+again820:
+ cmpl $0, %ebx # check to see if
+ jne jmpe820 # %ebx is set to EOF
+
+/* Multiboot spec says high mem should be the address of the first
+ * upper memory hole, minus 1 MB */
+ xorl %ebx, %ebx
+ xorl %ecx, %ecx
+ xorl %edx, %edx
+ movw $E820MAP, %di # Start at the beginning
+calc_highmem_loop:
+ cmpl $1, 16(%di) # is it usable memory?
+ jnz calc_highmem_next
+ cmpl $0, 4(%di) # is base < 4GB?
+ jnz calc_highmem_next
+ cmpl $0x100000, 0(%di) # is base <= 1MB?
+ jg calc_highmem_next
+ movl 8(%di), %ecx # Calculate base+length
+ shrl $10, %ecx # in kilobytes
+ movl 12(%di), %edx
+ shll $22, %edx
+ orl %edx, %ecx
+ movl 0(%di), %edx
+ shrl $10, %edx
+ addl %edx, %ecx
+ subl $1024, %ecx # - 1 MB
+ cmpl %cs:highmem_size, %ecx
+ jl calc_highmem_next
+ movl %ecx, %cs:highmem_size
+calc_highmem_next:
+ add $1, %bl
+ add $20, %di
+ cmp %bl, (E820NR)
+ je calc_highmem_done
+ jmp calc_highmem_loop
+calc_highmem_done:
+
+bail820:
+
+# method E801H:
+# memory size is in 1k chunksizes, to avoid confusing loadlin.
+
+meme801:
+ stc # fix to work around buggy
+ xorw %cx,%cx # BIOSes which dont clear/set
+ xorw %dx,%dx # carry on pass/error of
+ # e801h memory size call
+ # or merely pass cx,dx though
+ # without changing them.
+ movw $0xe801, %ax
+ int $0x15
+ jc mem88
+
+ cmpw $0x0, %cx # Kludge to handle BIOSes
+ jne e801usecxdx # which report their extended
+ cmpw $0x0, %dx # memory in AX/BX rather than
+ jne e801usecxdx # CX/DX. The spec I have read
+ movw %ax, %cx # seems to indicate AX/BX
+ movw %bx, %dx # are more reasonable anyway...
+
+e801usecxdx:
+ andl $0xffff, %edx # clear sign extend
+ shll $6, %edx # and go from 64k to 1k chunks
+ andl $0xffff, %ecx # clear sign extend
+ addl %ecx, %edx
+
+ cmpl %cs:highmem_size, %edx # store extended mem size
+ jl mem88 # if it's bigger than
+ movl %edx, %cs:highmem_size # what we already have
+
+# Ye Olde Traditional Methode. Returns the memory size (up to 16mb or
+# 64mb, depending on the bios) in ax.
+mem88:
+ movb $0x88, %ah
+ int $0x15
+
+ andl $0xffff, %eax # clear sign extend
+ cmpl %cs:highmem_size, %eax # store extended mem size
+ jl have_memsize # if it's bigger than
+ movl %eax, %cs:highmem_size # what we already have
+
+have_memsize:
+
+/* Culled: HDD probes, APM, speedstep */
+
+# Now we want to move to protected mode ...
+ cmpw $0, %cs:realmode_swtch
+ jz rmodeswtch_normal
+
+ lcall *%cs:realmode_swtch
+
+ jmp rmodeswtch_end
+
+rmodeswtch_normal:
+ pushw %cs
+ call default_switch
+
+rmodeswtch_end:
+
+/* Culled: code to take the 32bit entry address from the loader */
+/* Culled: code to relocate non-bzImage kernels */
+
+ # then we load the segment descriptors
+ movw %cs, %ax # aka SETUPSEG
+ movw %ax, %ds
+
+# Check whether we need to be downward compatible with version <=201
+ cmpl $0, cmd_line_ptr
+ jne end_move_self # loader uses version >=202 features
+ cmpb $0x20, type_of_loader
+ je end_move_self # bootsect loader, we know of it
+
+# Boot loader doesnt support boot protocol version 2.02.
+# If we have our code not at 0x90000, we need to move it there now.
+# We also then need to move the params behind it (commandline)
+# Because we would overwrite the code on the current IP, we move
+# it in two steps, jumping high after the first one.
+ movw %cs, %ax
+ cmpw $SETUPSEG, %ax
+ je end_move_self
+
+ cli # make sure we really have
+ # interrupts disabled !
+ # because after this the stack
+ # should not be used
+ subw $DELTA_INITSEG, %ax # aka INITSEG
+ movw %ss, %dx
+ cmpw %ax, %dx
+ jb move_self_1
+
+ addw $INITSEG, %dx
+ subw %ax, %dx # this will go into %ss after
+ # the move
+move_self_1:
+ movw %ax, %ds
+ movw $INITSEG, %ax # real INITSEG
+ movw %ax, %es
+ movw %cs:setup_move_size, %cx
+ std # we have to move up, so we use
+ # direction down because the
+ # areas may overlap
+ movw %cx, %di
+ decw %di
+ movw %di, %si
+ subw $move_self_here+0x200, %cx
+ rep
+ movsb
+ ljmp $SETUPSEG, $move_self_here
+
+move_self_here:
+ movw $move_self_here+0x200, %cx
+ rep
+ movsb
+ movw $SETUPSEG, %ax
+ movw %ax, %ds
+ movw %dx, %ss
+end_move_self: # now we are at the right place
+
+#
+# Enable A20. This is at the very best an annoying procedure.
+# A20 code ported from SYSLINUX 1.52-1.63 by H. Peter Anvin.
+# AMD Elan bug fix by Robert Schwebel.
+#
+
+#if defined(CONFIG_X86_ELAN)
+ movb $0x02, %al # alternate A20 gate
+ outb %al, $0x92 # this works on SC410/SC520
+a20_elan_wait:
+ call a20_test
+ jz a20_elan_wait
+ jmp a20_done
+#endif
+
+
+A20_TEST_LOOPS = 32 # Iterations per wait
+A20_ENABLE_LOOPS = 255 # Total loops to try
+
+
+#ifndef CONFIG_X86_VOYAGER
+a20_try_loop:
+
+ # First, see if we are on a system with no A20 gate.
+a20_none:
+ call a20_test
+ jnz a20_done
+
+ # Next, try the BIOS (INT 0x15, AX=0x2401)
+a20_bios:
+ movw $0x2401, %ax
+ pushfl # Be paranoid about flags
+ int $0x15
+ popfl
+
+ call a20_test
+ jnz a20_done
+
+ # Try enabling A20 through the keyboard controller
+#endif /* CONFIG_X86_VOYAGER */
+a20_kbc:
+ call empty_8042
+
+#ifndef CONFIG_X86_VOYAGER
+ call a20_test # Just in case the BIOS worked
+ jnz a20_done # but had a delayed reaction.
+#endif
+
+ movb $0xD1, %al # command write
+ outb %al, $0x64
+ call empty_8042
+
+ movb $0xDF, %al # A20 on
+ outb %al, $0x60
+ call empty_8042
+
+#ifndef CONFIG_X86_VOYAGER
+ # Wait until a20 really *is* enabled; it can take a fair amount of
+ # time on certain systems; Toshiba Tecras are known to have this
+ # problem.
+a20_kbc_wait:
+ xorw %cx, %cx
+a20_kbc_wait_loop:
+ call a20_test
+ jnz a20_done
+ loop a20_kbc_wait_loop
+
+ # Final attempt: use "configuration port A"
+a20_fast:
+ inb $0x92, %al # Configuration Port A
+ orb $0x02, %al # "fast A20" version
+ andb $0xFE, %al # don't accidentally reset
+ outb %al, $0x92
+
+ # Wait for configuration port A to take effect
+a20_fast_wait:
+ xorw %cx, %cx
+a20_fast_wait_loop:
+ call a20_test
+ jnz a20_done
+ loop a20_fast_wait_loop
+
+ # A20 is still not responding. Try frobbing it again.
+ #
+ decb (a20_tries)
+ jnz a20_try_loop
+
+ movw $a20_err_msg, %si
+ call prtstr
+
+a20_die:
+ hlt
+ jmp a20_die
+
+a20_tries:
+ .byte A20_ENABLE_LOOPS
+
+a20_err_msg:
+ .ascii "linux: fatal error: A20 gate not responding!"
+ .byte 13, 10, 0
+
+ # If we get here, all is good
+a20_done:
+
+
+#endif /* CONFIG_X86_VOYAGER */
+
+/* Another print, to show protected mode and A20 are OK */
+
+ jmp mb_hello_mess2_end
+mb_hello_mess2:
+ .string "pack "
+mb_hello_mess2_end:
+ lea mb_hello_mess2, %si
+ call prtstr
+
+# set up gdt and idt
+/* lidt idt_48 # load idt with 0,0 */
+/* Multiboot kernels must set up their own IDT: leave this for now,
+ * so we can print diagnostics */
+
+ xorl %eax, %eax # Compute gdt_base
+ movw %ds, %ax # (Convert %ds:gdt to a linear ptr)
+ shll $4, %eax
+ addl $gdt, %eax
+ movl %eax, (gdt_48+2)
+ lgdt gdt_48 # load gdt with whatever is
+ # appropriate
+
+# make sure any possible coprocessor is properly reset..
+ xorw %ax, %ax
+ outb %al, $0xf0
+ call delay
+
+ outb %al, $0xf1
+ call delay
+
+
+# well, that went ok, I hope. Now we mask all interrupts - the rest
+# is done in init_IRQ().
+ movb $0xFF, %al # mask all interrupts for now
+ outb %al, $0xA1
+ call delay
+
+ movb $0xFB, %al # mask all irq's but irq2 which
+ outb %al, $0x21 # is cascaded
+
+# Well, that certainly wasn't fun :-(. Hopefully it works, and we don't
+# need no steenking BIOS anyway (except for the initial loading :-).
+# The BIOS-routine wants lots of unnecessary data, and it's less
+# "interesting" anyway. This is how REAL programmers do it.
+
+/* Tailor the jump below so the target is the 32bit trampoline code */
+
+ xorl %eax, %eax # Calculate
+ movw %cs, %ax # the linear
+ shll $4, %eax # address of
+ addl $trampoline32, %eax # %cs:trampoline32
+ movl %eax, %cs:code32 # Stick it into the jmpi
+
+ /* Load a 32-bit pointer to the entry address into %ecx */
+ xorl %ecx, %ecx # Calculate
+ movw %cs, %cx # the linear
+ shll $4, %ecx # address of
+ addl $entry_address, %ecx # %cs:entry_address
+
+# Well, now's the time to actually move into protected mode.
+
+ lea mb_ready_mess, %si
+ call prtstr
+
+/* May as well load this IDT now */
+ lidt idt_48
+
+ xorl %eax, %eax
+ movw $1, %ax # protected mode (PE) bit
+ lmsw %ax # This is it!
+ jmp flush_instr
+flush_instr:
+
+ /* Set up segment registers */
+ movw $__BOOT_DS, %dx
+ movw %dx, %ds
+ movw %dx, %es
+ movw %dx, %fs
+ movw %dx, %gs
+ movw %dx, %ss
+
+ /* Trampoline expects this in %eax */
+ movl %ecx, %eax
+
+ /* Jump to the 32-bit trampoline */
+
+# NOTE: For high loaded big kernels we need a
+# jmpi 0x100000,__BOOT_CS
+#
+# but we yet haven't reloaded the CS register, so the default size
+# of the target offset still is 16 bit.
+# However, using an operand prefix (0x66), the CPU will properly
+# take our 48 bit far pointer. (INTeL 80386 Programmer's Reference
+# Manual, Mixing 16-bit and 32-bit code, page 16-6)
+
+ .byte 0x66, 0xea # prefix + jmpi-opcode
+code32: .long 0x1000 # will be set to trampoline32
+ # by code above.
+ .word __BOOT_CS
+
+# Here's a bunch of information about your current kernel..
+
+kernel_version: .string "mbootpack changeling bzImage"
+mb_ready_mess:
+ .ascii MBOOTPACK_VERSION_STRING
+ .ascii "\r\n"
+ .byte 0
+
+# This is the default real mode switch routine.
+# to be called just before protected mode transition
+default_switch:
+ cli # no interrupts allowed !
+ movb $0x80, %al # disable NMI for bootup
+ # sequence
+ outb %al, $0x70
+ lret
+
+
+#ifndef CONFIG_X86_VOYAGER
+# This routine tests whether or not A20 is enabled. If so, it
+# exits with zf = 0.
+#
+# The memory address used, 0x200, is the int $0x80 vector, which
+# should be safe.
+
+A20_TEST_ADDR = 4*0x80
+
+a20_test:
+ pushw %cx
+ pushw %ax
+ xorw %cx, %cx
+ movw %cx, %fs # Low memory
+ decw %cx
+ movw %cx, %gs # High memory area
+ movw $A20_TEST_LOOPS, %cx
+ movw %fs:(A20_TEST_ADDR), %ax
+ pushw %ax
+a20_test_wait:
+ incw %ax
+ movw %ax, %fs:(A20_TEST_ADDR)
+ call delay # Serialize and make delay constant
+ cmpw %gs:(A20_TEST_ADDR+0x10), %ax
+ loope a20_test_wait
+
+ popw %fs:(A20_TEST_ADDR)
+ popw %ax
+ popw %cx
+ ret
+
+#endif /* CONFIG_X86_VOYAGER */
+
+# This routine checks that the keyboard command queue is empty
+# (after emptying the output buffers)
+#
+# Some machines have delusions that the keyboard buffer is always full
+# with no keyboard attached...
+#
+# If there is no keyboard controller, we will usually get 0xff
+# to all the reads. With each IO taking a microsecond and
+# a timeout of 100,000 iterations, this can take about half a
+# second ("delay" == outb to port 0x80). That should be ok,
+# and should also be plenty of time for a real keyboard controller
+# to empty.
+#
+
+empty_8042:
+ pushl %ecx
+ movl $100000, %ecx
+
+empty_8042_loop:
+ decl %ecx
+ jz empty_8042_end_loop
+
+ call delay
+
+ inb $0x64, %al # 8042 status port
+ testb $1, %al # output buffer?
+ jz no_output
+
+ call delay
+ inb $0x60, %al # read it
+ jmp empty_8042_loop
+
+no_output:
+ testb $2, %al # is input buffer full?
+ jnz empty_8042_loop # yes - loop
+empty_8042_end_loop:
+ popl %ecx
+ ret
+
+# Read the cmos clock. Return the seconds in al
+gettime:
+ pushw %cx
+ movb $0x02, %ah
+ int $0x1a
+ movb %dh, %al # %dh contains the seconds
+ andb $0x0f, %al
+ movb %dh, %ah
+ movb $0x04, %cl
+ shrb %cl, %ah
+ aad
+ popw %cx
+ ret
+
+# Delay is needed after doing I/O
+delay:
+ outb %al,$0x80
+ ret
+
+# Descriptor tables
+#
+# NOTE: The intel manual says gdt should be sixteen bytes aligned for
+# efficiency reasons. However, there are machines which are known not
+# to boot with misaligned GDTs, so alter this at your peril! If you alter
+# GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two
+# empty GDT entries (one for NULL and one reserved).
+#
+# NOTE: On some CPUs, the GDT must be 8 byte aligned. This is
+# true for the Voyager Quad CPU card which will not boot without
+# This directive. 16 byte aligment is recommended by intel.
+#
+
+
+/* The boot-time code segment is set at the jmpi above */
+/* Dont change this without checking everything still matches */
+
+ .align 16
+gdt:
+ .fill GDT_ENTRY_BOOT_CS,8,0
+
+ .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
+ .word 0 # base address = 0
+ .word 0x9A00 # code read/exec
+ .word 0x00CF # granularity = 4096, 386
+ # (+5th nibble of limit)
+
+ .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
+ .word 0 # base address = 0
+ .word 0x9200 # data read/write
+ .word 0x00CF # granularity = 4096, 386
+ # (+5th nibble of limit)
+gdt_end:
+ .align 4
+
+ .word 0 # alignment byte
+idt_48:
+ .word 0 # idt limit = 0
+ .word 0, 0 # idt base = 0L
+
+ .word 0 # alignment byte
+gdt_48:
+ .word gdt_end - gdt - 1 # gdt limit
+ .word 0, 0 # gdt base (filled in later)
+
+# Include video setup & detection code
+
+/* #include "video.S" */
+
+.code32
+trampoline32:
+ /* Here, %eax = 32-bit pointer to entry_address */
+
+ /* Check if the bootloader gave us a (non-empty) command line */
+ movl -8(%eax), %ebx # cmd_line_ptr
+ cmpl $0, %ebx
+ je no_cmd_line
+ cmpb $0, 0(%ebx)
+ je no_cmd_line
+
+ /* Find the MBI command line */
+ movl %eax, %ecx # &entry_address
+ addl $(begtext-entry_address), %ecx # --> start of setup
+ subl $0x9200, %ecx # --> reloc offset
+ movl %ecx, %esi # (copy offset)
+ movl %ecx, %ebx # (copy offset)
+ addl 4(%eax), %ecx # --> current addr of MBI
+ addl 16(%ecx), %ebx # --> cur. addr of MB cmdline
+
+ /* Overwrite the built-in MBI kernel command line */
+ movl -8(%eax), %ecx
+ movl $0, %edi
+
+ /* Give the kernel a 'self' word, that linux doesn't get */
+ movw $0x202E, 0(%ebx) # '. '
+ addl $0x2, %ebx
+
+cmd_line_copy:
+ movb (%ecx, %edi), %dl
+ movb %dl, (%ebx, %edi)
+ inc %edi
+ cmp $CMD_LINE_SPACE-3, %edi
+ je cmd_line_copy_end
+
+ cmpb $0x0, %dl
+ jne cmd_line_copy
+cmd_line_copy_end:
+ movb $0x0, (%ebx, %edi)
+ subl $0x2, %ebx
+
+ /* Look for '--' in the kernel command line */
+cmd_line_scan:
+ inc %ebx
+ cmpb $0x0, 0(%ebx)
+ je no_cmd_line
+ cmpl $0x202D2D20, 0(%ebx) # ' -- '
+ jne cmd_line_scan
+
+ /* Found it: terminate kernel's command line */
+ movb $0x0, 0(%ebx)
+ inc %ebx
+ /* Relocate address to where it will be moved to */
+ subl %esi, %ebx
+
+ /* Is there a module 0? */
+ movl %esi, %ecx # Reloc offset
+ addl 4(%eax), %ecx # --> current addr of MBI
+ cmpl $0x0, 20(%ecx) # (check module count)
+ je no_cmd_line
+ /* Overwrite module 0's command line */
+ movl %esi, %edx # Reloc offset
+ addl 24(%ecx), %edx # --> cur. add. of Module 0
+ movl %ebx, 8(%edx) # --> blat mod. 0's cmdline
+no_cmd_line:
+
+
+ /* Relocate the MBI from after the setup code to its proper home
+ * between the MBI pointer and 0xa000 */
+ movl %eax, %ecx # &entry_address
+ addl $(begtext-entry_address), %ecx # --> start of setup
+ subl $0x9200, %ecx # --> reloc offset
+ addl 4(%eax), %ecx # --> current addr of MBI
+
+ movl $0xa000, %ebx # End of MBI
+ subl 4(%eax), %ebx # --> size of MBI
+ movl %ebx, %edi
+
+ movl 4(%eax), %ebx # Destination of MBI
+
+mbi_copy:
+ dec %edi
+ movb (%ecx, %edi), %dl
+ movb %dl, (%ebx, %edi)
+ cmp $0x0, %edi
+ jne mbi_copy
+
+ /* Copy memory size into MBI structure */
+ movl 4(%eax), %ebx # MBI pointer
+ movl 8(%eax), %ecx # highmem_size
+ movl %ecx, 8(%ebx) # --> mbi.mem_upper
+ movl $0x280, %ecx
+ movl %ecx, 4(%ebx) # --> mbi.mem_lower
+ /* Set the MB_INFO_MEMORY bit */
+ orl $1, 0(%ebx)
+
+ /* Recover the MBI pointer into %ebx */
+ movl 4(%eax), %ebx # MBI pointer
+ /* Extract the load address into %ecx */
+ movl 0(%eax), %ecx
+ /* Let the kernel know we're a multiboot loader */
+ movl $0x2BADB002, %eax
+ /* Jump to the kernel address supplied */
+ jmp *%ecx
+
+# Setup signature -- must be last
+setup_sig1: .word SIG1
+setup_sig2: .word SIG2
+
+# After this point, there is some free space which is used by the video mode
+# handling code to store the temporary mode table (not used by the kernel).
+
+modelist:
+
+.text
+endtext:
+.data
+enddata:
+.bss
+endbss: