2003-01-03 Yoshinori K. Okuji <okuji@enbug.org>

* include/i386/pc/util/biosdisk.h: New file.
	* util/i386/pc/biosdisk.c: Likewise.
	* util/i386/pc/pupa-setup.c: Likewise.

	* Makefile.in (INCLUDE_DISTFILES): Added
	include/pupa/i386/pc/util/biosdisk.h.
	(UTIL_DISTFILES): Added biosdisk.c and pupa-setup.c under the
	directory util/i386/pc.
	(install-local): Added a rule for sbin_UTILITIES.
	(uninstall): Likewise.

	* util/i386/pc/pupa-mkimage.c (usage): Fix a typo in the doc.

	* util/misc.c (xrealloc): New function.
	(pupa_malloc): Likewise.
	(pupa_free): Likewise.
	(pupa_realloc): Likewise.
	(pupa_stop): Likewise.
	(pupa_putchar): Likewise.

	* kern/disk.c (pupa_disk_read): Prevent L from underflowing.

	* include/pupa/util/misc.h (xrealloc): Declared.

	* include/pupa/i386/pc/boot.h (PUPA_BOOT_MACHINE_BPB_START): New
	macro.
	(PUPA_BOOT_MACHINE_BPBEND): Renamed to ...
	(PUPA_BOOT_MACHINE_BPB_END): ... this.

	* include/pupa/fs.h [PUPA_UTIL] (pupa_fat_init): Declared.
	[PUPA_UTIL] (pupa_fat_fini): Likewise.

	* fs/fat.c [PUPA_UTIL] (pupa_fat_init): Defined. Maybe a better
	way should be implemented.
	[PUPA_UTIL] (pupa_fat_fini): Likewise.

	* disk/i386/pc/biosdisk.c (pupa_biosdisk_call_hook): Increase
	the size of NAME for safety.
	(pupa_biosdisk_iterate): Search hard disks to 0x90 instead of
	0x88.

	* conf/i386-pc.rmk (sbin_UTILITIES): New variable.
	(pupa_setup_SOURCES): Likewise.

	* genmk.rb (Utility#rule): Add $(BUILD_CFLAGS) into the rules.
This commit is contained in:
okuji 2003-01-02 20:12:33 +00:00
parent 08b70fe8eb
commit 1cc73a62da
17 changed files with 1809 additions and 18 deletions

View File

@ -1,3 +1,51 @@
2003-01-03 Yoshinori K. Okuji <okuji@enbug.org>
* include/i386/pc/util/biosdisk.h: New file.
* util/i386/pc/biosdisk.c: Likewise.
* util/i386/pc/pupa-setup.c: Likewise.
* Makefile.in (INCLUDE_DISTFILES): Added
include/pupa/i386/pc/util/biosdisk.h.
(UTIL_DISTFILES): Added biosdisk.c and pupa-setup.c under the
directory util/i386/pc.
(install-local): Added a rule for sbin_UTILITIES.
(uninstall): Likewise.
* util/i386/pc/pupa-mkimage.c (usage): Fix a typo in the doc.
* util/misc.c (xrealloc): New function.
(pupa_malloc): Likewise.
(pupa_free): Likewise.
(pupa_realloc): Likewise.
(pupa_stop): Likewise.
(pupa_putchar): Likewise.
* kern/disk.c (pupa_disk_read): Prevent L from underflowing.
* include/pupa/util/misc.h (xrealloc): Declared.
* include/pupa/i386/pc/boot.h (PUPA_BOOT_MACHINE_BPB_START): New
macro.
(PUPA_BOOT_MACHINE_BPBEND): Renamed to ...
(PUPA_BOOT_MACHINE_BPB_END): ... this.
* include/pupa/fs.h [PUPA_UTIL] (pupa_fat_init): Declared.
[PUPA_UTIL] (pupa_fat_fini): Likewise.
* fs/fat.c [PUPA_UTIL] (pupa_fat_init): Defined. Maybe a better
way should be implemented.
[PUPA_UTIL] (pupa_fat_fini): Likewise.
* disk/i386/pc/biosdisk.c (pupa_biosdisk_call_hook): Increase
the size of NAME for safety.
(pupa_biosdisk_iterate): Search hard disks to 0x90 instead of
0x88.
* conf/i386-pc.rmk (sbin_UTILITIES): New variable.
(pupa_setup_SOURCES): Likewise.
* genmk.rb (Utility#rule): Add $(BUILD_CFLAGS) into the rules.
2002-12-28 Yoshinori K. Okuji <okuji@enbug.org>
* kern/i386/pc/startup.S (push_get_mmap_entry): Revert to a

View File

@ -93,7 +93,8 @@ INCLUDE_DISTFILES = $(addprefix include/pupa/,boot.h device.h disk.h \
$(addprefix include/pupa/util/,misc.h resolve.h) \
include/pupa/i386/types.h \
$(addprefix include/pupa/i386/pc/,biosdisk.h boot.h \
console.h init.h kernel.h loader.h memory.h partition.h)
console.h init.h kernel.h loader.h memory.h partition.h) \
$(addprefix include/pupa/i386/pc/util/,biosdisk.h)
KERN_DISTFILES = $(addprefix kern/,device.c disk.c dl.c err.c file.c \
fs.c loader.c main.c misc.c mm.c rescue.c term.c) \
@ -105,7 +106,8 @@ LOADER_DISTFILES = $(addprefix loader/i386/pc/,chainloader.c)
TERM_DISTFILES = $(addprefix term/i386/pc/,console.c)
UTIL_DISTFILES = $(addprefix util/,genmoddep.c misc.c resolve.c) \
util/i386/pc/pupa-mkimage.c
$(addprefix util/i386/pc/,biosdisk.c pupa-mkimage.c \
pupa-setup.c)
DISTFILES = $(COMMON_DISTFILES) $(BOOT_DISTFILES) $(CONF_DISTFILES) \
$(DISK_DISTFILES) $(FS_DISTFILES) $(INCLUDE_DISTFILES) \
@ -154,6 +156,12 @@ install-local: all
dest="`echo $$file | sed 's,.*/,,'`"; \
$(INSTALL_PROGRAM) $$dir$$file $(DESTDIR)$(bindir)/$$dest; \
done
$(mkinstalldirs) $(DESTDIR)$(sbindir)
@list='$(sbin_UTILITIES)'; for file in $$list; do \
if test -f "$$file"; then dir=; else dir="$(srcdir)"; fi; \
dest="`echo $$file | sed 's,.*/,,'`"; \
$(INSTALL_PROGRAM) $$dir$$file $(DESTDIR)$(sbindir)/$$dest; \
done
install-strip:
$(MAKE) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" install
@ -163,10 +171,14 @@ uninstall:
dest="`echo $$file | sed 's,.*/,,'`"; \
rm -f $(DESTDIR)$(pkgdatadir)/$$dest; \
done
@list = '$(bin_UTILITIES)'; for file in $$list; do \
@list='$(bin_UTILITIES)'; for file in $$list; do \
dest="`echo $$file | sed 's,.*/,,'`"; \
rm -f $(DESTDIR)$(bindir)/$$dest; \
done
@list='$(sbin_UTILITIES)'; for file in $$list; do \
dest="`echo $$file | sed 's,.*/,,'`"; \
rm -f $(DESTDIR)$(sbindir)/$$dest; \
done
clean:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)

View File

@ -84,7 +84,7 @@ cylinder_start:
.word 0
/* more space... */
. = _start + PUPA_BOOT_MACHINE_BPBEND
. = _start + PUPA_BOOT_MACHINE_BPB_END
/*
* End of BIOS parameter block.

View File

@ -239,6 +239,7 @@ kernel_syms.lst: $(addprefix include/pupa/,$(kernel_img_HEADERS)) genkernsyms.sh
# Utilities.
bin_UTILITIES = pupa-mkimage
sbin_UTILITIES = pupa-setup
noinst_UTILITIES = genmoddep
# For pupa-mkimage.
@ -251,30 +252,129 @@ pupa-mkimage: pupa_mkimage-util_i386_pc_pupa_mkimage.o pupa_mkimage-util_misc.o
$(BUILD_CC) $(BUILD_LDFLAGS) $(pupa_mkimage_LDFLAGS) -o $@ $^
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) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -c -o $@ $<
$(BUILD_CC) -Iutil/i386/pc -I$(srcdir)/util/i386/pc $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -c -o $@ $<
pupa_mkimage-util_i386_pc_pupa_mkimage.d: util/i386/pc/pupa-mkimage.c
set -e; $(BUILD_CC) -Iutil/i386/pc -I$(srcdir)/util/i386/pc $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -M $< | sed 's,pupa\-mkimage\.o[ :]*,pupa_mkimage-util_i386_pc_pupa_mkimage.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@
set -e; $(BUILD_CC) -Iutil/i386/pc -I$(srcdir)/util/i386/pc $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -M $< | sed 's,pupa\-mkimage\.o[ :]*,pupa_mkimage-util_i386_pc_pupa_mkimage.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@
-include pupa_mkimage-util_i386_pc_pupa_mkimage.d
pupa_mkimage-util_misc.o: util/misc.c
$(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -c -o $@ $<
$(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -c -o $@ $<
pupa_mkimage-util_misc.d: util/misc.c
set -e; $(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -M $< | sed 's,misc\.o[ :]*,pupa_mkimage-util_misc.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@
set -e; $(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -M $< | sed 's,misc\.o[ :]*,pupa_mkimage-util_misc.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@
-include pupa_mkimage-util_misc.d
pupa_mkimage-util_resolve.o: util/resolve.c
$(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -c -o $@ $<
$(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -c -o $@ $<
pupa_mkimage-util_resolve.d: util/resolve.c
set -e; $(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -M $< | sed 's,resolve\.o[ :]*,pupa_mkimage-util_resolve.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@
set -e; $(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -M $< | sed 's,resolve\.o[ :]*,pupa_mkimage-util_resolve.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@
-include pupa_mkimage-util_resolve.d
# For pupa-setup.
pupa_setup_SOURCES = util/i386/pc/pupa-setup.c util/i386/pc/biosdisk.c \
util/misc.c kern/device.c kern/disk.c kern/file.c kern/fs.c \
kern/err.c kern/misc.c disk/i386/pc/partition.c fs/fat.c
CLEANFILES += 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
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 $@ $^
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 $@ $<
pupa_setup-util_i386_pc_pupa_setup.d: util/i386/pc/pupa-setup.c
set -e; $(BUILD_CC) -Iutil/i386/pc -I$(srcdir)/util/i386/pc $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -M $< | sed 's,pupa\-setup\.o[ :]*,pupa_setup-util_i386_pc_pupa_setup.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@
-include pupa_setup-util_i386_pc_pupa_setup.d
pupa_setup-util_i386_pc_biosdisk.o: util/i386/pc/biosdisk.c
$(BUILD_CC) -Iutil/i386/pc -I$(srcdir)/util/i386/pc $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -c -o $@ $<
pupa_setup-util_i386_pc_biosdisk.d: util/i386/pc/biosdisk.c
set -e; $(BUILD_CC) -Iutil/i386/pc -I$(srcdir)/util/i386/pc $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -M $< | sed 's,biosdisk\.o[ :]*,pupa_setup-util_i386_pc_biosdisk.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@
-include pupa_setup-util_i386_pc_biosdisk.d
pupa_setup-util_misc.o: util/misc.c
$(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -c -o $@ $<
pupa_setup-util_misc.d: util/misc.c
set -e; $(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -M $< | sed 's,misc\.o[ :]*,pupa_setup-util_misc.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@
-include pupa_setup-util_misc.d
pupa_setup-kern_device.o: kern/device.c
$(BUILD_CC) -Ikern -I$(srcdir)/kern $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -c -o $@ $<
pupa_setup-kern_device.d: kern/device.c
set -e; $(BUILD_CC) -Ikern -I$(srcdir)/kern $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -M $< | sed 's,device\.o[ :]*,pupa_setup-kern_device.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@
-include pupa_setup-kern_device.d
pupa_setup-kern_disk.o: kern/disk.c
$(BUILD_CC) -Ikern -I$(srcdir)/kern $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -c -o $@ $<
pupa_setup-kern_disk.d: kern/disk.c
set -e; $(BUILD_CC) -Ikern -I$(srcdir)/kern $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -M $< | sed 's,disk\.o[ :]*,pupa_setup-kern_disk.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@
-include pupa_setup-kern_disk.d
pupa_setup-kern_file.o: kern/file.c
$(BUILD_CC) -Ikern -I$(srcdir)/kern $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -c -o $@ $<
pupa_setup-kern_file.d: kern/file.c
set -e; $(BUILD_CC) -Ikern -I$(srcdir)/kern $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -M $< | sed 's,file\.o[ :]*,pupa_setup-kern_file.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@
-include pupa_setup-kern_file.d
pupa_setup-kern_fs.o: kern/fs.c
$(BUILD_CC) -Ikern -I$(srcdir)/kern $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -c -o $@ $<
pupa_setup-kern_fs.d: kern/fs.c
set -e; $(BUILD_CC) -Ikern -I$(srcdir)/kern $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -M $< | sed 's,fs\.o[ :]*,pupa_setup-kern_fs.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@
-include pupa_setup-kern_fs.d
pupa_setup-kern_err.o: kern/err.c
$(BUILD_CC) -Ikern -I$(srcdir)/kern $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -c -o $@ $<
pupa_setup-kern_err.d: kern/err.c
set -e; $(BUILD_CC) -Ikern -I$(srcdir)/kern $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -M $< | sed 's,err\.o[ :]*,pupa_setup-kern_err.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@
-include pupa_setup-kern_err.d
pupa_setup-kern_misc.o: kern/misc.c
$(BUILD_CC) -Ikern -I$(srcdir)/kern $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -c -o $@ $<
pupa_setup-kern_misc.d: kern/misc.c
set -e; $(BUILD_CC) -Ikern -I$(srcdir)/kern $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -M $< | sed 's,misc\.o[ :]*,pupa_setup-kern_misc.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@
-include pupa_setup-kern_misc.d
pupa_setup-disk_i386_pc_partition.o: disk/i386/pc/partition.c
$(BUILD_CC) -Idisk/i386/pc -I$(srcdir)/disk/i386/pc $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -c -o $@ $<
pupa_setup-disk_i386_pc_partition.d: disk/i386/pc/partition.c
set -e; $(BUILD_CC) -Idisk/i386/pc -I$(srcdir)/disk/i386/pc $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -M $< | sed 's,partition\.o[ :]*,pupa_setup-disk_i386_pc_partition.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@
-include pupa_setup-disk_i386_pc_partition.d
pupa_setup-fs_fat.o: fs/fat.c
$(BUILD_CC) -Ifs -I$(srcdir)/fs $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -c -o $@ $<
pupa_setup-fs_fat.d: fs/fat.c
set -e; $(BUILD_CC) -Ifs -I$(srcdir)/fs $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -M $< | sed 's,fat\.o[ :]*,pupa_setup-fs_fat.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@
-include pupa_setup-fs_fat.d
# For genmoddep.
genmoddep_SOURCES = util/genmoddep.c
CLEANFILES += genmoddep genmoddep-util_genmoddep.o
@ -284,10 +384,10 @@ genmoddep: genmoddep-util_genmoddep.o
$(BUILD_CC) $(BUILD_LDFLAGS) $(genmoddep_LDFLAGS) -o $@ $^
genmoddep-util_genmoddep.o: util/genmoddep.c
$(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(genmoddep_CFLAGS) -c -o $@ $<
$(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(genmoddep_CFLAGS) -c -o $@ $<
genmoddep-util_genmoddep.d: util/genmoddep.c
set -e; $(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(genmoddep_CFLAGS) -M $< | sed 's,genmoddep\.o[ :]*,genmoddep-util_genmoddep.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@
set -e; $(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(genmoddep_CFLAGS) -M $< | sed 's,genmoddep\.o[ :]*,genmoddep-util_genmoddep.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@
-include genmoddep-util_genmoddep.d

View File

@ -44,12 +44,18 @@ kernel_syms.lst: $(addprefix include/pupa/,$(kernel_img_HEADERS)) genkernsyms.sh
# Utilities.
bin_UTILITIES = pupa-mkimage
sbin_UTILITIES = pupa-setup
noinst_UTILITIES = genmoddep
# For pupa-mkimage.
pupa_mkimage_SOURCES = util/i386/pc/pupa-mkimage.c util/misc.c \
util/resolve.c
# For pupa-setup.
pupa_setup_SOURCES = util/i386/pc/pupa-setup.c util/i386/pc/biosdisk.c \
util/misc.c kern/device.c kern/disk.c kern/file.c kern/fs.c \
kern/err.c kern/misc.c disk/i386/pc/partition.c fs/fat.c
# For genmoddep.
genmoddep_SOURCES = util/genmoddep.c

View File

@ -92,7 +92,7 @@ pupa_biosdisk_get_drive (const char *name)
static int
pupa_biosdisk_call_hook (int (*hook) (const char *name), int drive)
{
char name[4];
char name[10];
pupa_sprintf (name, (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80));
return hook (name);
@ -111,7 +111,7 @@ pupa_biosdisk_iterate (int (*hook) (const char *name))
return 1;
/* For hard disks, attempt to read the MBR. */
for (drive = 0x80; drive < 0x88; drive++)
for (drive = 0x80; drive < 0x90; drive++)
{
if (pupa_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1,
PUPA_MEMORY_MACHINE_SCRATCH_SEG) != 0)

View File

@ -745,12 +745,20 @@ static struct pupa_fs pupa_fat_fs =
.next = 0
};
#ifdef PUPA_UTIL
void pupa_fat_init (void)
#else
PUPA_MOD_INIT
#endif
{
pupa_fs_register (&pupa_fat_fs);
}
#ifdef PUPA_UTIL
void pupa_fat_fini (void)
#else
PUPA_MOD_FINI
#endif
{
pupa_fs_unregister (&pupa_fat_fs);
}

