diff options
author | Stefan Reinauer <stepan@coresystems.de> | 2008-02-15 18:16:06 +0000 |
---|---|---|
committer | Stefan Reinauer <stepan@openbios.org> | 2008-02-15 18:16:06 +0000 |
commit | b34eea348cb7d6d9c93d17d51a1f322114b8f15d (patch) | |
tree | 38dd85932dacaa7c7a174d87307baff6210d70c4 /util/mkelfImage/linux-i386 | |
parent | 46fc14dcc8cdba1d66ae6fa9fdcbbf33265d676e (diff) |
Importing mkelfimage from
ftp://ftp.lnxi.com/pub/mkelfImage/mkelfImage-2.7.tar.gz
Signed-off-by: Stefan Reinauer <stepan@coresystems.de>
Acked-by: Stefan Reinauer <stepan@coresystems.de>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3103 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'util/mkelfImage/linux-i386')
-rw-r--r-- | util/mkelfImage/linux-i386/Makefile | 35 | ||||
-rw-r--r-- | util/mkelfImage/linux-i386/convert.bin.c | 284 | ||||
-rw-r--r-- | util/mkelfImage/linux-i386/convert.h | 29 | ||||
-rw-r--r-- | util/mkelfImage/linux-i386/convert.lds | 36 | ||||
-rw-r--r-- | util/mkelfImage/linux-i386/convert_params.c | 1555 | ||||
-rw-r--r-- | util/mkelfImage/linux-i386/head.S | 476 | ||||
-rw-r--r-- | util/mkelfImage/linux-i386/mkelf-linux-i386.c | 388 | ||||
-rw-r--r-- | util/mkelfImage/linux-i386/uniform_boot.h | 67 | ||||
-rw-r--r-- | util/mkelfImage/linux-i386/x86-linux.h | 162 |
9 files changed, 3032 insertions, 0 deletions
diff --git a/util/mkelfImage/linux-i386/Makefile b/util/mkelfImage/linux-i386/Makefile new file mode 100644 index 0000000000..51531d6f4b --- /dev/null +++ b/util/mkelfImage/linux-i386/Makefile @@ -0,0 +1,35 @@ +LI386_DIR:=linux-i386 +LI386_OBJ:=$(OBJDIR)/$(LI386_DIR) +LI386_DEP=Makefile Makefile.conf $(LI386_DIR)/Makefile + +$(LI386_OBJ)/mkelf-linux-i386.o: $(LI386_DIR)/mkelf-linux-i386.c $(LI386_DIR)/convert.bin.c $(LI386_DEP) + $(MKDIR) -p $(@D) + $(HOST_CC) $(HOST_CFLAGS) -c -g $< -o $@ + + +ifdef I386_CC + +$(LI386_DIR)/convert.bin.c: $(LI386_OBJ)/convert.bin $(OBJDIR)/bin/bin-to-hex $(LI386_DEP) + $(MKDIR) -p $(@D) + $(OBJDIR)/bin/bin-to-hex < $(LI386_OBJ)/convert.bin > $@ + +$(LI386_OBJ)/convert.bin: $(LI386_OBJ)/convert $(LI386_DEP) + $(MKDIR) -p $(@D) + $(I386_OBJCOPY) -O binary $< $@ + +CONVERT_LI386_OBJS=$(LI386_OBJ)/head.o $(LI386_OBJ)/convert_params.o + +$(LI386_OBJ)/convert: $(LI386_DIR)/convert.lds $(CONVERT_LI386_OBJS) $(LI386_DEP) + $(MKDIR) -p $(@D) + $(I386_LD) $(I386_LDFLAGS) -T $(LI386_DIR)/convert.lds -o $@ $(CONVERT_LI386_OBJS) + +$(LI386_OBJ)/head.o: $(LI386_DIR)/head.S $(LI386_DIR)/convert.h + $(MKDIR) -p $(@D) + $(I386_CPP) $(I386_CPPFLAGS) -DASSEMBLY $< | $(I386_AS) $(I386_ASFLAGS) -o $@ + +$(LI386_OBJ)/convert_params.o: $(LI386_DIR)/convert_params.c $(LI386_DIR)/convert.h $(LI386_DEP) + $(MKDIR) -p $(@D) + $(I386_CC) $(I386_CFLAGS) -c -o $@ $< + +endif + diff --git a/util/mkelfImage/linux-i386/convert.bin.c b/util/mkelfImage/linux-i386/convert.bin.c new file mode 100644 index 0000000000..7cf0eb5e72 --- /dev/null +++ b/util/mkelfImage/linux-i386/convert.bin.c @@ -0,0 +1,284 @@ +0xfc, 0xfa, 0xa3, 0xee, 0x01, 0x01, 0x00, 0x89, 0x1d, 0xf2, 0x01, 0x01, 0x00, 0x83, 0xfc, 0x00, +0x74, 0x09, 0x8b, 0x44, 0x24, 0x04, 0xa3, 0xf6, 0x01, 0x01, 0x00, 0x8b, 0x25, 0x8c, 0x10, 0x01, +0x00, 0x6a, 0x00, 0x9d, 0x31, 0xc0, 0xbf, 0xbc, 0x11, 0x01, 0x00, 0xb9, 0x44, 0x54, 0x01, 0x00, +0x29, 0xf9, 0xfc, 0xf3, 0xaa, 0xbe, 0x0c, 0x02, 0x01, 0x00, 0xbf, 0x00, 0x10, 0x02, 0x00, 0xb9, +0x70, 0x00, 0x00, 0x00, 0xf3, 0xa4, 0x0f, 0x01, 0x15, 0x06, 0x02, 0x01, 0x00, 0x0f, 0x01, 0x1d, +0x00, 0x02, 0x01, 0x00, 0xb8, 0x18, 0x00, 0x00, 0x00, 0x8e, 0xd8, 0x8e, 0xc0, 0x8e, 0xe0, 0x8e, +0xe8, 0x8e, 0xd0, 0x68, 0xa0, 0x10, 0x01, 0x00, 0xff, 0x35, 0xf6, 0x01, 0x01, 0x00, 0xff, 0x35, +0xf2, 0x01, 0x01, 0x00, 0xff, 0x35, 0xee, 0x01, 0x01, 0x00, 0xe8, 0x50, 0x08, 0x00, 0x00, 0x89, +0xc6, 0x83, 0xc4, 0x10, 0x6a, 0x00, 0x9d, 0x31, 0xdb, 0x31, 0xc0, 0x31, 0xc9, 0x31, 0xd2, 0x31, +0xff, 0x31, 0xe4, 0x31, 0xed, 0xea, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x55, 0x89, 0xe5, 0x53, +0x56, 0x57, 0x8b, 0x7d, 0x08, 0x81, 0xef, 0x00, 0x00, 0x01, 0x00, 0x8b, 0x75, 0x0c, 0x56, 0xe8, +0xfc, 0x00, 0x00, 0x00, 0x66, 0x31, 0xdb, 0x66, 0xb8, 0x20, 0xe8, 0x00, 0x00, 0x66, 0xba, 0x50, +0x41, 0x4d, 0x53, 0x66, 0xb9, 0x14, 0x00, 0x00, 0x00, 0xcd, 0x15, 0x72, 0x18, 0x66, 0x3d, 0x50, +0x41, 0x4d, 0x53, 0x75, 0x10, 0x66, 0x4e, 0x66, 0x85, 0xf6, 0x74, 0x09, 0x83, 0xc7, 0x14, 0x66, +0x83, 0xfb, 0x00, 0x75, 0xd2, 0x66, 0xe8, 0x82, 0x00, 0x00, 0x00, 0x58, 0x29, 0xf0, 0x5f, 0x5e, +0x5b, 0x89, 0xec, 0x5d, 0xc3, 0x53, 0x56, 0x57, 0xe8, 0xb3, 0x00, 0x00, 0x00, 0xf9, 0x31, 0xc9, +0x31, 0xd2, 0xb8, 0x01, 0xe8, 0xcd, 0x15, 0x72, 0x28, 0x83, 0xf9, 0x00, 0x75, 0x09, 0x83, 0xfa, +0x00, 0x75, 0x04, 0x89, 0xc1, 0x89, 0xda, 0x66, 0x81, 0xe2, 0xff, 0xff, 0x00, 0x00, 0x66, 0xc1, +0xe2, 0x06, 0x66, 0x89, 0xd0, 0x66, 0x81, 0xe1, 0xff, 0xff, 0x00, 0x00, 0x66, 0x01, 0xc8, 0xeb, +0x03, 0x66, 0x31, 0xc0, 0x66, 0xe8, 0x33, 0x00, 0x00, 0x00, 0x5f, 0x5e, 0x5b, 0xc3, 0x53, 0x56, +0x57, 0xe8, 0x6a, 0x00, 0x00, 0x00, 0xb4, 0x88, 0xcd, 0x15, 0x66, 0x25, 0xff, 0xff, 0x00, 0x00, +0x66, 0xe8, 0x17, 0x00, 0x00, 0x00, 0x5f, 0x5e, 0x5b, 0xc3, 0xe8, 0x51, 0x00, 0x00, 0x00, 0xcd, +0x12, 0x89, 0xc1, 0x66, 0xe8, 0x04, 0x00, 0x00, 0x00, 0x66, 0x89, 0xc8, 0xc3, 0xfa, 0x2e, 0x67, +0x0f, 0x01, 0x15, 0x06, 0x02, 0x00, 0x00, 0x0f, 0x20, 0xc0, 0x66, 0x83, 0xc8, 0x01, 0x0f, 0x22, +0xc0, 0x66, 0xea, 0x89, 0x01, 0x01, 0x00, 0x10, 0x00, 0xb8, 0x18, 0x00, 0x00, 0x00, 0x8e, 0xd8, +0x8e, 0xc0, 0x8e, 0xd0, 0x81, 0xc4, 0x00, 0x00, 0x01, 0x00, 0x31, 0xc0, 0x8e, 0xe0, 0x8e, 0xe8, +0x58, 0x05, 0x00, 0x00, 0x01, 0x00, 0x50, 0x2e, 0x0f, 0x01, 0x1d, 0x00, 0x02, 0x01, 0x00, 0xc3, +0x58, 0x2d, 0x00, 0x00, 0x01, 0x00, 0x50, 0x81, 0xec, 0x00, 0x00, 0x01, 0x00, 0xea, 0xc4, 0x01, +0x00, 0x00, 0x08, 0x00, 0x0f, 0x20, 0xc0, 0x66, 0x83, 0xe0, 0xfe, 0x0f, 0x22, 0xc0, 0x66, 0xea, +0xd6, 0x01, 0x00, 0x00, 0x00, 0x10, 0x8c, 0xc8, 0x8e, 0xd8, 0x8e, 0xc0, 0x8e, 0xd0, 0x8e, 0xe0, +0x8e, 0xe8, 0x2e, 0x67, 0x0f, 0x01, 0x1d, 0xfa, 0x01, 0x00, 0x00, 0xfb, 0x66, 0xc3, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x01, 0x9b, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, +0x00, 0x9a, 0xcf, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00, 0xff, 0xff, 0x00, 0x00, +0x01, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, +0x00, 0x9a, 0xcf, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00, 0x55, 0x89, 0xe5, 0x89, +0xc1, 0xba, 0xfd, 0x03, 0x00, 0x00, 0xec, 0xa8, 0x20, 0x74, 0xf6, 0xb2, 0xf8, 0x88, 0xc8, 0xee, +0xba, 0xfd, 0x03, 0x00, 0x00, 0xec, 0xa8, 0x40, 0x74, 0xf6, 0xc9, 0xc3, 0x55, 0x83, 0xf8, 0x0a, +0x89, 0xe5, 0x53, 0x89, 0xc3, 0x75, 0x0a, 0xb8, 0x0d, 0x00, 0x00, 0x00, 0xe8, 0xcb, 0xff, 0xff, +0xff, 0x89, 0xd8, 0x5b, 0xc9, 0xeb, 0xc5, 0x55, 0x89, 0xe5, 0x57, 0x56, 0x53, 0x83, 0xec, 0x44, +0x8d, 0x45, 0x0c, 0x8b, 0x75, 0x08, 0x89, 0x45, 0xc0, 0x80, 0x3e, 0x00, 0x0f, 0x84, 0x5b, 0x01, +0x00, 0x00, 0x8a, 0x06, 0x3c, 0x25, 0x74, 0x0d, 0x0f, 0xbe, 0xc0, 0xe8, 0xbc, 0xff, 0xff, 0xff, +0xe9, 0x42, 0x01, 0x00, 0x00, 0x46, 0x8a, 0x06, 0x3c, 0x73, 0x75, 0x1d, 0x8b, 0x45, 0xc0, 0x8b, +0x18, 0x83, 0x45, 0xc0, 0x04, 0x80, 0x3b, 0x00, 0x0f, 0x84, 0x29, 0x01, 0x00, 0x00, 0x0f, 0xbe, +0x03, 0xe8, 0x96, 0xff, 0xff, 0xff, 0x43, 0xeb, 0xec, 0x3c, 0x4c, 0x8d, 0x7d, 0xc4, 0xc7, 0x45, +0xbc, 0x1c, 0x00, 0x00, 0x00, 0x75, 0x09, 0xc7, 0x45, 0xbc, 0x3c, 0x00, 0x00, 0x00, 0xeb, 0x1c, +0x3c, 0x6c, 0x74, 0x18, 0x3c, 0x68, 0x75, 0x15, 0xc7, 0x45, 0xbc, 0x0c, 0x00, 0x00, 0x00, 0x46, +0x80, 0x3e, 0x68, 0x75, 0x08, 0xc7, 0x45, 0xbc, 0x04, 0x00, 0x00, 0x00, 0x46, 0x8a, 0x16, 0x88, +0xd0, 0x83, 0xc8, 0x20, 0x3c, 0x78, 0x75, 0x61, 0x83, 0x7d, 0xbc, 0x1c, 0x7e, 0x0e, 0x8b, 0x45, +0xc0, 0x8b, 0x08, 0x83, 0x45, 0xc0, 0x08, 0x8b, 0x58, 0x04, 0xeb, 0x0b, 0x8b, 0x45, 0xc0, 0x8b, +0x08, 0x83, 0x45, 0xc0, 0x04, 0x31, 0xdb, 0x89, 0x5d, 0xb4, 0x89, 0xd3, 0x83, 0xe3, 0x20, 0x89, +0x4d, 0xb0, 0x89, 0x5d, 0xb8, 0x83, 0x7d, 0xbc, 0x00, 0x0f, 0x88, 0x96, 0x00, 0x00, 0x00, 0x8a, +0x4d, 0xbc, 0x8b, 0x55, 0xb4, 0x8b, 0x45, 0xb0, 0x0f, 0xad, 0xd0, 0xd3, 0xea, 0x80, 0xe1, 0x20, +0x74, 0x02, 0x89, 0xd0, 0x83, 0xe0, 0x0f, 0x8a, 0x5d, 0xb8, 0x0a, 0x98, 0x48, 0x0f, 0x01, 0x00, +0x88, 0x1f, 0x47, 0x83, 0x6d, 0xbc, 0x04, 0xeb, 0xd0, 0x80, 0xfa, 0x64, 0x75, 0x4e, 0x83, 0x7d, +0xbc, 0x1c, 0x7e, 0x09, 0x8b, 0x45, 0xc0, 0x83, 0x45, 0xc0, 0x08, 0xeb, 0x07, 0x8b, 0x45, 0xc0, +0x83, 0x45, 0xc0, 0x04, 0x8b, 0x10, 0x85, 0xd2, 0x79, 0x06, 0xc6, 0x07, 0x2d, 0xf7, 0xda, 0x47, +0x89, 0xfb, 0x89, 0xd0, 0x99, 0xb9, 0x0a, 0x00, 0x00, 0x00, 0xf7, 0xf9, 0x83, 0xc2, 0x30, 0x88, +0x17, 0x47, 0x85, 0xc0, 0x89, 0xc2, 0x75, 0xea, 0x8d, 0x4f, 0xff, 0x39, 0xd9, 0x76, 0x26, 0x0f, +0xbe, 0x11, 0x8a, 0x03, 0x88, 0x01, 0x88, 0x13, 0x49, 0x43, 0xeb, 0xef, 0x80, 0xfa, 0x63, 0x8d, +0x4f, 0x01, 0x75, 0x0d, 0x8b, 0x45, 0xc0, 0x8b, 0x00, 0x83, 0x45, 0xc0, 0x04, 0x88, 0x07, 0xeb, +0x02, 0x88, 0x17, 0x89, 0xcf, 0x8d, 0x5d, 0xc4, 0x39, 0xfb, 0x73, 0x0b, 0x0f, 0xbe, 0x03, 0xe8, +0x78, 0xfe, 0xff, 0xff, 0x43, 0xeb, 0xf1, 0x46, 0xe9, 0x9c, 0xfe, 0xff, 0xff, 0x83, 0xc4, 0x44, +0x5b, 0x5e, 0x5f, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x8b, 0x55, 0x08, 0x8b, 0x4d, 0x0c, 0x31, 0xc0, +0xeb, 0x07, 0x80, 0x3a, 0x00, 0x74, 0x06, 0x40, 0x42, 0x39, 0xc8, 0x72, 0xf5, 0xc9, 0xc3, 0x55, +0x89, 0xe5, 0x8b, 0x45, 0x08, 0x53, 0x8b, 0x4d, 0x10, 0x8b, 0x5d, 0x0c, 0x31, 0xd2, 0x39, 0xca, +0x73, 0x06, 0x88, 0x1c, 0x10, 0x42, 0xeb, 0xf6, 0x5b, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x53, +0x8b, 0x4d, 0x08, 0x8b, 0x75, 0x0c, 0x8b, 0x5d, 0x10, 0x31, 0xd2, 0x39, 0xda, 0x73, 0x09, 0x8a, +0x04, 0x16, 0x88, 0x04, 0x11, 0x42, 0xeb, 0xf3, 0x5b, 0x89, 0xc8, 0x5e, 0xc9, 0xc3, 0x55, 0x89, +0xe5, 0x57, 0x56, 0x53, 0x8b, 0x7d, 0x08, 0x8b, 0x75, 0x0c, 0x8b, 0x5d, 0x10, 0x31, 0xd2, 0x39, +0xda, 0x73, 0x15, 0x8a, 0x0f, 0x8a, 0x06, 0x38, 0xc1, 0x74, 0x0a, 0x0f, 0xb6, 0xd0, 0x0f, 0xb6, +0xc1, 0x29, 0xc2, 0xeb, 0x05, 0x42, 0xeb, 0xe7, 0x31, 0xd2, 0x5b, 0x5e, 0x89, 0xd0, 0x5f, 0xc9, +0xc3, 0x55, 0x89, 0xe5, 0x56, 0x53, 0x89, 0xd3, 0x51, 0x31, 0xc9, 0x31, 0xd2, 0x89, 0xc6, 0x39, +0xd9, 0x73, 0x26, 0xf6, 0xc2, 0x01, 0x0f, 0xb6, 0x04, 0x16, 0x74, 0x03, 0xc1, 0xe0, 0x08, 0x01, +0xc1, 0x81, 0xf9, 0xff, 0xff, 0x00, 0x00, 0x76, 0x0b, 0x89, 0xc8, 0xc1, 0xe8, 0x10, 0x8d, 0x04, +0x01, 0x0f, 0xb7, 0xc8, 0x42, 0x39, 0xda, 0xeb, 0xd8, 0x88, 0x4d, 0xf6, 0xc1, 0xe9, 0x08, 0x88, +0x4d, 0xf7, 0x66, 0x8b, 0x45, 0xf6, 0x5a, 0x5b, 0xf7, 0xd0, 0x0f, 0xb7, 0xc0, 0x5e, 0xc9, 0xc3, +0x55, 0x89, 0xe5, 0x57, 0x56, 0x53, 0x8b, 0x5d, 0x08, 0x68, 0x00, 0x01, 0x00, 0x00, 0x8d, 0x83, +0x00, 0x08, 0x00, 0x00, 0x50, 0x8b, 0x7d, 0x10, 0xe8, 0x08, 0xff, 0xff, 0xff, 0x01, 0xc3, 0x5e, +0xb8, 0xff, 0x00, 0x00, 0x00, 0x5a, 0xc6, 0x83, 0x00, 0x08, 0x00, 0x00, 0x20, 0x81, 0xc3, 0x01, +0x08, 0x00, 0x00, 0x39, 0xf8, 0x7e, 0x02, 0x89, 0xf8, 0x50, 0xff, 0x75, 0x0c, 0xe8, 0xe3, 0xfe, +0xff, 0xff, 0x50, 0xff, 0x75, 0x0c, 0x89, 0xc6, 0x53, 0xe8, 0x0d, 0xff, 0xff, 0xff, 0xc6, 0x04, +0x33, 0x00, 0x8d, 0x65, 0xf4, 0x5b, 0x5e, 0x5f, 0xc9, 0xc3, 0x55, 0x81, 0xfa, 0xff, 0xff, 0x3f, +0x00, 0x89, 0xe5, 0x89, 0xd1, 0x53, 0x89, 0xc3, 0x76, 0x05, 0xb9, 0xff, 0xff, 0x3f, 0x00, 0x8b, +0x83, 0xe0, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x00, 0x39, 0xc1, 0x76, 0x24, 0x8d, 0x91, +0x00, 0xfc, 0xff, 0xff, 0x8d, 0x81, 0x00, 0xfc, 0xff, 0xff, 0x81, 0xfa, 0xff, 0xff, 0x00, 0x00, +0x89, 0x93, 0xe0, 0x01, 0x00, 0x00, 0x66, 0x89, 0x43, 0x02, 0x76, 0x06, 0x66, 0xc7, 0x43, 0x02, +0x00, 0xfc, 0x5b, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x53, 0x83, 0xec, 0x10, 0x89, 0xc1, 0x8b, +0x55, 0x0c, 0x8b, 0x45, 0x08, 0x8b, 0x5d, 0x10, 0x8b, 0x75, 0x14, 0x89, 0x55, 0xf4, 0x89, 0x45, +0xf0, 0x89, 0x5d, 0xe8, 0x89, 0x75, 0xec, 0x0f, 0xb6, 0x81, 0xe8, 0x01, 0x00, 0x00, 0x83, 0xf8, +0x1f, 0x8b, 0x55, 0x18, 0x7f, 0x35, 0x6b, 0xc0, 0x14, 0x01, 0xc8, 0x8b, 0x5d, 0xf0, 0x8b, 0x75, +0xf4, 0x89, 0x98, 0xd0, 0x02, 0x00, 0x00, 0x89, 0xb0, 0xd4, 0x02, 0x00, 0x00, 0x8b, 0x5d, 0xe8, +0x8b, 0x75, 0xec, 0x89, 0x98, 0xd8, 0x02, 0x00, 0x00, 0x89, 0xb0, 0xdc, 0x02, 0x00, 0x00, 0x89, +0x90, 0xe0, 0x02, 0x00, 0x00, 0xfe, 0x81, 0xe8, 0x01, 0x00, 0x00, 0x4a, 0x75, 0x2e, 0x8b, 0x45, +0xf0, 0x03, 0x45, 0xe8, 0x8b, 0x55, 0xf4, 0x13, 0x55, 0xec, 0x81, 0xfa, 0xff, 0x03, 0x00, 0x00, +0x72, 0x07, 0x76, 0x05, 0x83, 0xca, 0xff, 0xeb, 0x06, 0x0f, 0xac, 0xd0, 0x0a, 0x89, 0xc2, 0x83, +0xc4, 0x10, 0x5b, 0x5e, 0x89, 0xc8, 0xc9, 0xe9, 0x1e, 0xff, 0xff, 0xff, 0x83, 0xc4, 0x10, 0x5b, +0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x8b, 0x45, 0x0c, 0x8b, 0x55, 0x10, 0x89, 0x45, 0x10, 0x8b, +0x45, 0x08, 0x8b, 0x40, 0x10, 0x89, 0x55, 0x0c, 0x89, 0x45, 0x08, 0xc9, 0xe9, 0x9f, 0xfe, 0xff, +0xff, 0x55, 0x89, 0xe5, 0x57, 0x56, 0x53, 0x39, 0xd0, 0x56, 0x56, 0x89, 0xc7, 0x89, 0x55, 0xf0, +0x73, 0x77, 0x8d, 0x58, 0x18, 0x81, 0x7b, 0xe8, 0x4c, 0x42, 0x49, 0x4f, 0x75, 0x60, 0x83, 0x7b, +0xec, 0x18, 0x75, 0x5a, 0xba, 0x18, 0x00, 0x00, 0x00, 0x89, 0xf8, 0xe8, 0x21, 0xfe, 0xff, 0xff, +0x85, 0xc0, 0x75, 0x4a, 0x8b, 0x53, 0xf4, 0x89, 0xd8, 0xe8, 0x13, 0xfe, 0xff, 0xff, 0x3b, 0x43, +0xf8, 0x75, 0x3b, 0x89, 0xde, 0x03, 0x73, 0xf4, 0x39, 0xf3, 0xc7, 0x45, 0xec, 0x00, 0x00, 0x00, +0x00, 0x89, 0xd9, 0x73, 0x1d, 0x89, 0xf0, 0x29, 0xd8, 0x8b, 0x53, 0x04, 0x39, 0xc2, 0x77, 0x12, +0x01, 0xd1, 0xff, 0x45, 0xec, 0x39, 0xf1, 0x73, 0x09, 0x89, 0xf0, 0x29, 0xc8, 0x8b, 0x51, 0x04, +0xeb, 0xea, 0x8b, 0x45, 0xec, 0x3b, 0x43, 0xfc, 0x75, 0x04, 0x89, 0xf8, 0xeb, 0x0d, 0x83, 0xc7, +0x10, 0x83, 0xc3, 0x10, 0x3b, 0x7d, 0xf0, 0x72, 0x8c, 0x31, 0xc0, 0x59, 0x5b, 0x5b, 0x5e, 0x5f, +0xc9, 0xc3, 0x55, 0x89, 0xe5, 0xba, 0x00, 0x10, 0x00, 0x00, 0x53, 0x89, 0xc3, 0x31, 0xc0, 0xe8, +0x5d, 0xff, 0xff, 0xff, 0x85, 0xc0, 0x75, 0x15, 0xba, 0x00, 0x00, 0x10, 0x00, 0xb8, 0x00, 0x00, +0x0f, 0x00, 0xe8, 0x4a, 0xff, 0xff, 0xff, 0x31, 0xd2, 0x85, 0xc0, 0x74, 0x0f, 0xc7, 0x43, 0x24, +0x01, 0x00, 0x00, 0x00, 0x89, 0x43, 0x28, 0xba, 0x01, 0x00, 0x00, 0x00, 0x89, 0xd0, 0x5b, 0xc9, +0xc3, 0x55, 0x89, 0xe5, 0x56, 0x53, 0x68, 0x00, 0x10, 0x00, 0x00, 0x8b, 0x75, 0x08, 0x6a, 0x00, +0xff, 0x76, 0x10, 0xe8, 0xf7, 0xfc, 0xff, 0xff, 0x8b, 0x46, 0x10, 0xc6, 0x00, 0x00, 0x8b, 0x46, +0x10, 0xc6, 0x40, 0x01, 0x19, 0x8b, 0x46, 0x10, 0xc6, 0x40, 0x06, 0x00, 0x66, 0xc7, 0x40, 0x04, +0x00, 0x00, 0x8b, 0x46, 0x10, 0xc6, 0x40, 0x07, 0x50, 0x8b, 0x46, 0x10, 0xc6, 0x40, 0x0e, 0x19, +0x8b, 0x46, 0x10, 0xc6, 0x40, 0x0f, 0x01, 0x66, 0xc7, 0x40, 0x0a, 0x00, 0x00, 0x8b, 0x46, 0x10, +0xc6, 0x80, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x66, 0xc7, 0x40, 0x10, 0x10, 0x00, 0x66, 0xc7, 0x40, +0x02, 0x00, 0x00, 0x8b, 0x46, 0x10, 0x8d, 0x90, 0x00, 0x08, 0x00, 0x00, 0x89, 0x90, 0x28, 0x02, +0x00, 0x00, 0x66, 0xc7, 0x40, 0x20, 0x3f, 0xa3, 0x66, 0xc7, 0x40, 0x22, 0x00, 0x08, 0x68, 0xff, +0x00, 0x00, 0x00, 0x8b, 0x46, 0x0c, 0x83, 0xc0, 0x1c, 0x50, 0xe8, 0x66, 0xfc, 0xff, 0xff, 0x50, +0x89, 0xc3, 0x8b, 0x46, 0x0c, 0x83, 0xc0, 0x1c, 0x50, 0x8b, 0x46, 0x10, 0x05, 0x00, 0x08, 0x00, +0x00, 0x50, 0xe8, 0x84, 0xfc, 0xff, 0xff, 0x83, 0xc4, 0x20, 0x8b, 0x46, 0x10, 0xc6, 0x84, 0x03, +0x00, 0x08, 0x00, 0x00, 0x00, 0x6a, 0x40, 0x6a, 0x00, 0x8b, 0x46, 0x10, 0x83, 0xc0, 0x40, 0x50, +0xe8, 0x4a, 0xfc, 0xff, 0xff, 0x6a, 0x20, 0x6a, 0x00, 0x8b, 0x46, 0x10, 0x83, 0xe8, 0x80, 0x50, +0xe8, 0x3a, 0xfc, 0xff, 0xff, 0x8b, 0x46, 0x10, 0x8b, 0x4e, 0x0c, 0x66, 0xc7, 0x80, 0xa0, 0x00, +0x00, 0x00, 0x00, 0x00, 0x66, 0xc7, 0x40, 0x02, 0x00, 0x00, 0x66, 0xc7, 0x80, 0xf2, 0x01, 0x00, +0x00, 0xff, 0xff, 0x66, 0x8b, 0x51, 0x0c, 0x66, 0x89, 0x90, 0xf8, 0x01, 0x00, 0x00, 0x66, 0x8b, +0x51, 0x0e, 0x66, 0x89, 0x90, 0xfc, 0x01, 0x00, 0x00, 0xc7, 0x80, 0xe0, 0x01, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xc6, 0x80, 0xff, 0x01, 0x00, 0x00, 0x00, 0x6a, 0x04, 0x68, 0x59, 0x0f, 0x01, +0x00, 0x8b, 0x46, 0x10, 0x05, 0x02, 0x02, 0x00, 0x00, 0x50, 0xe8, 0xfc, 0xfb, 0xff, 0xff, 0x8b, +0x46, 0x10, 0xc6, 0x80, 0x10, 0x02, 0x00, 0x00, 0x50, 0x66, 0xc7, 0x80, 0x06, 0x02, 0x00, 0x00, +0x01, 0x02, 0x8b, 0x46, 0x10, 0xc6, 0x80, 0x11, 0x02, 0x00, 0x00, 0x00, 0x8b, 0x4e, 0x10, 0xc7, +0x81, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x81, 0x1c, 0x02, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x8b, 0x56, 0x0c, 0x83, 0xc4, 0x24, 0x83, 0x7a, 0x18, 0x00, 0x74, 0x12, 0x8b, +0x42, 0x14, 0x89, 0x81, 0x18, 0x02, 0x00, 0x00, 0x8b, 0x42, 0x18, 0x89, 0x81, 0x1c, 0x02, 0x00, +0x00, 0xc7, 0x46, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x8d, 0x65, 0xf8, 0x5b, 0x5e, 0xc9, 0xc3, 0x55, +0x89, 0xe5, 0x57, 0x56, 0x53, 0x83, 0xec, 0x60, 0xa1, 0x90, 0x10, 0x01, 0x00, 0x89, 0x45, 0xd4, +0x8b, 0x45, 0x08, 0x89, 0x45, 0xc4, 0x8b, 0x45, 0x0c, 0x89, 0x45, 0xc8, 0x8b, 0x45, 0x10, 0x89, +0x45, 0xcc, 0x8b, 0x45, 0x14, 0x89, 0x45, 0xd0, 0x8d, 0x45, 0xc4, 0x50, 0xe8, 0x40, 0xfe, 0xff, +0xff, 0x58, 0x8b, 0x45, 0xc4, 0x31, 0xdb, 0x31, 0xf6, 0x3d, 0x02, 0xb0, 0xad, 0x2b, 0x75, 0x0b, +0xb3, 0x01, 0xc7, 0x45, 0xd8, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x2e, 0x3d, 0x07, 0xb0, 0x11, 0x0a, +0x75, 0x27, 0x8b, 0x45, 0xc8, 0x8b, 0x10, 0xe8, 0x95, 0xfb, 0xff, 0xff, 0x85, 0xc0, 0x75, 0x0e, +0xbb, 0x01, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xdc, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x0b, 0x68, 0x5e, +0x0f, 0x01, 0x00, 0xe8, 0x6f, 0xf9, 0xff, 0xff, 0x5f, 0x81, 0x7d, 0xc4, 0x07, 0xb0, 0x1f, 0x0e, +0x75, 0x03, 0x8b, 0x75, 0xc8, 0x8b, 0x45, 0xcc, 0x85, 0xc0, 0x74, 0x0a, 0x81, 0x38, 0x07, 0xb0, +0x1f, 0x0e, 0x75, 0x02, 0x89, 0xc6, 0x85, 0xdb, 0x0f, 0x85, 0x11, 0x01, 0x00, 0x00, 0x85, 0xf6, +0x0f, 0x84, 0xd1, 0x00, 0x00, 0x00, 0x66, 0x83, 0x7e, 0x08, 0x00, 0xc7, 0x45, 0xc0, 0x00, 0x00, +0x00, 0x00, 0x74, 0x0d, 0x8b, 0x56, 0x04, 0x89, 0xf0, 0xe8, 0x33, 0xfb, 0xff, 0xff, 0x89, 0x45, +0xc0, 0x89, 0xf3, 0x31, 0xff, 0x8d, 0x4e, 0x0c, 0x03, 0x5e, 0x04, 0x39, 0xd9, 0x73, 0x21, 0x8b, +0x01, 0x83, 0xc0, 0x03, 0x83, 0xe0, 0xfc, 0x8d, 0x54, 0x01, 0x0c, 0x8b, 0x41, 0x04, 0x83, 0xc0, +0x03, 0x83, 0xe0, 0xfc, 0x8d, 0x04, 0x02, 0x39, 0xd8, 0x77, 0x05, 0x47, 0x89, 0xc1, 0xeb, 0xdb, +0x81, 0x3e, 0x07, 0xb0, 0x1f, 0x0e, 0x75, 0x1d, 0x83, 0x7d, 0xc0, 0x00, 0x75, 0x17, 0x0f, 0xb7, +0x46, 0x0a, 0x39, 0xf8, 0x75, 0x0f, 0xc7, 0x45, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x89, 0x75, 0xcc, +0xe9, 0x9a, 0x00, 0x00, 0x00, 0x68, 0x81, 0x0f, 0x01, 0x00, 0xe8, 0xc8, 0xf8, 0xff, 0xff, 0x59, +0xff, 0x75, 0xc0, 0x68, 0x9b, 0x0f, 0x01, 0x00, 0xe8, 0xba, 0xf8, 0xff, 0xff, 0x58, 0x5a, 0x57, +0x68, 0xad, 0x0f, 0x01, 0x00, 0xe8, 0xad, 0xf8, 0xff, 0xff, 0x5f, 0x58, 0x56, 0x68, 0xbf, 0x0f, +0x01, 0x00, 0xe8, 0xa0, 0xf8, 0xff, 0xff, 0x59, 0x5b, 0xff, 0x76, 0x04, 0x68, 0xd1, 0x0f, 0x01, +0x00, 0xe8, 0x91, 0xf8, 0xff, 0xff, 0x58, 0x5a, 0xff, 0x36, 0x68, 0xe3, 0x0f, 0x01, 0x00, 0xe8, +0x83, 0xf8, 0xff, 0xff, 0x5f, 0x58, 0x0f, 0xb7, 0x46, 0x0a, 0x50, 0x68, 0xf5, 0x0f, 0x01, 0x00, +0xe8, 0x72, 0xf8, 0xff, 0xff, 0x5b, 0x5e, 0x68, 0x07, 0x10, 0x01, 0x00, 0xe8, 0x66, 0xf8, 0xff, +0xff, 0x59, 0xff, 0x75, 0xc4, 0x68, 0x22, 0x10, 0x01, 0x00, 0xe8, 0x58, 0xf8, 0xff, 0xff, 0x58, +0x5a, 0xff, 0x75, 0xc8, 0x68, 0x2b, 0x10, 0x01, 0x00, 0xe8, 0x49, 0xf8, 0xff, 0xff, 0x5e, 0x5f, +0xff, 0x75, 0xcc, 0x68, 0x34, 0x10, 0x01, 0x00, 0xe8, 0x3a, 0xf8, 0xff, 0xff, 0x59, 0x5b, 0x31, +0xc0, 0x83, 0x7d, 0xe0, 0x00, 0xc7, 0x45, 0xe4, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xe8, 0x00, +0x00, 0x00, 0x00, 0x0f, 0x84, 0x22, 0x01, 0x00, 0x00, 0x8b, 0x45, 0xcc, 0x89, 0xc6, 0xc7, 0x45, +0xb8, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x58, 0x0c, 0x03, +0x70, 0x04, 0x39, 0xf3, 0x73, 0x41, 0x8b, 0x0b, 0x8d, 0x51, 0x03, 0x8b, 0x43, 0x04, 0x83, 0xe2, +0xfc, 0x83, 0xc0, 0x03, 0x8d, 0x7b, 0x0c, 0x83, 0xe0, 0xfc, 0x8d, 0x14, 0x17, 0x8d, 0x04, 0x02, +0x39, 0xf0, 0x89, 0x45, 0xb4, 0x77, 0x20, 0x83, 0x7b, 0x08, 0x01, 0x75, 0x15, 0x85, 0xc9, 0x75, +0x11, 0x6a, 0x00, 0x6a, 0x00, 0x57, 0xe8, 0xa3, 0xf9, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x85, 0xc0, +0x74, 0x09, 0x8b, 0x5d, 0xb4, 0xeb, 0xbb, 0x31, 0xdb, 0xeb, 0x04, 0x85, 0xdb, 0x75, 0x09, 0xc7, +0x45, 0xb8, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x0e, 0x8b, 0x03, 0x83, 0xc0, 0x03, 0x83, 0xe0, 0xfc, +0x8d, 0x04, 0x07, 0x89, 0x45, 0xbc, 0x85, 0xdb, 0x0f, 0x84, 0x9a, 0x00, 0x00, 0x00, 0x83, 0x7b, +0x04, 0x07, 0x75, 0x1f, 0x6a, 0x07, 0x68, 0x74, 0x10, 0x01, 0x00, 0xff, 0x75, 0xbc, 0xe8, 0x5b, +0xf9, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x75, 0x09, 0xc7, 0x45, 0xe4, 0x01, 0x00, 0x00, +0x00, 0xeb, 0x59, 0x85, 0xdb, 0x74, 0x71, 0x83, 0x7b, 0x04, 0x0a, 0x75, 0x25, 0x6a, 0x0a, 0x68, +0x69, 0x10, 0x01, 0x00, 0xff, 0x75, 0xbc, 0xe8, 0x32, 0xf9, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x85, +0xc0, 0x75, 0x0f, 0x8d, 0x45, 0xc4, 0xe8, 0x97, 0xfb, 0xff, 0xff, 0x85, 0xc0, 0x89, 0x45, 0xb8, +0x75, 0x46, 0x85, 0xdb, 0x74, 0x42, 0x83, 0x7b, 0x04, 0x00, 0x74, 0x20, 0x85, 0xdb, 0x74, 0x38, +0x83, 0x7b, 0x04, 0x01, 0x75, 0x1f, 0x6a, 0x01, 0x68, 0x9a, 0x0f, 0x01, 0x00, 0xff, 0x75, 0xbc, +0xe8, 0xf9, 0xf8, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x75, 0x09, 0xc7, 0x45, 0xb8, 0x01, +0x00, 0x00, 0x00, 0xeb, 0x13, 0x85, 0xdb, 0x74, 0x0f, 0xff, 0x75, 0xbc, 0x68, 0x3e, 0x10, 0x01, +0x00, 0xe8, 0x01, 0xf7, 0xff, 0xff, 0x58, 0x5a, 0x8b, 0x45, 0xb8, 0x85, 0xc0, 0x75, 0x13, 0x8d, +0x45, 0xc4, 0xe8, 0x3b, 0xfb, 0xff, 0xff, 0x85, 0xc0, 0x75, 0x07, 0xc7, 0x45, 0xe4, 0x01, 0x00, +0x00, 0x00, 0x68, 0x59, 0x10, 0x01, 0x00, 0xe8, 0xdb, 0xf6, 0xff, 0xff, 0x83, 0x7d, 0xe8, 0x00, +0x5f, 0x74, 0x0b, 0x68, 0x68, 0x10, 0x01, 0x00, 0xe8, 0xca, 0xf6, 0xff, 0xff, 0x5e, 0x83, 0x7d, +0xe4, 0x00, 0x74, 0x0b, 0x68, 0x73, 0x10, 0x01, 0x00, 0xe8, 0xb9, 0xf6, 0xff, 0xff, 0x5b, 0x68, +0x99, 0x0f, 0x01, 0x00, 0xe8, 0xae, 0xf6, 0xff, 0xff, 0x83, 0x7d, 0xe8, 0x00, 0x59, 0x0f, 0x84, +0x84, 0x00, 0x00, 0x00, 0x8b, 0x45, 0xec, 0x8d, 0x50, 0x18, 0x8b, 0x40, 0x0c, 0x01, 0xd0, 0x39, +0xc2, 0x89, 0x45, 0xb0, 0x89, 0xd3, 0x73, 0x70, 0x29, 0xd8, 0x8b, 0x53, 0x04, 0x39, 0xc2, 0x77, +0x67, 0x83, 0x3b, 0x01, 0x75, 0x55, 0x8d, 0x42, 0xf8, 0xba, 0x14, 0x00, 0x00, 0x00, 0x89, 0xd1, +0x31, 0xd2, 0xf7, 0xf1, 0x31, 0xff, 0x39, 0xc7, 0x89, 0x45, 0xac, 0x7d, 0x37, 0x31, 0xf6, 0x31, +0xd2, 0x83, 0x7c, 0x1e, 0x18, 0x01, 0x0f, 0x95, 0xc2, 0x42, 0x52, 0xff, 0x74, 0x1e, 0x14, 0xff, +0x74, 0x1e, 0x10, 0xff, 0x74, 0x1e, 0x0c, 0xff, 0x74, 0x1e, 0x08, 0x8b, 0x45, 0xd4, 0x47, 0xe8, +0x41, 0xf9, 0xff, 0xff, 0x83, 0xc6, 0x14, 0x83, 0xc4, 0x14, 0x3b, 0x7d, 0xac, 0x7d, 0x05, 0x83, +0xff, 0x1f, 0x7e, 0xcb, 0xc7, 0x45, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x03, 0x5b, 0x04, 0x3b, 0x5d, +0xb0, 0x73, 0x05, 0x8b, 0x45, 0xb0, 0xeb, 0x90, 0x83, 0x7d, 0xe4, 0x00, 0x0f, 0x84, 0x94, 0x00, +0x00, 0x00, 0x6a, 0x20, 0x68, 0xc4, 0x51, 0x01, 0x00, 0xe8, 0xee, 0xf3, 0xff, 0xff, 0x31, 0xf6, +0x5f, 0x39, 0xc6, 0x5a, 0xa3, 0xc0, 0x51, 0x01, 0x00, 0x7d, 0x47, 0x31, 0xdb, 0x83, 0xbb, 0xd4, +0x51, 0x01, 0x00, 0x01, 0x75, 0x07, 0xc7, 0x45, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb3, 0xd4, +0x51, 0x01, 0x00, 0xff, 0xb3, 0xd0, 0x51, 0x01, 0x00, 0xff, 0xb3, 0xcc, 0x51, 0x01, 0x00, 0xff, +0xb3, 0xc8, 0x51, 0x01, 0x00, 0xff, 0xb3, 0xc4, 0x51, 0x01, 0x00, 0x8b, 0x45, 0xd4, 0x46, 0xe8, +0xc1, 0xf8, 0xff, 0xff, 0x83, 0xc3, 0x14, 0x83, 0xc4, 0x14, 0x3b, 0x35, 0xc0, 0x51, 0x01, 0x00, +0x7c, 0xbb, 0x8b, 0x5d, 0xd4, 0xe8, 0xeb, 0xf3, 0xff, 0xff, 0x89, 0x83, 0xe0, 0x01, 0x00, 0x00, +0x8b, 0x5d, 0xd4, 0xe8, 0x26, 0xf4, 0xff, 0xff, 0x66, 0x89, 0x43, 0x02, 0x8b, 0x45, 0xd4, 0x83, +0xb8, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x75, 0x07, 0x66, 0x83, 0x78, 0x02, 0x00, 0x74, 0x07, 0xc7, +0x45, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x83, 0x7d, 0xd8, 0x00, 0x0f, 0x84, 0x8a, 0x00, 0x00, 0x00, +0x83, 0x7d, 0xf0, 0x00, 0x8b, 0x75, 0xc8, 0x74, 0x16, 0xf6, 0x06, 0x01, 0x74, 0x11, 0x8b, 0x56, +0x08, 0x81, 0xc2, 0x00, 0x04, 0x00, 0x00, 0x8b, 0x45, 0xd4, 0xe8, 0x0b, 0xf8, 0xff, 0xff, 0xf6, +0x06, 0x04, 0x74, 0x10, 0x6a, 0xff, 0xff, 0x76, 0x10, 0xff, 0x75, 0xd4, 0xe8, 0x9f, 0xf7, 0xff, +0xff, 0x83, 0xc4, 0x0c, 0x83, 0x7d, 0xf0, 0x00, 0x74, 0x3b, 0xf6, 0x06, 0x40, 0x74, 0x36, 0x8b, +0x5e, 0x30, 0x8b, 0x45, 0xd4, 0x89, 0xdf, 0x8b, 0x4b, 0xfc, 0x89, 0x45, 0xa8, 0x03, 0x7e, 0x2c, +0x89, 0x4d, 0xa4, 0x39, 0xfb, 0x73, 0x1e, 0xff, 0x73, 0x10, 0xff, 0x73, 0x0c, 0xff, 0x73, 0x08, +0xff, 0x73, 0x04, 0xff, 0x33, 0x8b, 0x45, 0xa8, 0xe8, 0x08, 0xf8, 0xff, 0xff, 0x83, 0xc4, 0x14, +0x03, 0x5d, 0xa4, 0xeb, 0xde, 0xf6, 0x06, 0x41, 0x0f, 0x84, 0x51, 0x01, 0x00, 0x00, 0xc7, 0x45, +0xf0, 0x00, 0x00, 0x00, 0x00, 0xe9, 0x45, 0x01, 0x00, 0x00, 0x83, 0x7d, 0xdc, 0x00, 0x0f, 0x84, +0xc9, 0x00, 0x00, 0x00, 0x8b, 0x5d, 0xc8, 0x8b, 0x43, 0x0c, 0x85, 0xc0, 0x74, 0x0f, 0x50, 0xff, +0x73, 0x08, 0xff, 0x75, 0xd4, 0xe8, 0x26, 0xf7, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x8b, 0x7b, 0x14, +0x8b, 0x73, 0x10, 0x85, 0xff, 0x0f, 0x84, 0x14, 0x01, 0x00, 0x00, 0x83, 0x3e, 0x01, 0x0f, 0x85, +0x8d, 0x00, 0x00, 0x00, 0x83, 0x7d, 0xf0, 0x00, 0x0f, 0x84, 0x83, 0x00, 0x00, 0x00, 0x8b, 0x45, +0xd4, 0xba, 0x14, 0x00, 0x00, 0x00, 0x89, 0x45, 0xa0, 0x8b, 0x46, 0x04, 0x83, 0xe8, 0x08, 0x89, +0xd1, 0x31, 0xd2, 0xf7, 0xf1, 0xc7, 0x45, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x39, 0x45, 0x9c, 0x89, +0x45, 0x98, 0x7d, 0x56, 0x31, 0xdb, 0x8b, 0x44, 0x33, 0x18, 0x83, 0xf8, 0x03, 0xba, 0x03, 0x00, +0x00, 0x00, 0x74, 0x16, 0x77, 0x05, 0xb2, 0x01, 0x48, 0xeb, 0x08, 0xba, 0x04, 0x00, 0x00, 0x00, +0x83, 0xf8, 0x04, 0x74, 0x05, 0xba, 0x02, 0x00, 0x00, 0x00, 0x52, 0xff, 0x74, 0x33, 0x14, 0xff, +0x74, 0x33, 0x10, 0xff, 0x74, 0x33, 0x0c, 0xff, 0x74, 0x33, 0x08, 0x8b, 0x45, 0xa0, 0xe8, 0x42, +0xf7, 0xff, 0xff, 0xff, 0x45, 0x9c, 0x8b, 0x45, 0x98, 0x83, 0xc4, 0x14, 0x83, 0xc3, 0x14, 0x39, +0x45, 0x9c, 0x7d, 0x06, 0x83, 0x7d, 0x9c, 0x1f, 0x7e, 0xac, 0xc7, 0x45, 0xf0, 0x00, 0x00, 0x00, +0x00, 0x8b, 0x46, 0x04, 0x01, 0xc6, 0x29, 0xc7, 0xe9, 0x58, 0xff, 0xff, 0xff, 0x83, 0x7d, 0xe0, +0x00, 0x74, 0x6c, 0x8b, 0x45, 0xcc, 0x89, 0xc6, 0x8d, 0x58, 0x0c, 0x03, 0x70, 0x04, 0x39, 0xf3, +0x73, 0x5d, 0x8b, 0x13, 0x8d, 0x42, 0x03, 0x83, 0xe0, 0xfc, 0x8d, 0x4b, 0x0c, 0x8d, 0x3c, 0x01, +0x8b, 0x43, 0x04, 0x83, 0xc0, 0x03, 0x83, 0xe0, 0xfc, 0x8d, 0x04, 0x07, 0x39, 0xf0, 0x89, 0x45, +0x94, 0x77, 0x3c, 0xa1, 0x84, 0x10, 0x01, 0x00, 0x39, 0x43, 0x08, 0x75, 0x2d, 0x3b, 0x15, 0x7c, +0x10, 0x01, 0x00, 0x75, 0x25, 0x52, 0xff, 0x35, 0x80, 0x10, 0x01, 0x00, 0x51, 0xe8, 0x9c, 0xf5, +0xff, 0xff, 0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x75, 0x11, 0x57, 0xff, 0x73, 0x04, 0x8d, 0x4d, 0xc4, +0x51, 0xff, 0x15, 0x88, 0x10, 0x01, 0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x5d, 0x94, 0xeb, 0x9f, 0xb0, +0x80, 0xe6, 0x70, 0x31, 0xc0, 0xe6, 0xf0, 0xe6, 0xf1, 0xb0, 0x11, 0xe6, 0x20, 0xe6, 0xa0, 0xb0, +0x20, 0xe6, 0x21, 0xb0, 0x28, 0xe6, 0xa1, 0xb0, 0x04, 0xe6, 0x21, 0xb0, 0x02, 0xe6, 0xa1, 0xb0, +0x01, 0xe6, 0x21, 0xe6, 0xa1, 0xb0, 0xff, 0xe6, 0xa1, 0xb0, 0xfb, 0xe6, 0x21, 0x8b, 0x45, 0xd4, +0x8d, 0x65, 0xf4, 0x5b, 0x5e, 0x5f, 0xc9, 0xc3, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, +0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x00, 0x48, 0x64, 0x72, 0x53, 0x00, 0x42, 0x61, +0x64, 0x20, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x62, 0x6f, 0x6f, 0x74, 0x20, 0x68, +0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x21, 0x0a, +0x00, 0x42, 0x61, 0x64, 0x20, 0x45, 0x4c, 0x46, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, +0x65, 0x72, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x21, 0x0a, 0x00, 0x20, 0x20, 0x20, 0x63, 0x68, +0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x0a, 0x00, 0x20, 0x20, 0x20, +0x20, 0x20, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x0a, 0x00, 0x20, +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x68, 0x64, 0x72, 0x20, 0x3d, 0x20, 0x25, 0x78, 0x0a, +0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x3d, 0x20, 0x25, +0x78, 0x0a, 0x00, 0x62, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x3d, +0x20, 0x25, 0x78, 0x0a, 0x00, 0x20, 0x20, 0x62, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, +0x20, 0x3d, 0x20, 0x25, 0x78, 0x0a, 0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x62, +0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x21, +0x0a, 0x00, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x25, 0x78, 0x0a, 0x00, 0x64, 0x61, 0x74, 0x61, 0x3d, +0x25, 0x78, 0x0a, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x3d, 0x25, 0x78, 0x0a, 0x00, 0x55, 0x6e, +0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x20, 0x74, +0x79, 0x70, 0x65, 0x3a, 0x20, 0x25, 0x73, 0x0a, 0x00, 0x46, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, +0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x00, 0x20, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x42, 0x49, +0x4f, 0x53, 0x00, 0x20, 0x50, 0x43, 0x42, 0x49, 0x4f, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x9a, 0x0f, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x53, 0x06, 0x01, 0x00, 0xc0, 0x51, 0x01, 0x00, +0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xa5, 0xa5, 0xa5, 0xa5, 0x70, 0x00, 0x00, 0x00, 0xa8, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x4f, 0x4f, 0x54, +0x5f, 0x49, 0x4d, 0x41, 0x47, 0x45, 0x3d, 0x68, 0x65, 0x61, 0x64, 0x2e, 0x53, 0x20, 0x63, 0x6f, +0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x3d, 0x74, 0x74, 0x79, 0x53, 0x30, 0x20, 0x69, 0x70, 0x3d, 0x64, +0x68, 0x63, 0x70, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x3d, 0x2f, 0x64, 0x65, 0x76, 0x2f, 0x6e, 0x66, +0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/util/mkelfImage/linux-i386/convert.h b/util/mkelfImage/linux-i386/convert.h new file mode 100644 index 0000000000..369829f78f --- /dev/null +++ b/util/mkelfImage/linux-i386/convert.h @@ -0,0 +1,29 @@ + +/* Hard coded locations */ +#define CONVERTLOC 0x10000 +#define REAL_MODE_DATA_LOC 0x20000 +#define GDTLOC 0x21000 + +#define DEFAULT_ROOT_DEV ((0x3<<8)| 0) + +#define CMDLINE_MAX 256 + +#ifdef ASSEMBLY +#define CONVERT_MAGIC 0xA5A5A5A5 +#else +#define CONVERT_MAGIC 0xA5A5A5A5UL +#endif + +#ifndef ASSEMBLY +struct image_parameters { + uint32_t convert_magic; /* a signature to verify mkelfImage was built properly */ + uint32_t gdt_size; + uint32_t bss_size; + uint16_t ramdisk_flags; + uint16_t root_dev; + uint32_t entry; + uint32_t initrd_start; + uint32_t initrd_size; + uint8_t cmdline[CMDLINE_MAX]; +}; +#endif diff --git a/util/mkelfImage/linux-i386/convert.lds b/util/mkelfImage/linux-i386/convert.lds new file mode 100644 index 0000000000..2195fe435d --- /dev/null +++ b/util/mkelfImage/linux-i386/convert.lds @@ -0,0 +1,36 @@ +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) + + +ENTRY(startup_32) +SECTIONS +{ + . = 0x10000; + _text = .; /* Text and read-only data */ + .text . : { + *(.text) + *(.text.*) + } = 0x9090 + .rodata (.): { + *(.rodata) + *(.rodata.*) + } + _etext = .; /* End of text section */ + .data (.): { /* Data */ + *(.data) + *(.data.*) + *(.trailer) + } + _edata = .; /* End of data section */ + _bss = .; /* BSS */ + .bss (.): { + *(.bss) + } + _end = . ; + bss_size = _end - _bss; + + /DISCARD/ : { + *(.comment) + *(.note) + } +} diff --git a/util/mkelfImage/linux-i386/convert_params.c b/util/mkelfImage/linux-i386/convert_params.c new file mode 100644 index 0000000000..501adfbb11 --- /dev/null +++ b/util/mkelfImage/linux-i386/convert_params.c @@ -0,0 +1,1555 @@ +#include <stdarg.h> +#include <limits.h> +#include "arch/io.h" +#include "stdint.h" +#include "uniform_boot.h" +#include "linuxbios_tables.h" +#include "elf_boot.h" +#include "convert.h" +#define STACK_SIZE (4096) + +#define __unused __attribute__ ((unused)) + +long user_stack [STACK_SIZE] = { 0 }; + +unsigned long * stack_start = & user_stack[STACK_SIZE]; + +/* FIXME expand on drive_info_)struct... */ +struct drive_info_struct { + uint8_t dummy[32]; +}; +struct sys_desc_table { + uint16_t length; + uint8_t table[318]; +}; + +/* + * These are set up by the setup-routine at boot-time: + */ + +struct screen_info { + uint8_t orig_x; /* 0x00 */ + uint8_t orig_y; /* 0x01 */ + uint16_t dontuse1; /* 0x02 -- EXT_MEM_K sits here */ + uint16_t orig_video_page; /* 0x04 */ + uint8_t orig_video_mode; /* 0x06 */ + uint8_t orig_video_cols; /* 0x07 */ + uint16_t unused2; /* 0x08 */ + uint16_t orig_video_ega_bx; /* 0x0a */ + uint16_t unused3; /* 0x0c */ + uint8_t orig_video_lines; /* 0x0e */ + uint8_t orig_video_isVGA; /* 0x0f */ + uint16_t orig_video_points; /* 0x10 */ + + /* VESA graphic mode -- linear frame buffer */ + uint16_t lfb_width; /* 0x12 */ + uint16_t lfb_height; /* 0x14 */ + uint16_t lfb_depth; /* 0x16 */ + uint32_t lfb_base; /* 0x18 */ + uint32_t lfb_size; /* 0x1c */ + uint16_t dontuse2, dontuse3; /* 0x20 -- CL_MAGIC and CL_OFFSET here */ + uint16_t lfb_linelength; /* 0x24 */ + uint8_t red_size; /* 0x26 */ + uint8_t red_pos; /* 0x27 */ + uint8_t green_size; /* 0x28 */ + uint8_t green_pos; /* 0x29 */ + uint8_t blue_size; /* 0x2a */ + uint8_t blue_pos; /* 0x2b */ + uint8_t rsvd_size; /* 0x2c */ + uint8_t rsvd_pos; /* 0x2d */ + uint16_t vesapm_seg; /* 0x2e */ + uint16_t vesapm_off; /* 0x30 */ + uint16_t pages; /* 0x32 */ +}; + + +#define PAGE_SIZE 4096 + + +#define E820MAP 0x2d0 /* our map */ +#define E820MAX 32 /* number of entries in E820MAP */ +#define E820NR 0x1e8 /* # entries in E820MAP */ + + +struct e820entry { + unsigned long long addr; /* start of memory segment */ + unsigned long long size; /* size of memory segment */ + unsigned long type; /* type of memory segment */ +#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 +}; + +struct e820map { + int nr_map; + struct e820entry map[E820MAX]; +}; + + +struct apm_bios_info { + uint16_t version; /* 0x40 */ + uint16_t cseg; /* 0x42 */ + uint32_t offset; /* 0x44 */ + uint16_t cseg_16; /* 0x48 */ + uint16_t dseg; /* 0x4a */ + uint16_t flags; /* 0x4c */ + uint16_t cseg_len; /* 0x4e */ + uint16_t cseg_16_len; /* 0x50 */ + uint16_t dseg_len; /* 0x52 */ + uint8_t reserved[44]; /* 0x54 */ +}; + + +struct parameters { + uint8_t orig_x; /* 0x00 */ + uint8_t orig_y; /* 0x01 */ + uint16_t ext_mem_k; /* 0x02 -- EXT_MEM_K sits here */ + uint16_t orig_video_page; /* 0x04 */ + uint8_t orig_video_mode; /* 0x06 */ + uint8_t orig_video_cols; /* 0x07 */ + uint16_t unused2; /* 0x08 */ + uint16_t orig_video_ega_bx; /* 0x0a */ + uint16_t unused3; /* 0x0c */ + uint8_t orig_video_lines; /* 0x0e */ + uint8_t orig_video_isVGA; /* 0x0f */ + uint16_t orig_video_points; /* 0x10 */ + + /* VESA graphic mode -- linear frame buffer */ + uint16_t lfb_width; /* 0x12 */ + uint16_t lfb_height; /* 0x14 */ + uint16_t lfb_depth; /* 0x16 */ + uint32_t lfb_base; /* 0x18 */ + uint32_t lfb_size; /* 0x1c */ + uint16_t cl_magic; /* 0x20 */ +#define CL_MAGIC_VALUE 0xA33F + uint16_t cl_offset; /* 0x22 */ + uint16_t lfb_linelength; /* 0x24 */ + uint8_t red_size; /* 0x26 */ + uint8_t red_pos; /* 0x27 */ + uint8_t green_size; /* 0x28 */ + uint8_t green_pos; /* 0x29 */ + uint8_t blue_size; /* 0x2a */ + uint8_t blue_pos; /* 0x2b */ + uint8_t rsvd_size; /* 0x2c */ + uint8_t rsvd_pos; /* 0x2d */ + uint16_t vesapm_seg; /* 0x2e */ + uint16_t vesapm_off; /* 0x30 */ + uint16_t pages; /* 0x32 */ + uint8_t reserved4[12]; /* 0x34 -- 0x3f reserved for future expansion */ + + struct apm_bios_info apm_bios_info; /* 0x40 */ + struct drive_info_struct drive_info; /* 0x80 */ + struct sys_desc_table sys_desc_table; /* 0xa0 */ + uint32_t alt_mem_k; /* 0x1e0 */ + uint8_t reserved5[4]; /* 0x1e4 */ + uint8_t e820_map_nr; /* 0x1e8 */ + uint8_t reserved6[9]; /* 0x1e9 */ + uint16_t mount_root_rdonly; /* 0x1f2 */ + uint8_t reserved7[4]; /* 0x1f4 */ + uint16_t ramdisk_flags; /* 0x1f8 */ +#define RAMDISK_IMAGE_START_MASK 0x07FF +#define RAMDISK_PROMPT_FLAG 0x8000 +#define RAMDISK_LOAD_FLAG 0x4000 + uint8_t reserved8[2]; /* 0x1fa */ + uint16_t orig_root_dev; /* 0x1fc */ + uint8_t reserved9[1]; /* 0x1fe */ + uint8_t aux_device_info; /* 0x1ff */ + uint8_t reserved10[2]; /* 0x200 */ + uint8_t param_block_signature[4]; /* 0x202 */ + uint16_t param_block_version; /* 0x206 */ + uint8_t reserved11[8]; /* 0x208 */ + uint8_t loader_type; /* 0x210 */ +#define LOADER_TYPE_LOADLIN 1 +#define LOADER_TYPE_BOOTSECT_LOADER 2 +#define LOADER_TYPE_SYSLINUX 3 +#define LOADER_TYPE_ETHERBOOT 4 +#define LOADER_TYPE_KERNEL 5 + uint8_t loader_flags; /* 0x211 */ + uint8_t reserved12[2]; /* 0x212 */ + uint32_t kernel_start; /* 0x214 */ + uint32_t initrd_start; /* 0x218 */ + uint32_t initrd_size; /* 0x21c */ + uint8_t reserved13[4]; /* 0x220 */ + /* 2.01+ */ + uint16_t heap_end_ptr; /* 0x224 */ + uint8_t reserved14[2]; /* 0x226 */ + /* 2.02+ */ + uint32_t cmd_line_ptr; /* 0x228 */ + /* 2.03+ */ + uint32_t initrd_addr_max; /* 0x22c */ + uint8_t reserved15[0x2d0 - 0x230]; /* 0x230 */ + + struct e820entry e820_map[E820MAX]; /* 0x2d0 */ + uint8_t reserved16[688]; /* 0x550 */ +#define COMMAND_LINE_SIZE 256 + uint8_t command_line[COMMAND_LINE_SIZE]; /* 0x800 */ + uint8_t reserved17[1792]; /* 0x900 - 0x1000 */ +}; + +/* Keep track of which information I need to acquire. */ +struct param_info { + unsigned type; + void *data; + Elf_Bhdr *param; + struct image_parameters *image; + struct parameters *real_mode; + /* bootloader type */ + int has_multiboot; + int has_uniform_boot; + int has_elf_boot; + /* firmware type */ + int has_pcbios; + int has_linuxbios; + struct lb_header *lb_table; + /* machine information needed */ + int need_mem_sizes; +}; +/* + * This is set up by the setup-routine at boot-time + */ + + +#undef memcmp +#undef memset +#undef memcpy +#define memzero(s, n) memset ((s), 0, (n)) + + +/* FIXME handle systems with large EBDA's */ +static struct parameters *faked_real_mode = (void *)REAL_MODE_DATA_LOC; + + + +/* + * Output + * ============================================================================= + */ + +/* Base Address */ +#define TTYS0 0x3f8 +#define TTYS0_LSR (TTYS0+0x05) +#define TTYS0_TBR (TTYS0+0x00) + +static void ttys0_tx_byte(unsigned byte) +{ + /* Wait until I can send a byte */ + while((inb(TTYS0_LSR) & 0x20) == 0) + ; + outb(byte, TTYS0_TBR); + /* Wait until the byte is transmitted */ + while(!(inb(TTYS0_LSR) & 0x40)) + ; +} +static void put_char_serial(int c) +{ + if (c == '\n') { + ttys0_tx_byte('\r'); + } + ttys0_tx_byte(c); +} + +static void putchar(int c) +{ +#if 0 + put_char_video(c); +#endif + put_char_serial(c); +} + +#define LONG_LONG_SHIFT ((int)((sizeof(unsigned long long)*CHAR_BIT) - 4)) +#define LONG_SHIFT ((int)((sizeof(unsigned long)*CHAR_BIT) - 4)) +#define INT_SHIFT ((int)((sizeof(unsigned int)*CHAR_BIT) - 4)) +#define SHRT_SHIFT ((int)((sizeof(unsigned short)*CHAR_BIT) - 4)) +#define CHAR_SHIFT ((int)((sizeof(unsigned char)*CHAR_BIT) - 4)) + +/************************************************************************** +PRINTF and friends + + Formats: + %x - 4 bytes int (8 hex digits, lower case) + %X - 4 bytes int (8 hex digits, upper case) + %lx - 8 bytes long (16 hex digits, lower case) + %lX - 8 bytes long (16 hex digits, upper case) + %hx - 2 bytes int (4 hex digits, lower case) + %hX - 2 bytes int (4 hex digits, upper case) + %hhx - 1 byte int (2 hex digits, lower case) + %hhX - 1 byte int (2 hex digits, upper case) + - optional # prefixes 0x or 0X + %d - decimal int + %c - char + %s - string + Note: width specification not supported +**************************************************************************/ +static void printf(const char *fmt, ...) +{ + va_list args; + char *p; + va_start(args, fmt); + for ( ; *fmt != '\0'; ++fmt) { + if (*fmt != '%') { + putchar(*fmt); + continue; + } + if (*++fmt == 's') { + for(p = va_arg(args, char *); *p != '\0'; p++) + putchar(*p); + } + else { /* Length of item is bounded */ + char tmp[40], *q = tmp; + int shift = INT_SHIFT; + if (*fmt == 'L') { + shift = LONG_LONG_SHIFT; + fmt++; + } + else if (*fmt == 'l') { + shift = LONG_SHIFT; + fmt++; + } + else if (*fmt == 'h') { + shift = SHRT_SHIFT; + fmt++; + if (*fmt == 'h') { + shift = CHAR_SHIFT; + fmt++; + } + } + + /* + * Before each format q points to tmp buffer + * After each format q points past end of item + */ + if ((*fmt | 0x20) == 'x') { + /* With x86 gcc, sizeof(long) == sizeof(int) */ + unsigned long long h; + int ncase; + if (shift > LONG_SHIFT) { + h = va_arg(args, unsigned long long); + } + else if (shift > INT_SHIFT) { + h = va_arg(args, unsigned long); + } else { + h = va_arg(args, unsigned int); + } + ncase = (*fmt & 0x20); + for ( ; shift >= 0; shift -= 4) + *q++ = "0123456789ABCDEF"[(h >> shift) & 0xF] | ncase; + } + else if (*fmt == 'd') { + char *r; + long i; + if (shift > LONG_SHIFT) { + i = va_arg(args, long long); + } + else if (shift > INT_SHIFT) { + i = va_arg(args, long); + } else { + i = va_arg(args, int); + } + if (i < 0) { + *q++ = '-'; + i = -i; + } + p = q; /* save beginning of digits */ + do { + *q++ = '0' + (i % 10); + i /= 10; + } while (i); + /* reverse digits, stop in middle */ + r = q; /* don't alter q */ + while (--r > p) { + i = *r; + *r = *p; + *p++ = i; + } + } + else if (*fmt == 'c') + *q++ = va_arg(args, int); + else + *q++ = *fmt; + /* now output the saved string */ + for (p = tmp; p < q; ++p) + putchar(*p); + } + } + va_end(args); +} + +/* + * String Functions + * ============================================================================= + */ + + +size_t strnlen(const char *s, size_t max) +{ + size_t len = 0; + while(len < max && *s) { + len++; + s++; + } + return len; +} + +void* memset(void* s, int c, size_t n) +{ + size_t i; + char *ss = (char*)s; + + for (i=0;i<n;i++) ss[i] = c; + return s; +} + +void* memcpy(void *dest, const void *src, size_t len) +{ + size_t i; + unsigned char *d; + const unsigned char *s; + d = dest; + s = src; + + for (i=0; i < len; i++) + d[i] = s[i]; + + return dest; +} + +int memcmp(void *src1, void *src2, size_t len) +{ + unsigned char *s1, *s2; + size_t i; + s1 = src1; + s2 = src2; + for(i = 0; i < len; i++) { + if (*s1 != *s2) { + return *s2 - *s1; + } + } + return 0; + +} + +/* + * Checksum functions + * ============================================================================= + */ + + +static unsigned long checksum_partial(unsigned long sum, + void *addr, unsigned long length) +{ + uint8_t *ptr; + volatile union { + uint8_t byte[2]; + uint16_t word; + } value; + unsigned long i; + /* In the most straight forward way possible, + * compute an ip style checksum. + */ + sum = 0; + ptr = addr; + for(i = 0; i < length; i++) { + unsigned long value; + value = ptr[i]; + if (i & 1) { + value <<= 8; + } + /* Add the new value */ + sum += value; + /* Wrap around the carry */ + if (sum > 0xFFFF) { + sum = (sum + (sum >> 16)) & 0xFFFF; + } + } + value.byte[0] = sum & 0xff; + value.byte[1] = (sum >> 8) & 0xff; + return value.word & 0xFFFF; + +} + +static unsigned long checksum_final(unsigned long partial) +{ + return (~partial) & 0xFFFF; +} + +static unsigned long compute_checksum(void *vaddr, unsigned long length) +{ + return checksum_final(checksum_partial(0, vaddr, length)); +} + +/* + * Helper functions + * ============================================================================= + */ + + +void append_command_line(struct parameters *real_mode, char *arg, int arg_bytes) +{ + int len, max; + char *dest; + /* skip over what has already been set */ + len = strnlen(real_mode->command_line, sizeof(real_mode->command_line)); + dest = real_mode->command_line + len; + max = sizeof(real_mode->command_line) - 1; + if (max < 1) { + /* No room to append anything :( */ + return; + } + /* Add a space in between strings */ + *dest++ = ' '; + /* Append the added command line */ + max = sizeof(real_mode->command_line) - 1; + if (max > arg_bytes) { + max = arg_bytes; + } + len = strnlen(arg, max); + memcpy(dest, arg, len); + dest += len; + /* Null terminate the string */ + *dest++ = '\0'; +} + +static void set_memsize_k(struct parameters *real_mode, unsigned long mem_k) +{ + /* ALT_MEM_K maxes out at 4GB */ + if (mem_k > 0x3fffff) { + mem_k = 0x3fffff; + } + if (mem_k > (real_mode->alt_mem_k + (1 << 10))) { + /* Use our memory size less 1M */ + real_mode->alt_mem_k = mem_k - (1 << 10); + real_mode->ext_mem_k = mem_k - (1 << 10); + if ((mem_k - (1 << 10)) > 0xFFFF) { + real_mode->ext_mem_k = 0xFC00; /* 64 M */ + } + } +} + +static void add_e820_map(struct parameters *real_mode, + unsigned long long addr, unsigned long long size, + unsigned long type) +{ + unsigned long long high; + unsigned long mem_k; + int i; + i = real_mode->e820_map_nr; + if (i < E820MAX) { + real_mode->e820_map[i].addr = addr; + real_mode->e820_map[i].size = size; + real_mode->e820_map[i].type = type; + real_mode->e820_map_nr++; + } + /* policy I assume that for the legacy memory + * variables memory is contiguous. + */ + if (type == E820_RAM) { + high = addr + size; + if (high >= 0x40000000000ULL) { + mem_k = 0xFFFFFFFF; + } else { + mem_k = high >> 10; + } + set_memsize_k(real_mode, mem_k); + } +} + +/* + * Multiboot + * ============================================================================= + */ + +#define MULTI_MEM_DEBUG 0 +#if MULTI_MEM_DEBUG +#define multi_puts(x) printf("%s", x) +#define multi_put_hex(x) printf("%x", x) +#define multi_put_lhex(x) printf("%Lx", x) +#else +#define multi_puts(x) +#define multi_put_hex(x) +#define multi_put_lhex(x) +#endif /* MULTI_MEM_DEBUG */ + +/* Multiboot Specification */ +struct multiboot_mods { + unsigned mod_start; + unsigned mod_end; + unsigned char *string; + unsigned reserved; +}; + +struct memory_segment { + unsigned long long addr; + unsigned long long size; + unsigned type; +}; + +struct multiboot_info { + unsigned flags; +#define MULTIBOOT_MEM_VALID 0x01 +#define MULTIBOOT_BOOT_DEV_VALID 0x02 +#define MULTIBOOT_CMDLINE_VALID 0x04 +#define MULTIBOOT_MODS_VALID 0x08 +#define MULTIBOOT_AOUT_SYMS_VALID 0x10 +#define MULTIBOOT_ELF_SYMS_VALID 0x20 +#define MULTIBOOT_MMAP_VALID 0x40 + unsigned mem_lower; + unsigned mem_upper; + unsigned char boot_device[4]; + void *command_line; + unsigned mods_count; + struct multiboot_mods *mods_addr; + unsigned syms_num; + unsigned syms_size; + unsigned syms_addr; + unsigned syms_shndx; + unsigned mmap_length; + struct memory_segment *mmap_addr; +}; + +#define MULTIBOOT_MAX_COMMAND_LINE 0xFFFFFFFF + +static void convert_multiboot_memmap( + struct parameters *real_mode, + struct multiboot_info *info) +{ + unsigned size; + unsigned *size_addr; +#define next_seg(seg, size) ((struct memory_segment *)((char *)(seg) + (size))) + struct memory_segment *seg, *end; + + seg = info->mmap_addr; + end = (void *)(((char *)seg) + info->mmap_length); + size_addr = (unsigned *)(((char *)seg) - 4); + size = *size_addr; + multi_puts("mmap_addr: "); multi_put_hex((unsigned)info->mmap_addr); multi_puts("\n"); + multi_puts("mmap_length: "); multi_put_hex(info->mmap_length); multi_puts("\n"); + multi_puts("size_addr: "); multi_put_hex((unsigned)size_addr); multi_puts("\n"); + multi_puts("size: "); multi_put_hex(size); multi_puts("\n"); + multi_puts("end: "); multi_put_hex((unsigned)end); multi_puts("\n"); + for(seg = info->mmap_addr; (seg < end); seg = next_seg(seg,size)) { + multi_puts("multi-mem: "); + multi_put_lhex(seg->size); + multi_puts(" @ "); + multi_put_lhex(seg->addr); + multi_puts(" ("); + switch(seg->type) { + case E820_RAM: + multi_puts("ram"); + break; + case E820_ACPI: + multi_puts("ACPI data"); + break; + case E820_NVS: + multi_puts("ACPI NVS"); + break; + case E820_RESERVED: + default: + multi_puts("reserved"); + break; + } + multi_puts(")\n"); + add_e820_map(real_mode, seg->addr, seg->size, seg->type); + } +#undef next_seg +} + +static void convert_multiboot( + struct param_info *info, struct multiboot_info *mb_info) +{ + if (info->need_mem_sizes && (mb_info->flags & MULTIBOOT_MEM_VALID)) { + /* info->memory is short 1M */ + set_memsize_k(info->real_mode, mb_info->mem_upper + (1 << 10)); + } + if (mb_info->flags & MULTIBOOT_CMDLINE_VALID) { + append_command_line(info->real_mode, mb_info->command_line, + MULTIBOOT_MAX_COMMAND_LINE); + } + if (info->need_mem_sizes && (mb_info->flags & MULTIBOOT_MMAP_VALID)) { + convert_multiboot_memmap(info->real_mode, mb_info); + } + if (mb_info->flags & (MULTIBOOT_MEM_VALID | MULTIBOOT_MMAP_VALID)) { + info->need_mem_sizes = 0; + } +} + + +/* + * Uniform Boot Environment + * ============================================================================= + */ + +#define UBE_MEM_DEBUG 0 +#if UBE_MEM_DEBUG +#define ube_puts(x) printf("%s", x) +#define ube_put_hex(x) printf("%x", x) +#define ube_put_lhex(x) printf("%Lx", x) +#else +#define ube_puts(x) +#define ube_put_hex(x) +#define ube_put_lhex(x) +#endif /* UBE_MEM_DEBUG */ +static void convert_uniform_boot_memory( + struct parameters *real_mode, struct ube_memory *mem) +{ + int i; + int entries; + unsigned long mem_k; + mem_k = 0; + entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]); + for(i = 0; (i < entries) && (i < E820MAX); i++) { + unsigned long type; + ube_puts("ube-mem: "); + ube_put_lhex(mem->map[i].size); + ube_puts(" @ "); + ube_put_lhex(mem->map[i].start); + ube_puts(" ("); + switch(mem->map[i].type) { + case UBE_MEM_RAM: + type = E820_RAM; + ube_puts("ram"); + break; + case UBE_MEM_ACPI: + type = E820_ACPI; + ube_puts("ACPI data"); + break; + case UBE_MEM_NVS: + type = E820_NVS; + ube_puts("ACPI NVS"); + break; + case UBE_MEM_RESERVED: + default: + type = E820_RESERVED; + ube_puts("reserved"); + break; + } + ube_puts(")\n"); + add_e820_map(real_mode, + mem->map[i].start, mem->map[i].size, type); + } +} + +static void convert_uniform_boot(struct param_info *info, + struct uniform_boot_header *header) +{ + /* Uniform boot environment */ + unsigned long env_bytes; + char *env; + if (header->arg_bytes) { + append_command_line(info->real_mode, (void *)(header->arg), header->arg_bytes); + } + env = (void *)(header->env); + env_bytes = header->env_bytes; + while(env_bytes) { + struct ube_record *record; + record = (void *)env; + if (record->tag == UBE_TAG_MEMORY) { + if (info->need_mem_sizes) { + convert_uniform_boot_memory(info->real_mode, (void *)record); + info->need_mem_sizes = 0; + } + } + env += record->size; + env_bytes -= record->size; + } +} + + + + +/* + * Hardware + * ============================================================================= + */ + +/* we're getting screwed again and again by this problem of the 8259. + * so we're going to leave this lying around for inclusion into + * crt0.S on an as-needed basis. + * well, that went ok, I hope. Now we have to reprogram the interrupts :-( + * we put them right after the intel-reserved hardware interrupts, at + * int 0x20-0x2F. There they won't mess up anything. Sadly IBM really + * messed this up with the original PC, and they haven't been able to + * rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f, + * which is used for the internal hardware interrupts as well. We just + * have to reprogram the 8259's, and it isn't fun. + */ + +static void setup_i8259(void) +{ + outb(0x11, 0x20); /*! initialization sequence to 8259A-1*/ + outb(0x11, 0xA0); /*! and to 8259A-2*/ + + outb(0x20, 0x21); /*! start of hardware int's (0x20)*/ + outb(0x28, 0xA1); /*! start of hardware int's 2 (0x28)*/ + + outb(0x04, 0x21); /*! 8259-1 is master*/ + outb(0x02, 0xA1); /*! 8259-2 is slave*/ + + outb(0x01, 0x21); /*! 8086 mode for both*/ + outb(0x01, 0xA1); + + outb(0xFF, 0xA1); /*! mask off all interrupts for now*/ + outb(0xFB, 0x21); /*! mask all irq's but irq2 which is cascaded*/ +} + +static void hardware_setup(struct param_info *info __unused) +{ + /* Disable nmi */ + outb(0x80, 0x70); + + /* Make sure any coprocessor is properly reset.. */ + outb(0, 0xf0); + outb(0, 0xf1); + + setup_i8259(); +} + + +/* + * ELF Boot loader + * ============================================================================= + */ + +static int count_elf_notes(Elf_Bhdr *bhdr) +{ + unsigned char *note, *end; + int count; + count = 0; + note = ((char *)bhdr) + sizeof(*bhdr); + end = ((char *)bhdr) + bhdr->b_size; +#if 0 + printf("count_elf_notes %lx\n", (unsigned long)bhdr); +#endif + while (note < end) { + Elf_Nhdr *hdr; + unsigned char *n_name, *n_desc, *next; + hdr = (Elf_Nhdr *)note; + n_name = note + sizeof(*hdr); + n_desc = n_name + ((hdr->n_namesz + 3) & ~3); + next = n_desc + ((hdr->n_descsz + 3) & ~3); +#if 0 + printf("elf_note = %lx\n", (unsigned long)note); + printf("elf_namesz = %x\n", hdr->n_namesz); + printf("elf_descsz = %x\n", hdr->n_descsz); + printf("elf_type = %x\n", hdr->n_type); + printf("elf_name = %lx\n", (unsigned long)n_name); + printf("elf_desc = %lx\n", (unsigned long)n_desc); +#endif + if (next > end) + break; + count++; + note = next; + } + return count; +} + +static Elf_Nhdr *find_elf_note(Elf_Bhdr *bhdr, + Elf_Word namesz, unsigned char *name, Elf_Word type) +{ + unsigned char *note, *end; + note = ((char *)bhdr) + sizeof(*bhdr); + end = ((char *)bhdr) + bhdr->b_size; + while(note < end) { + Elf_Nhdr *hdr; + unsigned char *n_name, *n_desc, *next; + hdr = (Elf_Nhdr *)note; + n_name = note + sizeof(*hdr); + n_desc = n_name + ((hdr->n_namesz + 3) & ~3); + next = n_desc + ((hdr->n_descsz + 3) & ~3); + if (next > end) + break; + if ((hdr->n_type == type) && + (hdr->n_namesz == namesz) && + (memcmp(n_name, name, namesz) == 0)) { + return hdr; + } + note = next; + } + return 0; +} + +static void convert_elf_command_line(struct param_info *info, + Elf_Word descsz, unsigned char *desc) +{ + append_command_line(info->real_mode, desc, descsz); +} + +struct { + Elf_Word namesz; + unsigned char *name; + Elf_Word type; + void (*convert)(struct param_info *info, Elf_Word descsz, unsigned char *desc); +} elf_notes[] = +{ + { 0, "", EBN_COMMAND_LINE, convert_elf_command_line }, +}; + +static void convert_elf_boot(struct param_info *info, Elf_Bhdr *bhdr) +{ + unsigned char *note, *end; + note = ((char *)bhdr) + sizeof(*bhdr); + end = ((char *)bhdr) + bhdr->b_size; + while(note < end) { + Elf_Nhdr *hdr; + unsigned char *n_name, *n_desc, *next; + size_t i; + hdr = (Elf_Nhdr *)note; + n_name = note + sizeof(*hdr); + n_desc = n_name + ((hdr->n_namesz + 3) & ~3); + next = n_desc + ((hdr->n_descsz + 3) & ~3); + if (next > end) + break; + for(i = 0; i < sizeof(elf_notes)/sizeof(elf_notes[0]); i++) { + if ((hdr->n_type == elf_notes[i].type) && + (hdr->n_namesz == elf_notes[i].namesz) && + (memcmp(n_name, elf_notes[i].name, elf_notes[i].namesz) == 0)) { + elf_notes[i].convert(info, hdr->n_descsz, n_desc); + break; + } + } + note = next; + } +} + +/* + * LinuxBIOS + * ============================================================================= + */ + +#define LB_MEM_DEBUG 0 +#if LB_MEM_DEBUG +#define lb_puts(x) printf("%s", x) +#define lb_put_hex(x) printf("%x", x) +#define lb_put_lhex(x) printf("%Lx", x) +#else +#define lb_puts(x) +#define lb_put_hex(x) +#define lb_put_lhex(x) +#endif /* LB_MEM_DEBUG */ + +static unsigned count_lb_records(void *start, unsigned long length) +{ + struct lb_record *rec; + void *end; + unsigned count; + count = 0; + end = ((char *)start) + length; + for(rec = start; ((void *)rec < end) && + (rec->size <= (unsigned long)(end - (void *)rec)); + rec = (void *)(((char *)rec) + rec->size)) { + count++; + } + return count; +} + +static struct lb_header *__find_lb_table(void *start, void *end) +{ + unsigned char *ptr; + /* For now be stupid.... */ + for(ptr = start; (void *)ptr < end; ptr += 16) { + struct lb_header *head = (void *)ptr; + if ((head->signature[0] == 'L') && + (head->signature[1] == 'B') && + (head->signature[2] == 'I') && + (head->signature[3] == 'O') && + (head->header_bytes == sizeof(*head)) && + (compute_checksum(head, sizeof(*head)) == 0) && + (compute_checksum(ptr + sizeof(*head), head->table_bytes) == + head->table_checksum) && + (count_lb_records(ptr + sizeof(*head), head->table_bytes) == + head->table_entries) + ) { + return head; + } + }; + return 0; +} + +static int find_lb_table(struct param_info *info) +{ + struct lb_header *head; + head = 0; + if (!head) { + /* First try at address 0 */ + head = __find_lb_table((void *)0x00000, (void *)0x1000); + } + if (!head) { + /* Then try at address 0xf0000 */ + head = __find_lb_table((void *)0xf0000, (void *)0x100000); + } + if (head) { + info->has_linuxbios = 1; + info->lb_table = head; + return 1; + } + return 0; +} + +static void convert_lb_memory(struct param_info *info, struct lb_memory *mem) +{ + int i; + int entries; + entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]); + for(i = 0; (i < entries) && (i < E820MAX); i++) { + unsigned long type; + unsigned long long end; + end = mem->map[i].start + mem->map[i].size; + lb_puts("lb-mem: "); + lb_put_lhex(mem->map[i].start); + lb_puts(" - "); + lb_put_lhex(end); + lb_puts(" ("); + switch(mem->map[i].type) { + case LB_MEM_RAM: + type = E820_RAM; + lb_puts("ram"); + break; + default: + type = E820_RESERVED; + lb_puts("reserved"); + break; + } + lb_puts(")\n"); + add_e820_map(info->real_mode, + mem->map[i].start, mem->map[i].size, type); + } + info->need_mem_sizes = 0; +} + +static void query_lb_values(struct param_info *info) +{ + struct lb_header *head; + struct lb_record *rec; + void *start, *end; + head = info->lb_table; + start = ((unsigned char *)head) + sizeof(*head); + end = ((char *)start) + head->table_bytes; + for(rec = start; ((void *)rec < end) && + (rec->size <= (unsigned long)(end - (void *)rec)); + rec = (void *)(((char *)rec) + rec->size)) { + switch(rec->tag) { + case LB_TAG_MEMORY: + { + struct lb_memory *mem; + mem = (struct lb_memory *) rec; + convert_lb_memory(info, mem); + break; + } + default: + break; + }; + } +} + +/* + * PCBIOS + * ============================================================================= + */ +#define PC_MEM_DEBUG 0 +#if PC_MEM_DEBUG +#define pc_puts(x) printf("%s", x) +#define pc_put_hex(x) printf("%x", x) +#define pc_put_lhex(x) printf("%Lx", x) +#else +#define pc_puts(x) +#define pc_put_hex(x) +#define pc_put_lhex(x) +#endif /* PC_MEM_DEBUG */ + +/* functions for querying the pcbios */ +extern void noop(void); /* for testing purposes only */ +extern int meme820(struct e820entry *buf, int count); +extern unsigned int meme801(void); +extern unsigned short mem88(void); +extern unsigned short basememsize(void); + +struct meminfo { + int map_count; + struct e820entry map[E820MAX]; +}; + +static struct meminfo meminfo; +static void get_meminfo(struct param_info *info) +{ + int i; + pc_puts("getting meminfo...\n"); + meminfo.map_count = meme820(meminfo.map, E820MAX); + pc_puts("got meminfo count="); pc_put_hex(meminfo.map_count); pc_puts("\n"); + for(i = 0; i < meminfo.map_count; i++) { + unsigned long long end; + struct e820entry *seg = meminfo.map + i; + end = seg->addr + seg->size; + pc_puts("BIOS-e820: "); + pc_put_lhex(seg->addr); + pc_puts(" - "); + pc_put_lhex(end); + pc_puts(" ("); + switch(seg->type) { + case E820_RAM: + pc_puts("ram"); + info->need_mem_sizes = 0; + break; + case E820_ACPI: + pc_puts("ACPI data"); + break; + case E820_NVS: + pc_puts("ACPI NVS"); + break; + case E820_RESERVED: + default: + pc_puts("reserved"); + break; + } + pc_puts(")\n"); + add_e820_map(info->real_mode, + seg->addr, seg->size, seg->type); + } + info->real_mode->alt_mem_k = meme801(); + info->real_mode->ext_mem_k = mem88(); + if (info->real_mode->alt_mem_k || info->real_mode->ext_mem_k) { + info->need_mem_sizes = 0; + } +} + +static void query_pcbios_values(struct param_info *info) +{ + get_meminfo(info); +} + +/* + * Bootloaders + * ============================================================================= + */ + + +static void query_bootloader_param_class(struct param_info *info) +{ + int has_bootloader_type = 0; + Elf_Bhdr *hdr = 0; + if (!has_bootloader_type && (info->type == 0x2BADB002)) { + /* Orignal multiboot specification */ + info->has_multiboot = 1; + has_bootloader_type = 1; + } + if (!has_bootloader_type && (info->type == 0x0A11B007)) { + /* Uniform boot proposal */ + unsigned long checksum; + struct uniform_boot_header *header; + header = info->data; + checksum = compute_checksum(header, header->header_bytes); + if (checksum == 0) { + info->has_uniform_boot = 1; + has_bootloader_type = 1; + } else{ + printf("Bad uniform boot header checksum!\n"); + } + } + if (info->type == ELF_BHDR_MAGIC) { + hdr = info->data; + } + if (info->param && (info->param->b_signature == ELF_BHDR_MAGIC)) { + hdr = info->param; + } + if (!has_bootloader_type && hdr) { + /* Good ELF boot proposal... */ + unsigned long checksum; + int count; + checksum = 0; + if (hdr->b_checksum != 0) { + checksum = compute_checksum(hdr, hdr->b_size); + } + count = count_elf_notes(hdr); + if ((hdr->b_signature == ELF_BHDR_MAGIC) && + (checksum == 0) && + hdr->b_records == count) { + info->has_elf_boot = 1; + info->param = hdr; + has_bootloader_type = 1; + } + else { + printf("Bad ELF parameter table!\n"); + printf(" checksum = %x\n", checksum); + printf(" count = %x\n", count); + printf(" hdr = %x\n", (unsigned long)hdr); + printf(" b_size = %x\n", hdr->b_size); + printf("b_signature = %x\n", hdr->b_signature); + printf(" b_records = %x\n", hdr->b_records); + } + } + if (!has_bootloader_type) { + printf("Unknown bootloader class!\n"); + printf("type=%x\n", info->type); + printf("data=%x\n", (unsigned)info->data); + printf("param=%x\n", (unsigned)info->param); + } +} + +static void query_bootloader_values(struct param_info *info) +{ + if (info->has_multiboot) { + convert_multiboot(info, info->data); + } + else if (info->has_uniform_boot) { + convert_uniform_boot(info, info->data); + } + else if (info->has_elf_boot) { + convert_elf_boot(info, info->param); + } +} + +/* + * Firmware + * ============================================================================= + */ + +static int bootloader_query_firmware_class(struct param_info *info) +{ + Elf_Nhdr *hdr; + unsigned char *note, *n_name, *n_desc; + int detected_firmware_type; + if (!info->has_elf_boot) { + /* Only the elf boot tables gives us a firmware type */ + return 0; + } + detected_firmware_type = 0; + n_desc = 0; + + hdr = find_elf_note(info->param, 0, 0, EBN_FIRMWARE_TYPE); + if (!hdr) { + /* If I'm not explicitly told the firmware type + * do my best to guess it for myself. + */ + detected_firmware_type = 0; + } else { + note = (char *)hdr; + n_name = note + sizeof(*hdr); + n_desc = n_name + ((hdr->n_namesz + 3) & ~3); + } + if (!detected_firmware_type && hdr && + (hdr->n_descsz == 7) && + (memcmp(n_desc, "PCBIOS", 7) == 0)) { + info->has_pcbios = 1; + detected_firmware_type = 1; + } + if (!detected_firmware_type && hdr && + (hdr->n_descsz == 10) && + (memcmp(n_desc, "LinuxBIOS", 10) == 0)) { + /* Don't believe I'm linuxBIOS unless I can + * find the linuxBIOS table.. + */ + detected_firmware_type = find_lb_table(info); + } + if (!detected_firmware_type && hdr && + (hdr->n_descsz == 0)) { + /* No firmware is present */ + detected_firmware_type = 1; + } + if (!detected_firmware_type && hdr && + (hdr->n_descsz == 1) && + (memcmp(n_desc, "", 1) == 0)) { + /* No firmware is present */ + detected_firmware_type = 1; + } + if (!detected_firmware_type && hdr) { + printf("Unknown firmware type: %s\n", n_desc); + } + return detected_firmware_type; +} + +static void query_firmware_class(struct param_info *info) +{ + int detected_firmware_type = 0; + + /* First say I have no firmware at all... */ + info->has_pcbios = 0; + info->has_linuxbios = 0; + + /* See if the bootloader has told us what + * kind of firmware we are running on. + */ + detected_firmware_type = bootloader_query_firmware_class(info); + + /* See if we can detect linuxbios. */ + if (!detected_firmware_type) { + detected_firmware_type = find_lb_table(info); + } + + if (!detected_firmware_type) { + /* if all else fails assume a standard pcbios... */ + info->has_pcbios = 1; + } + + /* Now print out the firmware type... */ + printf("Firmware type:"); + if (info->has_linuxbios) { + printf(" LinuxBIOS"); + } + if (info->has_pcbios) { + printf(" PCBIOS"); + } + printf("\n"); +} + +static void query_firmware_values(struct param_info *info) +{ + if (info->has_linuxbios) { + query_lb_values(info); + } + if (info->has_pcbios) { + query_pcbios_values(info); + } + +} + +/* + * Debug + * ============================================================================= + */ + +#if 0 +static void print_offsets(void) +{ + struct parameters *real_mode = 0; + printf("print_offsets\n"); + + printf("orig_x =%x\n", (uint32_t)&real_mode->orig_x); + printf("orig_y =%x\n", (uint32_t)&real_mode->orig_y); + printf("ext_mem_k =%x\n", (uint32_t)&real_mode->ext_mem_k); + printf("orig_video_page =%x\n", (uint32_t)&real_mode->orig_video_page); + printf("orig_video_mode =%x\n", (uint32_t)&real_mode->orig_video_mode); + printf("orig_video_cols =%x\n", (uint32_t)&real_mode->orig_video_cols); + printf("unused2 =%x\n", (uint32_t)&real_mode->unused2); + printf("orig_video_ega_bx =%x\n", (uint32_t)&real_mode->orig_video_ega_bx); + printf("unused3 =%x\n", (uint32_t)&real_mode->unused3); + printf("orig_video_lines =%x\n", (uint32_t)&real_mode->orig_video_lines); + printf("orig_video_isVGA =%x\n", (uint32_t)&real_mode->orig_video_isVGA); + printf("orig_video_points =%x\n", (uint32_t)&real_mode->orig_video_points); + printf("lfb_width =%x\n", (uint32_t)&real_mode->lfb_width); + printf("lfb_height =%x\n", (uint32_t)&real_mode->lfb_height); + printf("lfb_depth =%x\n", (uint32_t)&real_mode->lfb_depth); + printf("lfb_base =%x\n", (uint32_t)&real_mode->lfb_base); + printf("lfb_size =%x\n", (uint32_t)&real_mode->lfb_size); + printf("cl_magic =%x\n", (uint32_t)&real_mode->cl_magic); + printf("cl_offset =%x\n", (uint32_t)&real_mode->cl_offset); + printf("lfb_linelength =%x\n", (uint32_t)&real_mode->lfb_linelength); + printf("red_size =%x\n", (uint32_t)&real_mode->red_size); + printf("red_pos =%x\n", (uint32_t)&real_mode->red_pos); + printf("green_size =%x\n", (uint32_t)&real_mode->green_size); + printf("green_pos =%x\n", (uint32_t)&real_mode->green_pos); + printf("blue_size =%x\n", (uint32_t)&real_mode->blue_size); + printf("blue_pos =%x\n", (uint32_t)&real_mode->blue_pos); + printf("rsvd_size =%x\n", (uint32_t)&real_mode->rsvd_size); + printf("rsvd_pos =%x\n", (uint32_t)&real_mode->rsvd_pos); + printf("vesapm_seg =%x\n", (uint32_t)&real_mode->vesapm_seg); + printf("vesapm_off =%x\n", (uint32_t)&real_mode->vesapm_off); + printf("pages =%x\n", (uint32_t)&real_mode->pages); + printf("reserved4 =%x\n", (uint32_t)&real_mode->reserved4); + printf("apm_bios_info =%x\n", (uint32_t)&real_mode->apm_bios_info); + printf("drive_info =%x\n", (uint32_t)&real_mode->drive_info); + printf("sys_desc_table =%x\n", (uint32_t)&real_mode->sys_desc_table); + printf("alt_mem_k =%x\n", (uint32_t)&real_mode->alt_mem_k); + printf("reserved5 =%x\n", (uint32_t)&real_mode->reserved5); + printf("e820_map_nr =%x\n", (uint32_t)&real_mode->e820_map_nr); + printf("reserved6 =%x\n", (uint32_t)&real_mode->reserved6); + printf("mount_root_rdonly =%x\n", (uint32_t)&real_mode->mount_root_rdonly); + printf("reserved7 =%x\n", (uint32_t)&real_mode->reserved7); + printf("ramdisk_flags =%x\n", (uint32_t)&real_mode->ramdisk_flags); + printf("reserved8 =%x\n", (uint32_t)&real_mode->reserved8); + printf("orig_root_dev =%x\n", (uint32_t)&real_mode->orig_root_dev); + printf("reserved9 =%x\n", (uint32_t)&real_mode->reserved9); + printf("aux_device_info =%x\n", (uint32_t)&real_mode->aux_device_info); + printf("reserved10 =%x\n", (uint32_t)&real_mode->reserved10); + printf("param_block_signature=%x\n", (uint32_t)&real_mode->param_block_signature); + printf("param_block_version =%x\n", (uint32_t)&real_mode->param_block_version); + printf("reserved11 =%x\n", (uint32_t)&real_mode->reserved11); + printf("loader_type =%x\n", (uint32_t)&real_mode->loader_type); + printf("loader_flags =%x\n", (uint32_t)&real_mode->loader_flags); + printf("reserved12 =%x\n", (uint32_t)&real_mode->reserved12); + printf("kernel_start =%x\n", (uint32_t)&real_mode->kernel_start); + printf("initrd_start =%x\n", (uint32_t)&real_mode->initrd_start); + printf("initrd_size =%x\n", (uint32_t)&real_mode->initrd_size); + printf("reserved13 =%x\n", (uint32_t)&real_mode->reserved13); + printf("e820_map =%x\n", (uint32_t)&real_mode->e820_map); + printf("reserved16 =%x\n", (uint32_t)&real_mode->reserved16); + printf("command_line =%x\n", (uint32_t)&real_mode->command_line); + printf("reserved17 =%x\n", (uint32_t)&real_mode->reserved17); +} + +static void print_linux_params(struct param_info *info) +{ + int i; + + printf("print_linux_params\n"); + /* Default screen size */ + printf("orig_x =%x\n", info->real_mode->orig_x); + printf("orig_y =%x\n", info->real_mode->orig_y); + printf("orig_video_page =%x\n", info->real_mode->orig_video_page); + printf("orig_video_mode =%x\n", info->real_mode->orig_video_mode); + printf("orig_video_cols =%x\n", info->real_mode->orig_video_cols); + printf("orig_video_lines =%x\n", info->real_mode->orig_video_lines); + printf("orig_video_ega_bx=%x\n", info->real_mode->orig_video_ega_bx); + printf("orig_video_isVGA =%x\n", info->real_mode->orig_video_isVGA); + printf("orig_video_points=%x\n", info->real_mode->orig_video_points); + + + /* System descriptor table... */ + printf("sys_dest_table_len=%x\n", info->real_mode->sys_desc_table.length); + + /* Memory sizes */ + printf("ext_mem_k =%x\n", info->real_mode->ext_mem_k); + printf("alt_mem_k =%x\n", info->real_mode->alt_mem_k); + printf("e820_map_nr =%x\n", info->real_mode->e820_map_nr); + for(i = 0; i < E820MAX; i++) { + printf("addr[%x] =%Lx\n", + i, info->real_mode->e820_map[i].addr); + printf("size[%x] =%Lx\n", + i, info->real_mode->e820_map[i].size); + printf("type[%x] =%Lx\n", + i, info->real_mode->e820_map[i].type); + } + printf("mount_root_rdonly=%x\n", info->real_mode->mount_root_rdonly); + printf("ramdisk_flags =%x\n", info->real_mode->ramdisk_flags); + printf("orig_root_dev =%x\n", info->real_mode->orig_root_dev); + printf("aux_device_info =%x\n", info->real_mode->aux_device_info); + printf("param_block_signature=%x\n", *((uint32_t *)info->real_mode->param_block_signature)); + printf("loader_type =%x\n", info->real_mode->loader_type); + printf("loader_flags =%x\n", info->real_mode->loader_flags); + printf("initrd_start =%x\n", info->real_mode->initrd_start); + printf("initrd_size =%x\n", info->real_mode->initrd_size); + + /* Where I'm putting the command line */ + printf("cl_magic =%x\n", info->real_mode->cl_magic); + printf("cl_offset =%x\n", info->real_mode->cl_offset); + + /* Now print the command line */ + printf("command_line =%s\n", info->real_mode->command_line); +} + + +#endif + +/* + * main + * ============================================================================= + */ + +void initialize_linux_params(struct param_info *info) +{ + int len; + /* First the defaults */ + memset(info->real_mode, 0, PAGE_SIZE); + + /* Default screen size */ + info->real_mode->orig_x = 0; + info->real_mode->orig_y = 25; + info->real_mode->orig_video_page = 0; + info->real_mode->orig_video_mode = 0; + info->real_mode->orig_video_cols = 80; + info->real_mode->orig_video_lines = 25; + info->real_mode->orig_video_ega_bx = 0; + info->real_mode->orig_video_isVGA = 1; + info->real_mode->orig_video_points = 16; + + /* Fill this in later */ + info->real_mode->ext_mem_k = 0; + + /* Fill in later... */ + info->real_mode->e820_map_nr = 0; + + /* Where I'm putting the command line */ + info->real_mode->cl_magic = CL_MAGIC_VALUE; + info->real_mode->cl_offset = 2048; + + info->real_mode->cmd_line_ptr = info->real_mode->cl_offset + (unsigned long) info->real_mode; + + /* Now set the command line */ + len = strnlen(info->image->cmdline, sizeof(info->real_mode->command_line) -1); + memcpy(info->real_mode->command_line, info->image->cmdline, len); + info->real_mode->command_line[len] = '\0'; + + /* from the bios initially */ + memset(&info->real_mode->apm_bios_info, 0, sizeof(info->real_mode->apm_bios_info)); + + memset(&info->real_mode->drive_info, 0, sizeof(info->real_mode->drive_info)); + + /* forget it for now... */ + info->real_mode->sys_desc_table.length = 0; + + /* Fill this in later */ + info->real_mode->alt_mem_k = 0; + info->real_mode->ext_mem_k = 0; + + /* default yes: this can be overridden on the command line */ + info->real_mode->mount_root_rdonly = 0xFFFF; + + /* old ramdisk options, These really should be command line + * things... + */ + info->real_mode->ramdisk_flags = info->image->ramdisk_flags; + + /* default to /dev/hda. + * Override this on the command line if necessary + */ + info->real_mode->orig_root_dev = info->image->root_dev; + + /* Originally from the bios? */ + info->real_mode->aux_device_info = 0; + + /* Boot block magic */ + memcpy(info->real_mode->param_block_signature, "HdrS", 4); + info->real_mode->param_block_version = 0x0201; + + /* Say I'm a kernel boot loader */ + info->real_mode->loader_type = (LOADER_TYPE_KERNEL << 4) + 0 /* version */; + + /* No loader flags */ + info->real_mode->loader_flags = 0; + + /* Ramdisk address and size ... */ + info->real_mode->initrd_start = 0; + info->real_mode->initrd_size = 0; + if (info->image->initrd_size) { + info->real_mode->initrd_start = info->image->initrd_start; + info->real_mode->initrd_size = info->image->initrd_size; + } + + /* Now remember those things that I need */ + info->need_mem_sizes = 1; +} + +void *convert_params(unsigned type, void *data, void *param, void *image) +{ + struct param_info info; +#if 0 + printf("hello world\n"); +#endif + info.real_mode = faked_real_mode; + info.type = type; + info.data = data; + info.param = param; + info.image = image; + initialize_linux_params(&info); + query_bootloader_param_class(&info); + query_firmware_class(&info); + query_firmware_values(&info); + query_bootloader_values(&info); + + /* Do the hardware setup that linux might forget... */ + hardware_setup(&info); + + /* Print some debugging information */ +#if 0 + printf("EXT_MEM_K=%x\n", info.real_mode->ext_mem_k); + printf("ALT_MEM_K=%x\n", info.real_mode->alt_mem_k); +#endif +#if 0 + print_offsets(); + print_linux_params(&info); +#endif +#if 0 + printf("info.real_mode = 0x%x\n", info.real_mode ); + printf("Jumping to Linux\n"); +#endif + return info.real_mode; +} + diff --git a/util/mkelfImage/linux-i386/head.S b/util/mkelfImage/linux-i386/head.S new file mode 100644 index 0000000000..c3990ac801 --- /dev/null +++ b/util/mkelfImage/linux-i386/head.S @@ -0,0 +1,476 @@ +/* + * exec_kernel/user_space/head.S + * + * Copyright (C) 2000, 2002, 2003 Eric Biederman + * + * Parts of this code were take from the linux startup + * code of linux-2.4.0-test9 + * + * Other parts were taken from etherboot-5.0.5 + */ + +#define ASSEMBLY 1 + +#define RELOC 0x10000 +#define PROT_CODE_SEG 0x10 +#define PROT_DATA_SEG 0x18 +#define REAL_CODE_SEG 0x08 +#define REAL_DATA_SEG 0x20 + + .equ CR0_PE,1 + +.text +.code32 + + +#include "convert.h" + + .globl startup_32 +startup_32: + cld + cli + + # Save the arguments safely out of the way + movl %eax, boot_type + movl %ebx, boot_data + cmp $0,%esp + jz 1f + movl 4(%esp), %eax + movl %eax, boot_param +1: + + movl stack_start, %esp + + # Clear eflags + pushl $0 + popfl + + # Clear BSS + xorl %eax,%eax + movl $ _edata,%edi + movl $ _end,%ecx + subl %edi,%ecx + cld + rep + stosb + + # Move the gdt where Linux will not smash it during decompression + movl $gdt, %esi + movl $GDTLOC, %edi + movl $(gdt_end - gdt), %ecx + rep movsb + + # Linux makes stupid assumptions about the segments + # that are already setup, so setup a new gdt & ldt + # and then reload the segment registers. + + lgdt gdt_48 + lidt idt_48 + + # Load the data segment registers + movl $ PROT_DATA_SEG, %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %fs + movl %eax, %gs + movl %eax, %ss + + pushl $image_params # image build time parameters as forth arg + pushl boot_param # boot_param pointer as third arg + pushl boot_data # boot data pointer as second arg + pushl boot_type # boot data type as first argument + call convert_params + + movl %eax, %esi # put the real mode pointer in a safe place + addl $16, %esp # pop the arguments + + + # Setup the registers before jumping to linux + + + # clear eflags + pushl $0 + popfl + + # Flag to indicate we are the bootstrap processor + xorl %ebx, %ebx + + # Clear the unspecified registers for good measure + xorl %eax, %eax + xorl %ecx, %ecx + xorl %edx, %edx + xorl %edi, %edi + xorl %esp, %esp + xorl %ebp, %ebp + + + # Jump to the linux kernel + ljmp $ PROT_CODE_SEG , $ 0x100000 + + + /* Routines to query the BIOS... */ + + +/************************************************************************** +E820_MEMSIZE - Get a listing of memory regions +**************************************************************************/ +#define SMAP 0x534d4150 + .globl meme820 +meme820: + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %esi + pushl %edi + movl 8(%ebp), %edi /* Address to return e820 structures at */ + subl $RELOC, %edi + movl 12(%ebp), %esi /* Maximum number of e820 structurs to return */ + pushl %esi + call _prot_to_real + .code16 + xorl %ebx, %ebx +jmpe820: + movl $0xe820, %eax + movl $SMAP, %edx + movl $20, %ecx + /* %di was setup earlier */ + int $0x15 + jc bail820 + + cmpl $SMAP, %eax + jne bail820 + +good820: + /* If this is useable memory, we save it by simply advancing %di by + * sizeof(e820rec) + */ + decl %esi + testl %esi,%esi + jz bail820 + + addw $20, %di +again820: + cmpl $0, %ebx /* check to see if %ebx is set to EOF */ + jne jmpe820 + +bail820: + data32 call _real_to_prot + .code32 + popl %eax + subl %esi, %eax /* Compute how many structure we read */ + + /* Restore everything else */ + popl %edi + popl %esi + popl %ebx + movl %ebp, %esp + popl %ebp + ret + + +/************************************************************************** +MEME801 - Determine size of extended memory +**************************************************************************/ + .globl meme801 +meme801: + pushl %ebx + pushl %esi + pushl %edi + call _prot_to_real + .code16 + + 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 e801absent + + 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 + movl %edx, %eax # store extended memory size + andl $0xffff, %ecx # clear sign extend + addl %ecx, %eax # and add lower memory into + + jmp e801out +e801absent: + xorl %eax,%eax + +e801out: + data32 call _real_to_prot + .code32 + /* Restore Everything */ + popl %edi + popl %esi + popl %ebx + ret + +/************************************************************************** +MEM88 - Determine size of extended memory +**************************************************************************/ + .globl mem88 +mem88: + pushl %ebx + pushl %esi + pushl %edi + call _prot_to_real + .code16 + + movb $0x88, %ah + int $0x15 + andl $0xffff, %eax + + data32 call _real_to_prot + .code32 + + /* Restore Everything */ + popl %edi + popl %esi + popl %ebx + ret + + +/************************************************************************** +BASEMEMSIZE - Get size of the conventional (base) memory +**************************************************************************/ + .globl basememsize +basememsize: + call _prot_to_real + .code16 + int $0x12 + movw %ax,%cx + DATA32 call _real_to_prot + .code32 + movw %cx,%ax + ret + +/************************************************************************** +_REAL_TO_PROT - Go from REAL mode to Protected Mode +**************************************************************************/ + .globl _real_to_prot +_real_to_prot: + .code16 + cli + cs + addr32 lgdt gdt_48 - RELOC + movl %cr0,%eax + orl $CR0_PE,%eax + movl %eax,%cr0 /* turn on protected mode */ + + /* flush prefetch queue, and reload %cs:%eip */ + data32 ljmp $PROT_CODE_SEG,$1f +1: + .code32 + /* reload other segment registers */ + movl $PROT_DATA_SEG,%eax + movl %eax,%ds + movl %eax,%es + movl %eax,%ss + addl $RELOC,%esp /* Fix up stack pointer */ + xorl %eax,%eax + movl %eax,%fs + movl %eax,%gs + popl %eax /* Fix up return address */ + addl $RELOC,%eax + pushl %eax + + /* switch to protected mode idt */ + cs + lidt idt_48 + ret + +/************************************************************************** +_PROT_TO_REAL - Go from Protected Mode to REAL Mode +**************************************************************************/ + .globl _prot_to_real +_prot_to_real: + .code32 + popl %eax + subl $RELOC,%eax /* Adjust return address */ + pushl %eax + subl $RELOC,%esp /* Adjust stack pointer */ + ljmp $REAL_CODE_SEG,$1f- RELOC /* jump to a 16 bit segment */ +1: + .code16 + /* clear the PE bit of CR0 */ + movl %cr0,%eax + andl $0!CR0_PE,%eax + movl %eax,%cr0 + + /* make intersegment jmp to flush the processor pipeline + * and reload %cs:%eip (to clear upper 16 bits of %eip). + */ + data32 ljmp $(RELOC)>>4,$2f- RELOC +2: + /* we are in real mode now + * set up the real mode segment registers : %ds, $ss, %es + */ + movw %cs,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%ss + movw %ax,%fs + movw %ax,%gs + + /* Switch to the real mode idt */ + cs + addr32 lidt idt_real - RELOC + + sti + data32 ret /* There is a 32 bit return address on the stack */ + .code32 + +boot_type: .long 0 +boot_data: .long 0 +boot_param: .long 0 + +idt_real: + .word 0x400 # idt limit = 256 + .word 0, 0 +idt_48: + .word 0 # idt limit = 0 + .word 0, 0 # idt base = 0L +gdt_48: + .word gdt_end - gdt - 1 # gdt limit=40, + # (5 GDT entries) + .long GDTLOC # gdt base + +# Descriptor tables +# These need to be in a seperate section so I can be +# certain later activities dont stomp them +gdt: + /* 0x00 */ + .word 0, 0, 0, 0 # dummy + + /* 0x08 */ + /* 16 bit real mode code segment */ + .word 0xffff,(RELOC&0xffff) + .byte (RELOC>>16),0x9b,0x00,(RELOC>>24) + + /* 0x10 */ + .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) + + /* 0x18 */ + .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) + + /* 0x20 */ + /* 16 bit real mode data segment */ + .word 0xffff,(RELOC&0xffff) + .byte (RELOC>>16),0x93,0x00,(RELOC>>24) + + /* For 2.5.x the kernel segments have moved */ + + /* 0x28 dummy */ + .quad 0 + + /* 0x30 dummy */ + .quad 0 + /* 0x38 dummy */ + .quad 0 + /* 0x40 dummy */ + .quad 0 + /* 0x48 dummy */ + .quad 0 + /* 0x50 dummy */ + .quad 0 + /* 0x58 dummy */ + .quad 0 + + + /* 0x60 */ + .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) + + /* 0x68 */ + .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) +/* + * The layout of the per-CPU GDT under Linux: + * + * 0 - null + * 1 - reserved + * 2 - reserved + * 3 - reserved + * + * 4 - default user CS <==== new cacheline + * 5 - default user DS + * + * ------- start of TLS (Thread-Local Storage) segments: + * + * 6 - TLS segment #1 [ glibc's TLS segment ] + * 7 - TLS segment #2 [ Wine's %fs Win32 segment ] + * 8 - TLS segment #3 + * 9 - reserved + * 10 - reserved + * 11 - reserved + * + * ------- start of kernel segments: + * + * 12 - kernel code segment <==== new cacheline + * 13 - kernel data segment + * 14 - TSS + * 15 - LDT + * 16 - PNPBIOS support (16->32 gate) + * 17 - PNPBIOS support + * 18 - PNPBIOS support + * 19 - PNPBIOS support + * 20 - PNPBIOS support + * 21 - APM BIOS support + * 22 - APM BIOS support + * 23 - APM BIOS support + */ +gdt_end: + + + + .section ".trailer", "a" + /* Constants set at build time, these are at the very end of my image */ + .balign 16 + .global image_params +image_params: + +convert_magic: + .long CONVERT_MAGIC +gdt_size: + .long gdt_end - gdt +bss_size: + .long bss_size +ramdisk_flags: + .word 0 +root_dev: + .word DEFAULT_ROOT_DEV +entry: + .long 0 +initrd_start: + .long 0 +initrd_size: + .long 0 +cmdline: + .asciz "BOOT_IMAGE=head.S console=ttyS0 ip=dhcp root=/dev/nfs" + .org cmdline + CMDLINE_MAX, 0 +cmdline_end: diff --git a/util/mkelfImage/linux-i386/mkelf-linux-i386.c b/util/mkelfImage/linux-i386/mkelf-linux-i386.c new file mode 100644 index 0000000000..200d4a55f9 --- /dev/null +++ b/util/mkelfImage/linux-i386/mkelf-linux-i386.c @@ -0,0 +1,388 @@ +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#define _GNU_SOURCE +#include <getopt.h> +#include "elf.h" +#include "elf_boot.h" +#include "convert.h" +#include "x86-linux.h" +#include "mkelfImage.h" + +static unsigned char payload[] = { +#include "convert.bin.c" +}; + +struct kernel_info; +static void (*parse_kernel_type)(struct kernel_info *info, char *kernel_buf, size_t kernel_size); +static void parse_bzImage_kernel(struct kernel_info *info, char *kernel_buf, size_t kernel_size); +static void parse_elf32_kernel(struct kernel_info *info, char *kernel_buf, size_t kernel_size); + +char *vmlinux_i386_probe(char *kernel_buf, off_t kernel_size) +{ + Elf32_Ehdr *ehdr; + Elf32_Phdr *phdr; + int i; + int hdr1, hdr2; + ehdr = (Elf32_Ehdr *)kernel_buf; + if ( + (ehdr->e_ident[EI_MAG0] != ELFMAG0) || + (ehdr->e_ident[EI_MAG1] != ELFMAG1) || + (ehdr->e_ident[EI_MAG2] != ELFMAG2) || + (ehdr->e_ident[EI_MAG3] != ELFMAG3)) { + return "No ELF signature found on kernel\n"; + } + if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) { + return "Not a 32bit ELF kernel\n"; + } + if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) { + return "Not a little endian ELF kernel\n"; + } + if (le16_to_cpu(ehdr->e_type) != ET_EXEC) { + return "Not an executable kernel\n"; + } + if (le16_to_cpu(ehdr->e_machine) != EM_386) { + return "Not an i386 kernel\n"; + } + if ( (ehdr->e_ident[EI_VERSION] != EV_CURRENT) || + (le32_to_cpu(ehdr->e_version) != EV_CURRENT)) { + return "Kernel not using ELF version 1.\n"; + } + if (le16_to_cpu(ehdr->e_phentsize) != sizeof(*phdr)) { + return "Kernel uses bad program header size.\n"; + } + phdr = (Elf32_Phdr *)(kernel_buf + le32_to_cpu(ehdr->e_phoff)); + hdr1 = hdr2 = -1; + for(i = 0; i < le32_to_cpu(ehdr->e_phnum); i++) { + if (le32_to_cpu(phdr[i].p_type) != PT_LOAD) + continue; + if (((hdr1 != -1) && + ((le32_to_cpu(phdr[hdr1].p_paddr) & 0xfffffff) != 0x100000)) || + (hdr2 != -1)) { + return "Too many PT_LOAD segments to be a linux kernel\n"; + } + if (hdr1 == -1) { + hdr1 = i; + } else { + hdr2 = i; + } + } + if (hdr1 == -1) { + return "No PT_LOAD segments!\n"; + } + parse_kernel_type = parse_elf32_kernel; + return 0; +} + +char *bzImage_i386_probe(char *kernel_buf, off_t kernel_size) +{ + struct x86_linux_header *hdr; + unsigned long offset; + int setup_sects; + hdr = (struct x86_linux_header *)kernel_buf; + + if (le16_to_cpu(hdr->boot_sector_magic) != 0xaa55) { + return "No bootsector magic"; + } + if (memcmp(hdr->header_magic, "HdrS", 4) != 0) { + return "Not a linux kernel"; + } + + if (le16_to_cpu(hdr->protocol_version) < 0x202) { + return "Kernel protcols version before 2.02 not supported"; + } + + setup_sects = hdr->setup_sects; + if (setup_sects == 0) { + setup_sects = 4; + } + offset = 512 + (512 *setup_sects); + if (offset > kernel_size) { + return "Not enough bytes"; + } + parse_kernel_type = parse_bzImage_kernel; + return 0; +} + +char *linux_i386_probe(char *kernel_buf, off_t kernel_size) +{ + char *result; + result = ""; + if (result) result = bzImage_i386_probe(kernel_buf, kernel_size); + if (result) result = vmlinux_i386_probe(kernel_buf, kernel_size); + if (result) result = bzImage_i386_probe(kernel_buf, kernel_size); + return result; +} + +struct kernel_info +{ + void *kernel; + size_t filesz; + size_t memsz; + size_t paddr; + size_t vaddr; + void *kernel2; + size_t filesz2; + size_t memsz2; + size_t paddr2; + size_t vaddr2; + size_t entry; + char *version; +}; + +static void parse_elf32_kernel(struct kernel_info *info, char *kernel_buf, size_t kernel_size) +{ + Elf32_Ehdr *ehdr; + Elf32_Phdr *phdr; + int i; + int hdr1, hdr2; + ehdr = (Elf32_Ehdr *)kernel_buf; + phdr = (Elf32_Phdr *)(kernel_buf + ehdr->e_phoff); + hdr1 = hdr2 = -1; + for(i = 0; i < le16_to_cpu(ehdr->e_phnum); i++) { + if (le32_to_cpu(phdr[i].p_type) != PT_LOAD) + continue; + if (hdr2 != -1) { + die("Too many PT_LOAD segments to be a linux kernel\n"); + } + if (hdr1 == -1) { + hdr1 = i; + } else { + hdr2 = i; + } + } + if (hdr1 == -1) { + die("No PT_LOAD segments!\n"); + } + info->kernel = kernel_buf + le32_to_cpu(phdr[hdr1].p_offset); + info->filesz = le32_to_cpu(phdr[hdr1].p_filesz); + info->memsz = le32_to_cpu(phdr[hdr1].p_memsz); + info->paddr = le32_to_cpu(phdr[hdr1].p_paddr) & 0xfffffff; + info->vaddr = le32_to_cpu(phdr[hdr1].p_vaddr); + + if (hdr2 != -1) { + info->kernel2 = kernel_buf + le32_to_cpu(phdr[hdr2].p_offset); + info->filesz2 = le32_to_cpu(phdr[hdr2].p_filesz); + info->memsz2 = le32_to_cpu(phdr[hdr2].p_memsz); + info->paddr2 = le32_to_cpu(phdr[hdr2].p_paddr) & 0xfffffff; + info->vaddr2 = le32_to_cpu(phdr[hdr2].p_vaddr); + } + + info->entry = 0x100000; + info->version = "unknown"; +} + +static void parse_bzImage_kernel(struct kernel_info *info, char *kernel_buf, size_t kernel_size) +{ + struct x86_linux_header *hdr; + unsigned long offset; + int setup_sects; + hdr = (struct x86_linux_header *)kernel_buf; + setup_sects = hdr->setup_sects; + if (setup_sects == 0) { + setup_sects = 4; + } + offset = 512 + (512 *setup_sects); + + info->kernel = kernel_buf + offset; + info->filesz = kernel_size - offset; + info->memsz = 0x700000; + info->paddr = 0x100000; + info->vaddr = 0x100000; + info->entry = info->paddr; + info->version = kernel_buf + 512 + le16_to_cpu(hdr->kver_addr); +} + +static void parse_kernel(struct kernel_info *info, char *kernel_buf, size_t kernel_size) +{ + memset(info, 0, sizeof(*info)); + if (parse_kernel_type) { + parse_kernel_type(info, kernel_buf, kernel_size); + } + else { + die("Unknown kernel format"); + } +} + +void linux_i386_usage(void) +{ + printf( + " --command-line=<string> Set the command line to <string>\n" + " --append=<string> Set the command line to <string>\n" + " --initrd=<filename> Set the initrd to <filename>\n" + " --ramdisk=<filename> Set the initrd to <filename>\n" + " --ramdisk-base=<addr> Set the initrd load address to <addr>\n" + ); + return; +} + + +#define OPT_CMDLINE OPT_MAX+0 +#define OPT_RAMDISK OPT_MAX+1 +#define OPT_RAMDISK_BASE OPT_MAX+2 + +#define DEFAULT_RAMDISK_BASE (8*1024*1024) + +int linux_i386_mkelf(int argc, char **argv, + struct memelfheader *ehdr, char *kernel_buf, off_t kernel_size) +{ + const char *ramdisk, *cmdline; + unsigned long ramdisk_base; + char *payload_buf, *ramdisk_buf; + off_t payload_size, ramdisk_size; + struct memelfphdr *phdr; + struct memelfnote *note; + struct kernel_info kinfo; + struct image_parameters *params; + int index; + + int opt; + static const struct option options[] = { + MKELF_OPTIONS + { "command-line", 1, 0, OPT_CMDLINE }, + { "append", 1, 0, OPT_CMDLINE }, + { "initrd", 1, 0, OPT_RAMDISK }, + { "ramdisk", 1, 0, OPT_RAMDISK }, + { "ramdisk-base", 1, 0, OPT_RAMDISK_BASE }, + { 0 , 0, 0, 0 }, + }; + static const char short_options[] = MKELF_OPT_STR; + + ramdisk_base = DEFAULT_RAMDISK_BASE; + ramdisk = 0; + cmdline=""; + + while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) { + switch(opt) { + case '?': + error("Unknown option %s\n", argv[optind]); + break; + case OPT_RAMDISK_BASE: + { + char *end; + unsigned long base; + base = strtoul(optarg, &end, 0); + if ((end == optarg) || (*end != '\0')) { + error("Invalid ramdisk base\n"); + } + ramdisk_base = base; + } + case OPT_RAMDISK: + ramdisk = optarg; + break; + case OPT_CMDLINE: + cmdline = optarg; + break; + default: + break; + } + } + ehdr->ei_class = ELFCLASS32; + ehdr->ei_data = ELFDATA2LSB; + ehdr->e_type = ET_EXEC; + ehdr->e_machine = EM_386; + + /* locate the payload buffer */ + payload_buf = payload; + payload_size = sizeof(payload); + + /* slurp the input files */ + ramdisk_buf = slurp_file(ramdisk, &ramdisk_size); + + /* parse the kernel */ + parse_kernel(&kinfo, kernel_buf, kernel_size); + + /* Find the parameters */ + params = (void *)(payload_buf + (payload_size - sizeof(*params))); + + /* A sanity check against bad versions of binutils */ + if (params->convert_magic != CONVERT_MAGIC) { + die("Internal error convert_magic %08x != %08x\n", + params->convert_magic, CONVERT_MAGIC); + } + + /* Copy the command line */ + strncpy(params->cmdline, cmdline, sizeof(params->cmdline)); + params->cmdline[sizeof(params->cmdline)-1]= '\0'; + + + /* Add a program header for the note section */ + index = 4; + index += kinfo.kernel2 ? 1:0; + index += ramdisk_size ? 1:0; + phdr = add_program_headers(ehdr, index); + + /* Fill in the program headers*/ + phdr[0].p_type = PT_NOTE; + + /* Fill in the converter program headers */ + phdr[1].p_paddr = CONVERTLOC; + phdr[1].p_vaddr = CONVERTLOC; + phdr[1].p_filesz = payload_size; + phdr[1].p_memsz = payload_size + params->bss_size; + phdr[1].p_data = payload; + + /* Reserve space for the REAL MODE DATA segment AND the GDT segment */ + phdr[2].p_paddr = REAL_MODE_DATA_LOC; + phdr[2].p_vaddr = REAL_MODE_DATA_LOC; + phdr[2].p_filesz = 0; + phdr[2].p_memsz = (GDTLOC - REAL_MODE_DATA_LOC) + params->gdt_size; + phdr[2].p_data = 0; + + phdr[3].p_paddr = kinfo.paddr; + phdr[3].p_vaddr = kinfo.vaddr; + phdr[3].p_filesz = kinfo.filesz; + phdr[3].p_memsz = kinfo.memsz; + phdr[3].p_data = kinfo.kernel; + + index = 4; + /* Put the second kernel frament if present */ + if (kinfo.kernel2) { + phdr[index].p_paddr = kinfo.paddr2; + phdr[index].p_vaddr = kinfo.vaddr2; + phdr[index].p_filesz = kinfo.filesz2; + phdr[index].p_memsz = kinfo.memsz2; + phdr[index].p_data = kinfo.kernel2; + index++; + } + + /* Put the ramdisk at ramdisk base. + */ + params->initrd_start = params->initrd_size = 0; + if (ramdisk_size) { + phdr[index].p_paddr = ramdisk_base; + phdr[index].p_vaddr = ramdisk_base; + phdr[index].p_filesz = ramdisk_size; + phdr[index].p_memsz = ramdisk_size; + phdr[index].p_data = ramdisk_buf; + params->initrd_start = phdr[index].p_paddr; + params->initrd_size = phdr[index].p_filesz; + index++; + } + + /* Set the start location */ + params->entry = kinfo.entry; + ehdr->e_entry = phdr[1].p_paddr; + + /* Setup the elf notes */ + note = add_notes(ehdr, 3); + note[0].n_type = EIN_PROGRAM_NAME; + note[0].n_name = "ELFBoot"; + note[0].n_desc = "Linux"; + note[0].n_descsz = strlen(note[0].n_desc)+1; + + note[1].n_type = EIN_PROGRAM_VERSION; + note[1].n_name = "ELFBoot"; + note[1].n_desc = kinfo.version; + note[1].n_descsz = strlen(note[1].n_desc); + + note[2].n_type = EIN_PROGRAM_CHECKSUM; + note[2].n_name = "ELFBoot"; + note[2].n_desc = 0; + note[2].n_descsz = 2; + + return 0; +} + diff --git a/util/mkelfImage/linux-i386/uniform_boot.h b/util/mkelfImage/linux-i386/uniform_boot.h new file mode 100644 index 0000000000..5291fa66bb --- /dev/null +++ b/util/mkelfImage/linux-i386/uniform_boot.h @@ -0,0 +1,67 @@ +#ifndef _LINUX_UNIFORM_BOOT_H +#define _LINUX_UNIFORM_BOOT_H + +/* The uniform boot environment information is restricted to + * hardware information. In particular for a simple enough machine + * all of the environment information should be able to reside in + * a rom and not need to be moved. This information is the + * information a trivial boot room can pass to linux to let it + * run the hardware. + * + * Also all of the information should be Position Independent Data. + * That is it should be safe to relocated any of the information + * without it's meaning/correctnes changing. The exception is the + * uniform_boot_header with it's two pointers arg & env. + * + * The addresses in the arg & env pointers must be physical + * addresses. A physical address is an address you put in the page + * table. + * + * The Command line is for user policy. Things like the default + * root device. + * + */ + +struct uniform_boot_header +{ + unsigned long header_bytes; + unsigned long header_checksum; + unsigned long arg; + unsigned long arg_bytes; + unsigned long env; + unsigned long env_bytes; +}; + +/* Every entry in the boot enviroment list will correspond to a boot + * info record. Encoding both type and size. The type is obviously + * so you can tell what it is. The size allows you to skip that + * boot enviroment record if you don't know what it easy. This allows + * forward compatibility with records not yet defined. + */ +struct ube_record { + unsigned long tag; /* tag ID */ + unsigned long size; /* size of record (in bytes) */ + unsigned long data[0]; /* data */ +}; + + +#define UBE_TAG_MEMORY 0x0001 + +struct ube_memory_range { + unsigned long long start; + unsigned long long size; + unsigned long type; +#define UBE_MEM_RAM 1 +#define UBE_MEM_RESERVED 2 +#define UBE_MEM_ACPI 3 +#define UBE_MEM_NVS 4 + +}; + +struct ube_memory { + unsigned long tag; + unsigned long size; + struct ube_memory_range map[0]; +}; + +#endif /* _LINUX_UNIFORM_BOOT_H */ diff --git a/util/mkelfImage/linux-i386/x86-linux.h b/util/mkelfImage/linux-i386/x86-linux.h new file mode 100644 index 0000000000..fe1673ea67 --- /dev/null +++ b/util/mkelfImage/linux-i386/x86-linux.h @@ -0,0 +1,162 @@ +#ifndef X86_LINUX_H +#define X86_LINUX_H + +#define E820MAP 0x2d0 /* our map */ +#define E820MAX 32 /* number of entries in E820MAP */ +#define E820NR 0x1e8 /* # entries in E820MAP */ + +#ifndef ASSEMBLY + +struct e820entry { + uint64_t addr; /* start of memory segment */ + uint64_t size; /* size of memory segment */ + uint32_t type; /* type of memory segment */ +#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 +} __attribute__((packed)); + +/* FIXME expand on drive_info_struct... */ +struct drive_info_struct { + uint8_t dummy[32]; +}; +struct sys_desc_table { + uint16_t length; + uint8_t table[318]; +}; + +struct apm_bios_info { + uint16_t version; /* 0x40 */ + uint16_t cseg; /* 0x42 */ + uint32_t offset; /* 0x44 */ + uint16_t cseg_16; /* 0x48 */ + uint16_t dseg; /* 0x4a */ + uint16_t flags; /* 0x4c */ + uint16_t cseg_len; /* 0x4e */ + uint16_t cseg_16_len; /* 0x50 */ + uint16_t dseg_len; /* 0x52 */ + uint8_t reserved[44]; /* 0x54 */ +}; + + +struct x86_linux_param_header { + uint8_t orig_x; /* 0x00 */ + uint8_t orig_y; /* 0x01 */ + uint16_t ext_mem_k; /* 0x02 -- EXT_MEM_K sits here */ + uint16_t orig_video_page; /* 0x04 */ + uint8_t orig_video_mode; /* 0x06 */ + uint8_t orig_video_cols; /* 0x07 */ + uint16_t unused2; /* 0x08 */ + uint16_t orig_video_ega_bx; /* 0x0a */ + uint16_t unused3; /* 0x0c */ + uint8_t orig_video_lines; /* 0x0e */ + uint8_t orig_video_isVGA; /* 0x0f */ + uint16_t orig_video_points; /* 0x10 */ + + /* VESA graphic mode -- linear frame buffer */ + uint16_t lfb_width; /* 0x12 */ + uint16_t lfb_height; /* 0x14 */ + uint16_t lfb_depth; /* 0x16 */ + uint32_t lfb_base; /* 0x18 */ + uint32_t lfb_size; /* 0x1c */ + uint16_t cl_magic; /* 0x20 */ +#define CL_MAGIC_VALUE 0xA33F + uint16_t cl_offset; /* 0x22 */ + uint16_t lfb_linelength; /* 0x24 */ + uint8_t red_size; /* 0x26 */ + uint8_t red_pos; /* 0x27 */ + uint8_t green_size; /* 0x28 */ + uint8_t green_pos; /* 0x29 */ + uint8_t blue_size; /* 0x2a */ + uint8_t blue_pos; /* 0x2b */ + uint8_t rsvd_size; /* 0x2c */ + uint8_t rsvd_pos; /* 0x2d */ + uint16_t vesapm_seg; /* 0x2e */ + uint16_t vesapm_off; /* 0x30 */ + uint16_t pages; /* 0x32 */ + uint8_t reserved4[12]; /* 0x34 -- 0x3f reserved for future expansion */ + + struct apm_bios_info apm_bios_info; /* 0x40 */ + struct drive_info_struct drive_info; /* 0x80 */ + struct sys_desc_table sys_desc_table; /* 0xa0 */ + uint32_t alt_mem_k; /* 0x1e0 */ + uint8_t reserved5[4]; /* 0x1e4 */ + uint8_t e820_map_nr; /* 0x1e8 */ + uint8_t reserved6[8]; /* 0x1e9 */ + uint8_t setup_sects; /* 0x1f1 */ + uint16_t mount_root_rdonly; /* 0x1f2 */ + uint8_t reserved7[4]; /* 0x1f4 */ + uint16_t ramdisk_flags; /* 0x1f8 */ +#define RAMDISK_IMAGE_START_MASK 0x07FF +#define RAMDISK_PROMPT_FLAG 0x8000 +#define RAMDISK_LOAD_FLAG 0x4000 + uint16_t vid_mode; /* 0x1fa */ + uint16_t root_dev; /* 0x1fc */ + uint8_t reserved9[1]; /* 0x1fe */ + uint8_t aux_device_info; /* 0x1ff */ + /* 2.00+ */ + uint8_t reserved10[2]; /* 0x200 */ + uint8_t header_magic[4]; /* 0x202 */ + uint16_t protocol_version; /* 0x206 */ + uint8_t reserved11[8]; /* 0x208 */ + uint8_t loader_type; /* 0x210 */ +#define LOADER_TYPE_LOADLIN 1 +#define LOADER_TYPE_BOOTSECT_LOADER 2 +#define LOADER_TYPE_SYSLINUX 3 +#define LOADER_TYPE_ETHERBOOT 4 +#define LOADER_TYPE_UNKNOWN 0xFF + uint8_t loader_flags; /* 0x211 */ + uint8_t reserved12[2]; /* 0x212 */ + uint32_t kernel_start; /* 0x214 */ + uint32_t initrd_start; /* 0x218 */ + uint32_t initrd_size; /* 0x21c */ + uint8_t reserved13[4]; /* 0x220 */ + /* 2.01+ */ + uint16_t heap_end_ptr; /* 0x224 */ + uint8_t reserved14[2]; /* 0x226 */ + /* 2.02+ */ + uint32_t cmd_line_ptr; /* 0x228 */ + /* 2.03+ */ + uint32_t initrd_addr_max; /* 0x22c */ + uint8_t reserved15[160]; /* 0x230 */ + struct e820entry e820_map[E820MAX]; /* 0x2d0 */ + /* 0x550 */ +#define COMMAND_LINE_SIZE 256 +}; + +struct x86_linux_header { + uint8_t reserved1[0x1f1]; /* 0x000 */ + uint8_t setup_sects; /* 0x1f1 */ + uint16_t root_flags; /* 0x1f2 */ + uint8_t reserved2[6]; /* 0x1f4 */ + uint16_t vid_mode; /* 0x1fa */ + uint16_t root_dev; /* 0x1fc */ + uint16_t boot_sector_magic; /* 0x1fe */ + /* 2.00+ */ + uint8_t reserved3[2]; /* 0x200 */ + uint8_t header_magic[4]; /* 0x202 */ + uint16_t protocol_version; /* 0x206 */ + uint32_t realmode_swtch; /* 0x208 */ + uint16_t start_sys; /* 0x20c */ + uint16_t kver_addr; /* 0x20e */ + uint8_t type_of_loader; /* 0x210 */ + uint8_t loadflags; /* 0x211 */ + uint16_t setup_move_size; /* 0x212 */ + uint32_t code32_start; /* 0x214 */ + uint32_t ramdisk_image; /* 0x218 */ + uint32_t ramdisk_size; /* 0x21c */ + uint8_t reserved4[4]; /* 0x220 */ + /* 2.01+ */ + uint16_t heap_end_ptr; /* 0x224 */ + uint8_t reserved5[2]; /* 0x226 */ + /* 2.02+ */ + uint32_t cmd_line_ptr; /* 0x228 */ + /* 2.03+ */ + uint32_t initrd_addr_max; /* 0x22c */ + uint8_t tail[32*1024]; /* 0x230 */ +} __attribute__ ((packed)); + +#endif /* ASSEMBLY */ + +#endif /* X86_LINUX_H */ |