From 1f5ab4280a60375166b70d83cdd7ab12558160a5 Mon Sep 17 00:00:00 2001 From: okuji Date: Fri, 31 Jan 2003 03:26:56 +0000 Subject: [PATCH] 2003-01-31 Yoshinori K. Okuji * kern/i386/pc/lzo1x.S: New file. * util/i386/pc/pupa-mkimage.c: Include lzo1x.h. (compress_kernel): New variable. (generate_image): Heavily modified to support compressing a large part of the core image. * util/misc.c (pupa_util_read_image): Fix a file descriptor leak. (pupa_util_load_image): New function. * kern/i386/pc/startup.S: Include pupa/machine/kernel.h. (pupa_compressed_size): New variable. (codestart): Enable Gate A20 here. Decompress the compressed part of the core image. Rearrange the code to put functions and variables which are required for initialization in the non-compressed part. Include lzo1x.S. * kern/i386/pc/init.c (pupa_machine_init): Don't enable Gate A20 here. * include/pupa/util/misc.h (pupa_util_write_image): Declared. * include/pupa/i386/pc/kernel.h (PUPA_KERNEL_MACHINE_COMPRESSED_SIZE): New macro. (PUPA_KERNEL_MACHINE_INSTALL_DOS_PART): Increased by 4. (PUPA_KERNEL_MACHINE_INSTALL_BSD_PART): Likewise. (PUPA_KERNEL_MACHINE_PREFIX): Likewise. (PUPA_KERNEL_MACHINE_RAW_SIZE): New macro. * conf/i386-pc.rmk (pupa_mkimage_LDFLAGS): New variable. * genmk.rb (Image#rule): Put LDFLAGS at the end of a line. (Utility#rule): Likewise. * configure.ac: Check if LZO is available. --- ChangeLog | 40 +++ INSTALL | 1 + NEWS | 6 + THANKS | 4 +- conf/i386-pc.mk | 13 +- conf/i386-pc.rmk | 1 + config.h.in | 3 + configure | 146 ++++++++++ configure.ac | 11 +- genmk.rb | 6 +- include/grub/i386/pc/kernel.h | 22 +- include/grub/util/misc.h | 3 +- kern/i386/pc/init.c | 4 +- kern/i386/pc/lzo1x.S | 323 +++++++++++++++++++++ kern/i386/pc/startup.S | 525 ++++++++++++++++++---------------- kern/mm.c | 2 +- util/i386/pc/grub-mkimage.c | 95 ++++-- util/misc.c | 24 +- 18 files changed, 931 insertions(+), 298 deletions(-) create mode 100644 kern/i386/pc/lzo1x.S diff --git a/ChangeLog b/ChangeLog index 7a078f7a0..80b8ae35e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,43 @@ +2003-01-31 Yoshinori K. Okuji + + * kern/i386/pc/lzo1x.S: New file. + + * util/i386/pc/pupa-mkimage.c: Include lzo1x.h. + (compress_kernel): New variable. + (generate_image): Heavily modified to support compressing a + large part of the core image. + + * util/misc.c (pupa_util_read_image): Fix a file descriptor + leak. + (pupa_util_load_image): New function. + + * kern/i386/pc/startup.S: Include pupa/machine/kernel.h. + (pupa_compressed_size): New variable. + (codestart): Enable Gate A20 here. + Decompress the compressed part of the core image. + Rearrange the code to put functions and variables which are + required for initialization in the non-compressed part. + Include lzo1x.S. + + * kern/i386/pc/init.c (pupa_machine_init): Don't enable Gate A20 + here. + + * include/pupa/util/misc.h (pupa_util_write_image): Declared. + + * include/pupa/i386/pc/kernel.h + (PUPA_KERNEL_MACHINE_COMPRESSED_SIZE): New macro. + (PUPA_KERNEL_MACHINE_INSTALL_DOS_PART): Increased by 4. + (PUPA_KERNEL_MACHINE_INSTALL_BSD_PART): Likewise. + (PUPA_KERNEL_MACHINE_PREFIX): Likewise. + (PUPA_KERNEL_MACHINE_RAW_SIZE): New macro. + + * conf/i386-pc.rmk (pupa_mkimage_LDFLAGS): New variable. + + * genmk.rb (Image#rule): Put LDFLAGS at the end of a line. + (Utility#rule): Likewise. + + * configure.ac: Check if LZO is available. + 2003-01-20 Yoshinori K. Okuji * include/pupa/normal.h: New file. diff --git a/INSTALL b/INSTALL index 228029e42..4f6e79586 100644 --- a/INSTALL +++ b/INSTALL @@ -15,6 +15,7 @@ configuring the PUPA. * GNU Make * GNU binutils 2.9.1.0.23 or later * Other standard GNU/Unix tools +* LZO 1.02 or later If you'd like to develop PUPA, these below are also required. diff --git a/NEWS b/NEWS index 974707acc..1837fdd81 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,12 @@ New in 0.7: * Linux support is added. Initrd is not support yet. +* Reduce the size of a core image significantly by compressing a large + part of the core image and decompressing itself at boot time. The + currently used algorithm is LZO (more precisely, LZO1X-999). So you + have to install LZO to build PUPA. See + , for more information. + New in 0.6 - 2002-12-27, Yoshinori K. Okuji: diff --git a/THANKS b/THANKS index 6c0277094..3f1b71829 100644 --- a/THANKS +++ b/THANKS @@ -9,8 +9,8 @@ generally assist in the PUPA maintainership process: NIIBE Yutaka Tsuneyoshi Yasuo -Also, we thank the projects GNU GRUB and GNU Automake. Some code were -stolen from them. +Also, we thank the projects GNU GRUB, GNU Automake and LZO. Some code +were stolen from them. This project is supported by Information-technology Promotion Agency, Japan. diff --git a/conf/i386-pc.mk b/conf/i386-pc.mk index 25bd00297..a44441bfd 100644 --- a/conf/i386-pc.mk +++ b/conf/i386-pc.mk @@ -15,7 +15,7 @@ boot.img: boot.exec $(OBJCOPY) -O binary -R .note -R .comment $< $@ boot.exec: boot_img-boot_i386_pc_boot.o - $(CC) $(LDFLAGS) $(boot_img_LDFLAGS) -o $@ $^ + $(CC) -o $@ $^ $(LDFLAGS) $(boot_img_LDFLAGS) boot_img-boot_i386_pc_boot.o: boot/i386/pc/boot.S $(CC) -Iboot/i386/pc -I$(srcdir)/boot/i386/pc $(CPPFLAGS) -DASM_FILE=1 $(ASFLAGS) $(boot_img_ASFLAGS) -c -o $@ $< @@ -37,7 +37,7 @@ diskboot.img: diskboot.exec $(OBJCOPY) -O binary -R .note -R .comment $< $@ diskboot.exec: diskboot_img-boot_i386_pc_diskboot.o - $(CC) $(LDFLAGS) $(diskboot_img_LDFLAGS) -o $@ $^ + $(CC) -o $@ $^ $(LDFLAGS) $(diskboot_img_LDFLAGS) diskboot_img-boot_i386_pc_diskboot.o: boot/i386/pc/diskboot.S $(CC) -Iboot/i386/pc -I$(srcdir)/boot/i386/pc $(CPPFLAGS) -DASM_FILE=1 $(ASFLAGS) $(diskboot_img_ASFLAGS) -c -o $@ $< @@ -65,7 +65,7 @@ kernel.img: kernel.exec $(OBJCOPY) -O binary -R .note -R .comment $< $@ kernel.exec: kernel_img-kern_i386_pc_startup.o kernel_img-kern_main.o kernel_img-kern_device.o kernel_img-kern_disk.o kernel_img-kern_dl.o kernel_img-kern_file.o kernel_img-kern_fs.o kernel_img-kern_err.o kernel_img-kern_misc.o kernel_img-kern_mm.o kernel_img-kern_loader.o kernel_img-kern_rescue.o kernel_img-kern_term.o kernel_img-kern_i386_dl.o kernel_img-kern_i386_pc_init.o kernel_img-disk_i386_pc_partition.o kernel_img-disk_i386_pc_biosdisk.o kernel_img-term_i386_pc_console.o kernel_img-symlist.o - $(CC) $(LDFLAGS) $(kernel_img_LDFLAGS) -o $@ $^ + $(CC) -o $@ $^ $(LDFLAGS) $(kernel_img_LDFLAGS) kernel_img-kern_i386_pc_startup.o: kern/i386/pc/startup.S $(CC) -Ikern/i386/pc -I$(srcdir)/kern/i386/pc $(CPPFLAGS) -DASM_FILE=1 $(ASFLAGS) $(kernel_img_ASFLAGS) -c -o $@ $< @@ -249,7 +249,7 @@ CLEANFILES += pupa-mkimage pupa_mkimage-util_i386_pc_pupa_mkimage.o pupa_mkimage MOSTLYCLEANFILES += pupa_mkimage-util_i386_pc_pupa_mkimage.d pupa_mkimage-util_misc.d pupa_mkimage-util_resolve.d pupa-mkimage: pupa_mkimage-util_i386_pc_pupa_mkimage.o pupa_mkimage-util_misc.o pupa_mkimage-util_resolve.o - $(BUILD_CC) $(BUILD_LDFLAGS) $(pupa_mkimage_LDFLAGS) -o $@ $^ + $(BUILD_CC) -o $@ $^ $(BUILD_LDFLAGS) $(pupa_mkimage_LDFLAGS) pupa_mkimage-util_i386_pc_pupa_mkimage.o: util/i386/pc/pupa-mkimage.c $(BUILD_CC) -Iutil/i386/pc -I$(srcdir)/util/i386/pc $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -c -o $@ $< @@ -275,6 +275,7 @@ pupa_mkimage-util_resolve.d: util/resolve.c -include pupa_mkimage-util_resolve.d +pupa_mkimage_LDFLAGS = -llzo # For pupa-setup. pupa_setup_SOURCES = util/i386/pc/pupa-setup.c util/i386/pc/biosdisk.c \ @@ -284,7 +285,7 @@ CLEANFILES += pupa-setup pupa_setup-util_i386_pc_pupa_setup.o pupa_setup-util_i3 MOSTLYCLEANFILES += pupa_setup-util_i386_pc_pupa_setup.d pupa_setup-util_i386_pc_biosdisk.d pupa_setup-util_misc.d pupa_setup-kern_device.d pupa_setup-kern_disk.d pupa_setup-kern_file.d pupa_setup-kern_fs.d pupa_setup-kern_err.d pupa_setup-kern_misc.d pupa_setup-disk_i386_pc_partition.d pupa_setup-fs_fat.d pupa-setup: pupa_setup-util_i386_pc_pupa_setup.o pupa_setup-util_i386_pc_biosdisk.o pupa_setup-util_misc.o pupa_setup-kern_device.o pupa_setup-kern_disk.o pupa_setup-kern_file.o pupa_setup-kern_fs.o pupa_setup-kern_err.o pupa_setup-kern_misc.o pupa_setup-disk_i386_pc_partition.o pupa_setup-fs_fat.o - $(BUILD_CC) $(BUILD_LDFLAGS) $(pupa_setup_LDFLAGS) -o $@ $^ + $(BUILD_CC) -o $@ $^ $(BUILD_LDFLAGS) $(pupa_setup_LDFLAGS) pupa_setup-util_i386_pc_pupa_setup.o: util/i386/pc/pupa-setup.c $(BUILD_CC) -Iutil/i386/pc -I$(srcdir)/util/i386/pc $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -c -o $@ $< @@ -381,7 +382,7 @@ CLEANFILES += genmoddep genmoddep-util_genmoddep.o MOSTLYCLEANFILES += genmoddep-util_genmoddep.d genmoddep: genmoddep-util_genmoddep.o - $(BUILD_CC) $(BUILD_LDFLAGS) $(genmoddep_LDFLAGS) -o $@ $^ + $(BUILD_CC) -o $@ $^ $(BUILD_LDFLAGS) $(genmoddep_LDFLAGS) genmoddep-util_genmoddep.o: util/genmoddep.c $(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(genmoddep_CFLAGS) -c -o $@ $< diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index 847f83bea..f8123ae46 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -50,6 +50,7 @@ noinst_UTILITIES = genmoddep # For pupa-mkimage. pupa_mkimage_SOURCES = util/i386/pc/pupa-mkimage.c util/misc.c \ util/resolve.c +pupa_mkimage_LDFLAGS = -llzo # For pupa-setup. pupa_setup_SOURCES = util/i386/pc/pupa-setup.c util/i386/pc/biosdisk.c \ diff --git a/config.h.in b/config.h.in index 44ab1f719..125f5e3bc 100644 --- a/config.h.in +++ b/config.h.in @@ -22,6 +22,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H +/* Define to 1 if you have the `lzo' library (-llzo). */ +#undef HAVE_LIBLZO + /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H diff --git a/configure b/configure index 51c69c0fd..c08d80883 100644 --- a/configure +++ b/configure @@ -3358,6 +3358,8 @@ tmp_CPPFLAGS="$CPPFLAGS" CC="$BUILD_CC" CFLAGS="$BUILD_CFLAGS" CPPFLAGS="$BUILD_CPPFLAGS" + +# Identify characteristics of the build architecture. echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6 if test "${ac_cv_c_bigendian+set}" = set; then @@ -4682,6 +4684,150 @@ cat >>confdefs.h <<_ACEOF _ACEOF + +# Check LZO. + +echo "$as_me:$LINENO: checking for __lzo_init2 in -llzo" >&5 +echo $ECHO_N "checking for __lzo_init2 in -llzo... $ECHO_C" >&6 +if test "${ac_cv_lib_lzo___lzo_init2+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llzo $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char __lzo_init2 (); +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +__lzo_init2 (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_lzo___lzo_init2=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_lib_lzo___lzo_init2=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_lzo___lzo_init2" >&5 +echo "${ECHO_T}$ac_cv_lib_lzo___lzo_init2" >&6 +if test $ac_cv_lib_lzo___lzo_init2 = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBLZO 1 +_ACEOF + + LIBS="-llzo $LIBS" + +else + { { echo "$as_me:$LINENO: error: LZO library version 1.02 or later is required" >&5 +echo "$as_me: error: LZO library version 1.02 or later is required" >&2;} + { (exit 1); exit 1; }; } +fi + +echo "$as_me:$LINENO: checking for lzo1x_999_compress" >&5 +echo $ECHO_N "checking for lzo1x_999_compress... $ECHO_C" >&6 +if test "${ac_cv_func_lzo1x_999_compress+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char lzo1x_999_compress (); below. */ +#include +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char lzo1x_999_compress (); +char (*f) (); + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_lzo1x_999_compress) || defined (__stub___lzo1x_999_compress) +choke me +#else +f = lzo1x_999_compress; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_lzo1x_999_compress=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_func_lzo1x_999_compress=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_lzo1x_999_compress" >&5 +echo "${ECHO_T}$ac_cv_func_lzo1x_999_compress" >&6 +if test $ac_cv_func_lzo1x_999_compress = yes; then + : +else + { { echo "$as_me:$LINENO: error: LZO1X-999 must be enabled" >&5 +echo "$as_me: error: LZO1X-999 must be enabled" >&2;} + { (exit 1); exit 1; }; } +fi + + CC="$tmp_CC" CFLAGS="$tmp_CFLAGS" CPPFLAGS="$tmp_CPPFLAGS" diff --git a/configure.ac b/configure.ac index c26fe4e94..4045133b2 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ # Process this file with autoconf to produce a configure script. -# Copyright (C) 2002 Yoshinori K. Okuji +# Copyright (C) 2002,2003 Yoshinori K. Okuji # # This configure.ac is free software; the author # gives unlimited permission to copy and/or distribute it, @@ -117,9 +117,18 @@ tmp_CPPFLAGS="$CPPFLAGS" CC="$BUILD_CC" CFLAGS="$BUILD_CFLAGS" CPPFLAGS="$BUILD_CPPFLAGS" + +# Identify characteristics of the build architecture. AC_C_BIGENDIAN AC_CHECK_SIZEOF(void *) AC_CHECK_SIZEOF(long) + +# Check LZO. +AC_CHECK_LIB(lzo, __lzo_init2, , + AC_MSG_ERROR([LZO library version 1.02 or later is required])) +AC_CHECK_FUNC(lzo1x_999_compress, , + [AC_MSG_ERROR([LZO1X-999 must be enabled])]) + CC="$tmp_CC" CFLAGS="$tmp_CFLAGS" CPPFLAGS="$tmp_CPPFLAGS" diff --git a/genmk.rb b/genmk.rb index a48aa04bd..b7b23dd57 100644 --- a/genmk.rb +++ b/genmk.rb @@ -1,6 +1,6 @@ #! /usr/bin/ruby -w # -# Copyright (C) 2002 Yoshinori K. Okuji +# Copyright (C) 2002,2003 Yoshinori K. Okuji # # This genmk.rb is free software; the author # gives unlimited permission to copy and/or distribute it, @@ -60,7 +60,7 @@ MOSTLYCLEANFILES += #{deps_str} $(OBJCOPY) -O binary -R .note -R .comment $< $@ #{exe}: #{objs_str} - $(CC) $(LDFLAGS) $(#{prefix}_LDFLAGS) -o $@ $^ + $(CC) -o $@ $^ $(LDFLAGS) $(#{prefix}_LDFLAGS) " + objs.collect_with_index do |obj, i| src = sources[i] @@ -181,7 +181,7 @@ class Utility MOSTLYCLEANFILES += #{deps_str} #{@name}: #{objs_str} - $(BUILD_CC) $(BUILD_LDFLAGS) $(#{prefix}_LDFLAGS) -o $@ $^ + $(BUILD_CC) -o $@ $^ $(BUILD_LDFLAGS) $(#{prefix}_LDFLAGS) " + objs.collect_with_index do |obj, i| src = sources[i] diff --git a/include/grub/i386/pc/kernel.h b/include/grub/i386/pc/kernel.h index e7a785a05..ee63d6f5c 100644 --- a/include/grub/i386/pc/kernel.h +++ b/include/grub/i386/pc/kernel.h @@ -1,6 +1,6 @@ /* * PUPA -- Preliminary Universal Programming Architecture for GRUB - * Copyright (C) 2002 Yoshinori K. Okuji + * Copyright (C) 2002,2003 Yoshinori K. Okuji * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,22 +20,30 @@ #ifndef KERNEL_MACHINE_HEADER #define KERNEL_MACHINE_HEADER 1 -#include - /* The offset of PUPA_TOTAL_MODULE_SIZE. */ #define PUPA_KERNEL_MACHINE_TOTAL_MODULE_SIZE 0x8 /* The offset of PUPA_KERNEL_IMAGE_SIZE. */ #define PUPA_KERNEL_MACHINE_KERNEL_IMAGE_SIZE 0xc +/* The offset of PUPA_COMPRESSED_SIZE. */ +#define PUPA_KERNEL_MACHINE_COMPRESSED_SIZE 0x10 + /* The offset of PUPA_INSTALL_DOS_PART. */ -#define PUPA_KERNEL_MACHINE_INSTALL_DOS_PART 0x10 +#define PUPA_KERNEL_MACHINE_INSTALL_DOS_PART 0x14 /* The offset of PUPA_INSTALL_BSD_PART. */ -#define PUPA_KERNEL_MACHINE_INSTALL_BSD_PART 0x14 +#define PUPA_KERNEL_MACHINE_INSTALL_BSD_PART 0x18 /* The offset of PUPA_PREFIX. */ -#define PUPA_KERNEL_MACHINE_PREFIX 0x18 +#define PUPA_KERNEL_MACHINE_PREFIX 0x1c + +/* The size of the first region which won't be compressed. */ +#define PUPA_KERNEL_MACHINE_RAW_SIZE 0x400 + +#ifndef ASM_FILE + +#include /* The DOS partition number of the installed partition. */ extern pupa_int32_t pupa_install_dos_part; @@ -50,4 +58,6 @@ extern char pupa_prefix[]; /* The boot BIOS drive number. */ extern pupa_int32_t pupa_boot_drive; +#endif /* ! ASM_FILE */ + #endif /* ! KERNEL_MACHINE_HEADER */ diff --git a/include/grub/util/misc.h b/include/grub/util/misc.h index 10d0a47b2..03c01a4c2 100644 --- a/include/grub/util/misc.h +++ b/include/grub/util/misc.h @@ -1,6 +1,6 @@ /* * PUPA -- Preliminary Universal Programming Architecture for GRUB - * Copyright (C) 2002 Yoshinori K. Okuji + * Copyright (C) 2002,2003 Yoshinori K. Okuji * * PUPA is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,6 +36,7 @@ char *xstrdup (const char *str); char *pupa_util_get_path (const char *dir, const char *file); size_t pupa_util_get_image_size (const char *path); char *pupa_util_read_image (const char *path); +void pupa_util_load_image (const char *path, char *buf); void pupa_util_write_image (const char *img, size_t size, FILE *out); #endif /* ! PUPA_UTIL_MISC_HEADER */ diff --git a/kern/i386/pc/init.c b/kern/i386/pc/init.c index 7e0db5c03..57c6d3d75 100644 --- a/kern/i386/pc/init.c +++ b/kern/i386/pc/init.c @@ -130,9 +130,11 @@ pupa_machine_init (void) /* Sanity check. */ if (pupa_lower_mem < PUPA_MEMORY_MACHINE_RESERVED_END) pupa_fatal ("too small memory"); - + +#if 0 /* Turn on Gate A20 to access >1MB. */ pupa_gate_a20 (1); +#endif /* Add the lower memory into free memory. */ if (pupa_lower_mem >= PUPA_MEMORY_MACHINE_RESERVED_END) diff --git a/kern/i386/pc/lzo1x.S b/kern/i386/pc/lzo1x.S new file mode 100644 index 000000000..616d146a5 --- /dev/null +++ b/kern/i386/pc/lzo1x.S @@ -0,0 +1,323 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer + * Copyright (C) 2003 Yoshinori K. Okuji + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * This code was stolen from the files enter.sh, leave.sh, lzo1x_d.sh, + * lzo1x_f.s and lzo_asm.h in LZO version 1.08, and was heavily modified + * to adapt it to PUPA's requirement. + * + * See , for more information + * about LZO. + */ + +#define INP 4+16(%esp) +#define INS 8+16(%esp) +#define OUTP 12+16(%esp) +#define NN 3 +#define N_3 %ebp +#define N_255 $255 +#define LODSB movb (%esi), %al ; incl %esi +#define NOTL_3(r) xorl N_3, r +#define MOVSL(r1,r2,x) movl (r1), x ; addl $4, r1 ; movl x, (r2) ; addl $4, r2 +#define COPYL_C(r1,r2,x,rc) 9: MOVSL(r1,r2,x) ; decl rc ; jnz 9b +#define COPYL(r1,r2,x) COPYL_C(r1,r2,x,%ecx) + +lzo1x_decompress: + pushl %ebp + pushl %edi + pushl %esi + pushl %ebx + + cld + + movl INP, %esi + movl OUTP, %edi + movl $3, %ebp + + + xorl %eax, %eax + xorl %ebx, %ebx /* high bits 9-32 stay 0 */ + lodsb + cmpb $17, %al + jbe .L01 + subb $17-NN, %al + jmp .LFLR + + +/*********************************************************************** +// literal run +************************************************************************/ + +0: addl N_255, %eax +1: movb (%esi), %bl + incl %esi + orb %bl, %bl + jz 0b + leal 18+NN(%eax,%ebx), %eax + jmp 3f + + + .align 8 +.L00: + LODSB +.L01: + cmpb $16, %al + jae .LMATCH + + /* a literal run */ + orb %al, %al + jz 1b + addl $3+NN, %eax +3: +.LFLR: + movl %eax, %ecx + NOTL_3(%eax) + shrl $2, %ecx + andl N_3, %eax + COPYL(%esi,%edi,%edx) + subl %eax, %esi + subl %eax, %edi + + LODSB + cmpb $16, %al + jae .LMATCH + + +/*********************************************************************** +// R1 +************************************************************************/ + + shrl $2, %eax + movb (%esi), %bl + leal -0x801(%edi), %edx + leal (%eax,%ebx,4), %eax + incl %esi + subl %eax, %edx + movl (%edx), %ecx + movl %ecx, (%edi) + addl N_3, %edi + jmp .LMDONE + + +/*********************************************************************** +// M2 +************************************************************************/ + + .align 8 +.LMATCH: + cmpb $64, %al + jb .LM3MATCH + + /* a M2 match */ + movl %eax, %ecx + shrl $2, %eax + leal -1(%edi), %edx + andl $7, %eax + movb (%esi), %bl + shrl $5, %ecx + leal (%eax,%ebx,8), %eax + incl %esi + subl %eax, %edx + + addl $1+3, %ecx + + cmpl N_3, %eax + jae .LCOPYLONG + jmp .LCOPYBYTE + + +/*********************************************************************** +// M3 +************************************************************************/ + +0: addl N_255, %eax +1: movb (%esi), %bl + incl %esi + orb %bl, %bl + jz 0b + leal 33+NN(%eax,%ebx), %ecx + xorl %eax, %eax + jmp 3f + + + .align 8 +.LM3MATCH: + cmpb $32, %al + jb .LM4MATCH + + /* a M3 match */ + andl $31, %eax + jz 1b + lea 2+NN(%eax), %ecx +3: + movw (%esi), %ax + leal -1(%edi), %edx + shrl $2, %eax + addl $2, %esi + subl %eax, %edx + + cmpl N_3, %eax + jb .LCOPYBYTE + + +/*********************************************************************** +// copy match +************************************************************************/ + + .align 2 +.LCOPYLONG: /* copy match using longwords */ + leal -3(%edi,%ecx), %eax + shrl $2, %ecx + COPYL(%edx,%edi,%ebx) + movl %eax, %edi + xorl %ebx, %ebx + +.LMDONE: + movb -2(%esi), %al + andl N_3, %eax + jz .L00 +.LFLR3: + movl (%esi), %edx + addl %eax, %esi + movl %edx, (%edi) + addl %eax, %edi + + LODSB + jmp .LMATCH + + + .align 8 +.LCOPYBYTE: /* copy match using bytes */ + xchgl %edx,%esi + subl N_3,%ecx + + rep + movsb + movl %edx, %esi + jmp .LMDONE + + +/*********************************************************************** +// M4 +************************************************************************/ + +0: addl N_255, %ecx +1: movb (%esi), %bl + incl %esi + orb %bl, %bl + jz 0b + leal 9+NN(%ebx,%ecx), %ecx + jmp 3f + + + .align 8 +.LM4MATCH: + cmpb $16, %al + jb .LM1MATCH + + /* a M4 match */ + movl %eax, %ecx + andl $8, %eax + shll $13, %eax /* save in bit 16 */ + andl $7, %ecx + jz 1b + addl $2+NN, %ecx +3: + movw (%esi), %ax + addl $2, %esi + leal -0x4000(%edi), %edx + shrl $2, %eax + jz .LEOF + subl %eax, %edx + jmp .LCOPYLONG + + +/*********************************************************************** +// M1 +************************************************************************/ + + .align 8 +.LM1MATCH: + /* a M1 match */ + shrl $2, %eax + movb (%esi), %bl + leal -1(%edi), %edx + leal (%eax,%ebx,4), %eax + incl %esi + subl %eax, %edx + + movb (%edx), %al /* we must use this because edx can be edi-1 */ + movb %al, (%edi) + movb 1(%edx), %bl + movb %bl, 1(%edi) + addl $2, %edi + jmp .LMDONE + + +/*********************************************************************** +// +************************************************************************/ + +.LEOF: +/**** xorl %eax,%eax eax=0 from above */ + + cmpl $3+NN, %ecx /* ecx must be 3/6 */ + setnz %al + + /* check compressed size */ + movl INP, %edx + addl INS, %edx + cmpl %edx, %esi /* check compressed size */ + ja .L_input_overrun + jb .L_input_not_consumed + +.L_leave: + negl %eax + jnz 1f + + subl OUTP, %edi /* write back the uncompressed size */ + movl %edi, %eax + +1: popl %ebx + popl %esi + popl %edi + popl %ebp + ret + +.L_input_not_consumed: + movl $8, %eax /* LZO_E_INPUT_NOT_CONSUMED */ + jmp .L_leave + +.L_input_overrun: + movl $4, %eax /* LZO_E_INPUT_OVERRUN */ + jmp .L_leave + +#undef INP +#undef INS +#undef OUTP +#undef NN +#undef NN +#undef N_3 +#undef N_255 +#undef LODSB +#undef NOTL_3 +#undef MOVSL +#undef COPYL_C +#undef COPYL diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S index f2cb6e902..da3f8668b 100644 --- a/kern/i386/pc/startup.S +++ b/kern/i386/pc/startup.S @@ -1,7 +1,7 @@ /* * PUPA -- Preliminary Universal Programming Architecture for GRUB * Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc. - * Copyright (C) 2002 Yoshinori K. Okuji + * Copyright (C) 2002,2003 Yoshinori K. Okuji * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -50,7 +50,8 @@ #include #include #include - +#include + #define ABS(x) ((x) - EXT_C(start) + PUPA_BOOT_MACHINE_KERNEL_ADDR + 0x200) .file "startup.S" @@ -88,6 +89,8 @@ VARIABLE(pupa_total_module_size) .long 0 VARIABLE(pupa_kernel_image_size) .long 0 +VARIABLE(pupa_compressed_size) + .long 0 VARIABLE(pupa_install_dos_part) .long 0xFFFFFFFF VARIABLE(pupa_install_bsd_part) @@ -129,6 +132,25 @@ codestart: /* The ".code32" directive takes GAS out of 16-bit mode. */ .code32 + incl %eax + call EXT_C(pupa_gate_a20) + + /* decompress the compressed part and put the result at 1MB */ + movl $0x100000, %esi + movl $(START_SYMBOL + PUPA_KERNEL_MACHINE_RAW_SIZE), %edi + + pushl %esi + pushl EXT_C(pupa_compressed_size) + pushl %edi + call lzo1x_decompress + addl $12, %esp + + /* copy back the decompressed part */ + movl %eax, %ecx + cld + rep + movsb + /* copy modules before cleaning out the bss */ movl EXT_C(pupa_total_module_size), %ecx movl EXT_C(pupa_kernel_image_size), %esi @@ -148,8 +170,9 @@ codestart: /* compute the bss length */ movl $END_SYMBOL, %ecx subl %edi, %ecx - + /* clean out */ + xorl %eax, %eax cld rep stosb @@ -160,6 +183,255 @@ codestart: call EXT_C(pupa_main) +/* + * This is the area for all of the special variables. + */ + + .p2align 2 /* force 4-byte alignment */ + +protstack: + .long PUPA_MEMORY_MACHINE_PROT_STACK + +VARIABLE(pupa_boot_drive) + .long 0 + +VARIABLE(pupa_start_addr) + .long START_SYMBOL + +VARIABLE(pupa_end_addr) + .long END_SYMBOL + +VARIABLE(pupa_apm_bios_info) + .word 0 /* version */ + .word 0 /* cseg */ + .long 0 /* offset */ + .word 0 /* cseg_16 */ + .word 0 /* dseg_16 */ + .word 0 /* cseg_len */ + .word 0 /* cseg_16_len */ + .word 0 /* dseg_16_len */ + +/* + * This is the Global Descriptor Table + * + * An entry, a "Segment Descriptor", looks like this: + * + * 31 24 19 16 7 0 + * ------------------------------------------------------------ + * | | |B| |A| | | |1|0|E|W|A| | + * | BASE 31..24 |G|/|0|V| LIMIT |P|DPL| TYPE | BASE 23:16 | + * | | |D| |L| 19..16| | |1|1|C|R|A| | + * ------------------------------------------------------------ + * | | | + * | BASE 15..0 | LIMIT 15..0 | + * | | | + * ------------------------------------------------------------ + * + * Note the ordering of the data items is reversed from the above + * description. + */ + + .p2align 2 /* force 4-byte alignment */ +gdt: + .word 0, 0 + .byte 0, 0, 0, 0 + + /* code segment */ + .word 0xFFFF, 0 + .byte 0, 0x9A, 0xCF, 0 + + /* data segment */ + .word 0xFFFF, 0 + .byte 0, 0x92, 0xCF, 0 + + /* 16 bit real mode CS */ + .word 0xFFFF, 0 + .byte 0, 0x9E, 0, 0 + + /* 16 bit real mode DS */ + .word 0xFFFF, 0 + .byte 0, 0x92, 0, 0 + + +/* this is the GDT descriptor */ +gdtdesc: + .word 0x27 /* limit */ + .long gdt /* addr */ + + +/* + * These next two routines, "real_to_prot" and "prot_to_real" are structured + * in a very specific way. Be very careful when changing them. + * + * NOTE: Use of either one messes up %eax and %ebp. + */ + +real_to_prot: + .code16 + cli + + /* load the GDT register */ + DATA32 ADDR32 lgdt gdtdesc + + /* turn on protected mode */ + movl %cr0, %eax + orl $PUPA_MEMORY_MACHINE_CR0_PE_ON, %eax + movl %eax, %cr0 + + /* jump to relocation, flush prefetch queue, and reload %cs */ + DATA32 ljmp $PUPA_MEMORY_MACHINE_PROT_MODE_CSEG, $protcseg + + .code32 +protcseg: + /* reload other segment registers */ + movw $PUPA_MEMORY_MACHINE_PROT_MODE_DSEG, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + movw %ax, %ss + + /* put the return address in a known safe location */ + movl (%esp), %eax + movl %eax, PUPA_MEMORY_MACHINE_REAL_STACK + + /* get protected mode stack */ + movl protstack, %eax + movl %eax, %esp + movl %eax, %ebp + + /* get return address onto the right stack */ + movl PUPA_MEMORY_MACHINE_REAL_STACK, %eax + movl %eax, (%esp) + + /* zero %eax */ + xorl %eax, %eax + + /* return on the old (or initialized) stack! */ + ret + + +prot_to_real: + /* just in case, set GDT */ + lgdt gdtdesc + + /* save the protected mode stack */ + movl %esp, %eax + movl %eax, protstack + + /* get the return address */ + movl (%esp), %eax + movl %eax, PUPA_MEMORY_MACHINE_REAL_STACK + + /* set up new stack */ + movl $PUPA_MEMORY_MACHINE_REAL_STACK, %eax + movl %eax, %esp + movl %eax, %ebp + + /* set up segment limits */ + movw $PUPA_MEMORY_MACHINE_PSEUDO_REAL_DSEG, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + movw %ax, %ss + + /* this might be an extra step */ + /* jump to a 16 bit segment */ + ljmp $PUPA_MEMORY_MACHINE_PSEUDO_REAL_CSEG, $tmpcseg + +tmpcseg: + .code16 + + /* clear the PE bit of CR0 */ + movl %cr0, %eax + andl $(~PUPA_MEMORY_MACHINE_CR0_PE_ON), %eax + movl %eax, %cr0 + + /* flush prefetch queue, reload %cs */ + DATA32 ljmp $0, $realcseg + +realcseg: + /* we are in real mode now + * set up the real mode segment registers : DS, SS, ES + */ + /* zero %eax */ + xorl %eax, %eax + + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + movw %ax, %ss + + /* restore interrupts */ + sti + + /* return on new stack! */ + DATA32 ret + + .code32 + + +/* + * pupa_gate_a20(int on) + * + * Gate address-line 20 for high memory. + * + * This routine is probably overconservative in what it does, but so what? + * + * It also eats any keystrokes in the keyboard buffer. :-( + */ + +FUNCTION(pupa_gate_a20) + movl %eax, %ecx + + call gloop1 + + movb $0xd1, %al + outb $0x64 + +gloopint1: + inb $0x64 + andb $0x02, %al + jnz gloopint1 + + movb $0xdd, %al + testl %ecx, %ecx + jz gdoit + + orb $0x02, %al +gdoit: + outb $0x60 + + call gloop1 + + /* output a dummy command (USB keyboard hack) */ + movb $0xff, %al + outb $0x64 + call gloop1 + + ret + +gloop1: + inb $0x64 + andb $0x02, %al + jnz gloop1 + +gloop2: + inb $0x64 + andb $0x01, %al + jz gloop2ret + inb $0x60 + jmp gloop2 + +gloop2ret: + ret + + +#include "lzo1x.S" + + /* * This call is special... it never returns... in fact it should simply * hang at this point! @@ -348,120 +620,6 @@ linux_setup_seg: .code32 -/* - * These next two routines, "real_to_prot" and "prot_to_real" are structured - * in a very specific way. Be very careful when changing them. - * - * NOTE: Use of either one messes up %eax and %ebp. - */ - -real_to_prot: - .code16 - cli - - /* load the GDT register */ - DATA32 ADDR32 lgdt gdtdesc - - /* turn on protected mode */ - movl %cr0, %eax - orl $PUPA_MEMORY_MACHINE_CR0_PE_ON, %eax - movl %eax, %cr0 - - /* jump to relocation, flush prefetch queue, and reload %cs */ - DATA32 ljmp $PUPA_MEMORY_MACHINE_PROT_MODE_CSEG, $protcseg - - .code32 -protcseg: - /* reload other segment registers */ - movw $PUPA_MEMORY_MACHINE_PROT_MODE_DSEG, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - movw %ax, %ss - - /* put the return address in a known safe location */ - movl (%esp), %eax - movl %eax, PUPA_MEMORY_MACHINE_REAL_STACK - - /* get protected mode stack */ - movl protstack, %eax - movl %eax, %esp - movl %eax, %ebp - - /* get return address onto the right stack */ - movl PUPA_MEMORY_MACHINE_REAL_STACK, %eax - movl %eax, (%esp) - - /* zero %eax */ - xorl %eax, %eax - - /* return on the old (or initialized) stack! */ - ret - - -prot_to_real: - /* just in case, set GDT */ - lgdt gdtdesc - - /* save the protected mode stack */ - movl %esp, %eax - movl %eax, protstack - - /* get the return address */ - movl (%esp), %eax - movl %eax, PUPA_MEMORY_MACHINE_REAL_STACK - - /* set up new stack */ - movl $PUPA_MEMORY_MACHINE_REAL_STACK, %eax - movl %eax, %esp - movl %eax, %ebp - - /* set up segment limits */ - movw $PUPA_MEMORY_MACHINE_PSEUDO_REAL_DSEG, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - movw %ax, %ss - - /* this might be an extra step */ - /* jump to a 16 bit segment */ - ljmp $PUPA_MEMORY_MACHINE_PSEUDO_REAL_CSEG, $tmpcseg - -tmpcseg: - .code16 - - /* clear the PE bit of CR0 */ - movl %cr0, %eax - andl $(~PUPA_MEMORY_MACHINE_CR0_PE_ON), %eax - movl %eax, %cr0 - - /* flush prefetch queue, reload %cs */ - DATA32 ljmp $0, $realcseg - -realcseg: - /* we are in real mode now - * set up the real mode segment registers : DS, SS, ES - */ - /* zero %eax */ - xorl %eax, %eax - - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - movw %ax, %ss - - /* restore interrupts */ - sti - - /* return on new stack! */ - DATA32 ret - - .code32 - - /* * int pupa_biosdisk_rw_int13_extensions (int ah, int drive, void *dap) * @@ -931,63 +1089,6 @@ xsmap: ret -/* - * pupa_gate_a20(int on) - * - * Gate address-line 20 for high memory. - * - * This routine is probably overconservative in what it does, but so what? - * - * It also eats any keystrokes in the keyboard buffer. :-( - */ - -FUNCTION(pupa_gate_a20) - pushl %eax - - call gloop1 - - movb $0xd1, %al - outb $0x64 - -gloopint1: - inb $0x64 - andb $0x02, %al - jnz gloopint1 - - movb $0xdd, %al - cmpb $0, 0x8(%esp) - jz gdoit - - orb $0x02, %al -gdoit: - outb $0x60 - - call gloop1 - - /* output a dummy command (USB keyboard hack) */ - movb $0xff, %al - outb $0x64 - call gloop1 - - popl %eax - ret - -gloop1: - inb $0x64 - andb $0x02, %al - jnz gloop1 - -gloop2: - inb $0x64 - andb $0x01, %al - jz gloop2ret - inb $0x60 - jmp gloop2 - -gloop2ret: - ret - - /* * void pupa_console_putchar (int c) * @@ -1413,79 +1514,3 @@ FUNCTION(pupa_currticks) popl %ebp ret - - -/* - * This is the area for all of the special variables. - */ - - .p2align 2 /* force 4-byte alignment */ - -protstack: - .long PUPA_MEMORY_MACHINE_PROT_STACK - -VARIABLE(pupa_boot_drive) - .long 0 - -VARIABLE(pupa_start_addr) - .long START_SYMBOL - -VARIABLE(pupa_end_addr) - .long END_SYMBOL - -VARIABLE(pupa_apm_bios_info) - .word 0 /* version */ - .word 0 /* cseg */ - .long 0 /* offset */ - .word 0 /* cseg_16 */ - .word 0 /* dseg_16 */ - .word 0 /* cseg_len */ - .word 0 /* cseg_16_len */ - .word 0 /* dseg_16_len */ - -/* - * This is the Global Descriptor Table - * - * An entry, a "Segment Descriptor", looks like this: - * - * 31 24 19 16 7 0 - * ------------------------------------------------------------ - * | | |B| |A| | | |1|0|E|W|A| | - * | BASE 31..24 |G|/|0|V| LIMIT |P|DPL| TYPE | BASE 23:16 | - * | | |D| |L| 19..16| | |1|1|C|R|A| | - * ------------------------------------------------------------ - * | | | - * | BASE 15..0 | LIMIT 15..0 | - * | | | - * ------------------------------------------------------------ - * - * Note the ordering of the data items is reversed from the above - * description. - */ - - .p2align 2 /* force 4-byte alignment */ -gdt: - .word 0, 0 - .byte 0, 0, 0, 0 - - /* code segment */ - .word 0xFFFF, 0 - .byte 0, 0x9A, 0xCF, 0 - - /* data segment */ - .word 0xFFFF, 0 - .byte 0, 0x92, 0xCF, 0 - - /* 16 bit real mode CS */ - .word 0xFFFF, 0 - .byte 0, 0x9E, 0, 0 - - /* 16 bit real mode DS */ - .word 0xFFFF, 0 - .byte 0, 0x92, 0, 0 - - -/* this is the GDT descriptor */ -gdtdesc: - .word 0x27 /* limit */ - .long gdt /* addr */ diff --git a/kern/mm.c b/kern/mm.c index 6eba8d3d8..ce88f9a89 100644 --- a/kern/mm.c +++ b/kern/mm.c @@ -135,7 +135,7 @@ static void * pupa_real_malloc (pupa_mm_header_t *first, pupa_size_t n, pupa_size_t align) { pupa_mm_header_t p, q; - + if ((*first)->magic == PUPA_MM_ALLOC_MAGIC) return 0; diff --git a/util/i386/pc/grub-mkimage.c b/util/i386/pc/grub-mkimage.c index 0713a6647..ea850dc4e 100644 --- a/util/i386/pc/grub-mkimage.c +++ b/util/i386/pc/grub-mkimage.c @@ -1,7 +1,7 @@ /* pupa-mkimage.c - make a bootable image */ /* * PUPA -- Preliminary Universal Programming Architecture for GRUB - * Copyright (C) 2002 Yoshinori K. Okuji + * Copyright (C) 2002,2003 Yoshinori K. Okuji * * PUPA is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,14 +35,49 @@ #define _GNU_SOURCE 1 #include +#include + +static void +compress_kernel (char *kernel_img, size_t kernel_size, + char **core_img, size_t *core_size) +{ + lzo_uint size; + char *wrkmem; + + pupa_util_info ("kernel_img=%p, kernel_size=0x%x", kernel_img, kernel_size); + if (kernel_size < PUPA_KERNEL_MACHINE_RAW_SIZE) + pupa_util_error ("the core image is too small"); + + if (lzo_init () != LZO_E_OK) + pupa_util_error ("cannot initialize LZO"); + + *core_img = xmalloc (kernel_size + kernel_size / 64 + 16 + 3); + wrkmem = xmalloc (LZO1X_999_MEM_COMPRESS); + + memcpy (*core_img, kernel_img, PUPA_KERNEL_MACHINE_RAW_SIZE); + + pupa_util_info ("compressing the core image"); + if (lzo1x_999_compress (kernel_img + PUPA_KERNEL_MACHINE_RAW_SIZE, + kernel_size - PUPA_KERNEL_MACHINE_RAW_SIZE, + *core_img + PUPA_KERNEL_MACHINE_RAW_SIZE, + &size, wrkmem) + != LZO_E_OK) + pupa_util_error ("cannot compress the kernel image"); + + free (wrkmem); + + *core_size = (size_t) size + PUPA_KERNEL_MACHINE_RAW_SIZE; +} + static void generate_image (const char *dir, FILE *out, char *mods[]) { pupa_addr_t module_addr = 0; - char *kernel_img, *boot_img; - size_t kernel_size, boot_size, total_module_size; + char *kernel_img, *boot_img, *core_img; + size_t kernel_size, boot_size, total_module_size, core_size; char *kernel_path, *boot_path; unsigned num; + size_t offset; struct pupa_util_path_list *path_list, *p, *next; path_list = pupa_util_resolve_dependencies (dir, "moddep.lst", mods); @@ -56,9 +91,32 @@ generate_image (const char *dir, FILE *out, char *mods[]) + sizeof (struct pupa_module_header)); pupa_util_info ("the total module size is 0x%x", total_module_size); + + kernel_img = xmalloc (kernel_size + total_module_size); + pupa_util_load_image (kernel_path, kernel_img); + offset = kernel_size; + for (p = path_list; p; p = p->next) + { + struct pupa_module_header *header; + size_t mod_size; + + mod_size = pupa_util_get_image_size (p->name); + + header = (struct pupa_module_header *) (kernel_img + offset); + header->offset = pupa_cpu_to_le32 (sizeof (*header)); + header->size = pupa_cpu_to_le32 (mod_size + sizeof (*header)); + + pupa_util_load_image (p->name, kernel_img + offset + sizeof (*header)); + + offset += sizeof (*header) + mod_size; + } + + compress_kernel (kernel_img, kernel_size + total_module_size, + &core_img, &core_size); + + pupa_util_info ("the core size is 0x%x", core_size); - num = ((kernel_size + total_module_size + PUPA_DISK_SECTOR_SIZE - 1) - >> PUPA_DISK_SECTOR_BITS); + num = ((core_size + PUPA_DISK_SECTOR_SIZE - 1) >> PUPA_DISK_SECTOR_BITS); if (num > 0xffff) pupa_util_error ("the core image is too big"); @@ -78,42 +136,27 @@ generate_image (const char *dir, FILE *out, char *mods[]) free (boot_img); free (boot_path); - kernel_img = pupa_util_read_image (kernel_path); module_addr = (path_list ? (PUPA_BOOT_MACHINE_KERNEL_ADDR + PUPA_DISK_SECTOR_SIZE + kernel_size) : 0); pupa_util_info ("the first module address is 0x%x", module_addr); - *((pupa_uint32_t *) (kernel_img + PUPA_KERNEL_MACHINE_TOTAL_MODULE_SIZE)) + *((pupa_uint32_t *) (core_img + PUPA_KERNEL_MACHINE_TOTAL_MODULE_SIZE)) = pupa_cpu_to_le32 (total_module_size); - *((pupa_uint32_t *) (kernel_img + PUPA_KERNEL_MACHINE_KERNEL_IMAGE_SIZE)) + *((pupa_uint32_t *) (core_img + PUPA_KERNEL_MACHINE_KERNEL_IMAGE_SIZE)) = pupa_cpu_to_le32 (kernel_size); + *((pupa_uint32_t *) (core_img + PUPA_KERNEL_MACHINE_COMPRESSED_SIZE)) + = pupa_cpu_to_le32 (core_size - PUPA_KERNEL_MACHINE_RAW_SIZE); - pupa_util_write_image (kernel_img, kernel_size, out); + pupa_util_write_image (core_img, core_size, out); free (kernel_img); + free (core_img); free (kernel_path); while (path_list) { - struct pupa_module_header header; - size_t mod_size; - char *mod_img; - next = path_list->next; - - mod_size = pupa_util_get_image_size (path_list->name); - - header.offset = pupa_cpu_to_le32 (sizeof (header)); - header.size = pupa_cpu_to_le32 (mod_size + sizeof (header)); - - pupa_util_info ("offset=0x%x, size=0x%x", header.offset, header.size); - pupa_util_write_image ((char *) &header, sizeof (header), out); - - mod_img = pupa_util_read_image (path_list->name); - pupa_util_write_image (mod_img, mod_size, out); - free (mod_img); - free ((void *) path_list->name); free (path_list); path_list = next; diff --git a/util/misc.c b/util/misc.c index 95b10e36e..a8a0b9717 100644 --- a/util/misc.c +++ b/util/misc.c @@ -1,6 +1,6 @@ /* * PUPA -- Preliminary Universal Programming Architecture for GRUB - * Copyright (C) 2002 Yoshinori K. Okuji + * Copyright (C) 2002,2003 Yoshinori K. Okuji * * PUPA is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -136,9 +136,31 @@ pupa_util_read_image (const char *path) if (fread (img, 1, size, fp) != size) pupa_util_error ("cannot read %s", path); + fclose (fp); + return img; } +void +pupa_util_load_image (const char *path, char *buf) +{ + FILE *fp; + size_t size; + + pupa_util_info ("reading %s", path); + + size = pupa_util_get_image_size (path); + + fp = fopen (path, "rb"); + if (! fp) + pupa_util_error ("cannot open %s", path); + + if (fread (buf, 1, size, fp) != size) + pupa_util_error ("cannot read %s", path); + + fclose (fp); +} + void pupa_util_write_image (const char *img, size_t size, FILE *out) {