View File

@ -190,11 +190,11 @@ MOSTLYCLEANFILES += #{deps_str}
dir = File.dirname(src)
"#{obj}: #{src}
$(BUILD_CC) -I#{dir} -I$(srcdir)/#{dir} $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(#{prefix}_CFLAGS) -c -o $@ $<
$(BUILD_CC) -I#{dir} -I$(srcdir)/#{dir} $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(#{prefix}_CFLAGS) -c -o $@ $<
#{dep}: #{src}
set -e; \
$(BUILD_CC) -I#{dir} -I$(srcdir)/#{dir} $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(#{prefix}_CFLAGS) -M $< \
$(BUILD_CC) -I#{dir} -I$(srcdir)/#{dir} $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(#{prefix}_CFLAGS) -M $< \
| sed 's,#{Regexp.quote(fake_obj)}[ :]*,#{obj} $@ : ,g' > $@; \
[ -s $@ ] || rm -f $@

View File

@ -60,4 +60,9 @@ void EXPORT_FUNC(pupa_fs_unregister) (pupa_fs_t fs);
void EXPORT_FUNC(pupa_fs_iterate) (int (*hook) (const pupa_fs_t fs));
pupa_fs_t EXPORT_FUNC(pupa_fs_probe) (pupa_device_t device);
#ifdef PUPA_UTIL
void pupa_fat_init (void);
void pupa_fat_fini (void);
#endif /* PUPA_UTIL */
#endif /* ! PUPA_FS_HEADER */

View File

@ -24,8 +24,11 @@
/* The signature for bootloader. */
#define PUPA_BOOT_MACHINE_SIGNATURE 0xaa55
/* The offset of the start of BPB (BIOS Parameter Block). */
#define PUPA_BOOT_MACHINE_BPB_START 0x3
/* The offset of the end of BPB (BIOS Parameter Block). */
#define PUPA_BOOT_MACHINE_BPBEND 0x3e
#define PUPA_BOOT_MACHINE_BPB_END 0x3e
/* The offset of the major version. */
#define PUPA_BOOT_MACHINE_VER_MAJ 0x3e

View File

@ -0,0 +1,28 @@
/* biosdisk.h - emulate biosdisk */
/*
* PUPA -- Preliminary Universal Programming Architecture for GRUB
* Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
*
* PUPA 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 PUPA; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef PUPA_BIOSDISK_MACHINE_UTIL_HEADER
#define PUPA_BIOSDISK_MACHINE_UTIL_HEADER 1
void pupa_util_biosdisk_init (const char *dev_map);
void pupa_util_biosdisk_fini (void);
char *pupa_util_biosdisk_get_pupa_dev (const char *os_dev);
#endif /* ! PUPA_BIOSDISK_MACHINE_UTIL_HEADER */

View File

@ -30,6 +30,7 @@ void pupa_util_info (const char *fmt, ...);
void pupa_util_error (const char *fmt, ...) __attribute__ ((noreturn));
void *xmalloc (size_t size);
void *xrealloc (void *ptr, size_t size);
char *xstrdup (const char *str);
char *pupa_util_get_path (const char *dir, const char *file);

View File

@ -396,6 +396,10 @@ pupa_disk_read (pupa_disk_t disk, unsigned long sector,
((l > PUPA_DISK_SECTOR_SIZE)
? PUPA_DISK_SECTOR_SIZE
: l));
if (l < PUPA_DISK_SECTOR_SIZE - offset)
break;
s++;
l -= PUPA_DISK_SECTOR_SIZE - offset;
offset = 0;

776
util/i386/pc/biosdisk.c Normal file
View File

@ -0,0 +1,776 @@
/* biosdisk.c - emulate biosdisk */
/*
* PUPA -- Preliminary Universal Programming Architecture for GRUB
* Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc.
* Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
*
* PUPA 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 PUPA; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <pupa/machine/biosdisk.h>
#include <pupa/disk.h>
#include <pupa/machine/partition.h>
#include <pupa/types.h>
#include <pupa/err.h>
#include <pupa/util/misc.h>
/* Try to use glibc's transparant LFS support. */
#define _LARGEFILE_SOURCE 1
/* lseek becomes synonymous with lseek64. */
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#ifdef __linux__
# include <sys/ioctl.h> /* ioctl */
# if !defined(__GLIBC__) || \
((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
/* Maybe libc doesn't have large file support. */
# include <linux/unistd.h> /* _llseek */
# endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */
# ifndef BLKFLSBUF
# define BLKFLSBUF _IO (0x12,97) /* flush buffer cache */
# endif /* ! BLKFLSBUF */
# include <sys/ioctl.h> /* ioctl */
# ifndef HDIO_GETGEO
# define HDIO_GETGEO 0x0301 /* get device geometry */
/* If HDIO_GETGEO is not defined, it is unlikely that hd_geometry is
defined. */
struct hd_geometry
{
unsigned char heads;
unsigned char sectors;
unsigned short cylinders;
unsigned long start;
};
# endif /* ! HDIO_GETGEO */
# ifndef MAJOR
# ifndef MINORBITS
# define MINORBITS 8
# endif /* ! MINORBITS */
# define MAJOR(dev) ((unsigned) ((dev) >> MINORBITS))
# endif /* ! MAJOR */
# ifndef FLOPPY_MAJOR
# define FLOPPY_MAJOR 2
# endif /* ! FLOPPY_MAJOR */
# ifndef LOOP_MAJOR
# define LOOP_MAJOR 7
# endif /* ! LOOP_MAJOR */
#endif /* __linux__ */
static char *map[256];
#ifdef __linux__
/* Check if we have devfs support. */
static int
have_devfs (void)
{
static int dev_devfsd_exists = -1;
if (dev_devfsd_exists < 0)
{
struct stat st;
dev_devfsd_exists = stat ("/dev/.devfsd", &st) == 0;
}
return dev_devfsd_exists;
}
#endif /* __linux__ */
static int
get_drive (const char *name)
{
unsigned long drive;
char *p;
if ((name[0] != 'f' && name[0] != 'h') || name[1] != 'd')
goto fail;
drive = strtoul (name + 2, &p, 10);
if (p == name + 2)
goto fail;
if (name[0] == 'h')
drive += 0x80;
if (drive > sizeof (map) / sizeof (map[0]))
goto fail;
return (int) drive;
fail:
pupa_error (PUPA_ERR_UNKNOWN_DEVICE, "not a biosdisk");
return -1;
}
static int
call_hook (int (*hook) (const char *name), int drive)
{
char name[10];
sprintf (name, (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80));
return hook (name);
}
static int
pupa_util_biosdisk_iterate (int (*hook) (const char *name))
{
unsigned i;
for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
if (map[i] && call_hook (hook, i))
return 1;
return 0;
}
static pupa_err_t
pupa_util_biosdisk_open (const char *name, pupa_disk_t disk)
{
int drive;
struct stat st;
drive = get_drive (name);
if (drive < 0)
return pupa_errno;
if (! map[drive])
return pupa_error (PUPA_ERR_BAD_DEVICE,
"no mapping exists for `%s'", name);
disk->has_partitions = (drive & 0x80);
disk->id = drive;
/* Get the size. */
if (lstat (map[drive], &st) < 0)
return pupa_error (PUPA_ERR_BAD_DEVICE, "cannot stat `%s'", map[drive]);
if (st.st_blocks)
disk->total_sectors = st.st_blocks;
else
/* Hmm... Use st_size instead. */
disk->total_sectors = st.st_size >> PUPA_DISK_SECTOR_BITS;
return PUPA_ERR_NONE;
}
#ifdef __linux__
static int
linux_find_partition (char *dev, unsigned long sector)
{
size_t len = strlen (dev);
const char *format;
char *p;
int i;
if (have_devfs () && strcmp (dev + len - 5, "/disc") == 0)
{
p = dev + len - 4;
format = "part%d";
}
else if ((strncmp (dev + 5, "hd", 2) == 0
|| strncmp (dev + 5, "sd", 2) == 0)
&& dev[7] >= 'a' && dev[7] <= 'z')
{
p = dev + 8;
format = "%d";
}
else if (strncmp (dev + 5, "rd/c", 4) == 0)
{
p = strchr (dev + 9, 'd');
if (! p)
return 0;
p++;
while (*p && isdigit (*p))
p++;
format = "p%d";
}
else
return 0;
for (i = 0; i < 10000; i++)
{
int fd;
struct hd_geometry hdg;
sprintf (p, format, i);
fd = open (dev, O_RDONLY);
if (! fd)
return 0;
if (ioctl (fd, HDIO_GETGEO, &hdg))
{
close (fd);
return 0;
}
close (fd);
if (hdg.start == sector)
return 1;
}
return 0;
}
#endif /* __linux__ */
static int
open_device (const pupa_disk_t disk, unsigned long sector, int flags)
{
int fd;
#ifdef O_LARGEFILE
flags |= O_LARGEFILE;
#endif
#ifdef O_SYNC
flags |= O_SYNC;
#endif
#ifdef O_FSYNC
flags |= O_FSYNC;
#endif
#ifdef __linux__
/* Linux has a bug that the disk cache for a whole disk is not consistent
with the one for a partition of the disk. */
{
int is_partition = 0;
char dev[PATH_MAX];
strcpy (dev, map[disk->id]);
if (disk->partition && strncmp (map[disk->id], "/dev/", 5) == 0)
is_partition = linux_find_partition (dev, disk->partition->start);
/* Open the partition. */
fd = open (dev, flags);
if (fd < 0)
{
pupa_error (PUPA_ERR_BAD_DEVICE, "cannot open `%s'", dev);
return -1;
}
if (is_partition)
sector -= disk->partition->start;
}
#else /* ! __linux__ */
fd = open (map[disk->id], flags);
if (! fd)
{
pupa_error (PUPA_ERR_BAD_DEVICE, "cannot open `%s'", map[disk->id]);
return -1;
}
#endif /* ! __linux__ */
#if defined(__linux__) && (!defined(__GLIBC__) || \
((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
/* Maybe libc doesn't have large file support. */
{
loff_t offset, result;
static int _llseek (uint filedes, ulong hi, ulong lo,
loff_t *res, uint wh);
_syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
loff_t *, res, uint, wh);
offset = (loff_t) sector << PUPA_DISK_SECTOR_BITS;
if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
{
pupa_error (PUPA_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id]);
close (fd);
return -1;
}
}
#else
{
off_t offset = (off_t) sector << PUPA_DISK_SECTOR_BITS;
if (lseek (fd, offset, SEEK_SET) != offset)
{
pupa_error (PUPA_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id]);
close (fd);
return -1;
}
}
#endif
return fd;
}
/* Read LEN bytes from FD in BUF. Return less than or equal to zero if an
error occurs, otherwise return LEN. */
static ssize_t
nread (int fd, char *buf, size_t len)
{
ssize_t size = len;
while (len)
{
ssize_t ret = read (fd, buf, len);
if (ret <= 0)
{
if (errno == EINTR)
continue;
else
return ret;
}
len -= ret;
buf += ret;
}
return size;
}
/* Write LEN bytes from BUF to FD. Return less than or equal to zero if an
error occurs, otherwise return LEN. */
static ssize_t
nwrite (int fd, const char *buf, size_t len)
{
ssize_t size = len;
while (len)
{
ssize_t ret = write (fd, buf, len);
if (ret <= 0)
{
if (errno == EINTR)
continue;
else
return ret;
}
len -= ret;
buf += ret;
}
return size;
}
static pupa_err_t
pupa_util_biosdisk_read (pupa_disk_t disk, unsigned long sector,
unsigned long size, char *buf)
{
int fd;
fd = open_device (disk, sector, O_RDONLY);
if (fd < 0)
return pupa_errno;
#ifdef __linux__
if (sector == 0 && size > 1)
{
/* Work around a bug in linux's ez remapping. Linux remaps all
sectors that are read together with the MBR in one read. It
should only remap the MBR, so we split the read in two
parts. -jochen */
if (nread (fd, buf, PUPA_DISK_SECTOR_SIZE) != PUPA_DISK_SECTOR_SIZE)
{
pupa_error (PUPA_ERR_READ_ERROR, "cannot read `%s'", map[disk->id]);
close (fd);
return pupa_errno;
}
buf += PUPA_DISK_SECTOR_SIZE;
size--;
}
#endif /* __linux__ */
if (nread (fd, buf, size << PUPA_DISK_SECTOR_BITS)
!= (ssize_t) (size << PUPA_DISK_SECTOR_BITS))
pupa_error (PUPA_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id]);
close (fd);
return pupa_errno;
}
static pupa_err_t
pupa_util_biosdisk_write (pupa_disk_t disk, unsigned long sector,
unsigned long size, const char *buf)
{
int fd;
fd = open_device (disk, sector, O_WRONLY);
if (fd < 0)
return pupa_errno;
if (nwrite (fd, buf, size << PUPA_DISK_SECTOR_BITS)
!= (ssize_t) (size << PUPA_DISK_SECTOR_BITS))
pupa_error (PUPA_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id]);
close (fd);
return pupa_errno;
}
static struct pupa_disk_dev pupa_util_biosdisk_dev =
{
.name = "biosdisk",
.iterate = pupa_util_biosdisk_iterate,
.open = pupa_util_biosdisk_open,
.close = 0,
.read = pupa_util_biosdisk_read,
.write = pupa_util_biosdisk_write,
.next = 0
};
static void
read_device_map (const char *dev_map)
{
FILE *fp;
char buf[1024]; /* XXX */
int lineno = 0;
auto void show_error (const char *msg);
void show_error (const char *msg)
{
pupa_util_error ("%s:%d: %s", dev_map, lineno, msg);
}
fp = fopen (dev_map, "r");
if (! fp)
pupa_util_error ("Cannot open `%s'", dev_map);
while (fgets (buf, sizeof (buf), fp))
{
char *p = buf;
char *e;
int drive;
lineno++;
/* Skip leading spaces. */
while (*p && isspace (*p))
p++;
/* If the first character is `#' or NUL, skip this line. */
if (*p == '\0' || *p == '#')
continue;
if (*p != '(')
show_error ("No open parenthesis found");
p++;
drive = get_drive (p);
if (drive < 0 || drive >= (int) (sizeof (map) / sizeof (map[0])))
show_error ("Bad device name");
p = strchr (p, ')');
if (! p)
show_error ("No close parenthesis found");
p++;
/* Skip leading spaces. */
while (*p && isspace (*p))
p++;
if (*p == '\0')
show_error ("No filename found");
/* NUL-terminate the filename. */
e = p;
while (*e && ! isspace (*e))
e++;
*e = '\0';
/* Multiple entries for a given drive is not allowed. */
if (map[drive])
show_error ("Duplicated entry found");
#ifdef __linux__
/* On Linux, the devfs uses symbolic links horribly, and that
confuses the interface very much, so use realpath to expand
symbolic links. */
map[drive] = xmalloc (PATH_MAX);
if (! realpath (p, map[drive]))
pupa_util_error ("Cannot get the real path of `%s'", p);
#else
map[drive] = xstrdup (p);
#endif
}
fclose (fp);
}
void
pupa_util_biosdisk_init (const char *dev_map)
{
read_device_map (dev_map);
pupa_disk_dev_register (&pupa_util_biosdisk_dev);
}
void
pupa_util_biosdisk_fini (void)
{
unsigned i;
for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
free (map[i]);
pupa_disk_dev_unregister (&pupa_util_biosdisk_dev);
}
static char *
make_device_name (int drive, int dos_part, int bsd_part)
{
char *p;
p = xmalloc (30);
sprintf (p, (drive & 0x80) ? "hd%d" : "fd%d", drive & ~0x80);
if (dos_part >= 0)
sprintf (p + strlen (p), ",%d", dos_part);
if (bsd_part >= 0)
sprintf (p + strlen (p), ",%c", bsd_part + 'a');
return p;
}
static char *
get_os_disk (const char *os_dev)
{
char *path, *p;
#if defined(__linux__)
path = xmalloc (PATH_MAX);
if (! realpath (os_dev, path))
return 0;
if (strncmp ("/dev/", path, 4) == 0)
{
p = path + 4;
if (have_devfs ())
{
/* If this is an IDE disk. */
if (strncmp ("/dev/ide/", p, 9) == 0)
{
p = strstr (p, "part");
if (p)
strcpy (p, "disc");
return path;
}
/* If this is a SCSI disk. */
if (strncmp ("/dev/scsi/", p, 10) == 0)
{
p = strstr (p, "part");
if (p)
strcpy (p, "disc");
return path;
}
}
/* If this is a DAC960 disk. */
if (strncmp ("rd/c", p, 4) == 0)
{
/* /dev/rd/c[0-9]+d[0-9]+(p[0-9]+)? */
p = strchr (p, 'p');
if (p)
*p = '\0';
return path;
}
/* If this is an IDE disk or a SCSI disk. */
if ((strncmp ("hd", p, 2) == 0
|| strncmp ("sd", p, 2) == 0)
&& p[2] >= 'a' && p[2] <= 'z')
{
/* /dev/[hs]d[a-z][0-9]* */
p[3] = '\0';
return path;
}
}
return path;
#elif defined(__GNU__)
path = xstrdup (os_dev);
if (strncmp ("/dev/sd", path, 7) == 0 || strncmp ("/dev/hd", path, 7) == 0)
{
p = strchr (path, 's');
if (p)
*p = '\0';
}
return path;
#else
# warning "The function `get_os_disk' might not work on your OS correctly."
return xstrdup (os_dev);
#endif
}
static int
find_drive (const char *os_dev)
{
int i;
char *os_disk;
os_disk = get_os_disk (os_dev);
if (! os_disk)
return -1;
for (i = 0; i < (int) (sizeof (map) / sizeof (map[0])); i++)
if (map[i] && strcmp (map[i], os_disk) == 0)
{
free (os_disk);
return i;
}
free (os_disk);
return -1;
}
char *
pupa_util_biosdisk_get_pupa_dev (const char *os_dev)
{
struct stat st;
int drive;
if (lstat (os_dev, &st) < 0)
{
pupa_error (PUPA_ERR_BAD_DEVICE, "cannot stat `%s'", os_dev);
return 0;
}
drive = find_drive (os_dev);
if (drive < 0)
{
pupa_error (PUPA_ERR_BAD_DEVICE,
"no mapping exists for `%s'", os_dev);
return 0;
}
if (! S_ISBLK (st.st_mode))
return make_device_name (drive, -1, -1);
#if defined(__linux__)
/* Linux counts partitions uniformly, whether a BSD partition or a DOS
partition, so mapping them to PUPA devices is not trivial.
Here, get the start sector of a partition by HDIO_GETGEO, and
compare it with each partition PUPA recognizes. */
{
char *name;
pupa_disk_t disk;
int fd;
struct hd_geometry hdg;
int dos_part = -1;
int bsd_part = -1;
auto int find_partition (const pupa_partition_t partition);
int find_partition (const pupa_partition_t partition)
{
if (hdg.start == partition->start)
{
dos_part = partition->dos_part;
bsd_part = partition->bsd_part;
return 1;
}
return 0;
}
name = make_device_name (drive, -1, -1);
if (MAJOR (st.st_rdev) == FLOPPY_MAJOR)
return name;
fd = open (os_dev, O_RDONLY);
if (! fd)
{
pupa_error (PUPA_ERR_BAD_DEVICE, "cannot open `%s'", os_dev);
free (name);
return 0;
}
if (ioctl (fd, HDIO_GETGEO, &hdg))
{
pupa_error (PUPA_ERR_BAD_DEVICE,
"cannot get geometry of `%s'", os_dev);
close (fd);
free (name);
return 0;
}
close (fd);
if (hdg.start == 0)
return name;
disk = pupa_disk_open (name);
free (name);
if (! disk)
return 0;
pupa_partition_iterate (disk, find_partition);
if (dos_part < 0)
{
pupa_disk_close (disk);
pupa_error (PUPA_ERR_BAD_DEVICE,
"cannot find the partition of `%s'", os_dev);
return 0;
}
return make_device_name (drive, dos_part, bsd_part);
}
#elif defined(__GNU__)
/* GNU uses "/dev/[hs]d[0-9]+(s[0-9]+[a-z]?)?". */
{
char *p;
int dos_part = -1;
int bsd_part = -1;
p = strrchr (os_dev, 's');
if (p)
{
unsigned long n;
char *q;
p++;
n = strtoul (p, &q, 10);
if (p != q && n != LONG_MIN && n != LONG_MAX)
{
dos_part = (int) n;
if (*q >= 'a' && *q <= 'g')
bsd_part = *q - 'a';
}
}
return make_device_name (drive, dos_part, bsd_part);
}
#else
# warning "The function `pupa_util_biosdisk_get_pupa_dev' might not work on your OS correctly."
return make_device_name (drive, -1, -1);
#endif
}

View File

@ -145,7 +145,7 @@ Make a bootable image of PUPA.\n\
\n\
-d, --directory=DIR use images and modules under DIR [default=%s]\n\
-o, --output=FILE output a generated image to FILE [default=stdout]\n\
-h, --help display this image and exit\n\
-h, --help display this message and exit\n\
-V, --version print version information and exit\n\
-v, --verbose print verbose messages\n\
\n\

759
util/i386/pc/grub-setup.c Normal file
View File

@ -0,0 +1,759 @@
/* pupa-setup.c - make PUPA usable */
/*
* PUPA -- Preliminary Universal Programming Architecture for GRUB
* Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc.
* Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
*
* PUPA 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 PUPA; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#include <pupa/types.h>
#include <pupa/util/misc.h>
#include <pupa/device.h>
#include <pupa/disk.h>
#include <pupa/file.h>
#include <pupa/fs.h>
#include <pupa/machine/partition.h>
#include <pupa/machine/util/biosdisk.h>
#include <pupa/machine/boot.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#define _GNU_SOURCE 1
#include <getopt.h>
#define DEFAULT_BOOT_FILE "boot.img"
#define DEFAULT_CORE_FILE "core.img"
#ifdef __NetBSD__
/* NetBSD uses /boot for its boot block. */
# define DEFAULT_DIRECTORY "/pupa"
#else
# define DEFAULT_DIRECTORY "/boot/pupa"
#endif
#define DEFAULT_DEVICE_MAP DEFAULT_DIRECTORY "/device.map"
/* This is the blocklist used in the diskboot image. */
struct boot_blocklist
{
pupa_uint32_t start;
pupa_uint16_t len;
pupa_uint16_t segment;
} __attribute__ ((packed));
static void
setup (const char *prefix, const char *dir,
const char *boot_file, const char *core_file,
const char *root, const char *dest)
{
char *boot_path, *core_path;
char *boot_img, *core_img;
size_t boot_size, core_size;
pupa_uint16_t core_sectors;
pupa_device_t root_dev, dest_dev;
pupa_uint8_t *boot_drive;
pupa_uint32_t *kernel_sector;
struct boot_blocklist *first_block, *block;
char *tmp_img;
int i;
unsigned long first_sector;
pupa_uint16_t current_segment
= PUPA_BOOT_MACHINE_KERNEL_SEG + (PUPA_DISK_SECTOR_SIZE >> 4);
pupa_uint16_t last_length = PUPA_DISK_SECTOR_SIZE;
pupa_file_t file;
FILE *fp;
auto void save_first_sector (unsigned long sector, unsigned offset,
unsigned length);
auto void save_blocklists (unsigned long sector, unsigned offset,
unsigned length);
void save_first_sector (unsigned long sector, unsigned offset,
unsigned length)
{
pupa_util_info ("the fist sector is <%lu,%u,%u>",
sector, offset, length);
if (offset != 0 || length != PUPA_DISK_SECTOR_SIZE)
pupa_util_error ("The first sector of the core file is not sector-aligned");
first_sector = sector;
}
void save_blocklists (unsigned long sector, unsigned offset, unsigned length)
{
struct boot_blocklist *prev = block + 1;
pupa_util_info ("saving <%lu,%u,%u> with the segment 0x%x",
sector, offset, length, (unsigned) current_segment);
if (offset != 0 || last_length != PUPA_DISK_SECTOR_SIZE)
pupa_util_error ("Non-sector-aligned data is found in the core file");
if (block != first_block
&& (pupa_le_to_cpu32 (prev->start)
+ pupa_le_to_cpu16 (prev->len)) == sector)
prev->len = pupa_le_to_cpu16 (prev->len) + 1;
else
{
block->start = pupa_cpu_to_le32 (sector);
block->len = pupa_cpu_to_le16 (1);
block->segment = pupa_cpu_to_le16 (current_segment);
block--;
if (block->len)
pupa_util_error ("The sectors of the core file are too fragmented");
}
last_length = length;
current_segment += PUPA_DISK_SECTOR_SIZE >> 4;
}
/* Read the boot image by the OS service. */
boot_path = pupa_util_get_path (dir, boot_file);
boot_size = pupa_util_get_image_size (boot_path);
if (boot_size != PUPA_DISK_SECTOR_SIZE)
pupa_util_error ("The size of `%s' is not %d",
boot_path, PUPA_DISK_SECTOR_SIZE);
boot_img = pupa_util_read_image (boot_path);
free (boot_path);
/* Set the addresses of BOOT_DRIVE and KERNEL_SECTOR. */
boot_drive = (pupa_uint8_t *) (boot_img + PUPA_BOOT_MACHINE_BOOT_DRIVE);
kernel_sector = (pupa_uint32_t *) (boot_img
+ PUPA_BOOT_MACHINE_KERNEL_SECTOR);
core_path = pupa_util_get_path (dir, core_file);
core_size = pupa_util_get_image_size (core_path);
core_sectors = ((core_size + PUPA_DISK_SECTOR_SIZE - 1)
>> PUPA_DISK_SECTOR_BITS);
if (core_size < PUPA_DISK_SECTOR_SIZE)
pupa_util_error ("The size of `%s' is too small", core_path);
else if (core_size > 0xFFFF * PUPA_DISK_SECTOR_SIZE)
pupa_util_error ("The size of `%s' is too large", core_path);
core_img = pupa_util_read_image (core_path);
free (core_path);
/* Have FIRST_BLOCK to point to the first blocklist. */
first_block = (struct boot_blocklist *) (core_img
+ PUPA_DISK_SECTOR_SIZE
- sizeof (*block));
/* Open the root device and the destination device. */
root_dev = pupa_device_open (root);
if (! root_dev)
pupa_util_error ("%s", pupa_errmsg);
dest_dev = pupa_device_open (dest);
if (! dest_dev)
pupa_util_error ("%s", pupa_errmsg);
pupa_util_info ("setting the root device to `%s'", root);
if (pupa_device_set_root (root) != PUPA_ERR_NONE)
pupa_util_error ("%s", pupa_errmsg);
/* Read the original sector from the disk. */
tmp_img = xmalloc (PUPA_DISK_SECTOR_SIZE);
if (pupa_disk_read (dest_dev->disk, 0, 0, PUPA_DISK_SECTOR_SIZE, tmp_img))
pupa_util_error ("%s", pupa_errmsg);
/* Copy the possible DOS BPB. */
memcpy (boot_img + PUPA_BOOT_MACHINE_BPB_START,
tmp_img + PUPA_BOOT_MACHINE_BPB_START,
PUPA_BOOT_MACHINE_BPB_END - PUPA_BOOT_MACHINE_BPB_START);
/* Copy the possible partition table. */
if (dest_dev->disk->has_partitions)
memcpy (boot_img + PUPA_BOOT_MACHINE_WINDOWS_NT_MAGIC,
tmp_img + PUPA_BOOT_MACHINE_WINDOWS_NT_MAGIC,
PUPA_BOOT_MACHINE_PART_END - PUPA_BOOT_MACHINE_WINDOWS_NT_MAGIC);
free (tmp_img);
/* If the destination device can have partitions and it is the MBR,
try to embed the core image into after the MBR. */
if (dest_dev->disk->has_partitions && ! dest_dev->disk->partition)
{
auto int find_first_partition_start (const pupa_partition_t p);
unsigned long first_sector = ~0UL;
int find_first_partition_start (const pupa_partition_t p)
{
if (! pupa_partition_is_empty (p->dos_type)
&& ! pupa_partition_is_bsd (p->dos_type)
&& first_sector > p->start)
first_sector = p->start;
return 0;
}
pupa_partition_iterate (dest_dev->disk, find_first_partition_start);
/* If there is enough space... */
if ((unsigned long) core_sectors + 1 <= first_sector)
{
pupa_util_info ("will embed the core image into after the MBR");
/* The first blocklist contains the whole sectors. */
first_block->start = pupa_cpu_to_le32 (2);
first_block->len = pupa_cpu_to_le16 (core_sectors - 1);
first_block->segment
= pupa_cpu_to_le16 (PUPA_BOOT_MACHINE_KERNEL_SEG
+ (PUPA_DISK_SECTOR_SIZE >> 4));
/* Make sure that the second blocklist is a terminator. */
block = first_block - 1;
block->start = 0;
block->len = 0;
block->segment = 0;
/* Write the core image onto the disk. */
if (pupa_disk_write (dest_dev->disk, 1, 0, core_size, core_img))
pupa_util_error ("%s", pupa_errmsg);
/* The boot image and the core image are on the same drive,
so there is no need to specify the boot drive explicitly. */
*boot_drive = 0xff;
*kernel_sector = pupa_cpu_to_le32 (1);
/* Write the boot image onto the disk. */
if (pupa_disk_write (dest_dev->disk, 0, 0, PUPA_DISK_SECTOR_SIZE,
boot_img))
pupa_util_error ("%s", pupa_errmsg);
goto finish;
}
}
/* The core image must be put on a filesystem unfortunately. */
pupa_util_info ("will leave the core image on the filesystem");
/* Make sure that PUPA reads the identical image as the OS. */
tmp_img = xmalloc (core_size);
core_path = pupa_util_get_path (prefix, core_file);
/* It is a Good Thing to sync two times. */
sync ();
sync ();
#define MAX_TRIES 5
for (i = 0; i < MAX_TRIES; i++)
{
pupa_util_info ("attempting to read the core image `%s' from PUPA%s",
core_path, (i == 0) ? "" : " again");
pupa_disk_cache_invalidate_all ();
file = pupa_file_open (core_path);
if (file)
{
if (pupa_file_size (file) != (pupa_ssize_t) core_size)
pupa_util_info ("succeeded in opening the core image but the size is different (%d != %d)",
(int) pupa_file_size (file), (int) core_size);
else if (pupa_file_read (file, tmp_img, core_size)
!= (pupa_ssize_t) core_size)
pupa_util_info ("succeeded in opening the core image but cannot read %d bytes",
(int) core_size);
else if (memcmp (core_img, tmp_img, core_size) != 0)
pupa_util_info ("succeeded in opening the core image but the data is different");
else
{
pupa_file_close (file);
break;
}
pupa_file_close (file);
}
else
pupa_util_info ("couldn't open the core image");
pupa_errno = PUPA_ERR_NONE;
sync ();
sleep (1);
}
if (i == MAX_TRIES)
pupa_util_error ("Cannot read `%s' correctly", core_path);
/* Clean out the blocklists. */
block = first_block;
while (block->len)
{
block->start = 0;
block->len = 0;
block->segment = 0;
block--;
if ((char *) block <= core_img)
pupa_util_error ("No terminator in the core image");
}
/* Now read the core image to determine where the sectors are. */
file = pupa_file_open (core_path);
if (! file)
pupa_util_error ("%s", pupa_errmsg);
file->read_hook = save_first_sector;
if (pupa_file_read (file, tmp_img, PUPA_DISK_SECTOR_SIZE)
!= PUPA_DISK_SECTOR_SIZE)
pupa_util_error ("Failed to read the first sector of the core image");
block = first_block;
file->read_hook = save_blocklists;
if (pupa_file_read (file, tmp_img, core_size - PUPA_DISK_SECTOR_SIZE)
!= (pupa_ssize_t) core_size - PUPA_DISK_SECTOR_SIZE)
pupa_util_error ("Failed to read the rest sectors of the core image");
free (core_path);
free (tmp_img);
*kernel_sector = pupa_cpu_to_le32 (first_sector);
/* If the destination device is different from the root device,
it is necessary to embed the boot drive explicitly. */
if (root_dev->disk->id != dest_dev->disk->id)
*boot_drive = (pupa_uint8_t) root_dev->disk->id;
else
*boot_drive = 0xFF;
/* Write the first sector of the core image onto the disk. */
core_path = pupa_util_get_path (dir, core_file);
pupa_util_info ("opening the core image `%s'", core_path);
fp = fopen (core_path, "r+b");
if (! fp)
pupa_util_error ("Cannot open `%s'", core_path);
pupa_util_write_image (core_img, PUPA_DISK_SECTOR_SIZE, fp);
fclose (fp);
free (core_path);
/* Write the boot image onto the disk. */
if (pupa_disk_write (dest_dev->disk, 0, 0, PUPA_DISK_SECTOR_SIZE, boot_img))
pupa_util_error ("%s", pupa_errmsg);
finish:
/* Sync is a Good Thing. */
sync ();
free (core_img);
free (boot_img);
pupa_device_close (dest_dev);
pupa_device_close (root_dev);
}
static struct option options[] =
{
{"boot-image", required_argument, 0, 'b'},
{"core-image", required_argument, 0, 'c'},
{"directory", required_argument, 0, 'd'},
{"device-map", required_argument, 0, 'm'},
{"root-device", required_argument, 0, 'r'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{"verbose", no_argument, 0, 'v'},
{0, 0, 0, 0}
};
static void
usage (int status)
{
if (status)
fprintf (stderr, "Try ``pupa-setup --help'' for more information.\n");
else
printf ("\
Usage: pupa-setup [OPTION]... DEVICE\n\
\n\
Set up images to boot from DEVICE.\n\
DEVICE must be a PUPA device (e.g. ``(hd0,0)'').\n\
\n\
-b, --boot-file=FILE use FILE as the boot file [default=%s]\n\
-c, --core-file=FILE use FILE as the core file [default=%s]\n\
-d, --directory=DIR use PUPA files in the directory DIR [default=%s]\n\
-m, --device-map=FILE use FILE as the device map [default=%s]\n\
-r, --root-device=DEV use DEV as the root device [default=guessed]\n\
-h, --help display this message and exit\n\
-V, --version print version information and exit\n\
-v, --verbose print verbose messages\n\
\n\
Report bugs to <okuji@enbug.org>.\n\
",
DEFAULT_BOOT_FILE, DEFAULT_CORE_FILE,
DEFAULT_DIRECTORY, DEFAULT_DEVICE_MAP);
exit (status);
}
static char *
get_device_name (char *dev)
{
size_t len = strlen (dev);
if (dev[0] != '(' || dev[len - 1] != ')')
return 0;
dev[len - 1] = '\0';
return dev + 1;
}
static char *
xgetcwd (void)
{
size_t size = 10;
char *path;
path = xmalloc (size);
while (! getcwd (path, size))
{
size <<= 1;
path = xrealloc (path, size);
}
return path;
}
static void
strip_extra_slashes (char *dir)
{
char *p = dir;
while ((p = strchr (p, '/')) != 0)
{
if (p[1] == '/')
{
memmove (p, p + 1, strlen (p));
continue;
}
else if (p[1] == '\0')
{
p[0] = '\0';
break;
}
p++;
}
}
static char *
get_prefix (const char *dir)
{
char *saved_cwd;
char *abs_dir, *prev_dir;
char *prefix;
struct stat st, prev_st;
/* Save the current directory. */
saved_cwd = xgetcwd ();
if (chdir (dir) < 0)
pupa_util_error ("Cannot change directory to `%s'", dir);
abs_dir = xgetcwd ();
strip_extra_slashes (abs_dir);
prev_dir = xstrdup (abs_dir);
if (stat (".", &prev_st) < 0)
pupa_util_error ("Cannot stat `%s'", dir);
if (! S_ISDIR (prev_st.st_mode))
pupa_util_error ("`%s' is not a directory", dir);
while (1)
{
if (chdir ("..") < 0)
pupa_util_error ("Cannot change directory to the parent");
if (stat (".", &st) < 0)
pupa_util_error ("Cannot stat current directory");
if (! S_ISDIR (st.st_mode))
pupa_util_error ("Current directory is not a directory???");
if (prev_st.st_dev != st.st_dev || prev_st.st_ino == st.st_ino)
break;
free (prev_dir);
prev_dir = xgetcwd ();
prev_st = st;
}
strip_extra_slashes (prev_dir);
prefix = xmalloc (strlen (abs_dir) - strlen (prev_dir) + 2);
prefix[0] = '/';
strcpy (prefix + 1, abs_dir + strlen (prev_dir));
strip_extra_slashes (prefix);
if (chdir (saved_cwd) < 0)
pupa_util_error ("Cannot change directory to `%s'", dir);
free (saved_cwd);
free (abs_dir);
free (prev_dir);
pupa_util_info ("prefix = %s", prefix);
return prefix;
}
static char *
find_root_device (const char *dir, dev_t dev)
{
DIR *dp;
char *saved_cwd;
struct dirent *ent;
dp = opendir (dir);
if (! dp)
return 0;
saved_cwd = xgetcwd ();
if (chdir (dir) < 0)
{
free (saved_cwd);
closedir (dp);
return 0;
}
while ((ent = readdir (dp)) != 0)
{
struct stat st;
if (strcmp (ent->d_name, ".") == 0 || strcmp (ent->d_name, "..") == 0)
continue;
if (stat (ent->d_name, &st) < 0)
/* Ignore any error. */
continue;
if (S_ISDIR (st.st_mode))
{
/* Find it recursively. */
char *res;
res = find_root_device (ent->d_name, dev);
if (res)
{
if (chdir (saved_cwd) < 0)
pupa_util_error ("Cannot restore the original directory");
free (saved_cwd);
closedir (dp);
return res;
}
}
if (S_ISBLK (st.st_mode) && st.st_rdev == dev)
{
/* Found! */
char *res;
res = xmalloc (strlen (saved_cwd) + strlen (dir)
+ strlen (ent->d_name) + 3);
sprintf (res, "%s/%s/%s", saved_cwd, dir, ent->d_name);
strip_extra_slashes (res);
if (chdir (saved_cwd) < 0)
pupa_util_error ("Cannot restore the original directory");
free (saved_cwd);
closedir (dp);
return res;
}
}
if (chdir (saved_cwd) < 0)
pupa_util_error ("Cannot restore the original directory");
free (saved_cwd);
closedir (dp);
return 0;
}
static char *
guess_root_device (const char *dir)
{
struct stat st;
char *os_dev;
if (stat (dir, &st) < 0)
pupa_util_error ("Cannot stat `%s'", dir);
/* This might be truly slow, but is there any better way? */
os_dev = find_root_device ("/dev", st.st_dev);
if (! os_dev)
return 0;
return pupa_util_biosdisk_get_pupa_dev (os_dev);
}
int
main (int argc, char *argv[])
{
char *boot_file = 0;
char *core_file = 0;
char *dir = 0;
char *dev_map = 0;
char *root_dev = 0;
char *prefix;
char *dest_dev;
progname = "pupa-setup";
/* Check for options. */
while (1)
{
int c = getopt_long (argc, argv, "b:c:d:m:r:hVv", options, 0);
if (c == -1)
break;
else
switch (c)
{
case 'b':
if (boot_file)
free (boot_file);
boot_file = xstrdup (optarg);
break;
case 'c':
if (core_file)
free (core_file);
core_file = xstrdup (optarg);
break;
case 'd':
if (dir)
free (dir);
dir = xstrdup (optarg);
break;
case 'm':
if (dev_map)
free (dev_map);
dev_map = xstrdup (optarg);
break;
case 'r':
if (root_dev)
free (root_dev);
root_dev = xstrdup (optarg);
break;
case 'h':
usage (0);
break;
case 'V':
printf ("pupa-setup (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
return 0;
case 'v':
verbosity++;
break;
default:
usage (1);
break;
}
}
/* Obtain DEST_DEV. */
if (optind >= argc)
{
fprintf (stderr, "No device is specified.\n");
usage (1);
}
if (optind + 1 != argc)
{
fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]);
usage (1);
}
dest_dev = get_device_name (argv[optind]);
if (! dest_dev)
{
fprintf (stderr, "Invalid device `%s'.\n", argv[optind]);
usage (1);
}
prefix = get_prefix (dir ? : DEFAULT_DIRECTORY);
/* Initialize the emulated biosdisk driver. */
pupa_util_biosdisk_init (dev_map ? : DEFAULT_DEVICE_MAP);
/* Initialize filesystems. */
pupa_fat_init ();
if (root_dev)
{
char *tmp = get_device_name (root_dev);
if (! tmp)
pupa_util_error ("Invalid root device `%s'", root_dev);
tmp = xstrdup (tmp);
free (root_dev);
root_dev = tmp;
}
else
{
root_dev = guess_root_device (dir ? : DEFAULT_DIRECTORY);
if (! root_dev)
{
pupa_util_error ("Cannot guess the root device. Specify the option ``--root-device''.");
}
}
/* Do the real work. */
setup (prefix,
dir ? : DEFAULT_DIRECTORY,
boot_file ? : DEFAULT_BOOT_FILE,
core_file ? : DEFAULT_CORE_FILE,
root_dev, dest_dev);
/* Free resources. */
pupa_fat_fini ();
pupa_util_biosdisk_fini ();
free (boot_file);
free (core_file);
free (prefix);
free (dir);
free (dev_map);
free (root_dev);
free (prefix);
return 0;
}

View File

@ -25,6 +25,8 @@
#include <sys/stat.h>
#include <pupa/util/misc.h>
#include <pupa/mm.h>
#include <pupa/term.h>
char *progname = 0;
int verbosity = 0;
@ -69,6 +71,16 @@ xmalloc (size_t size)
return p;
}
void *
xrealloc (void *ptr, size_t size)
{
ptr = realloc (ptr, size);
if (! ptr)
pupa_util_error ("out of memory");
return ptr;
}
char *
xstrdup (const char *str)
{
@ -135,3 +147,32 @@ pupa_util_write_image (const char *img, size_t size, FILE *out)
pupa_util_error ("write failed");
}
void *
pupa_malloc (unsigned size)
{
return malloc (size);
}
void
pupa_free (void *ptr)
{
free (ptr);
}
void *
pupa_realloc (void *ptr, unsigned size)
{
return realloc (ptr, size);
}
void
pupa_stop (void)
{
exit (1);
}
void
pupa_putchar (int c)
{
putchar (c);
}