diff options
author | setje <none@none> | 2007-12-07 16:04:33 -0800 |
---|---|---|
committer | setje <none@none> | 2007-12-07 16:04:33 -0800 |
commit | 986fd29a0dc13f7608ef7f508f6e700bd7bc2720 (patch) | |
tree | 8612567367832542a32a2c8bbf3b9b7ef7639ab7 | |
parent | f3b585ce799a83688c5532c430f6133f098431c2 (diff) | |
download | illumos-joyent-986fd29a0dc13f7608ef7f508f6e700bd7bc2720.tar.gz |
6521412 PSARC 2006/525: new boot sparc
6451467 bootadm update-archive does the wrong thing if interrupted
6477079 ability to pick up post bfu binaries from bfu PATH conflicts with sane scripting
--HG--
rename : usr/src/psm/stand/boot/sparc/common/boot.c => deleted_files/usr/src/psm/stand/boot/sparc/common/boot.c
rename : usr/src/psm/stand/boot/sparc/common/boot_services.c => deleted_files/usr/src/psm/stand/boot/sparc/common/boot_services.c
rename : usr/src/psm/stand/boot/sparc/common/hsfsconf.c => deleted_files/usr/src/psm/stand/boot/sparc/common/hsfsconf.c
rename : usr/src/psm/stand/boot/sparc/common/ufsconf.c => deleted_files/usr/src/psm/stand/boot/sparc/common/ufsconf.c
rename : usr/src/psm/stand/bootblks/Makefile.obp => deleted_files/usr/src/psm/stand/bootblks/Makefile.obp
rename : usr/src/psm/stand/bootblks/hsfs/common/Makefile.com => deleted_files/usr/src/psm/stand/bootblks/hsfs/common/Makefile.com
rename : usr/src/psm/stand/bootblks/hsfs/common/boot_obp.fth => deleted_files/usr/src/psm/stand/bootblks/hsfs/common/boot_obp.fth
rename : usr/src/psm/stand/bootblks/hsfs/common/hsfs.c => deleted_files/usr/src/psm/stand/bootblks/hsfs/common/hsfs.c
rename : usr/src/psm/stand/bootblks/hsfs/common/hsfs_sig.h => deleted_files/usr/src/psm/stand/bootblks/hsfs/common/hsfs_sig.h
rename : usr/src/psm/stand/bootblks/hsfs/common/hsfs_small.c => deleted_files/usr/src/psm/stand/bootblks/hsfs/common/hsfs_small.c
rename : usr/src/psm/stand/bootblks/hsfs/common/iob.h => deleted_files/usr/src/psm/stand/bootblks/hsfs/common/iob.h
rename : usr/src/psm/stand/bootblks/hsfs/sparc/unix/Makefile => deleted_files/usr/src/psm/stand/bootblks/hsfs/sparc/unix/Makefile
rename : usr/src/psm/stand/bootblks/obp-c/Makefile.rules => deleted_files/usr/src/psm/stand/bootblks/obp-c/Makefile.rules
rename : usr/src/psm/stand/bootblks/obp-c/Makefile.targ => deleted_files/usr/src/psm/stand/bootblks/obp-c/Makefile.targ
rename : usr/src/psm/stand/bootblks/obp-c/common/cbootblk.h => deleted_files/usr/src/psm/stand/bootblks/obp-c/common/cbootblk.h
rename : usr/src/psm/stand/bootblks/obp-c/common/makevers.sh => deleted_files/usr/src/psm/stand/bootblks/obp-c/common/makevers.sh
rename : usr/src/psm/stand/bootblks/obp-c/common/mkboot.c => deleted_files/usr/src/psm/stand/bootblks/obp-c/common/mkboot.c
rename : usr/src/psm/stand/bootblks/obp-c/common/romp.h => deleted_files/usr/src/psm/stand/bootblks/obp-c/common/romp.h
rename : usr/src/psm/stand/bootblks/obp-c/common/stub.c => deleted_files/usr/src/psm/stand/bootblks/obp-c/common/stub.c
rename : usr/src/psm/stand/bootblks/obp-c/common/unix_devio.c => deleted_files/usr/src/psm/stand/bootblks/obp-c/common/unix_devio.c
rename : usr/src/psm/stand/bootblks/obp-c/sparc/common/mapfile => deleted_files/usr/src/psm/stand/bootblks/obp-c/sparc/common/mapfile
rename : usr/src/psm/stand/bootblks/obp-c/sparc/common/obp_srt0.s => deleted_files/usr/src/psm/stand/bootblks/obp-c/sparc/common/obp_srt0.s
rename : usr/src/psm/stand/bootblks/ufs/common/Makefile.com => deleted_files/usr/src/psm/stand/bootblks/ufs/common/Makefile.com
rename : usr/src/psm/stand/bootblks/ufs/common/boot_1275.fth => deleted_files/usr/src/psm/stand/bootblks/ufs/common/boot_1275.fth
rename : usr/src/psm/stand/bootblks/ufs/common/boot_obp.fth => deleted_files/usr/src/psm/stand/bootblks/ufs/common/boot_obp.fth
rename : usr/src/psm/stand/bootblks/ufs/common/iob.h => deleted_files/usr/src/psm/stand/bootblks/ufs/common/iob.h
rename : usr/src/psm/stand/bootblks/ufs/common/ufs.c => deleted_files/usr/src/psm/stand/bootblks/ufs/common/ufs.c
rename : usr/src/psm/stand/bootblks/ufs/sparc/sun4c/Makefile => deleted_files/usr/src/psm/stand/bootblks/ufs/sparc/sun4c/Makefile
rename : usr/src/psm/stand/bootblks/ufs/sparc/sun4d/Makefile => deleted_files/usr/src/psm/stand/bootblks/ufs/sparc/sun4d/Makefile
rename : usr/src/psm/stand/bootblks/ufs/sparc/sun4m/Makefile => deleted_files/usr/src/psm/stand/bootblks/ufs/sparc/sun4m/Makefile
rename : usr/src/psm/stand/bootblks/ufs/sparc/unix/Makefile => deleted_files/usr/src/psm/stand/bootblks/ufs/sparc/unix/Makefile
rename : usr/src/uts/sparc/krtld/Makefile => deleted_files/usr/src/uts/sparc/krtld/Makefile
rename : usr/src/uts/sparc/krtld/kobj_alloc.c => deleted_files/usr/src/uts/sparc/krtld/kobj_alloc.c
rename : usr/src/uts/sparc/krtld/kobj_boot.c => deleted_files/usr/src/uts/sparc/krtld/kobj_boot.c
rename : usr/src/uts/sparc/krtld/kobj_crt.s => deleted_files/usr/src/uts/sparc/krtld/kobj_crt.s
rename : usr/src/cmd/boot/bootadm/filelist.ramdisk => usr/src/cmd/boot/filelist/i386/filelist.ramdisk
rename : usr/src/cmd/boot/bootadm/filelist.safe => usr/src/cmd/boot/filelist/i386/filelist.safe
246 files changed, 11400 insertions, 4627 deletions
diff --git a/usr/src/psm/stand/boot/sparc/common/boot.c b/deleted_files/usr/src/psm/stand/boot/sparc/common/boot.c index acfbad580b..acfbad580b 100644 --- a/usr/src/psm/stand/boot/sparc/common/boot.c +++ b/deleted_files/usr/src/psm/stand/boot/sparc/common/boot.c diff --git a/usr/src/psm/stand/boot/sparc/common/boot_services.c b/deleted_files/usr/src/psm/stand/boot/sparc/common/boot_services.c index 16a7acaebe..16a7acaebe 100644 --- a/usr/src/psm/stand/boot/sparc/common/boot_services.c +++ b/deleted_files/usr/src/psm/stand/boot/sparc/common/boot_services.c diff --git a/usr/src/psm/stand/boot/sparc/common/hsfsconf.c b/deleted_files/usr/src/psm/stand/boot/sparc/common/hsfsconf.c index 2f71220391..2f71220391 100644 --- a/usr/src/psm/stand/boot/sparc/common/hsfsconf.c +++ b/deleted_files/usr/src/psm/stand/boot/sparc/common/hsfsconf.c diff --git a/usr/src/psm/stand/boot/sparc/common/ufsconf.c b/deleted_files/usr/src/psm/stand/boot/sparc/common/ufsconf.c index 5d0195e5f3..5d0195e5f3 100644 --- a/usr/src/psm/stand/boot/sparc/common/ufsconf.c +++ b/deleted_files/usr/src/psm/stand/boot/sparc/common/ufsconf.c diff --git a/usr/src/psm/stand/bootblks/Makefile.obp b/deleted_files/usr/src/psm/stand/bootblks/Makefile.obp index 4572164d4b..4572164d4b 100644 --- a/usr/src/psm/stand/bootblks/Makefile.obp +++ b/deleted_files/usr/src/psm/stand/bootblks/Makefile.obp diff --git a/usr/src/psm/stand/bootblks/hsfs/common/Makefile.com b/deleted_files/usr/src/psm/stand/bootblks/hsfs/common/Makefile.com index 26b9823359..26b9823359 100644 --- a/usr/src/psm/stand/bootblks/hsfs/common/Makefile.com +++ b/deleted_files/usr/src/psm/stand/bootblks/hsfs/common/Makefile.com diff --git a/usr/src/psm/stand/bootblks/hsfs/common/boot_obp.fth b/deleted_files/usr/src/psm/stand/bootblks/hsfs/common/boot_obp.fth index 3ab085f7ba..3ab085f7ba 100644 --- a/usr/src/psm/stand/bootblks/hsfs/common/boot_obp.fth +++ b/deleted_files/usr/src/psm/stand/bootblks/hsfs/common/boot_obp.fth diff --git a/usr/src/psm/stand/bootblks/hsfs/common/hsfs.c b/deleted_files/usr/src/psm/stand/bootblks/hsfs/common/hsfs.c index 2ff62f6c24..2ff62f6c24 100644 --- a/usr/src/psm/stand/bootblks/hsfs/common/hsfs.c +++ b/deleted_files/usr/src/psm/stand/bootblks/hsfs/common/hsfs.c diff --git a/usr/src/psm/stand/bootblks/hsfs/common/hsfs_sig.h b/deleted_files/usr/src/psm/stand/bootblks/hsfs/common/hsfs_sig.h index 2b18abe8e7..2b18abe8e7 100644 --- a/usr/src/psm/stand/bootblks/hsfs/common/hsfs_sig.h +++ b/deleted_files/usr/src/psm/stand/bootblks/hsfs/common/hsfs_sig.h diff --git a/usr/src/psm/stand/bootblks/hsfs/common/hsfs_small.c b/deleted_files/usr/src/psm/stand/bootblks/hsfs/common/hsfs_small.c index b89892eafd..b89892eafd 100644 --- a/usr/src/psm/stand/bootblks/hsfs/common/hsfs_small.c +++ b/deleted_files/usr/src/psm/stand/bootblks/hsfs/common/hsfs_small.c diff --git a/usr/src/psm/stand/bootblks/hsfs/common/iob.h b/deleted_files/usr/src/psm/stand/bootblks/hsfs/common/iob.h index 844f1152fb..844f1152fb 100644 --- a/usr/src/psm/stand/bootblks/hsfs/common/iob.h +++ b/deleted_files/usr/src/psm/stand/bootblks/hsfs/common/iob.h diff --git a/usr/src/psm/stand/bootblks/hsfs/sparc/unix/Makefile b/deleted_files/usr/src/psm/stand/bootblks/hsfs/sparc/unix/Makefile index 8aa0b74787..8aa0b74787 100644 --- a/usr/src/psm/stand/bootblks/hsfs/sparc/unix/Makefile +++ b/deleted_files/usr/src/psm/stand/bootblks/hsfs/sparc/unix/Makefile diff --git a/usr/src/psm/stand/bootblks/obp-c/Makefile.rules b/deleted_files/usr/src/psm/stand/bootblks/obp-c/Makefile.rules index b320f564ac..b320f564ac 100644 --- a/usr/src/psm/stand/bootblks/obp-c/Makefile.rules +++ b/deleted_files/usr/src/psm/stand/bootblks/obp-c/Makefile.rules diff --git a/usr/src/psm/stand/bootblks/obp-c/Makefile.targ b/deleted_files/usr/src/psm/stand/bootblks/obp-c/Makefile.targ index 5644b688c1..5644b688c1 100644 --- a/usr/src/psm/stand/bootblks/obp-c/Makefile.targ +++ b/deleted_files/usr/src/psm/stand/bootblks/obp-c/Makefile.targ diff --git a/usr/src/psm/stand/bootblks/obp-c/common/cbootblk.h b/deleted_files/usr/src/psm/stand/bootblks/obp-c/common/cbootblk.h index 7a0565e88c..7a0565e88c 100644 --- a/usr/src/psm/stand/bootblks/obp-c/common/cbootblk.h +++ b/deleted_files/usr/src/psm/stand/bootblks/obp-c/common/cbootblk.h diff --git a/usr/src/psm/stand/bootblks/obp-c/common/makevers.sh b/deleted_files/usr/src/psm/stand/bootblks/obp-c/common/makevers.sh index 4665376d29..4665376d29 100644 --- a/usr/src/psm/stand/bootblks/obp-c/common/makevers.sh +++ b/deleted_files/usr/src/psm/stand/bootblks/obp-c/common/makevers.sh diff --git a/usr/src/psm/stand/bootblks/obp-c/common/mkboot.c b/deleted_files/usr/src/psm/stand/bootblks/obp-c/common/mkboot.c index 5f2f058723..5f2f058723 100644 --- a/usr/src/psm/stand/bootblks/obp-c/common/mkboot.c +++ b/deleted_files/usr/src/psm/stand/bootblks/obp-c/common/mkboot.c diff --git a/usr/src/psm/stand/bootblks/obp-c/common/romp.h b/deleted_files/usr/src/psm/stand/bootblks/obp-c/common/romp.h index 999564996d..999564996d 100644 --- a/usr/src/psm/stand/bootblks/obp-c/common/romp.h +++ b/deleted_files/usr/src/psm/stand/bootblks/obp-c/common/romp.h diff --git a/usr/src/psm/stand/bootblks/obp-c/common/stub.c b/deleted_files/usr/src/psm/stand/bootblks/obp-c/common/stub.c index 13b204597b..13b204597b 100644 --- a/usr/src/psm/stand/bootblks/obp-c/common/stub.c +++ b/deleted_files/usr/src/psm/stand/bootblks/obp-c/common/stub.c diff --git a/usr/src/psm/stand/bootblks/obp-c/common/unix_devio.c b/deleted_files/usr/src/psm/stand/bootblks/obp-c/common/unix_devio.c index b1399b9ccd..b1399b9ccd 100644 --- a/usr/src/psm/stand/bootblks/obp-c/common/unix_devio.c +++ b/deleted_files/usr/src/psm/stand/bootblks/obp-c/common/unix_devio.c diff --git a/usr/src/psm/stand/bootblks/obp-c/sparc/common/mapfile b/deleted_files/usr/src/psm/stand/bootblks/obp-c/sparc/common/mapfile index 5a96e9e689..5a96e9e689 100644 --- a/usr/src/psm/stand/bootblks/obp-c/sparc/common/mapfile +++ b/deleted_files/usr/src/psm/stand/bootblks/obp-c/sparc/common/mapfile diff --git a/usr/src/psm/stand/bootblks/obp-c/sparc/common/obp_srt0.s b/deleted_files/usr/src/psm/stand/bootblks/obp-c/sparc/common/obp_srt0.s index e2d36ca37a..e2d36ca37a 100644 --- a/usr/src/psm/stand/bootblks/obp-c/sparc/common/obp_srt0.s +++ b/deleted_files/usr/src/psm/stand/bootblks/obp-c/sparc/common/obp_srt0.s diff --git a/usr/src/psm/stand/bootblks/ufs/common/Makefile.com b/deleted_files/usr/src/psm/stand/bootblks/ufs/common/Makefile.com index b759d5cf8f..b759d5cf8f 100644 --- a/usr/src/psm/stand/bootblks/ufs/common/Makefile.com +++ b/deleted_files/usr/src/psm/stand/bootblks/ufs/common/Makefile.com diff --git a/usr/src/psm/stand/bootblks/ufs/common/boot_1275.fth b/deleted_files/usr/src/psm/stand/bootblks/ufs/common/boot_1275.fth index 8d0fe85209..8d0fe85209 100644 --- a/usr/src/psm/stand/bootblks/ufs/common/boot_1275.fth +++ b/deleted_files/usr/src/psm/stand/bootblks/ufs/common/boot_1275.fth diff --git a/usr/src/psm/stand/bootblks/ufs/common/boot_obp.fth b/deleted_files/usr/src/psm/stand/bootblks/ufs/common/boot_obp.fth index 9714b61f56..9714b61f56 100644 --- a/usr/src/psm/stand/bootblks/ufs/common/boot_obp.fth +++ b/deleted_files/usr/src/psm/stand/bootblks/ufs/common/boot_obp.fth diff --git a/usr/src/psm/stand/bootblks/ufs/common/iob.h b/deleted_files/usr/src/psm/stand/bootblks/ufs/common/iob.h index 7797839b4a..7797839b4a 100644 --- a/usr/src/psm/stand/bootblks/ufs/common/iob.h +++ b/deleted_files/usr/src/psm/stand/bootblks/ufs/common/iob.h diff --git a/usr/src/psm/stand/bootblks/ufs/common/ufs.c b/deleted_files/usr/src/psm/stand/bootblks/ufs/common/ufs.c index 0d1f0f0540..0d1f0f0540 100644 --- a/usr/src/psm/stand/bootblks/ufs/common/ufs.c +++ b/deleted_files/usr/src/psm/stand/bootblks/ufs/common/ufs.c diff --git a/usr/src/psm/stand/bootblks/ufs/sparc/sun4c/Makefile b/deleted_files/usr/src/psm/stand/bootblks/ufs/sparc/sun4c/Makefile index e177bae10b..e177bae10b 100644 --- a/usr/src/psm/stand/bootblks/ufs/sparc/sun4c/Makefile +++ b/deleted_files/usr/src/psm/stand/bootblks/ufs/sparc/sun4c/Makefile diff --git a/usr/src/psm/stand/bootblks/ufs/sparc/sun4d/Makefile b/deleted_files/usr/src/psm/stand/bootblks/ufs/sparc/sun4d/Makefile index abb8f28aec..abb8f28aec 100644 --- a/usr/src/psm/stand/bootblks/ufs/sparc/sun4d/Makefile +++ b/deleted_files/usr/src/psm/stand/bootblks/ufs/sparc/sun4d/Makefile diff --git a/usr/src/psm/stand/bootblks/ufs/sparc/sun4m/Makefile b/deleted_files/usr/src/psm/stand/bootblks/ufs/sparc/sun4m/Makefile index 5177d46a29..5177d46a29 100644 --- a/usr/src/psm/stand/bootblks/ufs/sparc/sun4m/Makefile +++ b/deleted_files/usr/src/psm/stand/bootblks/ufs/sparc/sun4m/Makefile diff --git a/usr/src/psm/stand/bootblks/ufs/sparc/unix/Makefile b/deleted_files/usr/src/psm/stand/bootblks/ufs/sparc/unix/Makefile index ae83da4aea..ae83da4aea 100644 --- a/usr/src/psm/stand/bootblks/ufs/sparc/unix/Makefile +++ b/deleted_files/usr/src/psm/stand/bootblks/ufs/sparc/unix/Makefile diff --git a/usr/src/uts/sparc/krtld/Makefile b/deleted_files/usr/src/uts/sparc/krtld/Makefile index e6e2e44b90..e6e2e44b90 100644 --- a/usr/src/uts/sparc/krtld/Makefile +++ b/deleted_files/usr/src/uts/sparc/krtld/Makefile diff --git a/usr/src/uts/sparc/krtld/kobj_alloc.c b/deleted_files/usr/src/uts/sparc/krtld/kobj_alloc.c index ab179e267f..ab179e267f 100644 --- a/usr/src/uts/sparc/krtld/kobj_alloc.c +++ b/deleted_files/usr/src/uts/sparc/krtld/kobj_alloc.c diff --git a/usr/src/uts/sparc/krtld/kobj_boot.c b/deleted_files/usr/src/uts/sparc/krtld/kobj_boot.c index 014e198efd..014e198efd 100644 --- a/usr/src/uts/sparc/krtld/kobj_boot.c +++ b/deleted_files/usr/src/uts/sparc/krtld/kobj_boot.c diff --git a/usr/src/uts/sparc/krtld/kobj_crt.s b/deleted_files/usr/src/uts/sparc/krtld/kobj_crt.s index f1accdb3e2..f1accdb3e2 100644 --- a/usr/src/uts/sparc/krtld/kobj_crt.s +++ b/deleted_files/usr/src/uts/sparc/krtld/kobj_crt.s diff --git a/usr/src/Makefile.psm b/usr/src/Makefile.psm index 4ade958609..79f451df40 100644 --- a/usr/src/Makefile.psm +++ b/usr/src/Makefile.psm @@ -139,6 +139,7 @@ USR_PSM_LIB_FS_DIR = $(USR_PSM_LIB_DIR)/fs USR_PSM_LIB_UFS_DIR = $(USR_PSM_LIB_FS_DIR)/ufs USR_PSM_LIB_NFS_DIR = $(USR_PSM_LIB_FS_DIR)/nfs USR_PSM_LIB_HSFS_DIR = $(USR_PSM_LIB_FS_DIR)/hsfs +USR_PSM_LIB_ZFS_DIR = $(USR_PSM_LIB_FS_DIR)/zfs USR_PSM_DRV_DIR_32 = $(USR_PSM_MOD_DIR)/drv USR_PSM_EXEC_DIR_32 = $(USR_PSM_MOD_DIR)/exec diff --git a/usr/src/Makefile.psm.targ b/usr/src/Makefile.psm.targ index 4570a118dc..5c23e3ca43 100644 --- a/usr/src/Makefile.psm.targ +++ b/usr/src/Makefile.psm.targ @@ -133,7 +133,8 @@ $(USR_PSM_LIB_FS_DIR): $(USR_PSM_LIB_DIR) $(LINKED_LIB_FS_DIRS) $(USR_PSM_LIB_UFS_DIR) \ $(USR_PSM_LIB_NFS_DIR) \ -$(USR_PSM_LIB_HSFS_DIR): $(USR_PSM_LIB_FS_DIR) +$(USR_PSM_LIB_HSFS_DIR) \ +$(USR_PSM_LIB_ZFS_DIR): $(USR_PSM_LIB_FS_DIR) -$(INS.dir.root.bin) $(USR_PSM_MOD_DIR): $(USR_PSM_DIR) @@ -173,6 +174,9 @@ $(USR_PSM_LIB_NFS_DIR)/%: % $(USR_PSM_LIB_NFS_DIR) $(USR_PSM_LIB_HSFS_DIR)/%: % $(USR_PSM_LIB_HSFS_DIR) $(INS.file) +$(USR_PSM_LIB_ZFS_DIR)/%: % $(USR_PSM_LIB_ZFS_DIR) + $(INS.file) + $(USR_PSM_MOD_DIR)/%: % $(USR_PSM_MOD_DIR) $(INS.file) diff --git a/usr/src/Targetdirs b/usr/src/Targetdirs index a281b3ba1a..8ae894cab2 100644 --- a/usr/src/Targetdirs +++ b/usr/src/Targetdirs @@ -48,18 +48,18 @@ $(BUILD64) SYMLINKS += $(SYM.ROOT.BIN64) $(SYM.ROOT.SFW64) TARGETDIRS += $(SYMLINKS) i386_ROOT.SYS= \ - /boot \ /boot/acpi \ /boot/acpi/tables \ /boot/grub \ /boot/grub/bin \ - /boot/solaris \ - /boot/solaris/bin \ /platform/i86pc sparc_ROOT.SYS= ROOT.SYS= \ + /boot \ + /boot/solaris \ + /boot/solaris/bin \ $($(MACH)_ROOT.SYS) \ /dev \ /dev/dsk \ diff --git a/usr/src/cmd/boot/Makefile b/usr/src/cmd/boot/Makefile index 51b1ebf3d8..31945e80f1 100644 --- a/usr/src/cmd/boot/Makefile +++ b/usr/src/cmd/boot/Makefile @@ -25,11 +25,12 @@ #ident "%Z%%M% %I% %E% SMI" # -include ../Makefile.cmd +include $(SRC)/cmd/Makefile.cmd .PARALLEL: COMMON_SUBDIRS= \ + filelist \ scripts \ bootadm @@ -38,7 +39,8 @@ i386_SUBDIRS= \ mbr \ symdef -sparc_SUBDIRS= +sparc_SUBDIRS= \ + fiocompress COMMON_LINTSUBDIRS= \ bootadm @@ -47,7 +49,8 @@ i386_LINTSUBDIRS= \ installgrub \ symdef -sparc_LINTSUBDIRS= +sparc_LINTSUBDIRS= \ + fiocompress COMMON_MSGSUBDIRS= \ bootadm @@ -55,7 +58,9 @@ COMMON_MSGSUBDIRS= \ i386_MSGSUBDIRS= \ installgrub -sparc_MSGSUBDIRS= +sparc_MSGSUBDIRS= \ + fiocompress + all:= TARGET= all install:= TARGET= install diff --git a/usr/src/cmd/boot/Makefile.com b/usr/src/cmd/boot/Makefile.com index 885a829995..c0a9a0e880 100644 --- a/usr/src/cmd/boot/Makefile.com +++ b/usr/src/cmd/boot/Makefile.com @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,13 +19,13 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" # -include ../../Makefile.cmd +include $(SRC)/cmd/Makefile.cmd CFLAGS += $(CCVERBOSE) @@ -34,8 +33,18 @@ ROOTBOOT= $(ROOT)/boot ROOTBOOTSOLARIS= $(ROOTBOOT)/solaris ROOTBOOTSOLARISBIN= $(ROOTBOOTSOLARIS)/bin -ROOTBOOTSOLARISBINPROG= $(PROG:%=$(ROOTBOOTSOLARISBIN)/%) +ROOTBOOTSOLARISBINPROG= $(BOOTPROG:%=$(ROOTBOOTSOLARISBIN)/%) $(ROOTBOOTSOLARISBINPROG) := OWNER= root $(ROOTBOOTSOLARISBINPROG) := GROUP= bin $(ROOTBOOTSOLARISBINPROG) := FILEMODE= 0555 + +ROOTBOOTSOLARISDATA= $(DATA:%=$(ROOTBOOTSOLARIS)/%) + +$(ROOTBOOTSOLARISDATA) := OWNER= root +$(ROOTBOOTSOLARISDATA) := GROUP= sys +$(ROOTBOOTSOLARISDATA) := FILEMODE= 0644 + +ROOTUSRSBINLINKS= $(SBINLINKS:%=$(ROOTUSRSBIN)/%) + +ROOTBOOTSOLARISBINLINKS= $(SBINLINKS:%=$(ROOTBOOTSOLARISBIN)/%) diff --git a/usr/src/cmd/boot/Makefile.targ b/usr/src/cmd/boot/Makefile.targ index ee78f8af05..f802db2730 100644 --- a/usr/src/cmd/boot/Makefile.targ +++ b/usr/src/cmd/boot/Makefile.targ @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -42,4 +41,10 @@ $(ROOTBOOTSOLARIS)/%: % $(ROOTBOOTSOLARISBIN)/%: % $(INS.file) -include ../../Makefile.targ +$(ROOTUSRSBINLINKS): + -$(RM) $@; $(SYMLINK) ../../sbin/$(@F) $@ + +$(ROOTBOOTSOLARISBINLINKS): + $(RM) $@; $(SYMLINK) ../../sbin/$(@F) $@ + +include $(SRC)/cmd/Makefile.targ diff --git a/usr/src/cmd/boot/bootadm/Makefile b/usr/src/cmd/boot/bootadm/Makefile index c077811679..c8ab308730 100644 --- a/usr/src/cmd/boot/bootadm/Makefile +++ b/usr/src/cmd/boot/bootadm/Makefile @@ -27,8 +27,6 @@ PROG= bootadm -i386_DATA= filelist.ramdisk filelist.safe - SBINLINKS= $(PROG) OBJS= bootadm.o bootadm_upgrade.o @@ -36,12 +34,6 @@ SRCS = $(OBJS:.o=.c) include ../Makefile.com -ROOTBOOTSOLARISDATA= $($(MACH)_DATA:%=$(ROOTBOOTSOLARIS)/%) -ROOTUSRSBINLINKS= $(SBINLINKS:%=$(ROOTUSRSBIN)/%) - -$(ROOTBOOTSOLARISDATA) := OWNER = root -$(ROOTBOOTSOLARISDATA) := GROUP = sys -$(ROOTBOOTSOLARISDATA) := FILEMODE = 0644 .KEEP_STATE: @@ -59,10 +51,7 @@ $(PROG): $(OBJS) bootadm.h $(LINK.c) -o $@ $(OBJS) $(LDLIBS) $(POST_PROCESS) -$(ROOTUSRSBINLINKS): - -$(RM) $@; $(SYMLINK) ../../sbin/$(@F) $@ - -install: all $(ROOTSBINPROG) $(ROOTBOOTSOLARISDATA) .WAIT $(ROOTUSRSBINLINKS) +install: all $(ROOTSBINPROG) .WAIT $(ROOTUSRSBINLINKS) clean: -$(RM) $(OBJS) diff --git a/usr/src/cmd/boot/bootadm/bootadm.c b/usr/src/cmd/boot/bootadm/bootadm.c index 2ebc4e1b1e..ce2e154314 100644 --- a/usr/src/cmd/boot/bootadm/bootadm.c +++ b/usr/src/cmd/boot/bootadm/bootadm.c @@ -54,7 +54,8 @@ #include <sys/systeminfo.h> #include <sys/dktp/fdisk.h> #include <sys/param.h> -#if defined(__i386) + +#if !defined(_OPB) #include <sys/ucode.h> #endif @@ -108,8 +109,9 @@ typedef struct { #define BAM_LOCK_FILE "/var/run/bootadm.lock" #define LOCK_FILE_PERMS (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) -#define CREATE_RAMDISK "/boot/solaris/bin/create_ramdisk" -#define CREATE_DISKMAP "/boot/solaris/bin/create_diskmap" +#define CREATE_RAMDISK "boot/solaris/bin/create_ramdisk" +#define CREATE_DISKMAP "boot/solaris/bin/create_diskmap" +#define EXTRACT_BOOT_FILELIST "boot/solaris/bin/extract_boot_filelist" #define GRUBDISK_MAP "/var/run/solaris_grubdisk.map" #define GRUB_slice "/etc/lu/GRUB_slice" @@ -201,56 +203,51 @@ static char rootbuf[PATH_MAX] = "/"; static int bam_update_all; /* function prototypes */ -static void parse_args_internal(int argc, char *argv[]); -static void parse_args(int argc, char *argv[]); -static error_t bam_menu(char *subcmd, char *opt, int argc, char *argv[]); -static error_t bam_archive(char *subcmd, char *opt); +static void parse_args_internal(int, char *[]); +static void parse_args(int, char *argv[]); +static error_t bam_menu(char *, char *, int, char *[]); +static error_t bam_archive(char *, char *); -static void bam_print(char *format, ...); -static void bam_exit(int excode); +static void bam_print(char *, ...); +static void bam_exit(int); static void bam_lock(void); static void bam_unlock(void); -static int exec_cmd(char *cmdline, char *output, int64_t osize); -static error_t read_globals(menu_t *mp, char *menu_path, - char *globalcmd, int quiet); - -static menu_t *menu_read(char *menu_path); -static error_t menu_write(char *root, menu_t *mp); -static void linelist_free(line_t *start); -static void menu_free(menu_t *mp); -static void line_free(line_t *lp); -static void filelist_free(filelist_t *flistp); -static error_t list2file(char *root, char *tmp, - char *final, line_t *start); -static error_t list_entry(menu_t *mp, char *menu_path, char *opt); -static error_t delete_all_entries(menu_t *mp, char *menu_path, char *opt); -static error_t update_entry(menu_t *mp, char *root, char *opt); -static error_t update_temp(menu_t *mp, char *root, char *opt); - -static error_t update_archive(char *root, char *opt); -static error_t list_archive(char *root, char *opt); -static error_t update_all(char *root, char *opt); -static error_t read_list(char *root, filelist_t *flistp); -static error_t set_global(menu_t *mp, char *globalcmd, int val); -static error_t set_option(menu_t *mp, char *globalcmd, char *opt); -static error_t set_kernel(menu_t *mp, menu_cmd_t optnum, char *path, - char *buf, size_t bufsize); -static char *expand_path(const char *partial_path); - -static long s_strtol(char *str); -static int s_fputs(char *str, FILE *fp); - -static char *s_strdup(char *str); +static int exec_cmd(char *, filelist_t *); +static error_t read_globals(menu_t *, char *, char *, int); + +static menu_t *menu_read(char *); +static error_t menu_write(char *, menu_t *); +static void linelist_free(line_t *); +static void menu_free(menu_t *); +static void line_free(line_t *); +static void filelist_free(filelist_t *); +static error_t list2file(char *, char *, char *, line_t *); +static error_t list_entry(menu_t *, char *, char *); +static error_t delete_all_entries(menu_t *, char *, char *); +static error_t update_entry(menu_t *, char *, char *); +static error_t update_temp(menu_t *, char *, char *); + +static error_t update_archive(char *, char *); +static error_t list_archive(char *, char *); +static error_t update_all(char *, char *); +static error_t read_list(char *, filelist_t *); +static error_t set_global(menu_t *, char *, int); +static error_t set_option(menu_t *, char *, char *); +static error_t set_kernel(menu_t *, menu_cmd_t, char *, char *, size_t); +static char *expand_path(const char *); + +static long s_strtol(char *); +static int s_fputs(char *, FILE *); + +static char *s_strdup(char *); static int is_readonly(char *); static int is_amd64(void); +static int is_sun4u(void); +static int is_sun4v(void); static void append_to_flist(filelist_t *, char *); -#if defined(__sparc) -static void sparc_abort(void); -#endif - -#if defined(__i386) +#if !defined(_OPB) static void ucode_install(); #endif @@ -298,7 +295,7 @@ usage(void) (void) fprintf(stderr, "\t%s update-archive [-vn] [-R altroot]\n", prog); (void) fprintf(stderr, "\t%s list-archive [-R altroot]\n", prog); -#ifndef __sparc +#if !defined(_OPB) /* x86 only */ (void) fprintf(stderr, "\t%s set-menu [-R altroot] key=value\n", prog); (void) fprintf(stderr, "\t%s list-menu [-R altroot]\n", prog); @@ -327,21 +324,6 @@ main(int argc, char *argv[]) parse_args(argc, argv); -#if defined(__sparc) - /* - * There are only two valid invocations of bootadm - * on SPARC: - * - * - SPARC diskless server creating boot_archive for i386 clients - * - archive creation call during reboot of a SPARC system - * - * The latter should be a NOP - */ - if (bam_cmd != BAM_ARCHIVE) { - sparc_abort(); - } -#endif - switch (bam_cmd) { case BAM_MENU: ret = bam_menu(bam_subcmd, bam_opt, bam_argc, bam_argv); @@ -361,17 +343,6 @@ main(int argc, char *argv[]) return (0); } -#if defined(__sparc) - -static void -sparc_abort(void) -{ - bam_error(NOT_ON_SPARC); - bam_exit(1); -} - -#endif - /* * Equivalence of public and internal commands: * update-archive -- -a update @@ -738,7 +709,7 @@ mount_grub_slice(int *mnted, char **physlice, char **logslice, char **fs_type) (void) snprintf(cmd, sizeof (cmd), "/sbin/mount -F %s %s %s", fstype, dev, mntpt); - if (exec_cmd(cmd, NULL, 0) != 0) { + if (exec_cmd(cmd, NULL) != 0) { bam_error(MOUNT_FAILED, dev, fstype); if (rmdir(mntpt) != 0) { bam_error(RMDIR_FAILED, mntpt, strerror(errno)); @@ -791,7 +762,7 @@ umount_grub_slice( if (mnted) { (void) snprintf(cmd, sizeof (cmd), "/sbin/umount %s", mntpt); - if (exec_cmd(cmd, NULL, 0) != 0) { + if (exec_cmd(cmd, NULL) != 0) { bam_error(UMOUNT_FAILED, mntpt); } if (rmdir(mntpt) != 0) { @@ -853,7 +824,7 @@ use_stubboot(void) */ (void) snprintf(cmd, sizeof (cmd), "/sbin/mount %s", STUBBOOT); - if (exec_cmd(cmd, NULL, 0) != 0) { + if (exec_cmd(cmd, NULL) != 0) { bam_error(MOUNT_MNTPT_FAILED, STUBBOOT); return (NULL); } @@ -908,6 +879,16 @@ bam_menu(char *subcmd, char *opt, int largc, char *largv[]) struct stat sb; int mnted; /* set if we did a mount */ error_t (*f)(menu_t *mp, char *menu_path, char *opt); + char *rootpath; + + /* + * Menu sub-command only applies to GRUB (i.e. x86) + */ + rootpath = (bam_alt_root) ? bam_root : "/"; + if (!is_grub((const char *)rootpath)) { + bam_error(NOT_ON_SPARC); + return (BAM_ERROR); + } /* * Check arguments @@ -1033,16 +1014,6 @@ bam_archive( return (BAM_ERROR); } -#if defined(__sparc) - /* - * A NOP if called on SPARC during reboot - */ - if (strcmp(subcmd, "update_all") == 0) - return (BAM_SUCCESS); - else if (strcmp(subcmd, "update") != 0) - sparc_abort(); -#endif - ret = dboot_or_multiboot(rootbuf); if (ret != BAM_SUCCESS) return (ret); @@ -1060,7 +1031,7 @@ bam_archive( if (strcmp(subcmd, "update_all") == 0) bam_update_all = 1; -#if defined(__i386) +#if !defined(_OPB) ucode_install(bam_root); #endif @@ -1496,24 +1467,34 @@ check_flags_and_files(char *root) /* * If archive is missing, create archive */ - (void) snprintf(path, sizeof (path), "%s%s", root, - DIRECT_BOOT_ARCHIVE_32); + + if (is_sun4u()) + (void) snprintf(path, sizeof (path), "%s%s", root, + SUN4U__ARCHIVE); + else if (is_sun4v()) + (void) snprintf(path, sizeof (path), "%s%s", root, + SUN4V__ARCHIVE); + else { + if (bam_direct == BAM_DIRECT_DBOOT) { + (void) snprintf(path, sizeof (path), "%s%s", root, + DIRECT_BOOT_ARCHIVE_64); + if (stat(path, &sb) != 0) { + if (bam_verbose && !bam_check) + bam_print(UPDATE_ARCH_MISS, path); + walk_arg.need_update = 1; + return; + } + } + (void) snprintf(path, sizeof (path), "%s%s", root, + DIRECT_BOOT_ARCHIVE_32); + } + if (stat(path, &sb) != 0) { if (bam_verbose && !bam_check) bam_print(UPDATE_ARCH_MISS, path); walk_arg.need_update = 1; return; } - if (bam_direct == BAM_DIRECT_DBOOT) { - (void) snprintf(path, sizeof (path), "%s%s", root, - DIRECT_BOOT_ARCHIVE_64); - if (stat(path, &sb) != 0) { - if (bam_verbose && !bam_check) - bam_print(UPDATE_ARCH_MISS, path); - walk_arg.need_update = 1; - return; - } - } } static error_t @@ -1547,17 +1528,55 @@ read_one_list(char *root, filelist_t *flistp, char *filelist) static error_t read_list(char *root, filelist_t *flistp) { - int rval; + char path[PATH_MAX]; + char cmd[PATH_MAX]; + struct stat sb; + int n, rval; flistp->head = flistp->tail = NULL; /* - * Read current lists of files - only the first is mandatory + * build and check path to extract_boot_filelist.ksh */ - rval = read_one_list(root, flistp, BOOT_FILE_LIST); - if (rval != BAM_SUCCESS) - return (rval); - (void) read_one_list(root, flistp, ETC_FILE_LIST); + n = snprintf(path, sizeof (path), "%s%s", root, EXTRACT_BOOT_FILELIST); + if (n >= sizeof (path)) { + bam_error(NO_FLIST); + return (BAM_ERROR); + } + + /* + * If extract_boot_filelist is present, exec it, otherwise read + * the filelists directly, for compatibility with older images. + */ + if (stat(path, &sb) == 0) { + /* + * build arguments to exec extract_boot_filelist.ksh + */ + if (strlen(root) > 1) { + n = snprintf(cmd, sizeof (cmd), "%s -R %s /%s /%s", + path, root, BOOT_FILE_LIST, ETC_FILE_LIST); + } else { + n = snprintf(cmd, sizeof (cmd), "%s /%s /%s", + path, BOOT_FILE_LIST, ETC_FILE_LIST); + } + if (n >= sizeof (cmd)) { + bam_error(NO_FLIST); + return (BAM_ERROR); + } + if (exec_cmd(cmd, flistp) != 0) { + if (bam_debug) + bam_error(FLIST_FAIL, path, strerror(errno)); + return (BAM_ERROR); + } + } else { + /* + * Read current lists of files - only the first is mandatory + */ + rval = read_one_list(root, flistp, BOOT_FILE_LIST); + if (rval != BAM_SUCCESS) + return (rval); + (void) read_one_list(root, flistp, ETC_FILE_LIST); + } if (flistp->head == NULL) { bam_error(NO_FLIST); @@ -1678,9 +1697,14 @@ walk_list(char *root, filelist_t *flistp) line_t *lp; for (lp = flistp->head; lp; lp = lp->next) { + /* + * Don't follow symlinks. A symlink must refer to + * a file that would appear in the archive through + * a direct reference. This matches the archive + * construction behavior. + */ (void) snprintf(path, sizeof (path), "%s%s", root, lp->line); - /* XXX shouldn't we use FTW_MOUNT ? */ - if (nftw(path, cmpstat, 20, 0) == -1) { + if (nftw(path, cmpstat, 20, FTW_PHYS) == -1) { /* * Some files may not exist. * For example: etc/rtc_config on a x86 diskless system @@ -1849,15 +1873,6 @@ update_required(char *root) return (0); } - /* - * At this point we need an update - so save new stat data - * However, if only checking (-n), don't save new stat data. - */ - if (!bam_check) - savenew(root); - - clear_walk_args(); - return (1); } @@ -1871,7 +1886,7 @@ create_ramdisk(char *root) /* * Setup command args for create_ramdisk.ksh */ - (void) snprintf(path, sizeof (path), "%s%s", root, CREATE_RAMDISK); + (void) snprintf(path, sizeof (path), "%s/%s", root, CREATE_RAMDISK); if (stat(path, &sb) != 0) { bam_error(ARCH_EXEC_MISS, path, strerror(errno)); return (BAM_ERROR); @@ -1887,7 +1902,7 @@ create_ramdisk(char *root) } else (void) snprintf(cmdline, len, "%s", path); - if (exec_cmd(cmdline, NULL, 0) != 0) { + if (exec_cmd(cmdline, NULL) != 0) { bam_error(ARCHIVE_FAIL, cmdline); free(cmdline); return (BAM_ERROR); @@ -1895,22 +1910,10 @@ create_ramdisk(char *root) free(cmdline); /* - * Verify that the archive has been created + * The existence of the expected archives used to be + * verified here. This check is done in create_ramdisk as + * it needs to be in sync with the altroot operated upon. */ - (void) snprintf(path, sizeof (path), "%s%s", root, - DIRECT_BOOT_ARCHIVE_32); - if (stat(path, &sb) != 0) { - bam_error(ARCHIVE_NOT_CREATED, path); - return (BAM_ERROR); - } - if (bam_direct == BAM_DIRECT_DBOOT) { - (void) snprintf(path, sizeof (path), "%s%s", root, - DIRECT_BOOT_ARCHIVE_64); - if (stat(path, &sb) != 0) { - bam_error(ARCHIVE_NOT_CREATED, path); - return (BAM_ERROR); - } - } return (BAM_SUCCESS); } @@ -1986,27 +1989,39 @@ is_ramdisk(char *root) } static int -is_newboot(char *root) +is_boot_archive(char *root) { char path[PATH_MAX]; struct stat sb; /* - * We can't boot without MULTI_BOOT + * We can't create an archive without the create_ramdisk script */ - (void) snprintf(path, sizeof (path), "%s%s", root, MULTI_BOOT); + (void) snprintf(path, sizeof (path), "%s/%s", root, CREATE_RAMDISK); if (stat(path, &sb) == -1) { if (bam_verbose) bam_print(FILE_MISS, path); return (0); } + return (1); +} + +/* + * Need to call this for anything that operates on the GRUB menu + */ +int +is_grub(const char *root) +{ + char path[PATH_MAX]; + struct stat sb; + /* - * We can't generate archive without GRUB_DIR + * GRUB_DIR is required to modify the menu */ (void) snprintf(path, sizeof (path), "%s%s", root, GRUB_DIR); if (stat(path, &sb) == -1) { - if (bam_verbose) + if (bam_debug) bam_print(DIR_MISS, path); return (0); } @@ -2045,10 +2060,9 @@ update_archive(char *root, char *opt) assert(opt == NULL); /* - * root must belong to a GRUB boot OS, - * don't care on sparc except for diskless clients + * root must belong to a boot archive based OS, */ - if (!is_newboot(root)) { + if (!is_boot_archive(root)) { /* * Emit message only if not in context of update_all. * If in update_all, emit only if verbose flag is set. @@ -2103,6 +2117,14 @@ update_archive(char *root, char *opt) /* create the ramdisk */ ret = create_ramdisk(root); } + + /* if the archive is updated, save the new stat data */ + if (ret == 0 && walk_arg.new_nvlp != NULL) { + savenew(root); + } + + clear_walk_args(); + return (ret); } @@ -2120,7 +2142,7 @@ update_fdisk(void) GRUB_fdisk, GRUB_fdisk_target); bam_print(UPDATING_FDISK); - if (exec_cmd(cmd, NULL, 0) != 0) { + if (exec_cmd(cmd, NULL) != 0) { bam_error(FDISK_UPDATE_FAILED); } @@ -2178,7 +2200,7 @@ restore_grub_slice(void) (void) snprintf(cmd, sizeof (cmd), "%s %s %s %s", INSTALLGRUB, STAGE1, STAGE2, physlice); - if (exec_cmd(cmd, NULL, 0) != 0) { + if (exec_cmd(cmd, NULL) != 0) { bam_error(RESTORE_GRUB_FAILED); umount_grub_slice(mnted, mntpt, physlice, NULL, NULL); return; @@ -2194,7 +2216,7 @@ restore_grub_slice(void) (void) snprintf(cmd, sizeof (cmd), "/bin/cp %s %s", GRUB_backup_menu, menupath); - if (exec_cmd(cmd, NULL, 0) != 0) { + if (exec_cmd(cmd, NULL) != 0) { bam_error(RESTORE_MENU_FAILED, menupath); umount_grub_slice(mnted, mntpt, physlice, NULL, NULL); return; @@ -2211,6 +2233,7 @@ update_all(char *root, char *opt) struct stat sb; FILE *fp; char multibt[PATH_MAX]; + char creatram[PATH_MAX]; error_t ret = BAM_SUCCESS; int ret1, ret2; @@ -2239,7 +2262,7 @@ update_all(char *root, char *opt) } (void) snprintf(multibt, sizeof (multibt), "/sbin/mount -F lofs -o nosub / %s", LOFS_PATCH_MNT); - if (exec_cmd(multibt, NULL, 0) != 0) { + if (exec_cmd(multibt, NULL) != 0) { bam_error(MOUNT_FAILED, LOFS_PATCH_MNT, "lofs"); ret = BAM_ERROR; } @@ -2255,7 +2278,7 @@ update_all(char *root, char *opt) */ (void) snprintf(multibt, sizeof (multibt), "/sbin/umount %s", LOFS_PATCH_MNT); - if (exec_cmd(multibt, NULL, 0) != 0) { + if (exec_cmd(multibt, NULL) != 0) { bam_error(UMOUNT_FAILED, LOFS_PATCH_MNT); ret = BAM_ERROR; } @@ -2292,10 +2315,10 @@ update_all(char *root, char *opt) if (strcmp(mnt.mnt_mountp, "/") == 0) continue; - (void) snprintf(multibt, sizeof (multibt), "%s%s", - mnt.mnt_mountp, MULTI_BOOT); + (void) snprintf(creatram, sizeof (creatram), "%s/%s", + mnt.mnt_mountp, CREATE_RAMDISK); - if (stat(multibt, &sb) == -1) + if (stat(creatram, &sb) == -1) continue; /* @@ -3019,7 +3042,7 @@ open_diskmap(char *root) fp = fopen(GRUBDISK_MAP, "r"); if (fp == NULL) { (void) snprintf(cmd, sizeof (cmd), - "%s%s > /dev/null", root, CREATE_DISKMAP); + "%s/%s > /dev/null", root, CREATE_DISKMAP); (void) system(cmd); fp = fopen(GRUBDISK_MAP, "r"); } @@ -4341,12 +4364,11 @@ menu_free(menu_t *mp) * Any other value indicates an error */ static int -exec_cmd(char *cmdline, char *output, int64_t osize) +exec_cmd(char *cmdline, filelist_t *flistp) { char buf[BUFSIZ]; int ret; FILE *ptr; - size_t len; sigset_t set; void (*disp)(int); @@ -4407,14 +4429,12 @@ exec_cmd(char *cmdline, char *output, int64_t osize) * we can safely reap the exit status of the command * from the value returned by pclose() */ - while (fgets(buf, sizeof (buf), ptr) != NULL) { - /* if (bam_verbose) XXX */ - bam_print(PRINT_NO_NEWLINE, buf); - if (output && osize > 0) { - (void) snprintf(output, osize, "%s", buf); - len = strlen(buf); - output += len; - osize -= len; + while (s_fgets(buf, sizeof (buf), ptr) != NULL) { + if (flistp == NULL) { + /* s_fgets strips newlines, so insert them at the end */ + bam_print(PRINT, buf); + } else { + append_to_flist(flistp, buf); } } @@ -4551,6 +4571,33 @@ is_amd64(void) return (amd64); } +static int +is_sun4u(void) +{ + static int sun4u = 0; + char mbuf[257]; /* from sysinfo(2) manpage */ + + if (sysinfo(SI_MACHINE, mbuf, sizeof (mbuf)) > 0 && + strncmp(mbuf, "sun4u", strlen("sun4u")) == 0) + sun4u = 1; + + return (sun4u); +} + +static int +is_sun4v(void) +{ + static int sun4v = 0; + char mbuf[257]; /* from sysinfo(2) manpage */ + + if (sysinfo(SI_MACHINE, mbuf, sizeof (mbuf)) > 0 && + strncmp(mbuf, "sun4v", strlen("sun4v")) == 0) + sun4v = 1; + + return (sun4v); +} + + static void append_to_flist(filelist_t *flistp, char *s) { @@ -4565,7 +4612,7 @@ append_to_flist(filelist_t *flistp, char *s) flistp->tail = lp; } -#if defined(__i386) +#if !defined(_OPB) UCODE_VENDORS; diff --git a/usr/src/cmd/boot/bootadm/bootadm.h b/usr/src/cmd/boot/bootadm/bootadm.h index 45d99e91ab..3dc4d6d201 100644 --- a/usr/src/cmd/boot/bootadm/bootadm.h +++ b/usr/src/cmd/boot/bootadm/bootadm.h @@ -150,6 +150,7 @@ extern char *get_special(char *); extern char *os_to_grubdisk(char *, int); extern void update_line(line_t *); extern int add_boot_entry(menu_t *, char *, char *, char *, char *, char *); +extern int is_grub(const char *); #define BAM_MAXLINE 8192 @@ -187,6 +188,8 @@ extern int add_boot_entry(menu_t *, char *, char *, char *, char *, char *); #define DIRECT_BOOT_FAILSAFE_LINE DIRECT_BOOT_FAILSAFE_KERNEL " -s" /* Boot archives */ +#define SUN4U__ARCHIVE "/platform/sun4u/boot_archive" +#define SUN4V__ARCHIVE "/platform/sun4v/boot_archive" #define DIRECT_BOOT_ARCHIVE "/platform/i86pc/$ISADIR/boot_archive" #define DIRECT_BOOT_ARCHIVE_32 "/platform/i86pc/boot_archive" #define DIRECT_BOOT_ARCHIVE_64 "/platform/i86pc/amd64/boot_archive" diff --git a/usr/src/cmd/boot/bootadm/bootadm_upgrade.c b/usr/src/cmd/boot/bootadm/bootadm_upgrade.c index 7235caf22a..9614cd2c7a 100644 --- a/usr/src/cmd/boot/bootadm/bootadm_upgrade.c +++ b/usr/src/cmd/boot/bootadm/bootadm_upgrade.c @@ -56,6 +56,12 @@ dboot_or_multiboot(const char *root) multiboot_header_t *mbh; struct stat sb; + if (!is_grub(root)) { + /* there is no non dboot sparc new-boot */ + bam_direct = BAM_DIRECT_DBOOT; + return (BAM_SUCCESS); + } + (void) snprintf(fname, PATH_MAX, "%s/%s", root, "platform/i86pc/kernel/unix"); fd = open(fname, O_RDONLY); diff --git a/usr/src/cmd/boot/filelist/Makefile b/usr/src/cmd/boot/filelist/Makefile new file mode 100644 index 0000000000..5b195ceace --- /dev/null +++ b/usr/src/cmd/boot/filelist/Makefile @@ -0,0 +1,46 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +SUBDIRS = $(MACH) + +all := TARGET= all +install := TARGET= install +clean := TARGET= clean +clobber := TARGET= clobber +_msg := TARGET= _msg +lint := TARGET= lint + +.KEEP_STATE: + +install: $(SUBDIRS) + +all clobber clean lint _msg: + +FRC: + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) diff --git a/usr/src/cmd/boot/filelist/Makefile.com b/usr/src/cmd/boot/filelist/Makefile.com new file mode 100644 index 0000000000..b7d0f1f6aa --- /dev/null +++ b/usr/src/cmd/boot/filelist/Makefile.com @@ -0,0 +1,39 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# Common prologue for /boot/solaris filelist generation +# + +# +# filelists +# +DATA= \ + filelist.ramdisk \ + filelist.safe + +include $(SRC)/cmd/boot/Makefile.com diff --git a/usr/src/cmd/boot/filelist/Makefile.targ b/usr/src/cmd/boot/filelist/Makefile.targ new file mode 100644 index 0000000000..1b44feebed --- /dev/null +++ b/usr/src/cmd/boot/filelist/Makefile.targ @@ -0,0 +1,32 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# Common epilogue for /boot/solaris filelist generation +# + +include $(SRC)/cmd/boot/Makefile.targ diff --git a/usr/src/cmd/boot/filelist/i386/Makefile b/usr/src/cmd/boot/filelist/i386/Makefile new file mode 100644 index 0000000000..e9bf8c5c80 --- /dev/null +++ b/usr/src/cmd/boot/filelist/i386/Makefile @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com + +.KEEP_STATE: + +all: + +install: $(ROOTBOOTSOLARISDATA) + +include ../Makefile.targ diff --git a/usr/src/cmd/boot/bootadm/filelist.ramdisk b/usr/src/cmd/boot/filelist/i386/filelist.ramdisk index 83f0df6a16..4029f595dc 100644 --- a/usr/src/cmd/boot/bootadm/filelist.ramdisk +++ b/usr/src/cmd/boot/filelist/i386/filelist.ramdisk @@ -1,23 +1,22 @@ -etc/rtc_config -etc/system -etc/name_to_major -etc/driver_aliases -etc/name_to_sysnum +boot/acpi/tables +boot/solaris/bootenv.rc +boot/solaris/devicedb/master +etc/cluster/nodeid etc/dacf.conf -etc/driver_classes -etc/path_to_inst -etc/mach etc/devices/devid_cache -etc/devices/retire_store -etc/devices/mdi_scsi_vhci_cache etc/devices/mdi_ib_cache -etc/cluster/nodeid +etc/devices/mdi_scsi_vhci_cache +etc/devices/retire_store +etc/driver_aliases +etc/driver_classes +etc/mach +etc/name_to_major +etc/name_to_sysnum +etc/path_to_inst +etc/rtc_config +etc/system kernel -platform/i86pc/biosint platform/i86pc/kernel platform/i86xpv/kernel platform/i86pc/ucode/GenuineIntel platform/i86pc/ucode/AuthenticAMD -boot/solaris/bootenv.rc -boot/solaris/devicedb/master -boot/acpi/tables diff --git a/usr/src/cmd/boot/bootadm/filelist.safe b/usr/src/cmd/boot/filelist/i386/filelist.safe index 7f09ac0da9..7f09ac0da9 100644 --- a/usr/src/cmd/boot/bootadm/filelist.safe +++ b/usr/src/cmd/boot/filelist/i386/filelist.safe diff --git a/usr/src/cmd/boot/filelist/sparc/Makefile b/usr/src/cmd/boot/filelist/sparc/Makefile new file mode 100644 index 0000000000..e9bf8c5c80 --- /dev/null +++ b/usr/src/cmd/boot/filelist/sparc/Makefile @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com + +.KEEP_STATE: + +all: + +install: $(ROOTBOOTSOLARISDATA) + +include ../Makefile.targ diff --git a/usr/src/cmd/boot/filelist/sparc/filelist.ramdisk b/usr/src/cmd/boot/filelist/sparc/filelist.ramdisk new file mode 100644 index 0000000000..aa02810afc --- /dev/null +++ b/usr/src/cmd/boot/filelist/sparc/filelist.ramdisk @@ -0,0 +1,75 @@ +etc/cluster/nodeid +etc/dacf.conf +etc/mach +kernel +platform/SUNW,A70/kernel +platform/SUNW,Netra-210 +platform/SUNW,Netra-210/kernel +platform/SUNW,Netra-240 +platform/SUNW,Netra-240/kernel +platform/SUNW,Netra-440 +platform/SUNW,Netra-440/kernel +platform/SUNW,Netra-CP2300/kernel +platform/SUNW,Netra-CP3010/kernel +platform/SUNW,Netra-CP3060 +platform/SUNW,Netra-CP3060/kernel +platform/SUNW,Netra-CP3260 +platform/SUNW,Netra-T12/kernel +platform/SUNW,Netra-T2000 +platform/SUNW,Netra-T4/kernel +platform/SUNW,Netra-T5220 +platform/SUNW,SPARC-Enterprise-T1000 +platform/SUNW,SPARC-Enterprise-T2000 +platform/SUNW,SPARC-Enterprise-T5120 +platform/SUNW,SPARC-Enterprise-T5220 +platform/SUNW,SPARC-Enterprise/kernel +platform/SUNW,Serverblade1/kernel +platform/SUNW,Sun-Blade-100/kernel +platform/SUNW,Sun-Blade-1000/kernel +platform/SUNW,Sun-Blade-1500/kernel +platform/SUNW,Sun-Blade-2500/kernel +platform/SUNW,Sun-Blade-T6300 +platform/SUNW,Sun-Blade-T6320 +platform/SUNW,Sun-Fire-15000/kernel +platform/SUNW,Sun-Fire-280R/kernel +platform/SUNW,Sun-Fire-480R/kernel +platform/SUNW,Sun-Fire-880/kernel +platform/SUNW,Sun-Fire-T1000 +platform/SUNW,Sun-Fire-T200 +platform/SUNW,Sun-Fire-T200/kernel +platform/SUNW,Sun-Fire-V210 +platform/SUNW,Sun-Fire-V210/kernel +platform/SUNW,Sun-Fire-V215/kernel +platform/SUNW,Sun-Fire-V240/kernel +platform/SUNW,Sun-Fire-V245 +platform/SUNW,Sun-Fire-V245/kernel +platform/SUNW,Sun-Fire-V250/kernel +platform/SUNW,Sun-Fire-V440/kernel +platform/SUNW,Sun-Fire-V445/kernel +platform/SUNW,Sun-Fire-V490 +platform/SUNW,Sun-Fire-V490/kernel +platform/SUNW,Sun-Fire-V890 +platform/SUNW,Sun-Fire-V890/kernel +platform/SUNW,Sun-Fire/kernel +platform/SUNW,T5140 +platform/SUNW,T5240 +platform/SUNW,T5440 +platform/SUNW,USBRDT-5240 +platform/SUNW,Ultra-2 +platform/SUNW,Ultra-250/kernel +platform/SUNW,Ultra-30 +platform/SUNW,Ultra-4/kernel +platform/SUNW,Ultra-5_10/kernel +platform/SUNW,Ultra-60 +platform/SUNW,Ultra-80/kernel +platform/SUNW,Ultra-Enterprise-10000/kernel +platform/SUNW,Ultra-Enterprise/kernel +platform/SUNW,UltraAX-i2/kernel +platform/SUNW,UltraSPARC-IIe-NetraCT-40/kernel +platform/SUNW,UltraSPARC-IIe-NetraCT-60/kernel +platform/SUNW,UltraSPARC-IIi-Netract/kernel +platform/TAD,SPARCLE/kernel +platform/sun4u-opl +platform/sun4u-us3/kernel +platform/sun4u/kernel +platform/sun4v/kernel diff --git a/usr/src/cmd/boot/filelist/sparc/filelist.safe b/usr/src/cmd/boot/filelist/sparc/filelist.safe new file mode 100644 index 0000000000..e648976739 --- /dev/null +++ b/usr/src/cmd/boot/filelist/sparc/filelist.safe @@ -0,0 +1,14 @@ +etc/cluster/nodeid +etc/dacf.conf +etc/devices/devid_cache +etc/devices/mdi_ib_cache +etc/devices/mdi_scsi_vhci_cache +etc/driver_aliases +etc/driver_classes +etc/mach +etc/name_to_major +etc/name_to_sysnum +etc/path_to_inst +etc/rtc_config +etc/system +etc/zfs/zpool.cache diff --git a/usr/src/cmd/boot/fiocompress/Makefile b/usr/src/cmd/boot/fiocompress/Makefile new file mode 100644 index 0000000000..1595b14bec --- /dev/null +++ b/usr/src/cmd/boot/fiocompress/Makefile @@ -0,0 +1,64 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +PROG= fiocompress + +SBINLINKS= $(PROG) + +OBJS= fiocompress.o +SRCS = $(OBJS:.o=.c) + +include ../Makefile.com + +.KEEP_STATE: + +LDLIBS += -lz + +CFLAGS += -I../../../uts/common +LINTFLAGS += -I../../../uts/common + +# definitions for lint +# until libz is compiled against ON header files (uid/gid) +LINTFLAGS += -erroff=E_INCONS_ARG_DECL2 +LINTFLAGS += -erroff=E_INCONS_VAL_TYPE_DECL2 + +all: $(PROG) + +$(PROG): $(OBJS) + $(LINK.c) -o $@ $(OBJS) $(LDLIBS) + $(POST_PROCESS) + +install: all $(ROOTSBINPROG) .WAIT $(ROOTUSRSBINLINKS) + +clean: + -$(RM) $(OBJS) + +_msg: + +lint: lint_SRCS + +include ../Makefile.targ diff --git a/usr/src/cmd/boot/fiocompress/fiocompress.c b/usr/src/cmd/boot/fiocompress/fiocompress.c new file mode 100644 index 0000000000..cef348b158 --- /dev/null +++ b/usr/src/cmd/boot/fiocompress/fiocompress.c @@ -0,0 +1,316 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * fiocompress - a utility to compress files with a filesystem. + * Used to build compressed boot archives to reduce memory + * requirements for booting. + */ + +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <unistd.h> +#include <utility.h> +#include <zlib.h> + +#include <sys/filio.h> +#include <sys/fs/decomp.h> + +#include "message.h" + +static void setup_infile(char *); +static void setup_outfile(char *); +static void do_comp(size_t); +static void do_decomp(void); + +static caddr_t srcaddr; +static size_t srclen; + +static int dstfd; + +static char *srcfile; +static char *dstfile; + + +int +main(int argc, char **argv) +{ + int compress = 0; + int decompress = 0; + int doioc = 0; + size_t blksize = 8192; + char c; + + while ((c = getopt(argc, argv, "mcdb:")) != -1) { + switch (c) { + case 'm': + doioc++; + break; + case 'c': + if (decompress) { + (void) fprintf(stderr, OPT_DC_EXCL); + exit(-1); + } + compress = 1; + break; + case 'd': + if (compress) { + (void) fprintf(stderr, OPT_DC_EXCL); + exit(-1); + } + decompress = 1; + break; + case 'b': + blksize = atoi(optarg); + if (blksize == 0 || (blksize & (blksize-1))) { + (void) fprintf(stderr, INVALID_BLKSZ); + exit(-1); + } + break; + case '?': + (void) fprintf(stderr, UNKNOWN_OPTION, optopt); + exit(-1); + } + } + if (argc - optind != 2) { + (void) fprintf(stderr, MISS_FILES); + exit(-1); + } + + setup_infile(argv[optind]); + setup_outfile(argv[optind + 1]); + + if (decompress) + do_decomp(); + else { + do_comp(blksize); + if (doioc) { + if (ioctl(dstfd, _FIO_COMPRESSED, 0) == -1) { + (void) fprintf(stderr, FIO_COMP_FAIL, + dstfile, strerror(errno)); + exit(-1); + } + } + } + return (0); +} + +static void +setup_infile(char *file) +{ + int fd; + void *addr; + struct stat stbuf; + + srcfile = file; + + fd = open(srcfile, O_RDONLY, 0); + if (fd == -1) { + (void) fprintf(stderr, CANT_OPEN, + srcfile, strerror(errno)); + exit(-1); + } + + if (fstat(fd, &stbuf) == -1) { + (void) fprintf(stderr, STAT_FAIL, + srcfile, strerror(errno)); + exit(-1); + } + srclen = stbuf.st_size; + + addr = mmap(0, srclen, PROT_READ, MAP_SHARED, fd, 0); + if (addr == MAP_FAILED) { + (void) fprintf(stderr, MMAP_FAIL, srcfile, strerror(errno)); + exit(-1); + } + srcaddr = addr; +} + +static void +setup_outfile(char *file) +{ + int fd; + + dstfile = file; + + fd = open(dstfile, O_WRONLY | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (fd == -1) { + (void) fprintf(stderr, OPEN_FAIL, dstfile, strerror(errno)); + exit(-1); + } + dstfd = fd; +} + +static void +do_comp(size_t blksize) +{ + struct comphdr *hdr; + off_t offset; + size_t blks, dstlen, hlen; + void *dstbuf; + int i; + + blks = ((srclen - 1) / blksize) + 1; + hlen = offset = sizeof (struct comphdr) + blks * sizeof (uint64_t); + hdr = malloc(hlen); + if (hdr == NULL) { + (void) fprintf(stderr, HDR_ALLOC, hlen); + exit(-1); + } + + hdr->ch_magic = CH_MAGIC; + hdr->ch_version = CH_VERSION; + hdr->ch_algorithm = CH_ALG_ZLIB; + hdr->ch_fsize = srclen; + hdr->ch_blksize = blksize; + + dstlen = ZMAXBUF(blksize); + dstbuf = malloc(dstlen); + if (dstbuf == NULL) { + (void) fprintf(stderr, BUF_ALLOC, dstlen); + exit(-1); + } + + if (lseek(dstfd, offset, SEEK_SET) == (off_t)-1) { + (void) fprintf(stderr, SEEK_ERR, + offset, dstfile, strerror(errno)); + exit(-1); + } + + for (i = 0; i < blks; i++) { + ulong_t slen, dlen; + int ret; + + hdr->ch_blkmap[i] = offset; + slen = MIN(srclen, blksize); + dlen = dstlen; + ret = compress2(dstbuf, &dlen, (Bytef *)srcaddr, slen, 9); + if (ret != Z_OK) { + (void) fprintf(stderr, COMP_ERR, srcfile, ret); + exit(-1); + } + + if (write(dstfd, dstbuf, dlen) != dlen) { + (void) fprintf(stderr, WRITE_ERR, + dlen, dstfile, strerror(errno)); + exit(-1); + } + + offset += dlen; + srclen -= slen; + srcaddr += slen; + } + + if (lseek(dstfd, 0, SEEK_SET) == (off_t)-1) { + (void) fprintf(stderr, SEEK_ERR, + 0, dstfile, strerror(errno)); + exit(-1); + } + + if (write(dstfd, hdr, hlen) != hlen) { + (void) fprintf(stderr, WRITE_ERR, + hlen, dstfile, strerror(errno)); + exit(-1); + } +} + +static void +do_decomp() +{ + struct comphdr *hdr; + size_t blks, blksize; + void *dstbuf; + int i; + ulong_t slen, dlen; + int ret; + + hdr = (struct comphdr *)(void *)srcaddr; + if (hdr->ch_magic != CH_MAGIC) { + (void) fprintf(stderr, BAD_MAGIC, + srcfile, (uint64_t)hdr->ch_magic, CH_MAGIC); + exit(-1); + } + if (hdr->ch_version != CH_VERSION) { + (void) fprintf(stderr, BAD_VERS, + srcfile, (uint64_t)hdr->ch_version, CH_VERSION); + exit(-1); + } + if (hdr->ch_algorithm != CH_ALG_ZLIB) { + (void) fprintf(stderr, BAD_ALG, + srcfile, (uint64_t)hdr->ch_algorithm, CH_ALG_ZLIB); + exit(-1); + } + + blksize = hdr->ch_blksize; + dstbuf = malloc(blksize); + if (dstbuf == NULL) { + (void) fprintf(stderr, HDR_ALLOC, blksize); + exit(-1); + } + + blks = (hdr->ch_fsize - 1) / blksize; + srcaddr += hdr->ch_blkmap[0]; + for (i = 0; i < blks; i++) { + dlen = blksize; + slen = hdr->ch_blkmap[i + 1] - hdr->ch_blkmap[i]; + ret = uncompress(dstbuf, &dlen, (Bytef *)srcaddr, slen); + if (ret != Z_OK) { + (void) fprintf(stderr, DECOMP_ERR, srcfile, ret); + exit(-1); + } + + if (dlen != blksize) { + (void) fprintf(stderr, CORRUPT, srcfile); + exit(-1); + } + if (write(dstfd, dstbuf, dlen) != dlen) { + (void) fprintf(stderr, WRITE_ERR, + dlen, dstfile, strerror(errno)); + exit(-1); + } + srcaddr += slen; + } + + dlen = blksize; + slen = hdr->ch_fsize - hdr->ch_blkmap[i]; + if ((ret = uncompress(dstbuf, &dlen, (Bytef *)srcaddr, slen)) != Z_OK) { + (void) fprintf(stderr, DECOMP_ERR, dstfile, ret); + exit(-1); + } + + if (write(dstfd, dstbuf, dlen) != dlen) { + (void) fprintf(stderr, WRITE_ERR, + dlen, dstfile, strerror(errno)); + exit(-1); + } +} diff --git a/usr/src/cmd/boot/fiocompress/message.h b/usr/src/cmd/boot/fiocompress/message.h new file mode 100644 index 0000000000..c92407bebd --- /dev/null +++ b/usr/src/cmd/boot/fiocompress/message.h @@ -0,0 +1,67 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _MESSAGE_H +#define _MESSAGE_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libintl.h> + +#define OPT_DC_EXCL gettext("fiocompress: -c and -d are exclusive\n") +#define INVALID_BLKSZ gettext("fiocompress: invalid block size\n") +#define UNKNOWN_OPTION gettext("fiocompress: unknown option -%c\n") +#define MISS_FILES gettext("fiocompress: input and output files\ + must be specified\n") +#define FIO_COMP_FAIL gettext("fiocompress: FIO_COMPRESSED on %s failed\ + - %s\n") +#define CANT_OPEN gettext("fiocompress: cannot open %s - %s\n") +#define STAT_FAIL gettext("fiocompress: stat of %s failed - %s\n") +#define MMAP_FAIL gettext("fiocompress: mmapping on %s failed - %s\n") +#define OPEN_FAIL gettext("fiocompress: open of %s failed - %s\n") +#define HDR_ALLOC gettext("fiocompress: failed to allocate %d bytes\ + for header\n") +#define BUF_ALLOC gettext("fiocompress: failed to allocate %d bytes\ + for buffer\n") +#define SEEK_ERR gettext("fiocompress: seek to %ld on %s failed - %s\n") +#define COMP_ERR gettext("fiocompress: %s - compression error %d\n") +#define WRITE_ERR gettext("fiocompress: write of %ld bytes on %s failed\ + - %s\n") +#define BAD_MAGIC gettext("fiocompress: %s - bad magic (0x%llx/0x%x)\n") +#define BAD_VERS gettext("fiocompress: %s - bad version (0x%llx/0x%x)\n") +#define BAD_ALG gettext("fiocompress: %s - bad algorithm\ + (0x%llx/0x%x)\n") +#define DECOMP_ERR gettext("fiocompress: %s - decompression error %d\n") +#define CORRUPT gettext("fiocompress: %s - corrupt file\n") + +#ifdef __cplusplus +} +#endif + +#endif /* _MESSAGE_H */ diff --git a/usr/src/cmd/boot/installgrub/Makefile b/usr/src/cmd/boot/installgrub/Makefile index f59050c1e7..b53a6d1f74 100644 --- a/usr/src/cmd/boot/installgrub/Makefile +++ b/usr/src/cmd/boot/installgrub/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -19,8 +18,7 @@ # # CDDL HEADER END # -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -36,8 +34,6 @@ SBINLINKS= $(PROG) include ../Makefile.com -ROOTUSRSBINLINKS= $(SBINLINKS:%=$(ROOTUSRSBIN)/%) - CPPFLAGS += -I$(SRC)/uts/i86pc -I$(SRC)/uts/intel -I$(SRC)/uts/common LINTFLAGS += \ @@ -59,9 +55,6 @@ $(PROG): $(OBJS) pcfs.o: $(PCFS_SRC) $(COMPILE.c) -o $@ $(PCFS_SRC) -$(ROOTUSRSBINLINKS): - -$(RM) $@; $(SYMLINK) ../../sbin/$(@F) $@ - install: all $(ROOTSBINPROG) .WAIT $(ROOTUSRSBINLINKS) clean: diff --git a/usr/src/cmd/boot/mbr/Makefile b/usr/src/cmd/boot/mbr/Makefile index 5d80e2f517..510257daac 100644 --- a/usr/src/cmd/boot/mbr/Makefile +++ b/usr/src/cmd/boot/mbr/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,24 +19,28 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # -PROG= mbr +BOOTPROG= mbr + +OBJS= $(BOOTPROG).o +SRCS = $(OBJS:.o=.c) include ../Makefile.com .KEEP_STATE: -all: $(PROG) +all: $(BOOTPROG) install: all $(ROOTBOOTSOLARISBINPROG) clean: + -$(RM) $(OBJS) -lint: lint_PROG +lint: lint_SRCS include ../Makefile.targ diff --git a/usr/src/cmd/boot/scripts/Makefile.com b/usr/src/cmd/boot/scripts/Makefile.com index b8fe31bc54..59ddadf0a0 100644 --- a/usr/src/cmd/boot/scripts/Makefile.com +++ b/usr/src/cmd/boot/scripts/Makefile.com @@ -30,36 +30,41 @@ MANIFEST= boot-archive-update.xml SVCMETHOD= boot-archive-update -PROG= create_ramdisk create_diskmap update_grub -METHODPROG= boot-archive-update -SBINPROG= root_archive +sparc_BOOTPROG= -SBINLINKS= $(SBINPROG) +i386_BOOTPROG= \ + create_diskmap \ + update_grub -include ../Makefile.com +COMMON_BOOTPROG= \ + create_ramdisk \ + extract_boot_filelist -ROOTSBINPROG= $(SBINPROG:%=$(ROOTUSRSBIN)/%) + +BOOTPROG= $(COMMON_BOOTPROG) $($(MACH)_BOOTPROG) +METHODPROG= boot-archive-update +PROG= root_archive + +include ../Makefile.com ROOTMANIFESTDIR= $(ROOTSVCSYSTEM) $(ROOTMANIFEST) := FILEMODE= 444 -ROOTBOOTSOLARISBINLINKS= $(SBINLINKS:%=$(ROOTBOOTSOLARISBIN)/%) +ROOTBOOTSOLARISUSRSBINLINKS= $(PROG:%=$(ROOTBOOTSOLARISBIN)/%) .KEEP_STATE: -all: $(PROG) $(METHODPROG) $(SBINPROG) - -$(ROOTBOOTSOLARISBINLINKS): - -$(RM) $@; $(SYMLINK) ../../../usr/sbin/$(@F) $@ +all: $(BOOTPROG) $(METHODPROG) $(PROG) check: $(CHKMANIFEST) clean: - $(RM) $(PROG) $(METHODPROG) $(SBINPROG) + $(RM) $(BOOTPROG) $(METHODPROG) $(PROG) - _msg: +lint _msg: -lint: +$(ROOTBOOTSOLARISUSRSBINLINKS): + $(RM) $@; $(SYMLINK) ../../../usr/sbin/$(@F) $@ # Default rule for building ksh scripts. .ksh: diff --git a/usr/src/cmd/boot/scripts/Makefile.i386 b/usr/src/cmd/boot/scripts/Makefile.i386 index 25f0533800..7fac1f59fd 100644 --- a/usr/src/cmd/boot/scripts/Makefile.i386 +++ b/usr/src/cmd/boot/scripts/Makefile.i386 @@ -18,8 +18,7 @@ # # CDDL HEADER END # -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -29,5 +28,9 @@ include Makefile.com .KEEP_STATE: -install: all $(ROOTBOOTSOLARISBINPROG) $(ROOTMANIFEST) $(ROOTSVCMETHOD) \ - $(ROOTSBINPROG) .WAIT $(ROOTBOOTSOLARISBINLINKS) +install: all \ + $(ROOTBOOTSOLARISBINPROG) \ + $(ROOTMANIFEST) \ + $(ROOTSVCMETHOD) \ + $(ROOTUSRSBINPROG) .WAIT \ + $(ROOTBOOTSOLARISUSRSBINLINKS) diff --git a/usr/src/cmd/boot/scripts/Makefile.sparc b/usr/src/cmd/boot/scripts/Makefile.sparc index e70274cd36..8816f19096 100644 --- a/usr/src/cmd/boot/scripts/Makefile.sparc +++ b/usr/src/cmd/boot/scripts/Makefile.sparc @@ -18,8 +18,7 @@ # # CDDL HEADER END # -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -29,4 +28,11 @@ include Makefile.com .KEEP_STATE: -install: all $(ROOTSBINPROG) .WAIT +install: all \ + $(ROOTBOOTSOLARISBINPROG) \ + $(ROOTMANIFEST) \ + $(ROOTSVCMETHOD) \ + $(ROOTUSRSBINPROG) + +# .WAIT \ +# $(ROOTBOOTSOLARISUSRSBINLINKS) diff --git a/usr/src/cmd/boot/scripts/boot-archive-update.ksh b/usr/src/cmd/boot/scripts/boot-archive-update.ksh index 57746dcb83..4db6b72478 100644 --- a/usr/src/cmd/boot/scripts/boot-archive-update.ksh +++ b/usr/src/cmd/boot/scripts/boot-archive-update.ksh @@ -20,7 +20,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -32,17 +32,14 @@ UPDATEFILE=/etc/svc/volatile/boot_archive_needs_update smf_is_globalzone || exit $SMF_EXIT_OK -# no boot-archive on sparc...yet -# -if [ `uname -p` = "sparc" ]; then - exit $SMF_EXIT_OK -fi - -# get rid of transient reboot entry in GRUB menu -if [ -f /stubboot/boot/grub/menu.lst ]; then - /sbin/bootadm -m update_temp -R /stubboot -else - /sbin/bootadm -m update_temp +# on x86 get rid of transient reboot entry in the GRUB menu +# +if [ `uname -p` = "i386" ]; then + if [ -f /stubboot/boot/grub/menu.lst ]; then + /sbin/bootadm -m update_temp -R /stubboot + else + /sbin/bootadm -m update_temp + fi fi if [ -f $UPDATEFILE ] || [ -f /reconfigure ]; then diff --git a/usr/src/cmd/boot/scripts/create_ramdisk.ksh b/usr/src/cmd/boot/scripts/create_ramdisk.ksh index f983ccc094..1c3d2b2d62 100644 --- a/usr/src/cmd/boot/scripts/create_ramdisk.ksh +++ b/usr/src/cmd/boot/scripts/create_ramdisk.ksh @@ -27,16 +27,34 @@ format=ufs ALT_ROOT= +ALTROOT_ARG= compress=yes SPLIT=unknown ERROR=0 dirsize32=0 dirsize64=0 -BOOT_ARCHIVE=platform/i86pc/boot_archive -BOOT_ARCHIVE_64=platform/i86pc/amd64/boot_archive +PLAT=`uname -m` +if [ $PLAT = i86pc ] ; then + ARCH64=amd64 +else + ARCH64=sparcv9 +fi +BOOT_ARCHIVE=platform/$PLAT/boot_archive +BOOT_ARCHIVE_64=platform/$PLAT/$ARCH64/boot_archive + +# +# set path, but inherit /tmp/bfubin if owned by +# same uid executing this process, which must be root. +# +if [ "`echo $PATH | cut -f 1 -d :`" = /tmp/bfubin ] && \ + [ -O /tmp/bfubin ] ; then + export PATH=/tmp/bfubin:/usr/sbin:/usr/bin:/sbin +else + export PATH=/usr/sbin:/usr/bin:/sbin +fi -export PATH=$PATH:/usr/sbin:/usr/bin:/sbin +EXTRACT_FILELIST="/boot/solaris/bin/extract_boot_filelist" # # Parse options @@ -48,6 +66,8 @@ do ALT_ROOT="$1" if [ "$ALT_ROOT" != "/" ]; then echo "Creating ram disk for $ALT_ROOT" + ALTROOT_ARG="-R $ALT_ROOT" + EXTRACT_FILELIST="${ALT_ROOT}${EXTRACT_FILELIST}" fi ;; -n|--nocompress) compress=no @@ -79,19 +99,24 @@ if [ $# -eq 1 ]; then echo "Creating ram disk for $ALT_ROOT" fi -rundir=`dirname $0` -if [ ! -x "$rundir"/symdef ]; then - # Shouldn't happen - echo "Warning: $rundir/symdef not present." - echo "Creating single archive at $ALT_ROOT/platform/i86pc/boot_archive" - SPLIT=no - compress=no -elif "$rundir"/symdef "$ALT_ROOT"/platform/i86pc/kernel/unix \ - dboot_image 2>/dev/null; then - SPLIT=yes -else - SPLIT=no - compress=no +if [ $PLAT = i86pc ] ; then + rundir=`dirname $0` + if [ ! -x "$rundir"/symdef ]; then + # Shouldn't happen + echo "Warning: $rundir/symdef not present." + echo "Creating single archive at $ALT_ROOT/$BOOT_ARCHIVE" + SPLIT=no + compress=no + elif "$rundir"/symdef "$ALT_ROOT"/platform/i86pc/kernel/unix \ + dboot_image 2>/dev/null; then + SPLIT=yes + else + SPLIT=no + compress=no + fi +else # must be sparc + SPLIT=no # there's only 64-bit (sparcv9), so don't split + compress=no fi [ -x /usr/bin/gzip ] || compress=no @@ -119,15 +144,19 @@ function getsize # next multiple of 1024. This mimics the behavior of ufs especially # with directories. This results in a total size that's slightly # bigger than if du was called on a ufs directory. - size32=$(cat "$list32" | xargs -I {} ls -lLd "{}" | nawk ' - {t += ($5 % 1024) ? (int($5 / 1024) + 1) * 1024 : $5} + size32=$(cat "$list32" | xargs -I {} ls -lLd "{}" 2> /dev/null | + nawk '{t += ($5 % 1024) ? (int($5 / 1024) + 1) * 1024 : $5} END {print int(t * 1.10 / 1024)}') (( size32 += dirsize32 )) - size64=$(cat "$list64" | xargs -I {} ls -lLd "{}" | nawk ' - {t += ($5 % 1024) ? (int($5 / 1024) + 1) * 1024 : $5} + size64=$(cat "$list64" | xargs -I {} ls -lLd "{}" 2> /dev/null | + nawk '{t += ($5 % 1024) ? (int($5 / 1024) + 1) * 1024 : $5} END {print int(t * 1.10 / 1024)}') (( size64 += dirsize64 )) (( total_size = size32 + size64 )) + + if [ $compress = yes ] ; then + total_size=`echo $total_size | nawk '{print int($1 / 2)}'` + fi } # @@ -161,6 +190,18 @@ function copy_files print "$path" fi done <"$list" | cpio -pdum "$rdmnt" 2>/dev/null + + if [ `uname -p` = sparc ] ; then + # copy links + find $filelist -type l -print 2>/dev/null |\ + cpio -pdum "$rdmnt" 2>/dev/null + if [ $compress = yes ] ; then + # always copy unix uncompressed + find $filelist -name unix -type f -print 2>/dev/null |\ + cpio -pdum "$rdmnt" 2>/dev/null + fi + fi + } # @@ -202,6 +243,12 @@ function create_ufs umount "$rdmnt" rmdir "$rdmnt" + if [ `uname -p` = sparc ] ; then + rlofidev=`echo "$lofidev" | sed -e "s/dev\/lofi/dev\/rlofi/"` + bb="$ALT_ROOT/usr/platform/`uname -i`/lib/fs/ufs/bootblk" + installboot "$bb" $rlofidev + fi + # # Check if gzip exists in /usr/bin, so we only try to run gzip # on systems that have gzip. Then run gzip out of the patch to @@ -211,7 +258,8 @@ function create_ufs # compressed, and the final compression will accomplish very # little. To save time, we skip the gzip in this case. # - if [ $compress = no ] && [ -x /usr/bin/gzip ] ; then + if [ `uname -p` = i386 ] && [ $compress = no ] && \ + [ -x /usr/bin/gzip ] ; then gzip -c "$rdfile" > "${archive}-new" else cat "$rdfile" > "${archive}-new" @@ -250,6 +298,11 @@ function create_isofs files= isocmd="mkisofs -quiet -graft-points -dlrDJN -relaxed-filenames" + if [ `uname -p` = sparc ] ; then + bb="$ALT_ROOT/usr/platform/`uname -i`/lib/fs/hsfs/bootblk" + isocmd="$isocmd -G \"$bb\"" + fi + copy_files "$list" isocmd="$isocmd \"$rdmnt\"" rm -f "$errlog" @@ -263,13 +316,22 @@ function create_isofs # compressed, and the final compression will accomplish very # little. To save time, we skip the gzip in this case. # - if [ $compress = no ] && [ -x /usr/bin/gzip ] ; then + if [ `uname -p` = i386 ] &&[ $compress = no ] && [ -x /usr/bin/gzip ] + then ksh -c "$isocmd" 2> "$errlog" | \ gzip > "${archive}-new" else ksh -c "$isocmd" 2> "$errlog" > "${archive}-new" fi + if [ `uname -p` = sparc ] ; then + bb="$ALT_ROOT/usr/platform/`uname -i`/lib/fs/hsfs/bootblk" + lofidev=`lofiadm -a "${archive}-new"` + rlofidev=`echo "$lofidev" | sed -e "s/dev\/lofi/dev\/rlofi/"` + installboot "$bb" "$rlofidev" + lofiadm -d "$lofidev" + fi + if [ -s "$errlog" ]; then grep Error: "$errlog" >/dev/null 2>&1 if [ $? -eq 0 ]; then @@ -286,7 +348,7 @@ function create_archive archive=$2 lofidev=$3 - echo "updating $archive...this may take a minute" + echo "updating $archive" if [ "$format" = "ufs" ]; then create_ufs "$which" "$archive" "$lofidev" @@ -297,8 +359,7 @@ function create_archive # sanity check the archive before moving it into place # ARCHIVE_SIZE=`ls -l "${archive}-new" | nawk '{ print $5 }'` - if [ $compress = yes ] - then + if [ $compress = yes ] || [ `uname -p` = sparc ] ; then # # 'file' will report "English text" for uncompressed # boot_archives. Checking for that doesn't seem stable, @@ -345,8 +406,8 @@ then print -u2 "Can't find filelist.ramdisk" exit 1 fi -filelist=$(cat "$ALT_ROOT/boot/solaris/filelist.ramdisk" \ - "$ALT_ROOT/etc/boot/solaris/filelist.ramdisk" 2>/dev/null | sort -u) +filelist=$($EXTRACT_FILELIST $ALTROOT_ARG /boot/solaris/filelist.ramdisk \ + /etc/boot/solaris/filelist.ramdisk 2>/dev/null | sort -u) # # We use /tmp/ for scratch space now. This may be changed later if there @@ -363,6 +424,8 @@ trap 'cleanup' EXIT list32="$rddir/filelist.32" list64="$rddir/filelist.64" +touch $list32 $list64 + # # This loop creates the 32-bit and 64-bit lists of files. The 32-bit list # is written to stdout, which is redirected at the end of the loop. The diff --git a/usr/src/cmd/boot/scripts/extract_boot_filelist.ksh b/usr/src/cmd/boot/scripts/extract_boot_filelist.ksh new file mode 100644 index 0000000000..a41d9bcf70 --- /dev/null +++ b/usr/src/cmd/boot/scripts/extract_boot_filelist.ksh @@ -0,0 +1,92 @@ +#!/bin/ksh -p +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" + +# +# set path, but inherit /tmp/bfubin if it is sane +# +if [ "`echo $PATH | cut -f 1 -d :`" = /tmp/bfubin ] && \ + [ -O /tmp/bfubin ] ; then + export PATH=/tmp/bfubin:/usr/sbin:/usr/bin:/sbin +else + export PATH=/usr/sbin:/usr/bin:/sbin +fi + +usage() { + echo "Usage: ${0##*/}: [-R \<root\>] <filelist> ..." + exit 2 +} + +altroot="" +filelists= +while getopts R FLAG +do + case $FLAG in + R) shift + if [ "$1" != "/" ]; then + altroot="$1" + fi + ;; + *) usage + ;; + esac + shift +done + +if [ $# -eq 0 ]; then + usage +fi + +filelists=$* + +filtering=no +if [ "$altroot" == "" ]; then + case `uname -m` in + i86pc) + filtering=no + ;; + sun4u) + filtering=yes + exclude_pattern="sun4v" + ;; + sun4v) + filtering=yes + exclude_pattern="sun4u" + ;; + esac +fi + +for list in $filelists +do + if [ -f $altroot/$list ]; then + if [ $filtering = yes ]; then + cat $altroot/$list | grep -v $exclude_pattern + else + cat $altroot/$list + fi + fi +done + +exit 0 diff --git a/usr/src/cmd/boot/scripts/root_archive.ksh b/usr/src/cmd/boot/scripts/root_archive.ksh index 8eacfd5484..215a2ae849 100644 --- a/usr/src/cmd/boot/scripts/root_archive.ksh +++ b/usr/src/cmd/boot/scripts/root_archive.ksh @@ -20,7 +20,7 @@ # CDDL HEADER END # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -41,10 +41,10 @@ # Solaris media and all the things that don't go into the ramdisk image # are (un)cpio'd as well # -# This utility is also used to pack parts (in essence the window system, -# usr/dt and usr/openwin) of the non ramdisk SPARC -# miniroot. (un)packmedia will recognize that they are being run a SPARC -# miniroot and do the appropriate work. +# This utility is also used to pack parts (in essence the window system, +# usr/dt and usr/openwin) of the non ramdisk SPARC +# miniroot. (un)packmedia will recognize that they are being run a SPARC +# miniroot and do the appropriate work. # usage() @@ -63,7 +63,10 @@ cleanup() fi lofiadm -d "$TMR" 2>/dev/null - rm -f "$TMR" "$TMR.gz" + if [ "$REALTHING" != true ] ; then + rm -f "$TMR" + fi + rm -f "$TMR.gz" } archive_Gnome() @@ -74,12 +77,7 @@ archive_Gnome() RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*` RELEASE=`basename "$RELEASE"` - if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then - CPIO_DIR="$MEDIA/$RELEASE/Tools/miniroot_extra" - mkdir -p "$CPIO_DIR" - else - CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot" - fi + CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot" # Create the gnome archive @@ -98,11 +96,13 @@ archive_Gnome() HOME="./tmp/root" export HOME umask 0022 - GCONF_CONFIG_SOURCE="xml:merged:"$MINIROOT"/.tmp_proto/root/etc/gconf/gconf.xml.defaults" + mumble=.tmp_proto/root/etc/gconf/gconf.xml.defaults + GCONF_CONFIG_SOURCE="xml:merged:$MINIROOT/$mumble" export GCONF_CONFIG_SOURCE SCHEMADIR="$MINIROOT/.tmp_proto/root/etc/gconf/schemas" export SCHEMADIR - /usr/bin/gconftool-2 --makefile-install-rule $SCHEMADIR/*.schemas >/dev/null 2>&1 + /usr/bin/gconftool-2 --makefile-install-rule \ + $SCHEMADIR/*.schemas >/dev/null 2>&1 echo ' xml:readwrite:/tmp/root/.gconf xml:readonly:/etc/gconf/gconf.xml.defaults @@ -124,7 +124,7 @@ archive_Gnome() if [ ! -f /tmp/gnome_share.$$ ] ; then echo "/tmp/gnome_share.$$ file list not found." - return + return fi # usr/lib gnome stuff @@ -191,7 +191,7 @@ archive_Gnome() if [ ! -f /tmp/gnome_bin.$$ ] ; then echo "/tmp/gnome_bin.$$ file list not found." - return + return fi # Cat all the files together and create the gnome archive @@ -221,13 +221,13 @@ archive_Gnome() cpio -ocmPuB < /tmp/gnome.$$ 2>/dev/null | bzip2 > \ "$CPIO_DIR/gnome.cpio.bz2" - # Remove files from miniroot that are in archive. + # Remove files from miniroot that are in archive. # Create symlinks for files in archive rm -rf `cat /tmp/gnome_share.$$` for i in `cat /tmp/gnome_share.$$` - do + do ln -s /tmp/root/$i $i 2>/dev/null done @@ -239,19 +239,19 @@ archive_Gnome() rm -rf `cat /tmp/gnome_libdir.$$` for i in `cat /tmp/gnome_libdir.$$` - do + do ln -s /tmp/root/$i $i 2>/dev/null done rm -rf `cat /tmp/gnome_sfw.$$` for i in `cat /tmp/gnome_sfw.$$` - do + do ln -s /tmp/root/$i $i 2>/dev/null done rm -rf `cat /tmp/gnome_bin.$$` for i in `cat /tmp/gnome_bin.$$` - do + do ln -s /tmp/root/$i $i 2>/dev/null done rm -f /tmp/gnome_share.$$ @@ -269,12 +269,7 @@ archive_JavaGUI() RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*` RELEASE=`basename "$RELEASE"` - if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then - CPIO_DIR="$MEDIA/$RELEASE/Tools/miniroot_extra" - mkdir -p "$CPIO_DIR" - else - CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot" - fi + CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot" # Archive the java wizard components that are only used in the # non developer express path. @@ -287,14 +282,15 @@ archive_JavaGUI() if [ ! -f /tmp/java_ui.$$ ] ; then echo "/tmp/java_ui.$$ file list not found." - return + return fi cpio -ocmPuB < /tmp/java_ui.$$ 2>/dev/null | bzip2 > \ "$CPIO_DIR/javaui.cpio.bz2" rm -rf `cat /tmp/java_ui.$$` - ln -s /tmp/root/usr/lib/install/data/wizards usr/lib/install/data/wizards 2>/dev/null + ln -s /tmp/root/usr/lib/install/data/wizards \ + usr/lib/install/data/wizards 2>/dev/null rm -f /tmp/java_ui.$$ @@ -309,12 +305,7 @@ archive_Misc() RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*` RELEASE=`basename "$RELEASE"` - if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then - CPIO_DIR="$MEDIA/$RELEASE/Tools/miniroot_extra" - mkdir -p "$CPIO_DIR" - else - CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot" - fi + CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot" # Archive misc stuff that is needed by non devex installer # @@ -324,7 +315,7 @@ archive_Misc() find usr/lib/lp -print > /tmp/lp.$$ 2>/dev/null if [ ! -f /tmp/lp.$$ ] ; then echo "/tmp/lp.$$ file list not found." - return + return fi cpio -ocmPuB < /tmp/lp.$$ 2>/dev/null | bzip2 > \ @@ -346,12 +337,7 @@ archive_Perl() RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*` RELEASE=`basename "$RELEASE"` - if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then - CPIO_DIR="$MEDIA/$RELEASE/Tools/miniroot_extra" - mkdir -p "$CPIO_DIR" - else - CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot" - fi + CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot" # Archive perl, it is only needed by gnome gui. # @@ -362,7 +348,7 @@ archive_Perl() if [ ! -f /tmp/perl.$$ ] ; then echo "/tmp/perl.$$ file list not found." - return + return fi cpio -ocmPuB < /tmp/perl.$$ 2>/dev/null | bzip2 > \ "$CPIO_DIR/perl.cpio.bz2" @@ -381,12 +367,7 @@ archive_X() RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*` RELEASE=`basename "$RELEASE"` - if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then - CPIO_DIR="$MEDIA/$RELEASE/Tools/miniroot_extra" - mkdir -p "$CPIO_DIR" - else - CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot" - fi + CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot" # create the graphics and non-graphics X archive # @@ -409,6 +390,24 @@ archive_X() ) } +archive_lu() +{ + MEDIA="$1" + MINIROOT="$2" + + RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*` + RELEASE=`basename "$RELEASE"` + + CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot" + + ( + cd "$MINIROOT" + find usr/lib/install usr/snadm usr/sbin | \ + cpio -ocmPuB 2> /dev/null | bzip2 > "$CPIO_DIR"/lu.cpio.bz2 + ls platform > "$CPIO_DIR/lu.platforms" + ) +} + packmedia() { MEDIA="$1" @@ -418,11 +417,56 @@ packmedia() RELEASE=`basename "$RELEASE"` mkdir -p "$MEDIA/$RELEASE/Tools/Boot" - mkdir -p "$MEDIA/boot/amd64" - mkdir -p "$MEDIA/boot/platform/i86pc/kernel" - mkdir -p "$MEDIA/boot/platform/i86pc/kernel/amd64" - mkdir -p "$MEDIA/boot/platform/i86xpv/kernel" - mkdir -p "$MEDIA/boot/platform/i86xpv/kernel/amd64" + + if [ -d "$MINIROOT/platform/i86pc" ] ; then + mkdir -p "$MEDIA/boot/amd64" + mkdir -p "$MEDIA/boot/platform/i86pc/kernel" + mkdir -p "$MEDIA/boot/platform/i86pc/kernel/amd64" + mkdir -p "$MEDIA/boot/platform/i86xpv/kernel" + mkdir -p "$MEDIA/boot/platform/i86xpv/kernel/amd64" + cp "$MINIROOT/platform/i86pc/multiboot" "$MEDIA/boot" + cp "$MINIROOT/platform/i86pc/kernel/unix" \ + "$MEDIA/boot/platform/i86pc/kernel/unix" + cp "$MINIROOT/platform/i86pc/kernel/amd64/unix" \ + "$MEDIA/boot/platform/i86pc/kernel/amd64/unix" + cp "$MINIROOT/platform/i86xpv/kernel/unix" \ + "$MEDIA/boot/platform/i86xpv/kernel/unix" + cp "$MINIROOT/platform/i86xpv/kernel/amd64/unix" \ + "$MEDIA/boot/platform/i86xpv/kernel/amd64/unix" + ( + cd "$MEDIA/$RELEASE/Tools/Boot" + ln -sf ../../../boot/x86.miniroot + ln -sf ../../../boot/multiboot + ln -sf ../../../boot/platform/i86pc/kernel/unix + ln -sf ../../../boot/platform/i86pc/kernel/amd64/unix + ln -sf ../../../boot/platform/i86xpv/kernel/unix + ln -sf ../../../boot/platform/i86xpv/kernel/amd64/unix + ln -sf ../../../boot/grub/pxegrub + ) + fi + + if [ -d "$MINIROOT/platform/sun4u" ] ; then + mkdir -p "$MEDIA/boot" + dd if="$MINIROOT/usr/platform/sun4u/lib/fs/hsfs/bootblk" \ + of="$MEDIA/boot/hsfs.bootblock" \ + bs=1b oseek=1 count=15 conv=sync 2> /dev/null + fi + + for arch in sun4u sun4v ; do + if [ -d "$MINIROOT/platform/$arch" ] ; then + archdir="$MEDIA/$RELEASE/Tools/Boot/platform/$arch" + mkdir -p $archdir + ln -sf ../../../../../boot/sparc.miniroot \ + "$archdir/boot_archive" + cp "$MINIROOT/usr/platform/$arch/lib/fs/nfs/inetboot" \ + "$archdir" + cp "$MINIROOT/platform/$arch/wanboot" \ + "$archdir" + mkdir -p "$MEDIA/platform/$arch" + ln -sf ../../boot/sparc.miniroot \ + "$MEDIA/platform/$arch/boot_archive" + fi + done # archive package databases to conserve memory # @@ -432,49 +476,37 @@ packmedia() cpio -ocmPuB 2> /dev/null | bzip2 > \ "$MEDIA/$RELEASE/Tools/Boot/pkg_db.cpio.bz2" ) - rm -rf "$MINIROOT/tmp/root/var/sadm/install" rm -rf "$MINIROOT/tmp/root/var/sadm/pkg" + if [ -d "$MINIROOT/kernel/drv/sparcv9" ] ; then + archive_lu "$MEDIA" "$MINIROOT" + elif [ "$STRIP_AMD64" != false ] ; then + # clear out 64 bit support to conserve memory + # + find "$MINIROOT" -name amd64 -type directory | xargs rm -rf + fi + archive_X "$MEDIA" "$MINIROOT" # Take out the gnome and java parts of the installer from # the miniroot. These are not required to boot the system # and start the installers. - - archive_Gnome "$MEDIA" "$MINIROOT" - archive_JavaGUI "$MEDIA" "$MINIROOT" - archive_Perl "$MEDIA" "$MINIROOT" - archive_Misc "$MEDIA" "$MINIROOT" - - cp "$MINIROOT/platform/i86pc/multiboot" "$MEDIA/boot" - cp "$MINIROOT/platform/i86pc/kernel/unix" \ - "$MEDIA/boot/platform/i86pc/kernel/unix" - cp "$MINIROOT/platform/i86pc/kernel/amd64/unix" \ - "$MEDIA/boot/platform/i86pc/kernel/amd64/unix" - cp "$MINIROOT/platform/i86xpv/kernel/unix" \ - "$MEDIA/boot/platform/i86xpv/kernel/unix" - cp "$MINIROOT/platform/i86xpv/kernel/amd64/unix" \ - "$MEDIA/boot/platform/i86xpv/kernel/amd64/unix" + + if [ -d "$MINIROOT/platform/i86pc" ] ; then + archive_Gnome "$MEDIA" "$MINIROOT" + archive_JavaGUI "$MEDIA" "$MINIROOT" + archive_Misc "$MEDIA" "$MINIROOT" + archive_Perl "$MEDIA" "$MINIROOT" + fi # copy the install menu to menu.lst so we have a menu # on the install media # - if [ -f "${MINIROOT}/boot/grub/install_menu" ] ; then - cp ${MINIROOT}/boot/grub/install_menu \ - ${MEDIA}/boot/grub/menu.lst + if [ -f "$MINIROOT/boot/grub/install_menu" ] ; then + cp $MINIROOT/boot/grub/install_menu \ + $MEDIA/boot/grub/menu.lst fi - - ( - cd "$MEDIA/$RELEASE/Tools/Boot" - ln -sf ../../../boot/x86.miniroot - ln -sf ../../../boot/platform/i86pc/kernel/unix - ln -sf ../../../boot/platform/i86pc/kernel/amd64/unix - ln -sf ../../../boot/platform/i86xpv/kernel/unix - ln -sf ../../../boot/platform/i86xpv/kernel/amd64/unix - ln -sf ../../../boot/multiboot - ln -sf ../../../boot/grub/pxegrub - ) } unarchive_X() @@ -485,11 +517,7 @@ unarchive_X() RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*` RELEASE=`basename "$RELEASE"` - if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then - CPIO_DIR="$MEDIA/$RELEASE/Tools/miniroot_extra" - else - CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot" - fi + CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot" # unpack X # @@ -527,7 +555,7 @@ unpackmedia() # Gnome list saved off from packmedia for i in `cat .tmp_proto/gnome_saved` - do + do rm -rf $i done @@ -561,7 +589,12 @@ unpack() exit 1 fi - gzcat "$MR" > $TMR + if [ `basename $MR` = x86.miniroot ] ; then + gzcat "$MR" > $TMR + else + REALTHING=true ; export REALTHING + TMR="$MR" + fi LOFIDEV=`/usr/sbin/lofiadm -a $TMR` if [ $? != 0 ] ; then @@ -583,9 +616,64 @@ unpack() printf "invalid root archive\n" fi + rmdir $MNT lofiadm -d $TMR ; LOFIDEV= - rm $TMR + if [ "$REALTHING" != true ] ; then + rm $TMR + fi +} + +compress() +{ + SRC=$1 + DST=$2 + + ( + cd $SRC + filelist=`find .` + + for file in $filelist ; do + + file=`echo $file | sed s#^./##` + + # copy all files over to preserve hard links + # + echo $file | cpio -pdum $DST 2> /dev/null + + if [ -f $file ] && [ -s $file ] && [ ! -h $file ] ; then + fiocompress -mc $file $DST/$file & + fi + + done + + # now re-copy a couple of uncompressed files + # + + find kernel platform -name unix | cpio -pdum $DST 2> /dev/null + find kernel platform -name genunix | cpio -pdum $DST \ + 2> /dev/null + find kernel platform -name platmod | cpio -pdum $DST \ + 2> /dev/null + find `find kernel platform -name cpu` | cpio -pdum $DST \ + 2> /dev/null + find `find kernel platform -name kmdb\*` | cpio -pdum $DST \ + 2> /dev/null + find kernel/misc/sparcv9/ctf kernel/fs/sparcv9/dcfs \ + etc/system etc/name_to_major etc/path_to_inst \ + etc/name_to_sysnum | cpio -pdum $DST 2> /dev/null + ) +} + +root_is_ramdisk() +{ + grep -v "set root_is_ramdisk=" "$UNPACKED_ROOT"/etc/system | \ + grep -v "set ramdisk_size=" > /tmp/system.$$ + cat /tmp/system.$$ > "$UNPACKED_ROOT"/etc/system + rm /tmp/system.$$ + + echo set root_is_ramdisk=1 >> "$UNPACKED_ROOT"/etc/system + echo set ramdisk_size=$1 >> "$UNPACKED_ROOT"/etc/system } pack() @@ -595,10 +683,17 @@ pack() exit 1 fi + # always compress on sparc if fiocompress exists + # + if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] && \ + [ -x /usr/sbin/fiocompress ] ; then + COMPRESS=true + fi + # Estimate image size and add %10 overhead for ufs stuff. # Note, we can't use du here in case $UNPACKED_ROOT is on a filesystem, # e.g. zfs, in which the disk usage is less than the sum of the file - # sizes. The nawk code + # sizes. The nawk code # # {t += ($7 % 1024) ? (int($7 / 1024) + 1) * 1024 : $7} # @@ -606,9 +701,16 @@ pack() # next multiple of 1024. This mimics the behavior of ufs especially # with directories. This results in a total size that's slightly # bigger than if du was called on a ufs directory. + # + # if the operation in turn is compressing the files the amount + # of typical shrinkage is used to come up with a useful archive + # size size=$(find "$UNPACKED_ROOT" -ls | nawk ' {t += ($7 % 1024) ? (int($7 / 1024) + 1) * 1024 : $7} END {print int(t * 1.10 / 1024)}') + if [ "$COMPRESS" = true ] ; then + size=`echo $size | nawk '{s = $1} END {print int(s * .53)}'` + fi /usr/sbin/mkfile ${size}k "$TMR" @@ -619,23 +721,45 @@ pack() fi RLOFIDEV=`echo $LOFIDEV | sed s/lofi/rlofi/` - newfs $RLOFIDEV < /dev/null 2> /dev/null + newfs $RLOFIDEV < /dev/null 2> /dev/null mkdir -p $MNT - mount -o nologging $LOFIDEV $MNT + mount -o nologging $LOFIDEV $MNT rmdir $MNT/lost+found + + if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then + root_is_ramdisk $size + fi + ( cd "$UNPACKED_ROOT" - find . -print | cpio -pdum $MNT 2> /dev/null + if [ "$COMPRESS" = true ] ; then + compress . $MNT + else + find . -print | cpio -pdum $MNT 2> /dev/null + fi ) lockfs -f $MNT umount $MNT rmdir $MNT + + if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then + "$UNPACKED_ROOT/usr/sbin/installboot" \ + "$UNPACKED_ROOT/usr/platform/sun4u/lib/fs/ufs/bootblk" \ + $RLOFIDEV + fi + lofiadm -d $LOFIDEV LOFIDEV= rm -f "$TMR.gz" - gzip -f "$TMR" - mv "$TMR.gz" "$MR" + + if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then + mv "$TMR" "$MR" + else + gzip -f "$TMR" + mv "$TMR.gz" "$MR" + fi + chmod a+r "$MR" } @@ -644,13 +768,18 @@ pack() EXTRA_SPACE=0 STRIP_AMD64= +COMPRESS= + +PATH=/usr/sbin:/usr/bin:/opt/sfw/bin ; export PATH -while getopts s:6 opt ; do +while getopts s:6c opt ; do case $opt in s) EXTRA_SPACE="$OPTARG" ;; 6) STRIP_AMD64=false ;; + c) COMPRESS=true + ;; *) usage exit 1 ;; @@ -677,45 +806,36 @@ if [ "`dirname $UNPACKED_ROOT`" = . ] ; then UNPACKED_ROOT="$BASE/$UNPACKED_ROOT" fi + +MEDIA="$MR" + trap cleanup EXIT case $1 in packmedia) - MEDIA="$MR" - MR="$MEDIA/boot/x86.miniroot" - if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then - archive_X "$MEDIA" "$UNPACKED_ROOT" + ARCHIVE=sparc.miniroot else - packmedia "$MEDIA" "$UNPACKED_ROOT" - - # create the 64-bit miniroot - # if the -6 option was passed, don't strip - # the 64-bit modules from the 32-bit miniroot - MR="$MEDIA/boot/amd64/x86.miniroot" - pack - - if [ "$STRIP_AMD64" = false ] ; then - ln $MR $MEDIA/boot/x86.miniroot - else - # create the 32-bit miniroot - MR="$MEDIA/boot/x86.miniroot" - find "$UNPACKED_ROOT" -name amd64 \ - -type directory | xargs rm -rf - pack - fi - fi ;; + ARCHIVE=x86.miniroot + fi + MR="$MR/boot/$ARCHIVE" + packmedia "$MEDIA" "$UNPACKED_ROOT" + pack + ;; unpackmedia) - MEDIA="$MR" - MR="$MR/boot/x86.miniroot" - - if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then - unarchive_X "$MEDIA" "$UNPACKED_ROOT" + if [ -f "$MEDIA/boot/sparc.miniroot" ] ; then + ARCHIVE=sparc.miniroot else - unpack - unpackmedia "$MEDIA" "$UNPACKED_ROOT" - fi ;; - pack) pack ;; - unpack) unpack ;; - *) usage ;; + ARCHIVE=x86.miniroot + fi + MR="$MR/boot/$ARCHIVE" + unpack + unpackmedia "$MEDIA" "$UNPACKED_ROOT" + ;; + pack) pack + ;; + unpack) unpack + ;; + *) usage + ;; esac diff --git a/usr/src/cmd/boot/symdef/Makefile b/usr/src/cmd/boot/symdef/Makefile index dba76dea89..9e551fccae 100644 --- a/usr/src/cmd/boot/symdef/Makefile +++ b/usr/src/cmd/boot/symdef/Makefile @@ -25,9 +25,9 @@ # ident "%Z%%M% %I% %E% SMI" # -PROG= symdef +BOOTPROG= symdef -OBJS= symdef.o +OBJS= $(BOOTPROG).o SRCS = $(OBJS:.o=.c) include ../Makefile.com @@ -40,11 +40,7 @@ LDLIBS += -lelf # behavior, which causes us to take SIGSEGV on such a write. CFLAGS += $(XSTRCONST) -all: $(PROG) - -$(PROG): $(OBJS) - $(LINK.c) -o $@ $(OBJS) $(LDLIBS) - $(POST_PROCESS) +all: $(BOOTPROG) install: all $(ROOTBOOTSOLARISBINPROG) diff --git a/usr/src/cmd/sgs/libld/Makefile.com b/usr/src/cmd/sgs/libld/Makefile.com index e9914c6d9a..8f7df55423 100644 --- a/usr/src/cmd/sgs/libld/Makefile.com +++ b/usr/src/cmd/sgs/libld/Makefile.com @@ -74,6 +74,7 @@ package := DLLIB = $(VAR_PKG_DL_LIB) CPPFLAGS += -DUSE_LIBLD_MALLOC -I$(SRCBASE)/lib/libc/inc \ -I$(SRCBASE)/uts/common/krtld -I$(ELFCAP) \ + -I$(SRCBASE)/uts/sparc \ $(VAR_LIBLD_CPPFLAGS) -DDO_RELOC_LIBLD LDLIBS += $(CONVLIBDIR) $(CONV_LIB) $(LDDBGLIBDIR) $(LDDBG_LIB) \ $(ELFLIBDIR) -lelf $(DLLIB) -lc diff --git a/usr/src/cmd/sgs/librtld/Makefile.com b/usr/src/cmd/sgs/librtld/Makefile.com index 7b0763aeb4..c5d862ff8b 100644 --- a/usr/src/cmd/sgs/librtld/Makefile.com +++ b/usr/src/cmd/sgs/librtld/Makefile.com @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -41,7 +41,8 @@ include $(SRC)/cmd/sgs/Makefile.com SRCDIR = ../common CPPFLAGS += -I../../rtld/common -I$(SRCBASE)/lib/libc/inc \ - -I$(SRCBASE)/uts/common/krtld -I$(SRC)/common/sgsrtcid + -I$(SRCBASE)/uts/common/krtld -I$(SRC)/common/sgsrtcid \ + -I$(SRCBASE)/uts/sparc DYNFLAGS += $(VERSREF) $(ZLAZYLOAD) '-R$$ORIGIN' LDLIBS += $(CONVLIBDIR) $(CONV_LIB) $(ELFLIBDIR) -lelf -lc diff --git a/usr/src/cmd/sgs/rtld/Makefile.com b/usr/src/cmd/sgs/rtld/Makefile.com index bb12a510c4..c14ee7fe0b 100644 --- a/usr/src/cmd/sgs/rtld/Makefile.com +++ b/usr/src/cmd/sgs/rtld/Makefile.com @@ -76,6 +76,7 @@ CPPFEATUREMACROS= $(VAR_RTLD_CPPFEATUREMACROS) CPPFLAGS += -I$(SRCBASE)/lib/libc/inc \ -I$(SRCBASE)/uts/common/krtld \ + -I$(SRCBASE)/uts/$(PLAT) \ -I$(SRCBASE)/uts/$(PLAT)/krtld \ -I$(SRC)/common/sgsrtcid \ $(CPPFEATUREMACROS) diff --git a/usr/src/cmd/svc/milestone/README.share b/usr/src/cmd/svc/milestone/README.share index 4751b3cefc..4cb23168da 100644 --- a/usr/src/cmd/svc/milestone/README.share +++ b/usr/src/cmd/svc/milestone/README.share @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # -Copyright 2005 Sun Microsystems, Inc. All rights reserved. +Copyright 2007 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. ident "%Z%%M% %I% %E% SMI" @@ -63,11 +62,13 @@ potentially require interpreters other than sh(1) or ksh(1). 1. Boot archive failure -Boot archive may become out of sync with the root filesystem in -a reboot following an abnormal system shutdown. The recommended -action is to reboot immediately, choose "Solaris failsafe" when -the boot menu is displayed. Type 'i' to get an interactive recovery -shell and follow instructions to update the boot archive. +The boot archive may become out of sync with the root filesystem in a +reboot following an abnormal system shutdown. The recommended action is +to reboot immediately to rebuild the archive and correct the inconsistency. +To accomplish this, on a GRUB-based platform, choose "Solaris failsafe" +when the boot menu is displayed. Type 'i' to get an interactive recovery +shell and follow instructions to update the boot archive. On an OBP- +based platform, type 'boot -F failsafe' and follow the instructions. If the list of stale files are not yet loaded by the kernel or are compatible, you may continue booting by clearing the diff --git a/usr/src/cmd/svc/milestone/boot-archive b/usr/src/cmd/svc/milestone/boot-archive index 76ab9f1398..94a2006d23 100644 --- a/usr/src/cmd/svc/milestone/boot-archive +++ b/usr/src/cmd/svc/milestone/boot-archive @@ -20,7 +20,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -32,13 +32,6 @@ ERRORFILE=/etc/svc/volatile/boot_archive_error FILELIST=/etc/svc/volatile/boot_archive_filelist UPDATEFILE=/etc/svc/volatile/boot_archive_needs_update -# -# no boot-archive on sparc...yet -# -if [ `uname -p` = "sparc" ]; then - exit $SMF_EXIT_OK -fi - smf_is_globalzone || exit $SMF_EXIT_OK # @@ -69,10 +62,13 @@ cecho "" /sbin/bootadm update-archive -vn | grep -v "cannot find" > /dev/msglog cecho "" -cecho "The recommended action is to reboot and select the \"Solaris failsafe\"" -cecho "option from the boot menu. Then follow the prompts to update the" -cecho "boot archive. To continue booting at your own risk, you may clear the" -cecho "service by running: \"svcadm clear system/boot-archive\"" +cecho "The recommended action is to reboot to the failsafe archive to correct" +cecho "the above inconsistency. To accomplish this, on a GRUB-based platform," +cecho "reboot and select the \"Solaris failsafe\" option from the boot menu." +cecho "On an OBP-based platform, reboot then type \"boot -F failsafe\". Then" +cecho "follow the prompts to update the boot archive. Alternately, to continue" +cecho "booting at your own risk, you may clear the service by running:" +cecho "\"svcadm clear system/boot-archive\"" cecho "" exit $SMF_EXIT_ERR_FATAL diff --git a/usr/src/pkgdefs/SUNWcakr.i/prototype_com b/usr/src/pkgdefs/SUNWcakr.i/prototype_com index 10f820f3dd..4ccf723226 100644 --- a/usr/src/pkgdefs/SUNWcakr.i/prototype_com +++ b/usr/src/pkgdefs/SUNWcakr.i/prototype_com @@ -48,13 +48,10 @@ d none boot 755 root sys d none boot/solaris 755 root sys d none boot/solaris/bin 0755 root sys f none boot/solaris/bin/create_diskmap 0555 root sys -f none boot/solaris/bin/create_ramdisk 0555 root sys f none boot/solaris/bin/mbr 0555 root sys s none boot/solaris/bin/root_archive=../../../usr/sbin/root_archive f none boot/solaris/bin/symdef 0555 root sys f none boot/solaris/bin/update_grub 0555 root sys -f none boot/solaris/filelist.ramdisk 0644 root sys -f none boot/solaris/filelist.safe 0644 root sys d none platform 755 root sys d none platform/i86pc 755 root sys d none platform/i86pc/amd64 755 root sys diff --git a/usr/src/pkgdefs/SUNWcakr.u/prototype_com b/usr/src/pkgdefs/SUNWcakr.u/prototype_com index 7573a522ea..97d5cb6f9d 100644 --- a/usr/src/pkgdefs/SUNWcakr.u/prototype_com +++ b/usr/src/pkgdefs/SUNWcakr.u/prototype_com @@ -519,5 +519,4 @@ f none platform/sun4u/kernel/tod/sparcv9/todsg 755 root sys f none platform/sun4u/kernel/tod/sparcv9/todstarcat 755 root sys f none platform/sun4u/kernel/tod/sparcv9/todstarfire 755 root sys s none platform/sun4u/kernel/unix=sparcv9/unix -f none platform/sun4u/ufsboot 644 root sys f none platform/sun4u/wanboot 644 root sys diff --git a/usr/src/pkgdefs/SUNWcakr.v/prototype_com b/usr/src/pkgdefs/SUNWcakr.v/prototype_com index b42caed3d2..d5236b47f4 100644 --- a/usr/src/pkgdefs/SUNWcakr.v/prototype_com +++ b/usr/src/pkgdefs/SUNWcakr.v/prototype_com @@ -92,5 +92,6 @@ d none platform/sun4v/kernel/sys 755 root sys d none platform/sun4v/kernel/sys/sparcv9 755 root sys s none platform/sun4v/kernel/unix=sparcv9/unix # -f none platform/sun4v/ufsboot 644 root sys + + f none platform/sun4v/wanboot 644 root sys diff --git a/usr/src/pkgdefs/SUNWckr/prototype_sparc b/usr/src/pkgdefs/SUNWckr/prototype_sparc index 9b0a5c702e..18b28c5aac 100644 --- a/usr/src/pkgdefs/SUNWckr/prototype_sparc +++ b/usr/src/pkgdefs/SUNWckr/prototype_sparc @@ -145,6 +145,7 @@ d none kernel/fs/sparcv9 755 root sys f none kernel/fs/sparcv9/autofs 755 root sys f none kernel/fs/sparcv9/cachefs 755 root sys f none kernel/fs/sparcv9/ctfs 755 root sys +f none kernel/fs/sparcv9/dcfs 755 root sys f none kernel/fs/sparcv9/devfs 755 root sys f none kernel/fs/sparcv9/dev 755 root sys f none kernel/fs/sparcv9/fifofs 755 root sys @@ -189,7 +190,6 @@ f none kernel/misc/sparcv9/idmap 755 root sys f none kernel/misc/sparcv9/ipc 755 root sys f none kernel/misc/sparcv9/kbtrans 755 root sys f none kernel/misc/sparcv9/kcf 755 root sys -f none kernel/misc/sparcv9/krtld 755 root sys f none kernel/misc/sparcv9/mac 755 root sys l none kernel/misc/sparcv9/md5=../../../kernel/crypto/sparcv9/md5 f none kernel/misc/sparcv9/neti 755 root sys diff --git a/usr/src/pkgdefs/SUNWcsr/prototype_com b/usr/src/pkgdefs/SUNWcsr/prototype_com index cceeea6d89..fd364d5816 100644 --- a/usr/src/pkgdefs/SUNWcsr/prototype_com +++ b/usr/src/pkgdefs/SUNWcsr/prototype_com @@ -90,6 +90,13 @@ i i.kmfconfbase # SUNWcsr # s none bin=./usr/bin +d none boot 755 root sys +d none boot/solaris 755 root sys +d none boot/solaris/bin 0755 root sys +f none boot/solaris/bin/create_ramdisk 0555 root sys +f none boot/solaris/bin/extract_boot_filelist 0555 root sys +f none boot/solaris/filelist.ramdisk 0644 root sys +f none boot/solaris/filelist.safe 0644 root sys d none dev 755 root sys d none etc 755 root sys e renamenew etc/.login 644 root sys @@ -346,6 +353,7 @@ f none lib/svc/bin/svc.startd 0555 root sys d none lib/svc/capture 0755 root bin d none lib/svc/method 0755 root bin f none lib/svc/method/boot-archive 0555 root bin +f none lib/svc/method/boot-archive-update 0555 root bin f none lib/svc/method/console-login 0555 root bin f none lib/svc/method/devices-local 0555 root bin f none lib/svc/method/fs-local 0555 root bin @@ -515,6 +523,7 @@ d none var/svc/manifest/platform 755 root sys d none var/svc/manifest/site 755 root sys d none var/svc/manifest/system 755 root sys f manifest var/svc/manifest/system/boot-archive.xml 0444 root sys +f none var/svc/manifest/system/boot-archive-update.xml 0444 root sys d none var/svc/manifest/system/device 755 root sys f manifest var/svc/manifest/system/device/devices-local.xml 0444 root sys f manifest var/svc/manifest/system/device/mpxio-upgrade.xml 0444 root sys diff --git a/usr/src/pkgdefs/SUNWcsr/prototype_i386 b/usr/src/pkgdefs/SUNWcsr/prototype_i386 index 2cb46da075..e89fc5a4c7 100644 --- a/usr/src/pkgdefs/SUNWcsr/prototype_i386 +++ b/usr/src/pkgdefs/SUNWcsr/prototype_i386 @@ -46,9 +46,8 @@ # # SUNWcsr # -f none lib/svc/method/boot-archive-update 0555 root bin +f none boot/solaris/bin/create_diskmap 0555 root sys f none sbin/biosdev 555 root bin f none sbin/installgrub 0555 root sys d none var/ld/amd64 755 root bin s none var/ld/64=amd64 -f none var/svc/manifest/system/boot-archive-update.xml 0444 root sys diff --git a/usr/src/pkgdefs/SUNWcsr/prototype_sparc b/usr/src/pkgdefs/SUNWcsr/prototype_sparc index 9ceff74138..3c5e918767 100644 --- a/usr/src/pkgdefs/SUNWcsr/prototype_sparc +++ b/usr/src/pkgdefs/SUNWcsr/prototype_sparc @@ -46,6 +46,7 @@ # # SUNWcsr # +f none sbin/fiocompress 555 root bin d none var/ld/sparcv9 755 root bin s none var/ld/64=sparcv9 d none var/svc/manifest/platform/sun4u 755 root sys diff --git a/usr/src/pkgdefs/SUNWcsu/prototype_sparc b/usr/src/pkgdefs/SUNWcsu/prototype_sparc index f0f6830bc1..06773e1625 100644 --- a/usr/src/pkgdefs/SUNWcsu/prototype_sparc +++ b/usr/src/pkgdefs/SUNWcsu/prototype_sparc @@ -105,6 +105,7 @@ s none usr/lib/sparcv9/ld.so.1=../../../lib/sparcv9/ld.so.1 f none usr/lib/sparcv9/libshare.so.1 755 root bin d none usr/lib/fs/nfs 755 root sys d none usr/lib/fs/nfs/sparcv9 755 root sys +s none usr/sbin/fiocompress=../../sbin/fiocompress l none usr/sbin/prtdiag=../../usr/lib/platexec d none usr/sbin/sparcv9 755 root bin f none usr/sbin/sparcv9/add_drv 555 root sys diff --git a/usr/src/pkgdefs/SUNWhea/prototype_com b/usr/src/pkgdefs/SUNWhea/prototype_com index 81c0ddb2ae..2e9983f80a 100644 --- a/usr/src/pkgdefs/SUNWhea/prototype_com +++ b/usr/src/pkgdefs/SUNWhea/prototype_com @@ -837,6 +837,7 @@ f none usr/include/sys/fs/cachefs_fscache.h 644 root bin f none usr/include/sys/fs/cachefs_log.h 644 root bin f none usr/include/sys/fs/cachefs_dlog.h 644 root bin f none usr/include/sys/fs/cachefs_ioctl.h 644 root bin +f none usr/include/sys/fs/decomp.h 644 root bin f none usr/include/sys/fs/dv_node.h 644 root bin f none usr/include/sys/fs/sdev_node.h 644 root bin f none usr/include/sys/fs/sdev_impl.h 644 root bin diff --git a/usr/src/pkgdefs/SUNWkvm.c/prototype_com b/usr/src/pkgdefs/SUNWkvm.c/prototype_com index 959e58a29d..962918c0f5 100644 --- a/usr/src/pkgdefs/SUNWkvm.c/prototype_com +++ b/usr/src/pkgdefs/SUNWkvm.c/prototype_com @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,8 +19,8 @@ # CDDL HEADER END # # -# Copyright (c) 1990-1998 by Sun Microsystems, Inc. -# All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" # @@ -45,8 +44,3 @@ i copyright # d none usr 755 root sys d none usr/platform 755 root sys -d none usr/platform/sun4c 755 root sys -d none usr/platform/sun4c/lib 755 root bin -d none usr/platform/sun4c/lib/fs 755 root bin -d none usr/platform/sun4c/lib/fs/ufs 755 root bin -f none usr/platform/sun4c/lib/fs/ufs/bootblk 444 root sys diff --git a/usr/src/pkgdefs/SUNWkvm.d/prototype_com b/usr/src/pkgdefs/SUNWkvm.d/prototype_com index 8a53aa2983..528472c700 100644 --- a/usr/src/pkgdefs/SUNWkvm.d/prototype_com +++ b/usr/src/pkgdefs/SUNWkvm.d/prototype_com @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,8 +19,8 @@ # CDDL HEADER END # # -# Copyright (c) 1990-1998, 2001 by Sun Microsystems, Inc. -# All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" # @@ -45,8 +44,3 @@ i copyright # d none usr 755 root sys d none usr/platform 755 root sys -d none usr/platform/sun4d 755 root sys -d none usr/platform/sun4d/lib 755 root bin -d none usr/platform/sun4d/lib/fs 755 root bin -d none usr/platform/sun4d/lib/fs/ufs 755 root bin -f none usr/platform/sun4d/lib/fs/ufs/bootblk 444 root sys diff --git a/usr/src/pkgdefs/SUNWkvm.m/prototype_com b/usr/src/pkgdefs/SUNWkvm.m/prototype_com index 2f6c702131..b245dc8d48 100644 --- a/usr/src/pkgdefs/SUNWkvm.m/prototype_com +++ b/usr/src/pkgdefs/SUNWkvm.m/prototype_com @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 1990-1999, 2002 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -45,8 +44,3 @@ i copyright # d none usr 755 root sys d none usr/platform 755 root sys -d none usr/platform/sun4m 755 root sys -d none usr/platform/sun4m/lib 755 root bin -d none usr/platform/sun4m/lib/fs 755 root bin -d none usr/platform/sun4m/lib/fs/ufs 755 root bin -f none usr/platform/sun4m/lib/fs/ufs/bootblk 444 root sys diff --git a/usr/src/pkgdefs/SUNWkvm.u/prototype_com b/usr/src/pkgdefs/SUNWkvm.u/prototype_com index 0e316a23bb..104225aefb 100644 --- a/usr/src/pkgdefs/SUNWkvm.u/prototype_com +++ b/usr/src/pkgdefs/SUNWkvm.u/prototype_com @@ -287,6 +287,10 @@ s none usr/platform/TAD,SPARCLE/lib/fs=../../sun4u/lib/fs # d none usr/platform/sun4u/lib/fs/ufs 755 root bin f none usr/platform/sun4u/lib/fs/ufs/bootblk 444 root sys +d none usr/platform/sun4u/lib/fs/hsfs 755 root bin +f none usr/platform/sun4u/lib/fs/hsfs/bootblk 444 root sys +d none usr/platform/sun4u/lib/fs/zfs 755 root bin +f none usr/platform/sun4u/lib/fs/zfs/bootblk 444 root sys d none usr/platform/sun4u/lib/fs/nfs 755 root bin f none usr/platform/sun4u/lib/fs/nfs/inetboot 644 root sys # diff --git a/usr/src/pkgdefs/SUNWkvm.v/prototype_com b/usr/src/pkgdefs/SUNWkvm.v/prototype_com index 0d388e4eff..720506b5b0 100644 --- a/usr/src/pkgdefs/SUNWkvm.v/prototype_com +++ b/usr/src/pkgdefs/SUNWkvm.v/prototype_com @@ -72,5 +72,9 @@ d none usr/platform/sun4v/lib/fs 755 root bin # d none usr/platform/sun4v/lib/fs/ufs 755 root bin f none usr/platform/sun4v/lib/fs/ufs/bootblk 444 root sys +d none usr/platform/sun4v/lib/fs/hsfs 755 root bin +f none usr/platform/sun4v/lib/fs/hsfs/bootblk 444 root sys +d none usr/platform/sun4v/lib/fs/zfs 755 root bin +f none usr/platform/sun4v/lib/fs/zfs/bootblk 444 root sys d none usr/platform/sun4v/lib/fs/nfs 755 root bin f none usr/platform/sun4v/lib/fs/nfs/inetboot 644 root sys diff --git a/usr/src/psm/promif/ieee1275/sun4/prom_fio.c b/usr/src/psm/promif/ieee1275/sun4/prom_fio.c new file mode 100644 index 0000000000..3909b21170 --- /dev/null +++ b/usr/src/psm/promif/ieee1275/sun4/prom_fio.c @@ -0,0 +1,219 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/promif.h> +#include <sys/promimpl.h> + +int +prom_fopen(ihandle_t fsih, char *path) +{ + cell_t ci[10]; + size_t len; + +#ifdef PROM_32BIT_ADDRS + char *opath = NULL; + + if ((uintptr_t)path > (uint32_t)-1) { + opath = path; + len = prom_strlen(opath) + 1; /* include terminating NUL */ + path = promplat_alloc(len); + if (path == NULL) + return (0); + (void) prom_strcpy(path, opath); + } +#endif + len = prom_strlen(path); + + promif_preprom(); + ci[0] = p1275_ptr2cell("call-method"); /* Service name */ + ci[1] = (cell_t)4; /* #argument cells */ + ci[2] = (cell_t)3; /* #result cells */ + ci[3] = p1275_ptr2cell("open-file"); /* Arg1: Method name */ + ci[4] = p1275_ihandle2cell(fsih); /* Arg2: fs ihandle */ + ci[5] = p1275_uint2cell(len); /* Arg3: Len */ + ci[6] = p1275_ptr2cell(path); /* Arg4: Pathname */ + + (void) p1275_cif_handler(&ci); + + promif_postprom(); + +#ifdef PROM_32BIT_ADDRS + if (opath != NULL) + promplat_free(path, len + 1); +#endif + + if (ci[7] != 0) /* Catch result */ + return (-1); + + if (ci[8] == 0) /* Res1: failed */ + return (-1); + + return (p1275_cell2int(ci[9])); /* Res2: fd */ +} + + +int +prom_fseek(ihandle_t fsih, int fd, unsigned long long offset) +{ + cell_t ci[10]; + + ci[0] = p1275_ptr2cell("call-method"); /* Service name */ + ci[1] = (cell_t)4; /* #argument cells */ + ci[2] = (cell_t)3; /* #result cells */ + ci[3] = p1275_ptr2cell("seek-file"); /* Arg1: Method name */ + ci[4] = p1275_ihandle2cell(fsih); /* Arg2: fs ihandle */ + ci[5] = p1275_int2cell(fd); /* Arg3: file desc */ + ci[6] = p1275_ull2cell_low(offset); /* Arg4: Offset */ + + promif_preprom(); + (void) p1275_cif_handler(&ci); + promif_postprom(); + + if (ci[7] != 0) /* Catch result */ + return (-1); + + if (ci[8] == 0) /* Res1: failed */ + return (-1); + + return (p1275_cell2int(ci[9])); /* Res2: off */ +} + + +int +prom_fread(ihandle_t fsih, int fd, caddr_t buf, size_t len) +{ + cell_t ci[10]; +#ifdef PROM_32BIT_ADDRS + caddr_t obuf = NULL; + + if ((uintptr_t)buf > (uint32_t)-1) { + obuf = buf; + buf = promplat_alloc(len); + if (buf == NULL) + return (-1); + } +#endif + + promif_preprom(); + + ci[0] = p1275_ptr2cell("call-method"); /* Service name */ + ci[1] = (cell_t)5; /* #argument cells */ + ci[2] = (cell_t)2; /* #result cells */ + ci[3] = p1275_ptr2cell("read-file"); /* Arg1: Method name */ + ci[4] = p1275_ihandle2cell(fsih); /* Arg2: fs ihandle */ + ci[5] = p1275_int2cell(fd); /* Arg3: file desc */ + ci[6] = p1275_uint2cell(len); /* Arg4: buffer length */ + ci[7] = p1275_ptr2cell(buf); /* Arg5: buffer address */ + + (void) p1275_cif_handler(&ci); + + promif_postprom(); + +#ifdef PROM_32BIT_ADDRS + if (obuf != NULL) { + promplat_bcopy(buf, obuf, len); + promplat_free(buf, len); + } +#endif + + if (ci[8] != 0) /* Catch result */ + return (-1); + + return (p1275_cell2int(ci[9])); /* Res2: actual length */ +} + +int +prom_fsize(ihandle_t fsih, int fd, size_t *size) +{ + cell_t ci[8]; + + promif_preprom(); + + ci[0] = p1275_ptr2cell("call-method"); /* Service name */ + ci[1] = (cell_t)3; /* #argument cells */ + ci[2] = (cell_t)2; /* #result cells */ + ci[3] = p1275_ptr2cell("size-file"); /* Arg1: Method name */ + ci[4] = p1275_ihandle2cell(fsih); /* Arg2: fs ihandle */ + ci[5] = p1275_int2cell(fd); /* Arg3: file desc */ + + (void) p1275_cif_handler(&ci); + + promif_postprom(); + + if (ci[6] != 0) /* Catch result */ + return (-1); + + *size = p1275_cell2uint(ci[7]); /* Res2: size */ + return (0); +} + + +int +prom_compinfo(ihandle_t fsih, int fd, int *iscmp, size_t *fsize, size_t *bsize) +{ + cell_t ci[10]; + + promif_preprom(); + + ci[0] = p1275_ptr2cell("call-method"); /* Service name */ + ci[1] = (cell_t)3; /* #argument cells */ + ci[2] = (cell_t)4; /* #result cells */ + ci[3] = p1275_ptr2cell("cinfo-file"); /* Arg1: Method name */ + ci[4] = p1275_ihandle2cell(fsih); /* Arg2: fs ihandle */ + ci[5] = p1275_int2cell(fd); /* Arg3: file desc */ + + (void) p1275_cif_handler(&ci); + + promif_postprom(); + + if (ci[6] != 0) /* Catch result */ + return (-1); + + *iscmp = p1275_cell2int(ci[7]); /* Res2: iscmp */ + *fsize = p1275_cell2uint(ci[8]); /* Res3: fsize */ + *bsize = p1275_cell2uint(ci[9]); /* Res4: bsize */ + return (0); +} + +void +prom_fclose(ihandle_t fsih, int fd) +{ + cell_t ci[7]; + + ci[0] = p1275_ptr2cell("call-method"); /* Service name */ + ci[1] = (cell_t)3; /* #argument cells */ + ci[2] = (cell_t)1; /* #result cells */ + ci[3] = p1275_ptr2cell("close-file"); /* Arg1: Method name */ + ci[4] = p1275_ihandle2cell(fsih); /* Arg2: fs ihandle */ + ci[5] = p1275_int2cell(fd); /* Arg3: file desc */ + + promif_preprom(); + (void) p1275_cif_handler(&ci); + promif_postprom(); + +} diff --git a/usr/src/psm/promif/ieee1275/sun4/prom_init.c b/usr/src/psm/promif/ieee1275/sun4/prom_init.c index 66779087c9..8ca6d3742f 100644 --- a/usr/src/psm/promif/ieee1275/sun4/prom_init.c +++ b/usr/src/psm/promif/ieee1275/sun4/prom_init.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 1994, 2001-2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -107,12 +106,6 @@ prom_init(char *pgmname, void *p1275cookie) */ (void) prom_set_preprom(default_prepost_prom); (void) prom_set_postprom(default_prepost_prom); - - if (&plat_setprop_enter != NULL) { - prom_setprop_enter = &plat_setprop_enter; - prom_setprop_exit = &plat_setprop_exit; - ASSERT(prom_setprop_exit != NULL); - } } /* diff --git a/usr/src/psm/promif/ieee1275/sun4/prom_mem.c b/usr/src/psm/promif/ieee1275/sun4/prom_mem.c index 6983d1e09a..ada9a7fad2 100644 --- a/usr/src/psm/promif/ieee1275/sun4/prom_mem.c +++ b/usr/src/psm/promif/ieee1275/sun4/prom_mem.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,8 +19,8 @@ * CDDL HEADER END */ /* - * Copyright (c) 1991-1994, by Sun Microsystems, Inc. - * All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -62,7 +61,7 @@ prom_memory_ihandle(void) * and a single size cell in the "memory" node. */ int -prom_allocate_phys(size_t size, u_int align, unsigned long long *physaddr) +prom_allocate_phys(size_t size, uint_t align, unsigned long long *physaddr) { cell_t ci[10]; int rv; @@ -72,7 +71,7 @@ prom_allocate_phys(size_t size, u_int align, unsigned long long *physaddr) return (-1); if (align == 0) - align = (u_int)1; + align = (uint_t)1; ci[0] = p1275_ptr2cell("call-method"); /* Service name */ ci[1] = (cell_t)4; /* #argument cells */ @@ -162,3 +161,43 @@ prom_free_phys(size_t size, unsigned long long physaddr) (void) p1275_cif_handler(&ci); promif_postprom(); } + +static pnode_t +prom_mem_phandle(void) +{ + static pnode_t pmem = 0; + + if (pmem == (pnode_t)0) { + ihandle_t ih; + + if ((ih = prom_memory_ihandle()) == (ihandle_t)-1) + prom_panic("Can't get memory ihandle"); + pmem = prom_getphandle(ih); + } + return (pmem); +} + + +int +prom_phys_installed_len(void) +{ + return (prom_getproplen(prom_mem_phandle(), "reg")); +} + +int +prom_phys_avail_len(void) +{ + return (prom_getproplen(prom_mem_phandle(), "available")); +} + +int +prom_phys_installed(caddr_t prop) +{ + return (prom_getprop(prom_mem_phandle(), "reg", prop)); +} + +int +prom_phys_avail(caddr_t prop) +{ + return (prom_getprop(prom_mem_phandle(), "available", prop)); +} diff --git a/usr/src/psm/promif/ieee1275/sun4u/Makefile.files b/usr/src/psm/promif/ieee1275/sun4u/Makefile.files index 6808bc6499..40f83a581e 100644 --- a/usr/src/psm/promif/ieee1275/sun4u/Makefile.files +++ b/usr/src/psm/promif/ieee1275/sun4u/Makefile.files @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #pragma ident "%Z%%M% %I% %E% SMI" @@ -31,15 +31,17 @@ # # -# Note that the kernel doesn't use/need prom_map.o and prom_alloc.o +# Note that the kernel doesn't use/need prom_map.o # # # PROM Platform-dependent routines # CORE_OBJS += \ + prom_alloc.o \ prom_cpuctl.o \ prom_efcode.o \ + prom_fio.o \ prom_getunum.o \ prom_heartbeat.o \ prom_idprom.o \ diff --git a/usr/src/psm/promif/ieee1275/sun4u/prom_mmu.c b/usr/src/psm/promif/ieee1275/sun4u/prom_mmu.c index c5556dc756..a9cfe6662e 100644 --- a/usr/src/psm/promif/ieee1275/sun4u/prom_mmu.c +++ b/usr/src/psm/promif/ieee1275/sun4u/prom_mmu.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,8 +19,8 @@ * CDDL HEADER END */ /* - * Copyright (c) 1991-1994, by Sun Microsystems, Inc. - * All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -105,7 +104,7 @@ prom_unmap_phys(size_t size, caddr_t virt) * Allocate aligned or unaligned virtual address space, unmapped. */ caddr_t -prom_allocate_virt(u_int align, size_t size) +prom_allocate_virt(uint_t align, size_t size) { cell_t ci[9]; int rv; @@ -219,6 +218,34 @@ prom_unmap_virt(size_t size, caddr_t virt) promif_postprom(); } +static pnode_t +prom_mmu_phandle(void) +{ + static pnode_t pmmu = 0; + + if (pmmu == (pnode_t)0) { + ihandle_t ih; + + if ((ih = prom_mmu_ihandle()) == (ihandle_t)-1) + prom_panic("Can't get mmu ihandle"); + pmmu = prom_getphandle(ih); + } + return (pmmu); +} + + +int +prom_virt_avail_len(void) +{ + return (prom_getproplen(prom_mmu_phandle(), "available")); +} + +int +prom_virt_avail(caddr_t prop) +{ + return (prom_getprop(prom_mmu_phandle(), "available", prop)); +} + /* * Translate virtual address to physical address. * Returns 0: Success; Non-zero: failure. diff --git a/usr/src/psm/promif/ieee1275/sun4v/Makefile.files b/usr/src/psm/promif/ieee1275/sun4v/Makefile.files index 2914265a0c..0cb087efa2 100644 --- a/usr/src/psm/promif/ieee1275/sun4v/Makefile.files +++ b/usr/src/psm/promif/ieee1275/sun4v/Makefile.files @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #pragma ident "%Z%%M% %I% %E% SMI" @@ -31,15 +31,17 @@ # # -# Note that the kernel doesn't use/need prom_map.o and prom_alloc.o +# Note that the kernel doesn't use/need prom_map.o # # # PROM Platform-dependent routines # CORE_OBJS += \ + prom_alloc.o \ prom_cpuctl.o \ prom_efcode.o \ + prom_fio.o \ prom_getunum.o \ prom_idprom.o \ prom_heartbeat.o \ diff --git a/usr/src/psm/stand/boot/Makefile.boot b/usr/src/psm/stand/boot/Makefile.boot index b5d0f7c8ca..b57c66a046 100644 --- a/usr/src/psm/stand/boot/Makefile.boot +++ b/usr/src/psm/stand/boot/Makefile.boot @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -51,15 +50,9 @@ PSMPROMLIBDIR64 = $(PSMSTANDDIR)/lib/promif/$(MACH64) # XXX one day we should just be able to set PROG to 'cfsboot'.. # and everything will become a lot easier. # -# XXX note that we build but -don't- install the HSFS boot -# program - it's unused and untested, and until it is we -# shouldn't ship it! -# UNIBOOT = multiboot -UFSBOOT = ufsboot WANBOOT = wanboot NFSBOOT = inetboot -HSFSBOOT = hsfsboot # # Common install modes and owners @@ -73,10 +66,8 @@ GROUP = sys # Install locations # ROOT_PSM_UNIBOOT= $(ROOT_PSM_DIR)/$(UNIBOOT) -ROOT_PSM_UFSBOOT= $(ROOT_PSM_DIR)/$(UFSBOOT) ROOT_PSM_WANBOOT= $(ROOT_PSM_DIR)/$(WANBOOT) USR_PSM_NFSBOOT = $(USR_PSM_LIB_NFS_DIR)/$(NFSBOOT) -USR_PSM_HSFSBOOT= $(USR_PSM_LIB_HSFS_DIR)/$(HSFSBOOT) # # While things are pretty much 32-bit lint-clean, there are a ton of diff --git a/usr/src/psm/stand/boot/Makefile.targ b/usr/src/psm/stand/boot/Makefile.targ index 4d58601c91..fe366511e0 100644 --- a/usr/src/psm/stand/boot/Makefile.targ +++ b/usr/src/psm/stand/boot/Makefile.targ @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -22,15 +21,15 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright (c) 1994 by Sun Microsystems, Inc. -# All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # # psm/stand/boot/Makefile.files # # Targets common to all versions # -install: all $(ROOT_PSM_UFSBOOT) $(USR_PSM_NFSBOOT) +install: all $(USR_PSM_NFSBOOT) # # Install rules diff --git a/usr/src/psm/stand/boot/common/readfile.c b/usr/src/psm/stand/boot/common/readfile.c index 846dadcdaa..daacc98d7a 100644 --- a/usr/src/psm/stand/boot/common/readfile.c +++ b/usr/src/psm/stand/boot/common/readfile.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -187,7 +186,7 @@ extern void sas_symtab(int start, int end); * repeat reads (forever) until size of request is satisfied * (Thus, you don't want to use this cases where short reads are ok) */ -static ssize_t +ssize_t xread(int fd, char *p, size_t nbytes) { size_t bytesread = 0; @@ -274,7 +273,7 @@ readfile(int fd, int print) printf("FATAL: 64-bit ELF executable " "not for AMD64\n (e_machine " "= %d).\n", elfhdr.e_machine); - return (FAIL); + return (FAIL); } /* @@ -395,7 +394,7 @@ read_elf32(int fd, int print, Elf32_Ehdr *elfhdrp) continue; if (verbosemode) { dprintf("allocating 0x%x bytes for note hdr\n", - phdr->p_filesz); + phdr->p_filesz); } if ((note_buf = kmem_alloc(phdr->p_filesz, 0)) == NULL) goto elferror; @@ -405,14 +404,14 @@ read_elf32(int fd, int print, Elf32_Ehdr *elfhdrp) goto elferror; if (verbosemode) { dprintf("reading 0x%x bytes into %p\n", - phdr->p_filesz, (void *)nhdr); + phdr->p_filesz, (void *)nhdr); } nhdr = (Elf32_Nhdr *)note_buf; if (xread(fd, (caddr_t)nhdr, phdr->p_filesz) != phdr->p_filesz) goto elferror; if (verbosemode) { dprintf("p_note namesz %x descsz %x type %x\n", - nhdr->n_namesz, nhdr->n_descsz, nhdr->n_type); + nhdr->n_namesz, nhdr->n_descsz, nhdr->n_type); } /* @@ -453,9 +452,9 @@ read_elf32(int fd, int print, Elf32_Ehdr *elfhdrp) dprintf("Doing header 0x%x\n", i); dprintf("phdr\n"); dprintf("\tp_offset = %x, p_vaddr = %x\n", - phdr->p_offset, phdr->p_vaddr); + phdr->p_offset, phdr->p_vaddr); dprintf("\tp_memsz = %x, p_filesz = %x\n", - phdr->p_memsz, phdr->p_filesz); + phdr->p_memsz, phdr->p_filesz); } if (phdr->p_type == PT_LOAD) { if (verbosemode) @@ -464,7 +463,7 @@ read_elf32(int fd, int print, Elf32_Ehdr *elfhdrp) goto elferror; if (phdr->p_flags == (PF_R | PF_W) && - phdr->p_vaddr == 0) { + phdr->p_vaddr == 0) { /* * It's a PT_LOAD segment that is RW but * not executable and has a vaddr @@ -494,7 +493,7 @@ read_elf32(int fd, int print, Elf32_Ehdr *elfhdrp) if (use_align && npagesize != 0) { off = loadaddr & (npagesize - 1); size = roundup(phdr->p_memsz + off, - npagesize); + npagesize); base = loadaddr - off; } else { npagesize = 0; @@ -558,7 +557,7 @@ read_elf32(int fd, int print, Elf32_Ehdr *elfhdrp) if (verbosemode) { dprintf("reading 0x%x bytes into 0x%x\n", - phdr->p_filesz, loadaddr); + phdr->p_filesz, loadaddr); } /* use uintptr_t to suppress the gcc warning */ if (xread(fd, (caddr_t)(uintptr_t)loadaddr, @@ -590,7 +589,7 @@ read_elf32(int fd, int print, Elf32_Ehdr *elfhdrp) } #ifdef MPSAS sas_symtab(phdr->p_vaddr, - phdr->p_vaddr + phdr->p_memsz); + phdr->p_vaddr + phdr->p_memsz); #endif } else if (phdr->p_type == PT_INTERP) { /* @@ -799,7 +798,7 @@ read_elf64(int fd, int print, Elf64_Ehdr *elfhdrp) continue; if (verbosemode) { dprintf("allocating 0x%llx bytes for note hdr\n", - (u_longlong_t)phdr->p_filesz); + (u_longlong_t)phdr->p_filesz); } if ((note_buf = kmem_alloc(phdr->p_filesz, 0)) == NULL) goto elf64error; @@ -810,14 +809,14 @@ read_elf64(int fd, int print, Elf64_Ehdr *elfhdrp) goto elf64error; if (verbosemode) { dprintf("reading 0x%llx bytes into 0x%p\n", - (u_longlong_t)phdr->p_filesz, (void *)nhdr); + (u_longlong_t)phdr->p_filesz, (void *)nhdr); } nhdr = (Elf64_Nhdr *)note_buf; if (xread(fd, (caddr_t)nhdr, phdr->p_filesz) != phdr->p_filesz) goto elf64error; if (verbosemode) { dprintf("p_note namesz %x descsz %x type %x\n", - nhdr->n_namesz, nhdr->n_descsz, nhdr->n_type); + nhdr->n_namesz, nhdr->n_descsz, nhdr->n_type); } /* @@ -858,13 +857,13 @@ read_elf64(int fd, int print, Elf64_Ehdr *elfhdrp) dprintf("Doing header 0x%x\n", i); dprintf("phdr\n"); dprintf("\tp_offset = %llx, p_vaddr = %llx\n", - (u_longlong_t)phdr->p_offset, - (u_longlong_t)phdr->p_vaddr); + (u_longlong_t)phdr->p_offset, + (u_longlong_t)phdr->p_vaddr); dprintf("\tp_memsz = %llx, p_filesz = %llx\n", - (u_longlong_t)phdr->p_memsz, - (u_longlong_t)phdr->p_filesz); + (u_longlong_t)phdr->p_memsz, + (u_longlong_t)phdr->p_filesz); dprintf("\tp_type = %x, p_flags = %x\n", - phdr->p_type, phdr->p_flags); + phdr->p_type, phdr->p_flags); } if (phdr->p_type == PT_LOAD) { if (verbosemode) @@ -874,7 +873,7 @@ read_elf64(int fd, int print, Elf64_Ehdr *elfhdrp) goto elf64error; if (phdr->p_flags == (PF_R | PF_W) && - phdr->p_vaddr == 0) { + phdr->p_vaddr == 0) { /* * It's a PT_LOAD segment that is RW but * not executable and has a vaddr @@ -912,7 +911,7 @@ read_elf64(int fd, int print, Elf64_Ehdr *elfhdrp) if (use_align && npagesize != 0) { off = loadaddr & (npagesize - 1); size = roundup(phdr->p_memsz + off, - npagesize); + npagesize); base = loadaddr - off; } else { npagesize = 0; @@ -951,8 +950,8 @@ read_elf64(int fd, int print, Elf64_Ehdr *elfhdrp) if (verbosemode) { dprintf("reading 0x%llx bytes into 0x%llx\n", - (u_longlong_t)phdr->p_filesz, - (u_longlong_t)loadaddr); + (u_longlong_t)phdr->p_filesz, + (u_longlong_t)loadaddr); } if (xread(fd, (caddr_t)(uintptr_t) loadaddr, phdr->p_filesz) != phdr->p_filesz) @@ -984,7 +983,7 @@ read_elf64(int fd, int print, Elf64_Ehdr *elfhdrp) #ifdef MPSAS sas_symtab(phdr->p_vaddr, - phdr->p_vaddr + phdr->p_memsz); + phdr->p_vaddr + phdr->p_memsz); #endif } else if (phdr->p_type == PT_INTERP) { /* @@ -1090,7 +1089,7 @@ read_elf64(int fd, int print, Elf64_Ehdr *elfhdrp) } bcopy((char *)auxv, (char *)(elfbootvecELF64->eb_un.eb_ptr), - size); + size); #endif /* BOOTAMD64 */ } else { kmem_free(allphdrs, phdrsize); @@ -1180,13 +1179,13 @@ iload32(char *rtld, Elf32_Phdr *thdr, Elf32_Phdr *dhdr, auxv32_t **avp) * to do relocation, skip it. */ if (!(sp->sh_flags & SHF_ALLOC) && - sp->sh_type != SHT_SYMTAB && - sp->sh_type != SHT_STRTAB && #ifdef i386 - sp->sh_type != SHT_REL) + sp->sh_type != SHT_REL && #else - sp->sh_type != SHT_RELA) + sp->sh_type != SHT_RELA && #endif + sp->sh_type != SHT_SYMTAB && + sp->sh_type != SHT_STRTAB) continue; /* * If the section is read-only, @@ -1392,10 +1391,9 @@ iload64(char *rtld, Elf64_Phdr *thdr, Elf64_Phdr *dhdr, auxv64_t **avp) */ if (lseek(fd, sp->sh_offset, 0) == -1 || xread(fd, (caddr_t)(uintptr_t)load, sp->sh_size) != - sp->sh_size) { - printf("boot: error reading section %d\n", - i); - goto error; + sp->sh_size) { + printf("boot: error reading section %d\n", i); + goto error; } } /* diff --git a/usr/src/psm/stand/boot/sparc/common/boot_plat.c b/usr/src/psm/stand/boot/sparc/common/boot_plat.c index ff1f0fe23b..9a9423cf1b 100644 --- a/usr/src/psm/stand/boot/sparc/common/boot_plat.c +++ b/usr/src/psm/stand/boot/sparc/common/boot_plat.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -81,7 +80,6 @@ int client_isLP64 = 1; /* SPARC clients are always LP64 */ * filename is the name of the standalone we're going to execute. */ char filename[MAXPATHLEN]; -char *cmd_line_default_path; char * const defname = "kernel/sparcv9/unix"; @@ -236,24 +234,6 @@ boot_open(char *pathname, void *arg) return (open(pathname, O_RDONLY)); } -static int -boot_isdir(char *pathname) -{ - int fd, retval; - struct stat sbuf; - - dprintf("trying '%s'\n", pathname); - if ((fd = open(pathname, O_RDONLY)) == -1) - return (0); - retval = 1; - if (fstat(fd, &sbuf) == -1) - retval = 0; - else if ((sbuf.st_mode & S_IFMT) != S_IFDIR) - retval = 0; - (void) close(fd); - return (retval); -} - /* * Open the given filename, expanding to it's * platform-dependent location if necessary. @@ -266,8 +246,6 @@ int openfile(char *filename) { static char *fullpath; - static char *iarch; - static char *orig_impl_arch_name; static int once; int fd; @@ -282,78 +260,16 @@ openfile(char *filename) if (mfg_name == NULL) mfg_name = get_mfg_name(); - /* - * If impl_arch_name was specified on the command line - * via the -I <arch> argument, remember the original value. - */ - if (impl_arch_name) { - orig_impl_arch_name = (char *) - kmem_alloc(strlen(impl_arch_name) + 1, 0); - (void) strcpy(orig_impl_arch_name, impl_arch_name); - } - fullpath = (char *)kmem_alloc(MAXPATHLEN, 0); - iarch = (char *)kmem_alloc(MAXPATHLEN, 0); } - /* - * impl_arch_name is exported as boot property, and is - * set according to the following algorithm, depending - * on the contents of the filesystem. - * XXX: This shouldn't be a side effect of openfile(). - * - * impl_arch_name table: - * - * root name default name neither name - * boot args found found found - * - * relative path root name fail fail - * absolute path root name default name empty - * -I arch arch arch arch - * - */ - - /* - * If the caller -specifies- an absolute pathname, then we just try to - * open it. (Mostly for booting non-kernel standalones.) - * - * In case this absolute pathname is the kernel, make sure that - * impl_arch_name (exported as a boot property) is set to some - * valid string value. - */ if (*filename == '/') { - if (orig_impl_arch_name == NULL) { - if (find_platform_dir(boot_isdir, iarch, 1) != 0) - impl_arch_name = iarch; - else - impl_arch_name = ""; - } (void) strcpy(fullpath, filename); fd = boot_open(fullpath, NULL); return (fd); } - /* - * If the -I flag has been used, impl_arch_name will - * be specified .. otherwise we ask find_platform_dir() to - * look for the existance of a directory for this platform name. - * Preserve the given impl-arch-name, because the 'kernel file' - * may be elsewhere. (impl-arch-name could be 'SUNW,Ultra-1', - * but the kernel file itself might be in the 'sun4u' directory). - * - * When booting any file by relative pathname this code fails - * if the platform-name dir doesn't exist unless some - * -I <iarch> argument has been given on the command line. - */ - if (orig_impl_arch_name == NULL) { - if (find_platform_dir(boot_isdir, iarch, 0) != 0) - impl_arch_name = iarch; - else - return (-1); - } - - fd = open_platform_file(filename, boot_open, NULL, fullpath, - orig_impl_arch_name); + fd = open_platform_file(filename, boot_open, NULL, fullpath); if (fd == -1) return (-1); diff --git a/usr/src/psm/stand/boot/sparc/common/boot_plat.h b/usr/src/psm/stand/boot/sparc/common/boot_plat.h index 99066f70bb..e6dffbedc4 100644 --- a/usr/src/psm/stand/boot/sparc/common/boot_plat.h +++ b/usr/src/psm/stand/boot/sparc/common/boot_plat.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -36,7 +35,6 @@ extern "C" { /* boot_plat.c */ -extern char *cmd_line_default_path; extern int verbosemode; extern char filename[]; extern char *const defname; @@ -52,21 +50,11 @@ extern void set_client_bootargs(const char *, const char *); extern boolean_t is_netdev(char *devpath); -/* boot_1275entry.c */ -extern int boot1275_entry_asm(void *); -extern void boot_fail_gracefully_asm(void); - - -/* boot_services.c */ -extern int boot1275_entry(void *); - - /* bootops.c */ extern struct bootops bootops; extern void setup_bootops(void); extern void update_memlist(char *, char *, struct memlist **); -extern void boot_fail_gracefully(void); /* @@ -81,7 +69,6 @@ extern char *mfg_name; extern char *impl_arch_name; extern char *bootp_response; extern char *boot_message; -extern char *cmd_line_default_path; extern int cache_state; extern uint64_t memlistextent; extern char *netdev_path; diff --git a/usr/src/psm/stand/boot/sparc/common/bootflags.c b/usr/src/psm/stand/boot/sparc/common/bootflags.c index abb4573d24..f401f8ac57 100644 --- a/usr/src/psm/stand/boot/sparc/common/bootflags.c +++ b/usr/src/psm/stand/boot/sparc/common/bootflags.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -38,24 +37,19 @@ #include <util/getoptstr.h> #include "boot_plat.h" -static char impl_arch_buf[MAXNAMELEN]; static char default_path_buf[MAXPATHLEN]; char wanboot_arguments[OBP_MAXPATHLEN]; /* args following "-o" */ +char cmd_line_boot_archive[MAXPATHLEN]; + +boolean_t halt; + /* * Parse the boot arguments, adding the options found to the existing boothowto * value (if any) or other state. Then rewrite the buffer with arguments for * the standalone. * - * We assume that the buffer contains only the arguments (no preceeding - * filename or whitespace). We start interpreting flags, ignoring those used - * by the boot block (-H, -X, and -F filename) and acting on those intended - * for us (those documented in boot(1M) as well as some undocumented), and - * stop at unknown flags. Finally we reconstitute flags to be passed on to - * the standalone and the remaining arguments, excluding the first "--", to - * the beginning of the buffer, and return an integer representing our flags. - * * NOTE: boothowto may already have bits set when this function is called */ void @@ -67,8 +61,8 @@ bootflags(char *args, size_t argsz) char *np; size_t npres; int c; + char *cmd_line_default_path; - impl_arch_name = NULL; cmd_line_default_path = NULL; params.gos_opts = "HXF:VnI:D:advhko:"; @@ -77,11 +71,24 @@ bootflags(char *args, size_t argsz) while ((c = getoptstr(¶ms)) != -1) { switch (c) { /* - * Bootblock flags: ignore. + * Bootblock flags. */ case 'H': + halt = B_TRUE; + /*FALLTHRU*/ case 'X': + break; + case 'F': + if (params.gos_optarglen >= + sizeof (cmd_line_boot_archive)) { + printf("boot: -F argument too long. " + "Ignoring.\n"); + break; + } + (void) strncpy(cmd_line_boot_archive, + params.gos_optargp, params.gos_optarglen); + cmd_line_boot_archive[params.gos_optarglen] = '\0'; break; /* @@ -95,18 +102,6 @@ bootflags(char *args, size_t argsz) printf("Warning: boot will not enable cache\n"); break; - case 'I': - if (params.gos_optarglen >= sizeof (impl_arch_buf)) { - printf("boot: -I argument too long. " - "Ignoring.\n"); - break; - } - (void) strncpy(impl_arch_buf, params.gos_optargp, - params.gos_optarglen); - impl_arch_buf[params.gos_optarglen] = '\0'; - impl_arch_name = impl_arch_buf; - break; - case 'D': if (params.gos_optarglen >= sizeof (default_path_buf)) { printf("boot: -D argument too long. " @@ -160,8 +155,6 @@ bootflags(char *args, size_t argsz) */ switch (params.gos_last_opt) { case 'F': - /* -F is a bootblock flag, so ignore. */ - break; case 'I': case 'D': case 'o': @@ -271,4 +264,10 @@ done: */ if (cmd_line_default_path) set_default_filename(cmd_line_default_path); + + /* + * See if user wants to examine things + */ + if (halt == B_TRUE) + prom_enter_mon(); } diff --git a/usr/src/psm/stand/boot/sparc/common/bootops.c b/usr/src/psm/stand/boot/sparc/common/bootops.c index 662fcfaedc..10d7b87003 100644 --- a/usr/src/psm/stand/boot/sparc/common/bootops.c +++ b/usr/src/psm/stand/boot/sparc/common/bootops.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,17 +19,12 @@ * CDDL HEADER END */ /* - * Copyright 1996-2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" -/* - * Implementation of the vestigial bootops vector for platforms using the - * 1275-like boot interfaces. - */ - #include <sys/types.h> #include <sys/bootconf.h> #include <sys/param.h> @@ -51,38 +45,20 @@ static const int debug = 0; extern void closeall(int); -/* - * This is the number for this version of bootops, which is vestigial. - * Standalones that require the old bootops will look in bootops.bsys_version, - * see this number is higher than they expect and fail gracefully. - * They can make this "peek" successfully even if they are ILP32 programs. - */ -int boot_version = BO_VERSION; - struct bootops bootops; +static void +boot_fail(void) +{ + prom_panic("bootops is gone, it should not be called"); +} + void setup_bootops(void) { - /* sanity-check bsys_printf - old kernels need to fail with a message */ -#if !defined(lint) - if (offsetof(struct bootops, bsys_printf) != 60) { - printf("boot: bsys_printf is at offset 0x%lx instead of 60\n" - "boot: this will likely make old kernels die without " - "printing a message.\n", - offsetof(struct bootops, bsys_printf)); - } - /* sanity-check bsys_1275_call - if it moves, kernels cannot boot */ - if (offsetof(struct bootops, bsys_1275_call) != 24) { - printf("boot: bsys_1275_call is at offset 0x%lx instead of 24\n" - "boot: this will likely break the kernel\n", - offsetof(struct bootops, bsys_1275_call)); - } -#endif - bootops.bsys_version = boot_version; - bootops.bsys_1275_call = (uint64_t)boot1275_entry; - /* so old kernels die with a message */ - bootops.bsys_printf = (uint32_t)boot_fail_gracefully; + bootops.bsys_version = BO_VERSION; + bootops.bsys_1275_call = (uint64_t)boot_fail; + bootops.bsys_printf = (uint32_t)boot_fail; if (!memlistpage) /* paranoia runs rampant */ prom_panic("\nMemlistpage not setup yet."); @@ -204,10 +180,3 @@ kern_killboot(void) prom_enter_mon(); #endif } - -void -boot_fail_gracefully(void) -{ - prom_panic( - "mismatched version of /boot interface: new boot, old kernel"); -} diff --git a/usr/src/psm/stand/boot/sparc/common/inetboot.c b/usr/src/psm/stand/boot/sparc/common/inetboot.c new file mode 100644 index 0000000000..13a61bb30f --- /dev/null +++ b/usr/src/psm/stand/boot/sparc/common/inetboot.c @@ -0,0 +1,181 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/fcntl.h> +#include <sys/obpdefs.h> +#include <sys/reboot.h> +#include <sys/promif.h> +#include <sys/stat.h> +#include <sys/bootvfs.h> +#include <sys/platnames.h> +#include <sys/salib.h> +#include <sys/elf.h> +#include <sys/link.h> +#include <sys/auxv.h> +#include <sys/boot_policy.h> +#include <sys/boot_redirect.h> +#include <sys/bootconf.h> +#include <sys/boot.h> +#include "boot_plat.h" +#include "ramdisk.h" + +#define SUCCESS 0 +#define FAILURE -1 + +#ifdef DEBUG +extern int debug = 0; +#else +static const int debug = 0; +#endif + +#define dprintf if (debug) printf + +char *def_boot_archive = "boot_archive"; +char *def_miniroot = "miniroot"; +extern char cmd_line_boot_archive[]; + +extern int openfile(char *filename); + +static int +read_and_boot_ramdisk(int fd) +{ + struct stat st; + caddr_t virt; + size_t size; + extern ssize_t xread(int, char *, size_t); + + if ((fstat(fd, &st) != 0) || + ((virt = create_ramdisk(RD_ROOTFS, st.st_size, NULL)) == NULL)) + return (-1); + + dprintf("reading boot archive ...\n"); + if ((size = xread(fd, (char *)virt, st.st_size)) != st.st_size) { + (void) printf("Error reading boot archive, bytes read = %ld, " + "filesize = %ld\n", (long)size, (long)st.st_size); + destroy_ramdisk(RD_ROOTFS); + return (-1); + } + + boot_ramdisk(RD_ROOTFS); + /* NOT REACHED */ + return (0); /* to make cc happy */ +} + + +static void +post_mountroot_nfs(void) +{ + int fd; + char *fn; + char tmpname[MAXPATHLEN]; + + for (;;) { + fn = NULL; + if (boothowto & RB_ASKNAME) { + fn = (cmd_line_boot_archive[0] != '\0') ? + cmd_line_boot_archive : def_boot_archive; + printf("Enter filename [%s]: ", fn); + (void) cons_gets(tmpname, sizeof (tmpname)); + if (tmpname[0] != '\0') + fn = tmpname; + } + + if (boothowto & RB_HALT) { + printf("Boot halted.\n"); + prom_enter_mon(); + } + + if (fn != NULL) + fd = openfile(fn); + else if (cmd_line_boot_archive[0] != '\0') { + fn = cmd_line_boot_archive; + fd = openfile(fn); + } else { + fn = def_boot_archive; + if ((fd = openfile(fn)) == FAILURE) { + fn = def_miniroot; + fd = openfile(fn); + } + } + + if (fd == FAILURE) { + if (fn != def_miniroot) + printf("cannot open %s\n", fn); + else + printf("cannot open neither %s nor %s\n", + def_boot_archive, def_miniroot); + } else { + /* + * this function does not return if successful. + */ + (void) read_and_boot_ramdisk(fd); + + printf("boot failed\n"); + (void) close(fd); + } + boothowto |= RB_ASKNAME; + } +} + + +/* + * bpath is the boot device path buffer. + * bargs is the boot arguments buffer. + */ +/*ARGSUSED*/ +int +bootprog(char *bpath, char *bargs, boolean_t user_specified_filename) +{ + systype = set_fstype(v2path, bpath); + + if (verbosemode) { + printf("device path '%s'\n", bpath); + if (strcmp(bpath, v2path) != 0) + printf("client path '%s'\n", v2path); + } + + if (mountroot(bpath) != SUCCESS) + prom_panic("Could not mount filesystem."); + + /* + * kernname (default-name) might have changed if mountroot() called + * boot_nfs_mountroot(), and it called set_default_filename(). + */ + if (!user_specified_filename) + (void) strcpy(filename, kernname); + + if (verbosemode) + printf("standalone = `%s', args = `%s'\n", filename, bargs); + + set_client_bootargs(filename, bargs); + + post_mountroot_nfs(); + + return (1); +} diff --git a/usr/src/psm/stand/boot/sparc/common/ramdisk.c b/usr/src/psm/stand/boot/sparc/common/ramdisk.c index bba9f4b5d2..ee0116f3d0 100644 --- a/usr/src/psm/stand/boot/sparc/common/ramdisk.c +++ b/usr/src/psm/stand/boot/sparc/common/ramdisk.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,534 +33,400 @@ /* EXPORT DELETE END */ #include "ramdisk.h" -/* - * This is a chunk of Forth delivered by the OBP group. When loaded - * into OBP it creates a ramdisk device node whose functionality is - * defined in FWARC 2002/299. - * - * Note the %s in the line following " new-device" - this is where we - * plug the name of the node in. - */ -static const char ramdisk_fth[] = - -"headerless " - -"\" /\" find-package 0= if" -" .\" Can't find /\" abort " -"then push-package " - -"new-device" -" \" %s\" device-name" -" \" block\" encode-string \" device_type\" property" -/* CSTYLED */ +#include <sys/param.h> +#include <sys/fcntl.h> +#include <sys/obpdefs.h> +#include <sys/reboot.h> +#include <sys/promif.h> +#include <sys/stat.h> +#include <sys/bootvfs.h> +#include <sys/platnames.h> +#include <sys/salib.h> +#include <sys/elf.h> +#include <sys/link.h> +#include <sys/auxv.h> +#include <sys/boot_policy.h> +#include <sys/boot_redirect.h> +#include <sys/bootconf.h> +#include <sys/boot.h> +#include "boot_plat.h" + + +static char ramdisk_preamble_fth[] = + +": find-abort ( name$ -- ) " +" .\" Can't find \" type abort " +"; " + +": get-package ( pkg$ -- ph ) " +" 2dup find-package 0= if " +" find-abort " +" then ( pkg$ ph ) " +" nip nip ( ph ) " +"; " + +"\" /openprom/client-services\" get-package constant cif-ph " + +"instance defer cif-open ( dev$ -- ihandle|0 ) " +"instance defer cif-close ( ihandle -- ) " + +": find-cif-method ( adr,len -- acf ) " +" 2dup cif-ph find-method 0= if ( adr,len ) " +" find-abort " +" then ( adr,len acf ) " +" nip nip ( acf ) " +"; " + +"\" open\" find-cif-method to cif-open " +"\" close\" find-cif-method to cif-close " + +"0 value dev-ih " + +"d# 100 buffer: open-cstr " + +": dev-open ( dev$ -- okay? ) " +/* copy to C string for open */ +" 0 over open-cstr + c! " +" open-cstr swap move " +" open-cstr cif-open dup if " +" dup to dev-ih " +" then " +"; " + +": dev-close ( -- ) " +" dev-ih cif-close " +" 0 to dev-ih " +"; " + +": open-abort ( file$ -- ) " +" .\" Can't open \" type abort " +"; " +; + +static char ramdisk_fth[] = + +"\" /\" get-package push-package " + +"new-device " +" \" %s\" device-name " +" " +" \" block\" device-type " " \" SUNW,ramdisk\" encode-string \" compatible\" property" -" hex" - -" headerless" - -" 0 value mmu-ihandle" -" 0 value mem-ihandle" - -" : get-memory-ihandles" /* ( -- ) */ -" \" /chosen\" find-package drop dup \" mmu\" rot" -" get-package-property if" -" .\" Can't find chosen mmu property\" cr abort" -" then" -" decode-int to mmu-ihandle 2drop" -" \" memory\" rot get-package-property if" -" .\" Can't find chosen memory property\" cr abort" -" then" -" decode-int to mem-ihandle 2drop" -" ;" - -" : get-page-size" /* ( -- page-size ) */ -" mmu-ihandle ihandle>phandle \" page-size\" rot get-package-property" -" if h# 2000 else decode-int nip nip then " -" ;" - -" : get-mode" /* ( -- rw-mode ) */ -" here \" translate\" mmu-ihandle $call-method if" -" nip nip" -" else" -" h# 27" -" then" -" ;" - -" : 64>32bit-phys" /* ( 64bit.lo 64bit.hi -- 32bit.lo 32bit.hi ) */ -" drop xlsplit" -" ;" - -" : 32>64bit-phys" /* ( 32bit.lo 32bit.hi -- 64bit.lo 64bit.hi ) */ -" lxjoin 0" -" ;" - -" : phy-claim" /* ( size align -- base.lo base.hi 0 | error ) */ -" \" claim\" mem-ihandle ['] $call-method catch if" -" drop 2drop 2drop -1" -" else" -" 64>32bit-phys 0" -" then" -" ;" - -" : phy-release" /* ( phys.lo phys.hi size -- ) */ -" >r 32>64bit-phys r> \" release\" mem-ihandle $call-method" -" ;" - -" : vir-claim" /* ( [ virt ] size align -- base ) */ -" \" claim\" mmu-ihandle $call-method" -" ;" - -" : vir-release" /* ( virt size -- ) */ -" \" release\" mmu-ihandle $call-method" -" ;" - -" : vir-map" /* ( phys-lo phys-hi virt size mode -- ) */ -" >r >r >r 32>64bit-phys r> r> r>" -" \" map\" mmu-ihandle $call-method" -" ;" - -" : vir-unmap" /* ( virt size -- ) */ -" \" unmap\" mmu-ihandle $call-method" -" ;" -" headers" - -/* \ This structure represents a physical "chunk" of ramdisk memory */ -" struct" -" /l field >res-pa.lo" /* \ lower 32bits of physical address */ -" /l field >res-pa.hi" /* \ upper 32bits of physical address */ -" /l field >res-len.lo" /* \ lower 32bits of chunk size */ -" /l field >res-len.hi" /* \ upper 32bits of chunk size */ -" constant /res-entry" - -" 4 value max-res-entries" /* \ Max # of non-contig phys chunks */ - -" max-res-entries /res-entry *" /* \ size of resource buffer */ -" ( value ) buffer: my-resources" /* \ resource buffer label */ -" 0 value num-res-entries" /* \ current # of chunks allocated */ -" h# 10 constant label-size" /* \ size of disk-label buffer */ -" label-size instance buffer: my-label" /* \ for disk-label argument string */ - -" get-memory-ihandles" /* \ So we can claim/map/free memory */ -" get-page-size value pagesize" /* \ get virt pagesize from vmem node */ -" get-mode value mode" /* \ get mode to map virt memory with */ - -" 0 instance value window-mapped?" /* \ just in case for pa's near 0 */ -" 0 instance value window-pa" /* \ physical base of virtual window */ -" 0 instance value window-base" /* \ virtual window base */ -" h# 10000 constant window-size" /* \ virtual window size */ - -" 0 instance value filepos" /* \ file position marker */ -" -1 value new-disk?" /* \ need to alloc new resources? */ - -" 0 instance value offset-low" /* \ Offset to start of partition */ -" 0 instance value offset-high" /* \ For partition relative seeks */ -" 0 instance value label-package" /* \ ihandle for disk-label package */ - -" external" /* \ Because device_type = block */ - -" 0 value size" /* \ size of disk */ -" 0 value #blocks" /* \ size of disk / decimal 512 */ - -" headerless" - -" : round-up" /* ( n -- n' ) */ -" 1- tuck + swap invert and" -" ;" - -" : init-label-package" /* ( adr len -- okay? ) */ -" 0 to offset-high 0 to offset-low" -" \" disk-label\" $open-package to label-package" -" label-package if" -" 0 0 \" offset\" label-package $call-method" -" to offset-high to offset-low" -" true" -" else" -" .\" Can't open disk label package\" cr false" -" then" -" ;" - -" : res-entry-len" /* ( n -- 64bit-len | 0 ) \ Get length of chunk n */ -" dup num-res-entries > if" -" drop 0" -" else" -" /res-entry * my-resources +" -" dup >res-len.lo l@ swap >res-len.hi l@" -" lxjoin" -" then" -" ;" - -" : res-entry-pa" /* ( n -- 64bit-pa | 0 ) \ Get phys address of chunk n */ -" dup num-res-entries > if" /* ( n ) */ -" drop 0" /* ( 0 ) */ -" else" /* ( n ) */ -" /res-entry * my-resources +" /* ( chunk-adr ) */ -" dup >res-pa.lo l@ swap >res-pa.hi l@" /* ( pa.lo pa.hi ) */ -" lxjoin" /* ( 64bit-pa ) */ -" then" /* ( 64bit-pa ) */ -" ;" - -" : claim-window" /* ( -- ) \ Claim mem for virt window */ -" window-size pagesize vir-claim to window-base" -" ;" - -" : release-window" /* ( -- ) \ Free virt window memory */ -" window-base window-size" -" 2dup vir-unmap" -" vir-release" -" ;" - -" : map-window" /* ( 64bit-pa -- ) \ Map a physical address to the v-window */ -" dup to window-pa" -" xlsplit window-base window-size mode vir-map" -" -1 to window-mapped?" -" ;" - -" : unmap-window" /* ( -- ) \ Unmap the virtual window */ -" window-base window-size vir-unmap" -" 0 to window-mapped?" -" ;" - -" : in-window?" /* ( pa -- in-window? ) */ -" window-mapped? if" -" window-pa dup window-size + 1- between" -" else" -" drop 0" -" then" -" ;" - -" : window-left" /* ( offset -- space-left-in-window ) */ -" window-size mod" -" window-size swap -" -" ;" - -" : release-resources" /* ( -- ) \ release previously claimed phys addrs */ -" num-res-entries 0 2dup = if" /* ( res-entries 0 ) */ -" 2drop exit" /* ( ) */ -" then" /* ( res-entries 0 ) */ -" do" /* ( ) */ -" i res-entry-pa xlsplit" /* ( pa.lo pa.hi ) */ -" i res-entry-len phy-release" /* ( ) */ -" loop" /* ( ) */ -" 0 to num-res-entries" /* ( ) */ -" my-resources max-res-entries /res-entry * erase" /* ( ) */ -" ;" - -" : fill-entry" /* ( pa.lo pa.hi size.lo size.hi -- ) \ fill chunk buf */ -" num-res-entries /res-entry * my-resources +" -" tuck >res-len.hi l!" -" tuck >res-len.lo l!" -" tuck >res-pa.hi l!" -" >res-pa.lo l!" -" num-res-entries 1+ to num-res-entries" -" ;" - -/* \ First attempt to claim the whole ramdisk contiguously. */ -/* \ If that doesn't work, try to claim it in smaller chunks */ - -" : attempt-claim" /* ( size -- error? ) */ -" size 0 begin" /* ( next totcl ) */ -" over pagesize phy-claim if" /* ( next totcl ) */ -" swap 2 / window-size" /* ( totcl next' ) */ -" round-up swap" /* ( next' totcl ) */ -" else" /* ( next totcl pa.lo,hi ) */ -" 2over drop xlsplit" /* ( next totcl pa.lo,hi len.lo,hi ) */ -" fill-entry" /* ( next totcl ) */ -" over +" /* ( next totcl ) */ -" then" /* ( next totcl ) */ -" 2dup size - 0>=" /* ( next totcl next comp? ) */ -" swap size max-res-entries /" /* ( next totcl comp? next smallest ) */ -" - 0< or" /* ( next totcl ) */ -" until" /* ( next totcl ) */ -" nip size - 0< if -1 else 0 then" -" ;" - -" : claim-resources" /* ( -- error? ) */ -" attempt-claim if release-resources -1 else 0 then" -" ;" - -/* \ Given a 0-relative disk offset compute the proper physical address */ -" : offset>pa" /* ( disk-offset -- 64bit-pa error? ) */ -" 0 num-res-entries 0 do" /* ( disk-offset 0 ) */ -" i res-entry-len +" /* ( disk-offset len' ) */ -" 2dup - 0< if" /* ( disk-offset len' ) */ -" - i res-entry-len +" /* ( offset-into-pa ) \ briefly -ve */ -" i res-entry-pa + 0" /* ( pa 0 ) */ -" unloop exit" /* ( pa 0 ) */ -" then" /* ( disk-offset len' ) */ -" loop" /* ( disk-offset len' ) */ -" drop -1" /* ( offset error ) */ -" ;" - -/* \ Map the virtual window to the physical-address corresponding to the */ -/* \ given 0-relative disk offset */ -" : get-window" /* ( offset -- va len error? ) */ -" dup offset>pa if" /* ( offset pa ) */ -" -1" /* ( offset pa -1 ) */ -" else" /* ( offset pa ) */ -" dup in-window? 0= if" /* ( offset pa ) */ -" unmap-window" /* ( offset pa ) */ -" over window-size mod - map-window" /* ( offset ) */ -" else" -" drop" -" then" -" window-base over window-size mod +" /* ( offset va ) */ -" swap window-left 0" /* ( va len 0 ) */ -" then" /* ( va len error? ) */ -" ;" - -" headers" - -/* \ Write len1 bytes from src into va. */ -" : partial-write" /* ( src len0 va len1 -- len' ) */ -" rot min dup >r move r>" -" ;" - -/* \ Read len1 bytes from src into va. */ -" : partial-read" /* ( src len0 va len1 -- len' ) */ -" rot min dup >r >r swap r> move r>" -" ;" - -" defer operation ' partial-write is operation" - -/* \ Write or Read len given the src address. The block-operation word */ -/* \ determines the physical address that corresponds to the current file */ -/* \ position, and maps/unmaps the 64K virtual window */ -" : block-operation" /* ( src len acf -- len' ) */ -" is operation" -" 0 -rot begin" /* ( 0 src len ) */ -" dup 0>" /* ( len' src len more? ) */ -" while" /* ( len' src len ) */ -" 2dup filepos" /* ( len' src len src len filepos ) */ -" get-window if" /* ( len' src len src len va len ) */ -" 2drop 2drop 2drop exit" /* ( len' ) */ -" then" /* ( len src len src len va len ) */ -" operation" /* ( len src len len' ) */ -" dup filepos + to filepos" /* ( len src len len' ) */ -" >r r@ - rot r@ + rot r> + rot" /* ( len' src' len' ) */ -" repeat" /* ( len' src' len' ) */ -" 2drop" /* ( len' ) */ -" ;" - -" : range-bad?" /* ( adr -- range-bad? ) */ -" 0 size between 0=" -" ;" - -" : space-left" /* ( -- space-left ) */ -" size filepos -" -" ;" - -" : hex-number" /* ( adr,len -- true | n false ) */ -" base @ >r hex $number r> base !" -" ;" - -" : parse-size" /* ( $nums -- 64bit-size | 0 ) \ poss ',' seperated ints */ -" ascii , left-parse-string" /* ( $num $num ) */ -" hex-number if 2drop 0 exit then" /* ( $num n ) */ -" over 0= if nip nip exit then" /* ( $num n ) */ -" -rot hex-number if drop 0 exit then" /* ( hi lo ) */ -" swap lxjoin" -" ;" - -" : set-size" /* ( adr len -- error? ) */ -" parse-size dup 0= if" /* ( size ) */ -" drop -1" /* ( -1 ) */ -" else" /* ( size ) */ -" window-size round-up" /* ( size' ) */ -" dup to size" /* ( size' ) */ -" d# 512 / to #blocks" /* ( ) */ -" \" nolabel\" my-label pack" /* \ first open cannot have a label */ -" drop 0" /* ( 0 ) */ -" then" /* ( error? ) */ -" ;" - -" : $=" /* (s adr1 len1 adr2 len2 -- same? ) */ -" rot tuck <> if 3drop false exit then" /* ( adr1 adr2 len1 ) */ -" comp 0=" /* ( same? ) */ -" ;" - -" : is-label?" /* ( adr len -- is-label? ) \ $= "nolabel" or <a-z> */ -" dup 1 = if" /* ( adr len ) */ -" drop c@ ascii a ascii z between" /* ( is-label? ) */ -" else" /* ( adr len ) */ -" \" nolabel\" $=" /* ( is-label? ) */ -" then" /* ( is-label? ) */ -" ;" - -" : set-label" /* ( adr len -- error? ) */ -" my-label label-size erase" -" dup 1+ label-size > if" -" 2drop -1" -" else" -" my-label pack drop 0" -" then" -" ;" - -" : process-args" /* ( arg$ -- error? ) */ -" ascii = left-parse-string" /* ( value$ key$ ) */ -" new-disk? if" /* ( value$ key$ ) */ -" 2dup \" size\" $= if" /* ( value$ key$ ) */ -" 2drop set-size exit" /* ( error? ) */ -" then" /* ( value$ key$ ) */ -" else" /* ( value$ key$ ) */ -" 2dup is-label? if" /* ( value$ key$ ) */ -" 2swap 2drop set-label exit" /* ( error? ) */ -" then" /* ( value$ key$ ) */ -" then" /* ( value$ key$ ) */ -" .\" Inappropriate argument \" type cr 2drop -1" /* ( -1 ) */ -" ;" - -/* \ Publish the physical chunks that make up the ramdisk in the */ -/* \ existing property */ -" : create-existing-prop" /* ( -- ) */ -" 0 0 encode-bytes" /* ( adr 0 ) */ -" num-res-entries 0 do" /* ( adr 0 ) */ -" i /res-entry * my-resources + >r" /* ( adr len ) */ -" r@ >res-pa.hi l@ encode-int encode+" /* ( adr len ) */ -" r@ >res-pa.lo l@ encode-int encode+" /* ( adr len ) */ -" r@ >res-len.hi l@ encode-int encode+" /* ( adr len ) */ -" r> >res-len.lo l@ encode-int encode+" /* ( adr len ) */ -" loop" /* ( adr len ) */ -" \" existing\" property" /* ( ) */ -" ;" - -" external" - -" : read" /* ( adr,len -- len' ) */ -" space-left" /* ( adr len space-left ) */ -" min ['] partial-read" /* ( adr len' read-acf ) */ -" block-operation" /* ( len' ) */ -" ;" - -" : write" /* ( adr,len -- len' ) */ -" space-left" /* ( adr len space-left ) */ -" min ['] partial-write" /* ( adr len' write-acf ) */ -" block-operation" /* ( len' ) */ -" ;" - -" : seek" /* ( offset other -- error? ) */ -" offset-high + swap offset-low + swap drop" /* \ "other" arg unused */ -" dup 0< if" /* ( offset ) */ -" size +" /* ( offset' ) */ -" then" /* ( offset' ) */ -" 0 + dup range-bad? if" /* ( offset' ) */ -" drop -1" /* ( -1 ) */ -" else" /* ( offset' ) */ -" to filepos false" /* ( 0 ) */ -" then" /* ( error? ) */ -" ;" - -" : load" /* ( addr -- size ) */ -" \" load\" label-package $call-method" -" ;" - -" : offset" /* ( rel -- abs ) \ needed for device_type = block */ -" offset-low +" -" ;" - -/* \ release resources, initialize data, remove existing property */ -/* \ Can be called with no instance data */ -" : destroy" /* ( -- ) */ -" \" existing\" delete-property" -" 0 to size" -" -1 to new-disk?" -" release-resources" -" ;" - -" : open" /* ( -- flag ) */ -" my-args process-args if" -" 0 exit" /* \ unrecognized arguments */ -" then" -" new-disk? if" -" claim-resources if 0 exit then" /* \ can't claim */ -" create-existing-prop" /* \ advertise resources */ -" 0 to new-disk?" /* \ no longer a new-disk */ -" then" -" claim-window" /* \ claim virtual window */ -" my-label count init-label-package 0= if 0 exit then" -" -1" -" ;" - -" : close" /* ( -- ) */ -" window-base if " -" release-window" -" then" +" 0 instance value current-offset " +" " +" 0 value ramdisk-base-va " +" 0 value ramdisk-size " +" 0 value alloc-size " +" " +" : set-props " +" ramdisk-size encode-int \" size\" property " +" ramdisk-base-va encode-int \" address\" property " +" alloc-size encode-int \" alloc-size\" property " +" ; " +" set-props " +" " +" : current-va ( -- adr ) ramdisk-base-va current-offset + ; " +" " +" external " +" " +" : open ( -- okay? ) " +/* " .\" ramdisk-open\" cr " */ +" true " +" ; " +" " +" : close ( -- ) " +" ; " +" " +" : seek ( off.low off.high -- error? ) " +/* " 2dup .\" ramdisk-seek: \" .x .x " */ +" drop dup ramdisk-size > if " +/* " .\" fail\" cr " */ +" drop true exit ( failed ) " +" then " +" to current-offset false ( succeeded ) " +/* " .\" OK\" cr " */ " ; " +" " +" : read ( addr len -- actual-len ) " +/* " 2dup .\" ramdisk-read: \" .x .x " */ +" dup current-offset + ( addr len new-off ) " +" dup ramdisk-size > if " +" ramdisk-size - - ( addr len' ) " +" ramdisk-size ( addr len new-off ) " +" then -rot ( new-off addr len ) " +" tuck current-va -rot move ( new-off len ) " +" swap to current-offset ( len ) " +/* " dup .x cr " */ +" ; " +" " +" : create ( alloc-sz base size -- ) " +" to ramdisk-size " +" to ramdisk-base-va " +" to alloc-size " +" set-props " +" ; " +" " "finish-device " +"pop-package " + +"\" /%s\" 2dup dev-open 0= if " +" open-abort " +"then 2drop " + +/* %x %x %x will be replaced by alloc-sz, base, size respectively */ +"h# %x h# %x h# %x ( alloc-sz base size ) " +"\" create\" dev-ih $call-method ( ) " +"dev-close " + +; + +char ramdisk_bootable[] = + +"\" /chosen\" get-package push-package " +" \" nfs\" encode-string \" fstype\" property " +" \" /%s\" encode-string \" bootarchive\" property " +"pop-package " + +" h# %x d# 512 + to load-base init-program " +; + +#define BOOT_ARCHIVE_ALLOC_SIZE (32 * 1024 * 1024) /* 32 MB */ +#define BOOTFS_VIRT ((caddr_t)0x50f00000) +#define ROOTFS_VIRT ((caddr_t)0x51000000) + +struct ramdisk_attr { + char *rd_name; + caddr_t rd_base; + size_t rd_size; +} ramdisk_attr[] = { + RD_BOOTFS, BOOTFS_VIRT, 0, + RD_ROOTFS, ROOTFS_VIRT, 0, + 0 +}; + +static struct ramdisk_attr * +ramdisk_lookup(char *ramdisk_name) +{ + int i; -"pop-package" + for (i = 0; ramdisk_attr[i].rd_name != 0; i++) { + if (strcmp(ramdisk_name, ramdisk_attr[i].rd_name) == 0) { + return (&ramdisk_attr[i]); + } + } + return (NULL); +} -; /* end of ramdisk_fth[] initialization */ +static void +ramdisk_free_mem(caddr_t addr, size_t size) +{ + caddr_t end_addr; + for (end_addr = addr + size; addr < end_addr; + addr += BOOT_ARCHIVE_ALLOC_SIZE) { + prom_free(addr, MIN(BOOT_ARCHIVE_ALLOC_SIZE, end_addr - addr)); + } +} /* - * Create an actual ramdisk instance. + * Allocate memory for ramdisk image. */ -static void -create_ramdisk_node(const char *ramdisk_name) +static caddr_t +ramdisk_alloc_mem(caddr_t addr, size_t size) +{ + caddr_t virt = addr; + caddr_t end_addr; + + for (end_addr = virt + size; virt < end_addr; + virt += BOOT_ARCHIVE_ALLOC_SIZE) { + if (prom_alloc(virt, + MIN(BOOT_ARCHIVE_ALLOC_SIZE, end_addr - virt), + 1) == NULL) { + ramdisk_free_mem(addr, virt - addr); + return (NULL); + } + } + return (addr); +} + +caddr_t +create_ramdisk(char *ramdisk_name, size_t size, char **devpath) { char *fth_buf; size_t buf_size; + struct ramdisk_attr *rdp; + char tdevpath[80]; + caddr_t virt; + static int need_preamble = 1; + + /* + * lookup ramdisk name. + */ + if ((rdp = ramdisk_lookup(ramdisk_name)) == NULL) + prom_panic("invalid ramdisk name"); + + virt = rdp->rd_base; + + /* + * Allocate memory. + */ + size = roundup(size, PAGESIZE); + if (ramdisk_alloc_mem(virt, size) == NULL) + prom_panic("can't alloc ramdisk memory"); + + rdp->rd_size = size; - buf_size = sizeof (ramdisk_fth) + strlen(ramdisk_name); + if (need_preamble) { + prom_interpret(ramdisk_preamble_fth, 0, 0, 0, 0, 0); + need_preamble = 0; + } + + /* + * add some space to the size to accommodate a few words in the + * snprintf() below. + */ + buf_size = sizeof (ramdisk_fth) + 80; fth_buf = bkmem_alloc(buf_size); - if (fth_buf == NULL) { + if (fth_buf == NULL) prom_panic("unable to allocate Forth buffer for ramdisk"); - } - (void) snprintf(fth_buf, buf_size, ramdisk_fth, ramdisk_name); + (void) snprintf(fth_buf, buf_size, ramdisk_fth, + ramdisk_name, ramdisk_name, + BOOT_ARCHIVE_ALLOC_SIZE, virt, size); prom_interpret(fth_buf, 0, 0, 0, 0, 0); - bkmem_free(fth_buf, buf_size); + + if (devpath != NULL) { + (void) snprintf(tdevpath, sizeof (tdevpath), "/%s:nolabel", + ramdisk_name); + *devpath = strdup(tdevpath); + } + + return (virt); } -int -create_ramdisk(const char *ramdisk_name, size_t size, char **device_path) +void +destroy_ramdisk(char *ramdisk_name) { - static int first_time = 1; - char buf[OBP_MAXPATHLEN]; - ihandle_t ih; + struct ramdisk_attr *rdp; /* - * Ensure that size is a multiple of page size (rounded up). + * lookup ramdisk name. */ - size = ptob(btopr(size)); + if ((rdp = ramdisk_lookup(ramdisk_name)) == NULL) + prom_panic("invalid ramdisk name"); -/* EXPORT DELETE START */ - bootlog("wanboot", BOOTLOG_VERBOSE, "Creating ramdisk, size=0x%lx", - size); -/* EXPORT DELETE END */ - - if (strcmp(ramdisk_name, RD_ROOTFS) == 0 || - strcmp(ramdisk_name, RD_BOOTFS) == 0) { + ramdisk_free_mem(rdp->rd_base, rdp->rd_size); + rdp->rd_size = 0; +} - if (first_time) { - first_time = 0; +/* + * change cwp! to drop in the 2nd word of (init-program) - really + * init-c-stack, but that word has no header. + * (you are not expected to undertsnad this) + */ +char obpfix[] = "' drop ' cwp! ' (init-program) >body ta1+ token@ (patch"; +char obpver[OBP_MAXPROPNAME]; +const char badver[] = "OBP 4.27."; - create_ramdisk_node(RD_ROOTFS); - create_ramdisk_node(RD_BOOTFS); - } - (void) snprintf(buf, sizeof (buf), "/%s:nolabel", ramdisk_name); - *device_path = strdup(buf); +void +boot_ramdisk(char *ramdisk_name) +{ + char *fth_buf; + size_t buf_size; + struct ramdisk_attr *rdp; + void do_sg_go(void); - if (*device_path != NULL) { - (void) snprintf(buf, sizeof (buf), "/%s:size=%x,%x", - ramdisk_name, - (uint32_t)(size >> 32), (uint32_t)size); + /* + * OBP revs 4.27.0 to 4.27.8 started using + * windowed regs for the forth kernel, but + * init-program still blindly 0'd %cwp, which + * causes predictably disaterous consequences + * when called with %cwp != 0. + * + * We detect and fix this here + */ + if (prom_version_name(obpver, OBP_MAXPROPNAME) != -1 && + strncmp(obpver, badver, sizeof (badver) - 1) == 0) { + char ch = obpver[sizeof (badver) - 1]; - if ((ih = prom_open(buf)) != 0) { - return (ih); - } + if (ch >= '0' && ch <= '8') { + prom_interpret(obpfix, 0, 0, 0, 0, 0); } } -/* EXPORT DELETE START */ - bootlog("wanboot", BOOTLOG_CRIT, "Cannot create ramdisk \"%s\"", - ramdisk_name); -/* EXPORT DELETE END */ - prom_panic("create_ramdisk: fatal error"); - /* NOTREACHED */ + /* close all open devices */ + closeall(1); + + /* + * lookup ramdisk name. + */ + if ((rdp = ramdisk_lookup(ramdisk_name)) == NULL) + prom_panic("invalid ramdisk name"); + + /* + * add some space to the size to accommodate a few words in the + * snprintf() below. + */ + buf_size = sizeof (ramdisk_bootable) + 80; + + fth_buf = bkmem_alloc(buf_size); + if (fth_buf == NULL) + prom_panic("unable to allocate Forth buffer for ramdisk"); + + (void) snprintf(fth_buf, buf_size, ramdisk_bootable, + ramdisk_name, rdp->rd_base); + + prom_interpret(fth_buf, 0, 0, 0, 0, 0); + + /* + * Ugh Serengeti proms don't execute C programs + * in init-program, and 'go' doesn't work when + * launching a second C program (inetboot itself + * was launched as the 1st C program). Nested fcode + * programs work, but that doesn't help the kernel. + */ + do_sg_go(); +} + +void +do_sg_go() +{ + pnode_t chosen = prom_chosennode(); + Elf64_Ehdr *ehdr; + Elf64_Addr entry; + uint32_t eadr; + extern int is_sg; + extern caddr_t sg_addr; + extern size_t sg_len; + + if (!is_sg) + prom_panic("do_sg_go"); + + /* + * The ramdisk bootblk left a pointer to the elf image + * in 'elfheader-address' Use it to find the kernel's + * entry point. + */ + if (prom_getprop(chosen, "elfheader-address", (caddr_t)&eadr) == -1) + prom_panic("no elf header property"); + ehdr = (Elf64_Ehdr *)(uintptr_t)eadr; + if (ehdr->e_machine != EM_SPARCV9) + prom_panic("bad ELF header"); + entry = ehdr->e_entry; + + /* + * free extra bootmem + */ + prom_free(sg_addr, sg_len); + + /* + * Use pre-newboot's exitto64() to launch the kernel + */ + exitto64((int (*)())entry, NULL); + prom_panic("exitto returned"); } diff --git a/usr/src/psm/stand/boot/sparc/common/ramdisk.h b/usr/src/psm/stand/boot/sparc/common/ramdisk.h index 77eb021a11..561b210f75 100644 --- a/usr/src/psm/stand/boot/sparc/common/ramdisk.h +++ b/usr/src/psm/stand/boot/sparc/common/ramdisk.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -39,9 +38,11 @@ extern "C" { * Ramdisk names */ #define RD_BOOTFS "ramdisk-bootfs" -#define RD_ROOTFS "ramdisk-rootfs" +#define RD_ROOTFS "ramdisk-root" -extern int create_ramdisk(const char *, size_t, char **); +extern caddr_t create_ramdisk(char *, size_t, char **); +extern void destroy_ramdisk(char *); +extern void boot_ramdisk(char *); #ifdef __cplusplus } diff --git a/usr/src/psm/stand/boot/sparc/common/sun4x_standalloc.c b/usr/src/psm/stand/boot/sparc/common/sun4x_standalloc.c index 707c7ff5c2..a68c6d0d47 100644 --- a/usr/src/psm/stand/boot/sparc/common/sun4x_standalloc.c +++ b/usr/src/psm/stand/boot/sparc/common/sun4x_standalloc.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -104,6 +103,15 @@ static caddr_t free_addr[N_FREELIST]; static caddr_t top_bootmem = MAPPEDMEM_MINTOP; static caddr_t top_resvmem, scratchresvp; +/* + * with newboot, boot goes away when it launches the client, + * so we can safely extend bootmem on sg, and give it back + * before we die. + */ +int is_sg; +caddr_t sg_addr; +size_t sg_len; + static int impl_name(char *buf, size_t bufsz) { @@ -212,8 +220,13 @@ resalloc_init(void) * but we don't have the ability to check for the firmware version here. */ if (strcmp(iarch, "SUNW,Sun-Fire") == 0 || - strcmp(iarch, "SUNW,Netra-T12") == 0) - return; + strcmp(iarch, "SUNW,Netra-T12") == 0) { + is_sg = 1; + sg_addr = MAPPEDMEM_MINTOP; + sg_len = MAPPEDMEM_FULLTOP - MAPPEDMEM_MINTOP; + if (prom_alloc(sg_addr, sg_len, 1) != sg_addr) + prom_panic("can't extend sg bootmem"); + } top_bootmem = MAPPEDMEM_FULLTOP; @@ -264,7 +277,7 @@ resalloc(enum RESOURCES type, size_t bytes, caddr_t virthint, int align) if (vaddr == (caddr_t)virthint) return (vaddr); printf("Alloc of 0x%lx bytes at 0x%p refused.\n", - bytes, (void *)virthint); + bytes, (void *)virthint); return ((caddr_t)0); /*NOTREACHED*/ diff --git a/usr/src/psm/stand/boot/sparc/common/wanboot.c b/usr/src/psm/stand/boot/sparc/common/wanboot.c index 236746d9f6..2c8121f7a6 100644 --- a/usr/src/psm/stand/boot/sparc/common/wanboot.c +++ b/usr/src/psm/stand/boot/sparc/common/wanboot.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -77,7 +76,8 @@ /* * Experimentation has shown that an 8K download buffer is optimal */ -static char buffer[8192]; +#define HTTP_XFER_SIZE 8192 +static char buffer[HTTP_XFER_SIZE]; bc_handle_t bc_handle; @@ -428,7 +428,7 @@ read_digest(const char *what, http_handle_t handle, unsigned char *sdigest) lenstr = http_get_header_value(handle, CONTENT_LENGTH); if (lenstr == NULL) { bootlog("wanboot", BOOTLOG_ALERT, - "%s: error getting digest length", what); + "%s: error getting digest length", what); return (1); } digest_size = (size_t)strtol(lenstr, NULL, 10); @@ -439,8 +439,8 @@ read_digest(const char *what, http_handle_t handle, unsigned char *sdigest) */ if (digest_size != HMAC_DIGEST_LEN) { bootlog("wanboot", BOOTLOG_CRIT, - "%s: error validating response - invalid digest size", - what); + "%s: error validating response - invalid digest size", + what); return (-1); } @@ -449,7 +449,7 @@ read_digest(const char *what, http_handle_t handle, unsigned char *sdigest) */ if (read_bytes(handle, (char *)sdigest, digest_size) != 0) { bootlog("wanboot", BOOTLOG_ALERT, - "%s: error reading digest", what); + "%s: error reading digest", what); return (1); } @@ -469,7 +469,7 @@ read_digest(const char *what, http_handle_t handle, unsigned char *sdigest) * 1 = HTTP download error */ static int -write_msg_to_ramdisk(const char *what, int fd, http_handle_t handle, +write_msg_to_ramdisk(const char *what, caddr_t addr, http_handle_t handle, size_t ramdisk_size, off_t *offset, SHA1_CTX *sha) { int len; @@ -497,13 +497,14 @@ write_msg_to_ramdisk(const char *what, int fd, http_handle_t handle, "Continuing read of %s file system (%ld kB)", what, ramdisk_size / 1024); } - for (ret = 0; ret == 0 && *offset < ramdisk_size; *offset += len) { + for (ret = 0; ret == 0 && *offset < ramdisk_size; + *offset += len, addr += len) { nleft = ramdisk_size - *offset; if (nleft > sizeof (buffer)) nleft = sizeof (buffer); - len = http_read_body(handle, buffer, nleft); + len = http_read_body(handle, addr, nleft); if (len <= 0) { print_errors("http_read_body", handle); /* @@ -517,13 +518,7 @@ write_msg_to_ramdisk(const char *what, int fd, http_handle_t handle, ret = 1; } if (sha != NULL) { - HMACUpdate(sha, (uchar_t *)buffer, (size_t)len); - } - if (prom_write(fd, buffer, (size_t)len, 0, 0) != (ssize_t)len) { - bootlog("wanboot", BOOTLOG_CRIT, - "%s: write to ramdisk failed", what); - ret = -1; - continue; + HMACUpdate(sha, (uchar_t *)addr, (size_t)len); } if (bootlog_progress == bootlog_message_interval) { bootlog("wanboot", BOOTLOG_PROGRESS, @@ -790,10 +785,10 @@ establish_http_connection(const char *what, http_handle_t *handlep, if ((offset == 0 && resp->code != 200) || (offset != 0 && resp->code != 206)) { bootlog("wanboot", BOOTLOG_ALERT, - "%s: Request returned code %d", what, resp->code); + "%s: Request returned code %d", what, resp->code); if (resp->statusmsg != NULL && resp->statusmsg[0] != '\0') bootlog("wanboot", BOOTLOG_ALERT, - "%s", resp->statusmsg); + "%s", resp->statusmsg); http_free_respinfo(resp); (void) http_srv_close(*handlep); return (1); @@ -929,7 +924,7 @@ get_miniinfo(const url_t *server_url, size_t *mini_size, } if ((ret = process_miniinfo(handle, mini_size, - sdigest)) > 0) { + sdigest)) > 0) { if (!wanboot_retry(++retry_cnt, retry_max)) { (void) http_srv_close(handle); break; @@ -985,10 +980,10 @@ process_miniroot(http_handle_t handle, hash_type_t htype, { static SHA1_CTX sha; static size_t miniroot_size; - static int fd = -1; + static caddr_t miniroot_vaddr = NULL; int ret; - if (fd == -1) { + if (miniroot_vaddr == NULL) { if (htype == HASH_HMAC_SHA1) { bootlog("wanboot", BOOTLOG_INFO, "%s: Authentication will use HMAC-SHA1", MINIROOT); @@ -997,23 +992,14 @@ process_miniroot(http_handle_t handle, hash_type_t htype, miniroot_size = length; - fd = create_ramdisk(RD_ROOTFS, miniroot_size, devpath); + miniroot_vaddr = create_ramdisk(RD_ROOTFS, miniroot_size, + devpath); } - if (prom_seek(fd, *offset) == -1) { - bootlog("wanboot", BOOTLOG_CRIT, - "%s: prom_seek error", MINIROOT); - return (-1); - } + miniroot_vaddr += *offset; - if ((ret = write_msg_to_ramdisk(MINIROOT, fd, handle, miniroot_size, - offset, (htype == HASH_NONE) ? NULL : &sha)) != 0) { - if (ret < 0) { - /* - * Reentry not supported. - */ - (void) prom_close(fd); - } + if ((ret = write_msg_to_ramdisk(MINIROOT, miniroot_vaddr, handle, + miniroot_size, offset, (htype == HASH_NONE) ? NULL : &sha)) != 0) { return (ret); } @@ -1021,8 +1007,6 @@ process_miniroot(http_handle_t handle, hash_type_t htype, HMACFinal(&sha, g_hash_key, WANBOOT_HMAC_KEY_SIZE, cdigest); } - (void) prom_close(fd); - return (0); } @@ -1177,9 +1161,8 @@ encr_fini(encr_type_t etype, void *eh) } /* - * This routine is called by process_wanbootfs() to read the encrypted - * file system from ramdisk and decrypt it. This routine will rewrite - * the file system back to ramdisk in place. The method of decryption + * This routine is called by process_wanbootfs() to decrypt the encrypted + * file system from ramdisk in place. The method of decryption * (algorithm) will have already been determined by process_wanbootfs() * and the cbc_handle passed to this routine will already have been * initialized appropriately. @@ -1189,45 +1172,13 @@ encr_fini(encr_type_t etype, void *eh) * 0 = Success */ static int -decrypt_wanbootfs(int fd, cbc_handle_t *ch, uint8_t *iv, - size_t block_size, size_t wanbootfs_size) +decrypt_wanbootfs(caddr_t addr, cbc_handle_t *ch, uint8_t *iv, + size_t wanbootfs_size) { - size_t total; - size_t len; - size_t nleft; - size_t max_read_size; - - max_read_size = (sizeof (buffer) / block_size) * block_size; - for (total = 0; total < wanbootfs_size; total += len) { - if (prom_seek(fd, total) == -1) { - bootlog("wanboot", BOOTLOG_CRIT, - "%s: prom_seek error", WANBOOTFS); - return (-1); - } - nleft = wanbootfs_size - total; - if (nleft > max_read_size) - nleft = max_read_size; - len = prom_read(fd, buffer, nleft, 0, 0); - if (len != nleft) { - bootlog("wanboot", BOOTLOG_CRIT, - "%s: prom_read error", WANBOOTFS); - return (-1); - } - if (!cbc_decrypt(ch, (uint8_t *)buffer, len, iv)) { - bootlog("wanboot", BOOTLOG_CRIT, - "%s: cbc decrypt error", WANBOOTFS); - return (-1); - } - if (prom_seek(fd, total) == -1) { - bootlog("wanboot", BOOTLOG_CRIT, - "%s: prom_seek error", WANBOOTFS); - return (-1); - } - if (prom_write(fd, buffer, len, 0, 0) != len) { - bootlog("wanboot", BOOTLOG_CRIT, - "%s: prom_write error", WANBOOTFS); - return (-1); - } + if (!cbc_decrypt(ch, (uint8_t *)addr, wanbootfs_size, iv)) { + bootlog("wanboot", BOOTLOG_CRIT, + "%s: cbc decrypt error", WANBOOTFS); + return (-1); } return (0); } @@ -1279,7 +1230,7 @@ process_wanbootfs(http_handle_t handle, char **devpath, size_t wanbootfs_size; size_t block_size; off_t offset; - static int fd = -1; + static caddr_t bootfs_vaddr = NULL; int ret; switch (hash_type) { @@ -1371,25 +1322,16 @@ process_wanbootfs(http_handle_t handle, char **devpath, * the already existing ramdisk and seek back to the * beginning of the file. */ - if (fd == -1) { - fd = create_ramdisk(RD_BOOTFS, wanbootfs_size, devpath); + if (bootfs_vaddr == NULL) { + bootfs_vaddr = create_ramdisk(RD_BOOTFS, wanbootfs_size, + devpath); } offset = 0; - if (prom_seek(fd, offset) == -1) { - bootlog("wanboot", BOOTLOG_CRIT, - "%s: prom_seek error", WANBOOTFS); - return (-1); - } - if ((ret = write_msg_to_ramdisk(WANBOOTFS, fd, handle, wanbootfs_size, - &offset, (hash_type == HASH_NONE) ? NULL : &sha)) != 0) { - if (ret < 0) { - /* - * Reentry not supported. - */ - (void) prom_close(fd); - } + if ((ret = write_msg_to_ramdisk(WANBOOTFS, bootfs_vaddr, handle, + wanbootfs_size, &offset, (hash_type == HASH_NONE) ? NULL : &sha)) + != 0) { return (ret); } @@ -1401,18 +1343,14 @@ process_wanbootfs(http_handle_t handle, char **devpath, * If encrypted, then decrypt it. */ if (encr_type != ENCR_NONE) { - ret = decrypt_wanbootfs(fd, &ch, iv, block_size, - wanbootfs_size); + ret = decrypt_wanbootfs(bootfs_vaddr, &ch, iv, wanbootfs_size); if (ret != 0) { encr_fini(encr_type, eh); - (void) prom_close(fd); return (-1); } encr_fini(encr_type, eh); } - (void) prom_close(fd); - return (read_digest(WANBOOTFS, handle, sdigest)); } @@ -1472,7 +1410,7 @@ get_wanbootfs(const url_t *server_url) bzero(cdigest, sizeof (cdigest)); do { if ((ret = establish_http_connection(WANBOOTFS, &handle, - &req_url, 0)) < 0) { + &req_url, 0)) < 0) { break; } else if (ret > 0) { if (wanboot_retry(++retry_cnt, retry_max)) { @@ -1483,7 +1421,7 @@ get_wanbootfs(const url_t *server_url) } if ((ret = process_wanbootfs(handle, &devpath, - cdigest, sdigest)) > 0) { + cdigest, sdigest)) > 0) { if (!wanboot_retry(++retry_cnt, retry_max)) { (void) http_srv_close(handle); break; @@ -1498,7 +1436,7 @@ get_wanbootfs(const url_t *server_url) * Validate the computed digest against the one received. */ if (ret != 0 || - !verify_digests(WANBOOTFS, cdigest, sdigest)) { + !verify_digests(WANBOOTFS, cdigest, sdigest)) { bootlog("wanboot", BOOTLOG_CRIT, "The wanboot file system download aborted"); return (-1); @@ -1530,7 +1468,7 @@ get_wanbootfs(const url_t *server_url) */ if ((fd = open(WANBOOTFS_NONCE_FILE, O_RDONLY)) == -1) { bootlog("wanboot", BOOTLOG_CRIT, - "No nonce found in the wanboot file system"); + "No nonce found in the wanboot file system"); bootlog("wanboot", BOOTLOG_CRIT, "The wanboot file system download aborted"); return (-1); @@ -1540,7 +1478,7 @@ get_wanbootfs(const url_t *server_url) bcmp(nonce, buf, NONCELEN) != 0) { (void) close(fd); bootlog("wanboot", BOOTLOG_CRIT, - "Invalid nonce found in the wanboot file system"); + "Invalid nonce found in the wanboot file system"); bootlog("wanboot", BOOTLOG_CRIT, "The wanboot file system download aborted"); return (-1); @@ -1633,7 +1571,7 @@ init_netdev(char *bpath) * * - The wanboot miniroot is downloaded over http/https into the rootfs * ramdisk. The bootfs filesystem is unmounted, and the rootfs filesystem - * is mounted. + * is booted. */ /* EXPORT DELETE END */ /*ARGSUSED*/ @@ -1723,39 +1661,7 @@ bootprog(char *bpath, char *bargs, boolean_t user_specified_filename) */ (void) unmountroot(); - /* - * Mount the miniroot. - */ - if (determine_fstype_and_mountroot(miniroot_path) != VFS_SUCCESS) { - bootlog("wanboot", BOOTLOG_CRIT, - "Could not mount miniroot filesystem"); - return (-1); - } - bootlog("wanboot", BOOTLOG_VERBOSE, "The miniroot has been mounted"); - - v2path = "/ramdisk-rootfs:a"; - bootlog("wanboot", BOOTLOG_VERBOSE, "device path '%s'", v2path); - - /* - * kernname (default-name) might have changed if mountroot() called - * boot_nfs_mountroot(), and it called set_default_filename(). - */ - if (! user_specified_filename) - (void) strcpy(filename, kernname); - - bootlog("wanboot", BOOTLOG_VERBOSE, - "standalone = `%s', args = `%s'", filename, bargs); - - set_client_bootargs(filename, bargs); - - /* - * We're done with the mac interface that was initialized by - * mac_init() inside init_netdev(). - */ - mac_fini(); - - bootconf_end(&bc_handle); - bootinfo_end(); + boot_ramdisk(RD_ROOTFS); /* EXPORT DELETE END */ return (0); diff --git a/usr/src/psm/stand/boot/sparcv9/Makefile.com b/usr/src/psm/stand/boot/sparcv9/Makefile.com index aac89a4000..2417ee62ed 100644 --- a/usr/src/psm/stand/boot/sparcv9/Makefile.com +++ b/usr/src/psm/stand/boot/sparcv9/Makefile.com @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -22,7 +21,7 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # psm/stand/boot/sparcv9/Makefile.com @@ -40,9 +39,9 @@ MACH_DIR = ../../sparc/common PLAT_DIR = . BOOT_DIR = $(SRC)/psm/stand/boot -BOOT_SRC = boot.c wanboot.c +BOOT_SRC = inetboot.c wanboot.c -CONF_SRC = ufsconf.c nfsconf.c hsfsconf.c wbfsconf.c wbcli.c +CONF_SRC = nfsconf.c wbfsconf.c wbcli.c TOP_CMN_C_SRC = getoptstr.c @@ -50,7 +49,7 @@ MISC_SRC = ramdisk.c CMN_C_SRC = heap_kmem.c readfile.c -MACH_C_SRC = boot_plat.c bootops.c bootprop.c boot_services.c bootflags.c +MACH_C_SRC = boot_plat.c bootops.c bootprop.c bootflags.c MACH_C_SRC += get.c BOOT_OBJS = $(BOOT_SRC:%.c=%.o) @@ -120,9 +119,6 @@ LIBPROM_LIBS += libprom.a # The following libraries are built in LIBSYS_DIR # LIBSYS_DIR += $(SYSLIBDIR) -LIBSYS_LIBS += libufs.a libhsfs.a libnfs.a libxdr.a \ - libsock.a libinet.a libtcp.a libtcpstubs.a libscrypt.a \ - libwanboot.a libsa.a libmd5.a libnvpair.a # # Used to convert ELF to an a.out and ensure alignment @@ -139,22 +135,13 @@ ELFCONV = ./$(STRIPALIGN) # Default value .PARALLEL: $(OBJS) $(CONF_OBJS) $(MISC_OBJS) $(SRT0_OBJ) $(BOOT_OBJS) .PARALLEL: $(L_OBJS) $(CONF_L_OBJS) $(MISC_L_OBJS) $(SRT0_L_OBJ) \ $(BOOT_L_OBJS) -.PARALLEL: $(UFSBOOT) $(HSFSBOOT) $(NFSBOOT) $(WANBOOT) +.PARALLEL: $(NFSBOOT) $(WANBOOT) -all: $(ELFCONV) $(UFSBOOT) $(HSFSBOOT) $(NFSBOOT) $(WANBOOT) +all: $(ELFCONV) $(NFSBOOT) $(WANBOOT) $(STRIPALIGN): $(CMN_DIR)/$$(@).c $(NATIVECC) -o $@ $(CMN_DIR)/$@.c -# 4.2 ufs filesystem booter -# -# Libraries used to build ufsboot -# -LIBUFS_LIBS = libufs.a libnames.a libsa.a libprom.a $(LIBPLAT_LIBS) -UFS_LIBS = $(LIBUFS_LIBS:lib%.a=-l%) -UFS_DIRS = $(LIBNAME_DIR:%=-L%) $(LIBSYS_DIR:%=-L%) -UFS_DIRS += $(LIBPLAT_DIR:%=-L%) $(LIBPROM_DIR:%=-L%) - # # Note that the presumption is that someone has already done a `make # install' from usr/src/stand/lib, such that all of the standalone @@ -167,39 +154,6 @@ L_LIBDEPS= $(LIBPROM_DIR)/llib-lprom.ln $(LIBPLAT_DEP_L) \ $(LIBNAME_DIR)/llib-lnames.ln # -# Loader flags used to build ufsboot -# -UFS_MAPFILE = $(MACH_DIR)/mapfile -UFS_LDFLAGS = -dn -M $(UFS_MAPFILE) -e _start $(UFS_DIRS) -UFS_L_LDFLAGS = $(UFS_DIRS) - -# -# Object files used to build ufsboot -# -UFS_SRT0 = $(SRT0_OBJ) -UFS_OBJS = $(OBJS) ufsconf.o boot.o -UFS_L_OBJS = $(UFS_SRT0:%.o=%.ln) $(UFS_OBJS:%.o=%.ln) - -# -# Build rules to build ufsboot -# - -$(UFSBOOT).elf: $(UFS_MAPFILE) $(UFS_SRT0) $(UFS_OBJS) $(LIBDEPS) - $(LD) $(UFS_LDFLAGS) -o $@ $(UFS_SRT0) $(UFS_OBJS) $(UFS_LIBS) - $(MCS) -d $@ - $(POST_PROCESS) - $(POST_PROCESS) - $(MCS) -c $@ - -$(UFSBOOT): $(UFSBOOT).elf - $(RM) $@; cp $@.elf $@ - $(STRIP) $@ - -$(UFSBOOT)_lint: $(L_LIBDEPS) $(UFS_L_OBJS) - @echo "" - @echo ufsboot lint: global crosschecks: - $(LINT.c) $(UFS_L_LDFLAGS) $(UFS_L_OBJS) $(UFS_LIBS) - # WANboot booter # # Libraries used to build wanboot @@ -259,44 +213,6 @@ $(WANBOOT)_lint: $(L_LIBDEPS) $(WAN_L_OBJS) # High-sierra filesystem booter. Probably doesn't work. -# -# Libraries used to build hsfsboot -# -LIBHSFS_LIBS = libhsfs.a libnames.a libsa.a libprom.a $(LIBPLAT_LIBS) -HSFS_LIBS = $(LIBHSFS_LIBS:lib%.a=-l%) -HSFS_DIRS = $(LIBNAME_DIR:%=-L%) $(LIBSYS_DIR:%=-L%) -HSFS_DIRS += $(LIBPLAT_DIR:%=-L%) $(LIBPROM_DIR:%=-L%) - -# -# Loader flags used to build hsfsboot -# -HSFS_MAPFILE = $(MACH_DIR)/mapfile -HSFS_LDFLAGS = -dn -M $(HSFS_MAPFILE) -e _start $(HSFS_DIRS) -HSFS_L_LDFLAGS = $(HSFS_DIRS) - -# -# Object files used to build hsfsboot -# -HSFS_SRT0 = $(SRT0_OBJ) -HSFS_OBJS = $(OBJS) hsfsconf.o boot.o -HSFS_L_OBJS = $(HSFS_SRT0:%.o=%.ln) $(HSFS_OBJS:%.o=%.ln) - -$(HSFSBOOT).elf: $(HSFS_MAPFILE) $(HSFS_SRT0) $(HSFS_OBJS) $(LIBDEPS) - $(LD) $(HSFS_LDFLAGS) -o $@ $(HSFS_SRT0) $(HSFS_OBJS) $(HSFS_LIBS) - $(MCS) -d $@ - $(POST_PROCESS) - $(POST_PROCESS) - $(MCS) -c $@ - -$(HSFSBOOT): $(HSFSBOOT).elf - $(RM) $(@); cp $@.elf $@ - $(STRIP) $@ - -$(HSFSBOOT)_lint: $(HSFS_L_OBJS) $(L_LIBDEPS) - @echo "" - @echo hsfsboot lint: global crosschecks: - $(LINT.c) $(HSFS_L_LDFLAGS) $(HSFS_L_OBJS) $(HSFS_LIBS) - # NFS booter # @@ -320,7 +236,7 @@ NFS_L_LDFLAGS = $(NFS_DIRS) # Object files used to build inetboot # NFS_SRT0 = $(SRT0_OBJ) -NFS_OBJS = $(OBJS) nfsconf.o boot.o +NFS_OBJS = $(OBJS) nfsconf.o inetboot.o ramdisk.o NFS_L_OBJS = $(NFS_SRT0:%.o=%.ln) $(NFS_OBJS:%.o=%.ln) $(NFSBOOT).elf: $(ELFCONV) $(NFS_MAPFILE) $(NFS_SRT0) $(NFS_OBJS) $(LIBDEPS) @@ -350,13 +266,13 @@ install: $(ROOT_PSM_WANBOOT) clean: $(RM) make.out lint.out $(RM) $(OBJS) $(CONF_OBJS) $(MISC_OBJS) $(BOOT_OBJS) $(SRT0_OBJ) - $(RM) $(NFSBOOT).elf $(UFSBOOT).elf $(HSFSBOOT).elf $(WANBOOT).elf + $(RM) $(NFSBOOT).elf $(WANBOOT).elf $(RM) $(L_OBJS) $(CONF_L_OBJS) $(MISC_L_OBJS) $(BOOT_L_OBJS) \ $(SRT0_L_OBJ) clobber: clean - $(RM) $(UFSBOOT) $(HSFSBOOT) $(NFSBOOT) $(WANBOOT) $(STRIPALIGN) + $(RM) $(NFSBOOT) $(WANBOOT) $(STRIPALIGN) -lint: $(UFSBOOT)_lint $(NFSBOOT)_lint $(WANBOOT)_lint +lint: $(NFSBOOT)_lint $(WANBOOT)_lint include $(BOOTSRCDIR)/Makefile.targ diff --git a/usr/src/psm/stand/bootblks/Makefile b/usr/src/psm/stand/bootblks/Makefile index 81530b7c2b..b900dfb83d 100644 --- a/usr/src/psm/stand/bootblks/Makefile +++ b/usr/src/psm/stand/bootblks/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -22,14 +21,14 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright (c) 1994 by Sun Microsystems, Inc. -# All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # # psm/stand/bootblks/Makefile # include ../../../Makefile.master -SUBDIRS = ufs hsfs +SUBDIRS = ufs hsfs zfs all install clean clobber lint: $(SUBDIRS) diff --git a/usr/src/psm/stand/bootblks/Makefile.1275 b/usr/src/psm/stand/bootblks/Makefile.1275 index 1066fef16c..63f4ebcff9 100644 --- a/usr/src/psm/stand/bootblks/Makefile.1275 +++ b/usr/src/psm/stand/bootblks/Makefile.1275 @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -22,7 +21,8 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright (c) 1994, by Sun Microsystems, Inc. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # # psm/stand/bootblks/Makefile.1275 # @@ -31,23 +31,41 @@ # Sources and objects used to build the Forth-based bootblock # for all Sun OpenFirmware machines (IEEE Std. 1275) # -# Same names for both filesystems. +# Common pieces # -FORTH_SRC = boot_1275.fth -FORTH_FCODE = $(FORTH_SRC:%.fth=%.fcode) +BOOT_SRC = util.fth boot.fth +RD_SRC = rd.fth + +RD_FCODE = rd.fcode + +MKBB = mkbb +MKBB_SH = $(BASEDIR)/common/mkbb.sh + +%.fcode: $(BASEDIR)/common/%.fth + $(TOKENIZE) $< # # Targets # -$(PROG): $(FORTH_FCODE) +all: $(PROG) + +$(MKBB): $(MKBB_SH) + $(RM) $@ + cat $(MKBB_SH) > $@ + chmod +x $@ + +$(FS_BB): $(MKBB) $(FS_FCODE) $(RD_FCODE) + $(MKBB) $(FS_FCODE) $(RD_FCODE) $(FS_BB) + +$(PROG): $(FS_BB) @-$(RM) $@ - cp -p $(FORTH_FCODE) $@ + cp -p $(FS_BB) $@ clean: - -$(RM) $(FORTH_FCODE) + -$(RM) $(FS_FCODE) $(RD_FCODE) -clobber: clean - -$(RM) $(PROG) +clobber: clean + -$(RM) $(PROG) $(FS_BB) lint: FRC diff --git a/usr/src/psm/stand/bootblks/common/boot.fth b/usr/src/psm/stand/bootblks/common/boot.fth new file mode 100644 index 0000000000..997efb6b9f --- /dev/null +++ b/usr/src/psm/stand/bootblks/common/boot.fth @@ -0,0 +1,609 @@ +\ +\ CDDL HEADER START +\ +\ The contents of this file are subject to the terms of the +\ Common Development and Distribution License (the "License"). +\ You may not use this file except in compliance with the License. +\ +\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ or http://www.opensolaris.org/os/licensing. +\ See the License for the specific language governing permissions +\ and limitations under the License. +\ +\ When distributing Covered Code, include this CDDL HEADER in each +\ file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ If applicable, add the following below this CDDL HEADER, with the +\ fields enclosed by brackets "[]" replaced with your own identifying +\ information: Portions Copyright [yyyy] [name of copyright owner] +\ +\ CDDL HEADER END +\ +\ +\ ident "%Z%%M% %I% %E% SMI" +\ Copyright 2007 Sun Microsystems, Inc. All rights reserved. +\ Use is subject to license terms. +\ + +id: %Z%%M% %I% %E% SMI +purpose: boot block for OBP systems +copyright: Copyright 2007 Sun Microsystems, Inc. All Rights Reserved + + +headerless +d# 1024 dup * constant 1meg +d# 4 1meg * constant 4meg +d# 32 1meg * constant 32meg + +headers +" /" get-package constant root-ph + +0 value fs-ih +false value nested? +0 value file-sz + +/buf-len buffer: boot-dev +: boot-dev$ ( -- dev$ ) boot-dev cscount ; + +: loader-base ( -- base ) + nested? if + h# 5000.0000 + else + h# 5100.0000 + then +; + + +\ +\ methods we expect of fs reader packages +\ +headerless +: fs-open ( file$ -- fd true | false ) + " open-file" fs-ih $call-method +; + +: fs-close ( fd -- ) + " close-file" fs-ih $call-method +; + +: fs-size ( fd -- size ) + " size-file" fs-ih $call-method +; + +: fs-read ( adr len fd -- #read ) + " read-file" fs-ih $call-method +; + +: fs-getrd ( adr len -- ) + " get-rd" fs-ih $call-method +; + +: fs-bootprop ( -- propval propname true | false ) + " bootprop" fs-ih $call-method +; +headers + + +\ zfs bootblks with all headers exceeds 7.5k +\ 'bigbootblk' allows us to load the fs reader from elsewhere +[ifdef] bigbootblk + +: load-pkg ( -- ) + boot-dev$ 2dup dev-open ?dup 0= if ( dev$ ) + open-abort + then >r 2drop ( r: ih ) + /fs-fcode mem-alloc ( adr r: ih ) + dup /fs-fcode fs-offset r@ read-disk + dup 1 byte-load + /fs-fcode mem-free ( r: ih ) + r> dev-close +; + +[else] + +: load-pkg ( -- ) ; + +[then] + + +: get-bootdev ( -- ) + \ first try boot archive (nested boot from ramdisk) + \ then try boot device (direct boot from disk) + " bootarchive" chosen-ph get-package-property if + " bootpath" chosen-ph get-string-prop ( bootpath$ ) + else ( archiveprop$ ) + decode-string 2swap 2drop ( archivepath$ ) + true to nested? + then ( bootpath$ ) + boot-dev swap move ( ) +; + +: mount-root ( -- ) + boot-dev$ fs-pkg$ $open-package to fs-ih + fs-ih 0= if + ." Can't mount root" abort + then +; + +\ +\ cheap entertainment for those watching +\ boot progress +\ +headerless +create spin-data + ascii | c, ascii / c, ascii - c, ascii \ c, + +0 instance variable spindex + +: spinner ( -- ) + spindex @ 3 and spin-data + ( c-adr ) + c@ emit (cr + 1 spindex +! +; + +: spin-on ( -- ) ['] spinner d# 1000 alarm ; +: spin-off ( -- ) ['] spinner 0 alarm ; + +headers +\ allocate and return physical allocation size +: vmem-alloc-prop ( size virt -- alloc-size virt ) + 2dup ['] vmem-alloc catch if ( size virt ??? ??? ) + 2drop ( size virt ) + 2dup begin ( size virt len adr ) + over 32meg min >r ( size virt len adr r: alloc-sz ) + r@ over vmem-alloc ( size virt len adr adr r: alloc-sz ) + nip r@ + ( size virt len adr' r: alloc-sz ) + swap r> - ( size virt adr len' ) + swap over 0= ( size virt len adr done? ) + until ( size virt len adr ) + 2drop nip 32meg ( virt 32meg ) + else ( size virt virt ) + nip nip 0 ( virt 0 ) + then ( virt alloc-sz ) + swap +; + +\ read in file and return buffer +\ if base==0, vmem-alloc will allocate virt +: get-file ( base fd -- [ virt size ] failed? ) + dup >r fs-size ( base size r: fd ) + dup rot vmem-alloc-prop ( size alloc-sz virt r: fd ) + rot 2dup tuck r> ( alloc-sz virt size size virt size fd ) + spin-on fs-read spin-off ( alloc-sz virt size size size-rd ) + <> if ( alloc-sz virt size ) + 3drop true exit ( failed ) + then + false ( alloc-sz virt size succeeded ) +; + + +false value is-elf? +false value is-archive? + +: check-elf ( base -- is-elf? ) + l@ h# 7f454c46 ( \x7fELF ) = +; + +: check-fcode ( base -- is-fcode? ) + c@ dup h# f0 h# f3 between swap h# fd = or +; + +: >bootblk ( adr -- adr' ) d# 512 + ; + +\ figure out what we just loaded +: get-type ( adr -- ) + dup check-elf to is-elf? + + \ if not nested, check for boot archive (executable after label) + nested? invert if + >bootblk + dup check-fcode ( adr is-fcode? ) + over check-elf ( adr is-fcode? is-elf? ) + or to is-archive? + then + drop +; + + +\ +\ file name routines +\ + +\ boot file (-F name or boot archive) +false value fflag? +/buf-len buffer: boot-file +: boot-file$ ( -- file$ ) boot-file cscount ; + +\ kernel name (final name or unix) +false value kern? +/buf-len buffer: kern-file +: kern-file$ ( -- file$ ) kern-file cscount ; + +\ platform name +/buf-len buffer: plat-name +: plat-name$ ( -- plat$ ) plat-name cscount ; + +\ arch name +/buf-len buffer: arch-name +: arch-name$ ( -- arch$ ) arch-name cscount ; + +\ final name after /platform massaging +/buf-len buffer: targ-file +: targ-file$ ( -- file$ ) targ-file cscount ; + +: init-targ ( -- ) + targ-file /buf-len erase + " /platform/" targ-file swap move +; + +\ remove illegal file name chars (e.g., '/') +: munge-name ( name$ -- name$' ) + 2dup ( name$ name$ ) + begin dup while + over c@ ascii / = if + over ascii _ swap c! ( name$ name$' ) + then str++ + repeat 2drop ( name$ ) +; + +\ if the platform exists in the FS, use it +\ else use a default (e.g., sun4v) +: get-arch ( -- ) + " device_type" root-ph get-package-property if + \ some older sunfires don't have device_type set + false ( sun4u ) + else ( devtype-prop$ ) + decode-string 2swap 2drop ( devtype$ ) + " sun4v" $= ( sun4v? ) + then ( sun4v? ) + if " sun4v" else " sun4u" then ( arch$ ) + arch-name swap move + " name" root-ph get-string-prop ( name$ ) + munge-name ( name$' ) + init-targ 2dup targ-file$ $append + targ-file$ fs-open if ( name$ fd ) + fs-close ( name$ ) + else ( name$ ) + 2drop arch-name$ ( default$ ) + then ( name$ ) + plat-name swap move ( ) +; + +\ make <pre> <file> into /platform/<pre>/<file> +: $plat-prepend ( file$ pre$ -- file$' ) + init-targ + targ-file$ $append ( file$ ) + " /" targ-file$ $append + targ-file$ $append ( ) + targ-file$ ( new$ ) +; + +: get-boot ( -- file$ ) + fflag? if + boot-file$ + else + " boot_archive" + then +; + +: get-kern ( -- file$ ) + kern? if + kern-file$ + else + " kernel/sparcv9/unix" + then +; + +\ if we're nested, load the kernel, else load the bootarchive +: get-targ ( -- file$ ) + nested? if + get-kern + else + get-boot + then +; + + +: try-file ( file$ -- [ fd ] error? ) + diagnostic-mode? if + 2dup ." Loading: " type cr + then + fs-open invert ( fd false | true ) +; + +\ try "/platform/<plat-name>/<file>" e.g., SUNW,Sun-Blade-1000 +\ then "/platform/<arch-name>/<file>" e.g., sun4u +: open-path ( file$ - fd ) + over c@ ascii / <> if + 2dup plat-name$ $plat-prepend ( file$ file$' ) + try-file if ( file$ ) + 2dup arch-name$ $plat-prepend ( file$ file$' ) + try-file if ( file$ ) + open-abort + then ( file$ fd ) + then ( file$ fd ) + else ( file$ ) + \ copy to targ-file for 'whoami' prop + targ-file /buf-len erase + 2dup targ-file swap move + 2dup try-file if ( file$ ) + open-abort + then ( file$ fd ) + then ( file$ fd ) + -rot 2drop ( fd ) +; + + +\ ZFS support +\ -Z fsname opens specified filesystem in disk pool + +false value zflag? +/buf-len buffer: fs-name +: fs-name$ ( -- fs$ ) fs-name cscount ; + +[ifdef] zfs + +: open-zfs-fs ( fs$ -- ) + 2dup " open-fs" fs-ih $call-method 0= if + open-abort + then + 2drop ( ) +; + +[else] + +: open-zfs-fs ( fs$ -- ) + ." -Z not supported on non-zfs root" abort +; + +[then] + + +\ +\ arg parsing +\ + +headerless +: printable? ( n -- flag ) \ true if n is a printable ascii character + dup bl th 7f within swap th 80 th ff between or +; +: white-space? ( n -- flag ) \ true is n is non-printable? or a blank + dup printable? 0= swap bl = or +; + +: skip-blanks ( adr len -- adr' len' ) + begin dup while ( adr' len' ) + over c@ white-space? 0= if exit then + str++ + repeat +; + +: skip-non-blanks ( adr len -- adr' len' ) + begin dup while ( adr' len' ) + over c@ white-space? if exit then + str++ + repeat +; + +headers +\ left-parse-string w/ any white space as delimeter +: next-str ( adr len -- adr' len' s-adr s-len ) + 2dup skip-non-blanks ( s-adr len adr' len' ) + dup >r 2swap r> - ( adr' len' s-adr s-len ) +; + +: next-c ( adr len -- adr' len' c ) + over c@ >r str++ r> +; + +false value halt? + +: parse-bootargs ( -- ) + " bootargs" chosen-ph get-string-prop ( arg$ ) + + \ check for explicit kernel name + skip-blanks dup if + over c@ ascii - <> if + next-str ( arg$ kern$ ) + \ use default kernel if user specific a debugger + 2dup " kadb" $= >r ( arg$ kern$ r: kadb? ) + 2dup " kmdb" $= r> or ( arg$ kern$ debugger? ) + invert if ( arg$ kern$ ) + kern-file swap move ( arg$ ) + true to kern? + else 2drop then ( arg$ ) + then + then + + \ process args + begin + skip-blanks dup ( arg$ len ) + while + next-c ascii - = if + next-c case + ascii D of + \ for "boot kadb -D kernel.foo/unix" + skip-blanks next-str ( arg$ file$ ) + kern? invert if + ?dup if + kern-file swap move ( arg$ ) + true to kern? + else drop then ( arg$ ) + else 2drop then ( arg$ ) + endof + ascii F of + skip-blanks next-str ( arg$ file$ ) + ?dup if + boot-file swap move ( arg$ ) + true to fflag? + else drop then ( arg$ ) + endof + ascii H of + true to halt? + endof + ascii Z of + skip-blanks next-str ( arg$ fs-name$ ) + ?dup if + fs-name swap move ( arg$ ) + true to zflag? + else drop then ( arg$ ) + endof + endcase + then + repeat + 2drop ( ) +; + + +0 value rd-alloc-sz + +: "ramdisk" ( -- dev$ ) " /ramdisk-root" ; + +: setup-bootprops ( -- ) + chosen-ph push-package + + nested? invert if + fs-type$ encode-string " fstype" property + fs-ih encode-int " bootfs" property + fs-bootprop if property then + else + fs-type$ encode-string " archive-fstype" property + fs-ih encode-int " archfs" property + then + + is-archive? if + "ramdisk" encode-string " bootarchive" property + else + loader-base encode-int " elfheader-address" property + file-sz encode-int " elfheader-length" property + plat-name$ encode-string " impl-arch-name" property + targ-file$ encode-string " whoami" property + fs-pkg$ encode-string " fs-package" property + then + + pop-package +; + + +\ load ramdisk fcode and tell the driver where +\ we put the ramdisk data +: setup-ramdisk ( base size -- ) + /rd-fcode mem-alloc ( base size adr ) + dup /rd-fcode fs-getrd + + root-ph push-package + new-device + "ramdisk" str++ device-name + dup 1 byte-load + finish-device + pop-package + + /rd-fcode mem-free ( base size ) + + "ramdisk" dev-open dup 0= if + "ramdisk" open-abort + then >r ( base size r: ih ) + rd-alloc-sz ( base size alloc-sz r: ih ) + " create" r@ $call-method ( r: ih ) + r> dev-close ( ) +; + + +\ +\ ELF parsing +\ + +0 value elfhdr +0 value phdr + +: +elfhdr ( index -- value ) elfhdr swap ca+ ; +: e_machine ( -- n ) h# 12 +elfhdr w@ ; +: e_entry ( -- n ) h# 18 +elfhdr x@ ; +: e_phoff ( -- n ) h# 20 +elfhdr x@ ; +: e_phentsize ( -- n ) h# 36 +elfhdr w@ ; +: e_phnum ( -- n ) h# 38 +elfhdr w@ ; + +1 constant pt_load +: +phdr ( index -- value ) phdr swap ca+ ; +: p_type ( -- n ) h# 0 +phdr l@ ; +: p_vaddr ( -- n ) h# 10 +phdr x@ ; +: p_memsz ( -- n ) h# 28 +phdr x@ ; + +: get-phdr ( filebase index -- phdr ) + e_phentsize * e_phoff + + ( phdr ) +; + +\ alloc 4MB pages for kernel text/data +: vmem-alloc-4mb ( size virt -- base ) + swap 4meg roundup swap + 4meg (mem-alloc) +; + +\ OBP doesn't allocate memory for elf +\ programs, it assumes they'll fit +\ under the default 10MB limit +: fix-elf-mem ( base -- ) + dup to elfhdr + e_machine d# 43 <> if drop exit then \ 64b only + + e_phnum 0 ?do + dup i get-phdr to phdr + p_type pt_load = p_vaddr h# a0.0000 > and if + \ allocate 4MB segs for text & data + p_vaddr 4meg 1- and if + p_memsz p_vaddr vmem-alloc drop + else + p_memsz p_vaddr vmem-alloc-4mb drop + then + then + loop drop ( ) +; + + +: load-file ( -- virt ) + get-arch + get-targ open-path ( fd ) + loader-base over get-file if ( fd alloc-sz virt size ) + ." Boot load failed" abort + then + to file-sz ( fd alloc-sz virt ) + swap to rd-alloc-sz ( fd virt ) + swap fs-close ( virt ) +; + +: setup-props ( virt -- virt ) + dup get-type + setup-bootprops + is-archive? if + dup file-sz setup-ramdisk + then +; + +: exec-file ( virt -- ) + is-elf? if + dup fix-elf-mem + then + is-archive? if >bootblk then ( virt' ) + " to load-base init-program" evaluate +; + +: do-boot ( -- ) + parse-bootargs + halt? if + ." Halted with -H flag. " cr + exit + then + get-bootdev + load-pkg + mount-root + zflag? nested? invert and if + fs-name$ open-zfs-fs + then + load-file ( virt ) + setup-props + exec-file ( ) +; + +\ Tadpole proms don't initialize my-self +0 to my-self + +do-boot diff --git a/usr/src/psm/stand/bootblks/common/mkbb.sh b/usr/src/psm/stand/bootblks/common/mkbb.sh new file mode 100755 index 0000000000..d5d395d1fd --- /dev/null +++ b/usr/src/psm/stand/bootblks/common/mkbb.sh @@ -0,0 +1,85 @@ +#!/bin/ksh +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# + +#!/bin/sh + +# defaults +bblen=7680 +rdlen=256 +totlen=7680 + +while getopts b:r:e: a; do + case $a in + b) bblen=$OPTARG;; + r) rdlen=$OPTARG;; + e) extra=$OPTARG + totlen=15872;; + ?) printf "Usage: %s: [ -b bb_len ] [ -r rd_len ] boot_fcode ramdisk_fcode bootblk\n" $0 + exit -1;; + esac +done +shift $(($OPTIND - 1)) + +# +# check boot code and ramdisk code for size overflow +# +rdoff=$(($bblen - $rdlen)) + +bbsize=$(ls -l $1 | awk -e '{ print $5 }') +if [ $bbsize -gt $rdoff ]; then + printf "$1 must be smaller than $rdoff\n" + exit -1 +fi + +rdsize=$(ls -l $2 | awk -e '{ print $5 }') +if [ $rdsize -gt $rdlen ]; then + printf "$1 must be smaller than $rdlen\n" + exit -1 +fi + +# +# make the bootblk +# +mkfile -n $totlen $3 +chmod 644 $3 +dd if=$1 of=$3 conv=notrunc bs=1 +dd if=$2 of=$3 conv=notrunc bs=1 oseek=$rdoff + +# +# extended bootblk for zfs debug +# +if [ $totlen -gt $bblen ]; then + extsize=$(ls -l $extra | awk -e '{ print $5 }') + if [ $extsize -gt 8192 ]; then + printf "$1 must be smaller than 8k\n" + exit -1 + fi + dd if=$extra of=$3 conv=notrunc bs=1 oseek=$bblen +fi + +exit 0 diff --git a/usr/src/psm/stand/bootblks/common/rd.fth b/usr/src/psm/stand/bootblks/common/rd.fth new file mode 100644 index 0000000000..dee3a594e1 --- /dev/null +++ b/usr/src/psm/stand/bootblks/common/rd.fth @@ -0,0 +1,83 @@ +\ +\ CDDL HEADER START +\ +\ The contents of this file are subject to the terms of the +\ Common Development and Distribution License (the "License"). +\ You may not use this file except in compliance with the License. +\ +\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ or http://www.opensolaris.org/os/licensing. +\ See the License for the specific language governing permissions +\ and limitations under the License. +\ +\ When distributing Covered Code, include this CDDL HEADER in each +\ file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ If applicable, add the following below this CDDL HEADER, with the +\ fields enclosed by brackets "[]" replaced with your own identifying +\ information: Portions Copyright [yyyy] [name of copyright owner] +\ +\ CDDL HEADER END +\ +\ +\ ident "%Z%%M% %I% %E% SMI" +\ Copyright 2007 Sun Microsystems, Inc. All rights reserved. +\ Use is subject to license terms. +\ + +id: %Z%%M% %I% %E% SMI +purpose: simplified ramdisk driver +copyright: Copyright 2007 Sun Microsystems, Inc. All Rights Reserved + +headerless + +" block" device-type +" SUNW,ramdisk" encode-string " compatible" property + +0 instance value current-offset + +0 value ramdisk-base-va +0 value ramdisk-size +0 value alloc-size + +: set-props + ramdisk-size encode-int " size" property + ramdisk-base-va encode-int " address" property + alloc-size encode-int " alloc-size" property +; +set-props + +: current-va ( -- adr ) ramdisk-base-va current-offset + ; + +external + +: open ( -- okay? ) + true +; + +: close ( -- ) +; + +: seek ( off.low off.high -- error? ) + drop dup ramdisk-size > if + drop true exit ( failed ) + then + to current-offset false ( succeeded ) +; + +: read ( addr len -- actual-len ) + dup current-offset + ( addr len new-off ) + dup ramdisk-size > if + ramdisk-size - - ( addr len' ) + ramdisk-size ( addr len new-off ) + then -rot ( new-off addr len ) + tuck current-va -rot move ( new-off len ) + swap to current-offset ( len ) +; + +: create ( base size alloc-sz -- ) + to alloc-size + to ramdisk-size + to ramdisk-base-va + set-props +; + diff --git a/usr/src/psm/stand/bootblks/common/util.fth b/usr/src/psm/stand/bootblks/common/util.fth new file mode 100644 index 0000000000..d48904646c --- /dev/null +++ b/usr/src/psm/stand/bootblks/common/util.fth @@ -0,0 +1,219 @@ +\ +\ CDDL HEADER START +\ +\ The contents of this file are subject to the terms of the +\ Common Development and Distribution License (the "License"). +\ You may not use this file except in compliance with the License. +\ +\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ or http://www.opensolaris.org/os/licensing. +\ See the License for the specific language governing permissions +\ and limitations under the License. +\ +\ When distributing Covered Code, include this CDDL HEADER in each +\ file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ If applicable, add the following below this CDDL HEADER, with the +\ fields enclosed by brackets "[]" replaced with your own identifying +\ information: Portions Copyright [yyyy] [name of copyright owner] +\ +\ CDDL HEADER END +\ +\ +\ ident "%Z%%M% %I% %E% SMI" +\ Copyright 2007 Sun Microsystems, Inc. All rights reserved. +\ Use is subject to license terms. +\ + +id: %Z%%M% %I% %E% SMI +purpose: utility words +copyright: Copyright 2007 Sun Microsystems, Inc. All Rights Reserved + + +[ifdef] doheaders +headers +[else] +headerless +[then] + +d# 256 constant /buf-len + +\ +\ useful counting words +\ +: roundup ( x y -- x' ) 1- tuck + swap invert and ; + + +\ +\ various useful string manipulation words +\ + +: cstrlen ( cstr -- len ) + dup begin + dup c@ + while + char+ + repeat swap - +; + +: cscount ( cstr -- adr,len ) dup cstrlen ; + +\ Append str1 to the end of str2 +: $append ( adr,len1 adr,len2 -- ) + 2over 2over ca+ swap move ( adr,len1 adr,len2 ) + rot + ca+ 0 swap c! drop ( ) +; + +: $= ( str1$ str2$ -- same? ) + rot tuck <> if + 3drop false exit + then comp 0= +; + +\ advance str by 1 +: str++ ( adr len -- adr' len' ) + swap 1+ swap 1- +; + +: diag-cr? ( -- ) diagnostic-mode? if cr then ; + + +: find-abort ( name$ -- ) + ." Can't find " type abort +; + +: get-package ( pkg$ -- ph ) + 2dup find-package 0= if + find-abort + then ( pkg$ ph ) + nip nip ( ph ) +; + + +\ +\ CIF words for I/O and memory +\ +" /openprom/client-services" get-package constant cif-ph + +instance defer cif-open ( dev$ -- ihandle|0 ) +instance defer cif-close ( ihandle -- ) +instance defer cif-read ( len adr ihandle -- #read ) +instance defer cif-seek ( low high ihandle -- -1|0|1 ) +instance defer cif-release ( size virt -- ) + +: find-cif-method ( adr,len -- acf ) + 2dup cif-ph find-method 0= if ( adr,len ) + find-abort + then ( adr,len acf ) + nip nip ( acf ) +; + +" open" find-cif-method to cif-open +" close" find-cif-method to cif-close +" read" find-cif-method to cif-read +" seek" find-cif-method to cif-seek +" release" find-cif-method to cif-release + + +" /chosen" get-package constant chosen-ph + +: get-property ( name$ ph -- prop$ ) + >r 2dup r> get-package-property if ( name$ ) + find-abort + then ( name$ prop$ ) + 2swap 2drop ( prop$ ) +; + +: get-string-prop ( name$ ph -- val$ ) + get-property decode-string ( prop$' val$ ) + 2swap 2drop ( val$ ) +; + +: get-int-prop ( name$ ph -- n ) + get-property decode-int ( prop$' n ) + nip nip ( n ) +; + +\ +\ memory allocation +\ we bypass cif claim so we can do large page +\ allocations like promif can +\ + +" mmu" chosen-ph get-int-prop constant mmu-ih + +" memory" chosen-ph get-int-prop constant mem-ih + +: mmu-claim ( [ virt ] size align -- base ) + " claim" mmu-ih $call-method +; + +: mmu-map ( phys.lo phys.hi virt size -- ) + -1 " map" mmu-ih $call-method +; + +: mem-claim ( size align -- phys.lo phys.hi ) + " claim" mem-ih $call-method +; + +: (mem-alloc) ( size virt align -- virt ) + \ claim memory first since it may throw if fragmented + rot 2dup swap mem-claim ( virt align size phys.lo phys.hi ) + >r >r rot ?dup if ( align size virt r: phys.lo phys.hi ) + \ we picked virt - zero alignment + over 0 mmu-claim ( align size virt r: phys.lo phys.hi ) + else ( align size r: phys.lo phys.hi ) + \ OBP picks virt - pass alignment + 2dup swap mmu-claim ( align size virt r: phys.lo phys.hi ) + then ( align size virt r: phys.lo phys.hi ) + r> r> 2over swap mmu-map ( align size virt ) + nip nip ( virt ) +; + +: vmem-alloc ( size virt -- virt ) + swap h# 2000 roundup swap + 1 (mem-alloc) +; + +: mem-alloc ( size -- virt ) + h# 2000 roundup + 0 1 (mem-alloc) +; + +: mem-free ( virt size -- ) + h# 2000 roundup + swap cif-release ( ) +; + + + +\ put ramdisk fcode 256 bytes from end of bootblk +\ (currently 244 bytes in size) +d# 256 constant /rd-fcode +d# 8192 /rd-fcode - constant rd-offset + +: open-abort ( file$ -- ) + ." Can't open " type abort +; + +/buf-len buffer: open-cstr + +: dev-open ( dev$ -- ih | 0 ) + \ copy to C string for open + 0 over open-cstr + c! + open-cstr swap move + open-cstr cif-open +; + +: dev-close ( ih -- ) + cif-close +; + +: read-disk ( adr len off ih -- ) + dup >r 0 swap cif-seek if ( adr len r: ih ) + ." seek failed" abort + then + + tuck swap r> cif-read <> if ( ) + ." read failed" abort + then +; diff --git a/usr/src/psm/stand/bootblks/hsfs/Makefile b/usr/src/psm/stand/bootblks/hsfs/Makefile index cfae7b9a31..5bbc4326e0 100644 --- a/usr/src/psm/stand/bootblks/hsfs/Makefile +++ b/usr/src/psm/stand/bootblks/hsfs/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -22,7 +21,8 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright (c) 1989-1994, by Sun Microsystems, Inc. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # # psm/stand/bootblks/hsfs/Makefile # @@ -36,16 +36,10 @@ lint := TARGET= lint .KEEP_STATE: -all clean clobber lint : $(SUBDIRS) +all install clean clobber lint : $(SUBDIRS) $(SUBDIRS): FRC @cd $@; pwd; $(MAKE) $(TARGET) -# -# XXX There's no point in installing the hsfs stuff if we -# never use it (or test it!) -# -install: FRC - FRC: diff --git a/usr/src/psm/stand/bootblks/hsfs/Makefile.hsfs b/usr/src/psm/stand/bootblks/hsfs/Makefile.hsfs index 72ee6d8fd1..a5d61a916a 100644 --- a/usr/src/psm/stand/bootblks/hsfs/Makefile.hsfs +++ b/usr/src/psm/stand/bootblks/hsfs/Makefile.hsfs @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -22,14 +21,57 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright (c) 1994, by Sun Microsystems, Inc. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # # psm/stand/bootblks/hsfs/Makefile.hsfs # + include $(BASEDIR)/Makefile.com -include $(BASEDIR)/hsfs/common/Makefile.com # -# Where stuff gets installed +# Define FS dependent targets +# + +HSFS_DIR = $(BASEDIR)/hsfs/common + +FS_FCODE = boot-hsfs.fcode +FS_BB = hsfs.bb + +HSFSBOOT_FTH = $(HSFS_DIR)/boot-hsfs.fth +HSFS_FTH = $(HSFS_DIR)/hsfs.fth + +# +# This program is used to install the boot block +# +INSTALLBOOT = installboot + +# +# Where and how stuff gets installed # USR_PSM_BOOTBLOCK = $(USR_PSM_LIB_HSFS_DIR)/$(PROG) + +USR = $(ROOT)/usr +USR_SBIN = $(USR)/sbin +USR_SBIN_INSTALLBOOT = $(USR_SBIN)/$(INSTALLBOOT) + +# +# Overrides for installing installboot. +# +INS.file.555 = $(RM) $@; $(INS) -s -m 555 -f $(@D) $< +$(CH)INS.file.555 = $(INS) -s -m 555 -u $(OWNER) -g $(GROUP) -f $(@D) $< + +# +# dependencies +# +%.fcode: $(HSFS_DIR)/%.fth + $(TOKENIZE) $< + +$(FS_FCODE): $(UTIL_FTH) $(HSFS_FTH) $(BOOT_FTH) + $(TOKENIZE) $(HSFSBOOT_FTH) + +# +# install rules +# +$(USR_SBIN)/%: % $(USR_SBIN) + $(INS.file.555) diff --git a/usr/src/psm/stand/bootblks/hsfs/common/boot-hsfs.fth b/usr/src/psm/stand/bootblks/hsfs/common/boot-hsfs.fth new file mode 100644 index 0000000000..4328400421 --- /dev/null +++ b/usr/src/psm/stand/bootblks/hsfs/common/boot-hsfs.fth @@ -0,0 +1,44 @@ + +\ ident "%Z%%M% %I% %E% SMI" +\ Copyright 2007 Sun Microsystems, Inc. All rights reserved. +\ Use is subject to license terms. +\ +\ CDDL HEADER START +\ +\ The contents of this file are subject to the terms of the +\ Common Development and Distribution License (the "License"). +\ You may not use this file except in compliance with the License. +\ +\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ or http://www.opensolaris.org/os/licensing. +\ See the License for the specific language governing permissions +\ and limitations under the License. +\ +\ When distributing Covered Code, include this CDDL HEADER in each +\ file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ If applicable, add the following below this CDDL HEADER, with the +\ fields enclosed by brackets "[]" replaced with your own identifying +\ information: Portions Copyright [yyyy] [name of copyright owner] +\ +\ CDDL HEADER END +\ +\ + +id: %Z%%M% %I% %E% SMI +purpose: HSFS file system support package for NewBoot +copyright: Copyright 2006 Sun Microsystems, Inc. All Rights Reserved + +\ add headers +create doheaders + +: fs-pkg$ " hsfs-file-system" ; +: fs-type$ " hsfs" ; + +\ load common words +fload ../../../common/util.fth + +\ load fs reader +fload ../../common/hsfs.fth + +\ load booter +fload ../../../common/boot.fth diff --git a/usr/src/psm/stand/bootblks/hsfs/common/hsfs.fth b/usr/src/psm/stand/bootblks/hsfs/common/hsfs.fth new file mode 100644 index 0000000000..d5c3df8cb2 --- /dev/null +++ b/usr/src/psm/stand/bootblks/hsfs/common/hsfs.fth @@ -0,0 +1,636 @@ + +\ ident "%Z%%M% %I% %E% SMI" +\ Copyright 2007 Sun Microsystems, Inc. All rights reserved. +\ Use is subject to license terms. +\ +\ CDDL HEADER START +\ +\ The contents of this file are subject to the terms of the +\ Common Development and Distribution License (the "License"). +\ You may not use this file except in compliance with the License. +\ +\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ or http://www.opensolaris.org/os/licensing. +\ See the License for the specific language governing permissions +\ and limitations under the License. +\ +\ When distributing Covered Code, include this CDDL HEADER in each +\ file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ If applicable, add the following below this CDDL HEADER, with the +\ fields enclosed by brackets "[]" replaced with your own identifying +\ information: Portions Copyright [yyyy] [name of copyright owner] +\ +\ CDDL HEADER END +\ +\ + +id: %Z%%M% %I% %E% SMI +purpose: HSFS file system support package for NewBoot +copyright: Copyright 2006 Sun Microsystems, Inc. All Rights Reserved + +\ High Sierra, Rock Ridge (CD-ROM) file system reader and boot block + +headers +" /packages" get-package push-package + +new-device + fs-pkg$ device-name diag-cr? + + \ + \ HSFS variables + \ + 0 instance value dev-ih + 0 instance value vol-desc + 0 instance value dir-buf + 0 instance value sua-buf + 0 instance value ce-buf + + \ + \ HSFS volume descriptor routines + \ + + \ unaligned load of 2-byte item + : xw@ ( adr -- n ) + dup c@ swap char+ ( c0 adr+1 ) + c@ ( c0 c1 ) + bwjoin + ; + + \ unaligned store of 2-byte item + : xw! ( n adr -- ) + swap wbsplit swap 2 pick c! swap char+ c! + ; + + \ unaligned load of 4-byte item + : xl@ ( adr -- n ) + dup xw@ swap wa1+ ( w0 adr+2 ) + xw@ ( w0 w1 ) + wljoin + ; + \ unaligned store of 4-byte item + : xl! ( n adr -- ) + swap lwsplit swap 2 pick xw! swap wa1+ xw! + ; + + d# 2048 constant /sector + d# 16 constant vol-desc-sector# ( -- n ) + + : +vd ( index -- adr ) + vol-desc 0= if + ." invalid access of +vd" cr abort + then + vol-desc + + ; + + : root-dir ( -- n ) d# 156 +vd ; + : /block ( -- n ) d# 128 +vd xw@ ; + : byte>blkoff ( byte-off -- block-off ) /block mod ; + + : get-vol-desc ( -- ) + vol-desc /sector vol-desc-sector# /sector * dev-ih read-disk + ; + + : read-fs-blocks ( adr len fs-blk# -- ) /block * dev-ih read-disk ; + + \ + \ HSFS directory routines + \ + + \ Current directory variables. + instance variable cdir-blk \ Current directory device block ptr. + instance variable cdir-blk0 \ Current directory block0. + instance variable cdir-offset \ Current directory logical offset. + instance variable cdir-size \ Current directory logical size. + instance variable cdir-ptr \ Current directory entry pointer. + false instance value cdir-rescan \ Rescan current directory for symlink. + + \ Access of current directory entry. + : +dr ( n -- adr ) cdir-ptr @ + ; + + : dir-entrylen ( -- n ) d# 0 +dr c@ ; + : dir-block0 ( -- n ) d# 2 +dr xl@ ; + : dir-block0! ( n -- ) d# 2 +dr xl! ; + : dir-filesize ( -- n ) d# 10 +dr xl@ ; + : dir-filesize! ( n -- ) d# 10 +dr xl! ; + : dir-flags ( -- n ) d# 25 +dr c@ ; + : dir-flags! ( n -- ) d# 25 +dr c! ; + : dir-filenamelen ( -- n ) d# 32 +dr c@ ; + : dir-filename ( -- adr ) d# 33 +dr ; + + : dir-isdir? ( -- flag ) dir-flags h# 02 and 0<> ; + : dir-setdir ( -- ) h# 02 dir-flags! ; + : dir-file$ ( -- adr len ) dir-filename dir-filenamelen ; + : dir-sualen ( -- len ) dir-entrylen d# 33 - dir-filenamelen - ; + + false instance value symlink? + + : get-dirblk ( -- ) + dir-buf /block cdir-blk @ read-fs-blocks + 1 cdir-blk +! + ; + + : root-dir? ( -- flag ) root-dir cdir-ptr = ; + : froot ( -- ) root-dir cdir-ptr ! ; + + \ + \ SUAs - System Use Area in directory entry (Rock Ridge + \ Extensions to High Sierra/ISO 9660 Format). + \ Immediately follows directory entry name rounded up to + \ a half-word boundary. + \ + 0 instance value sua-ptr + 0 instance value sua-len + + : +suf ( n -- adr ) sua-ptr + ; + : suf-sig ( -- adr len ) sua-ptr 2 ; + : suf-len ( -- len ) 2 +suf c@ ; + : suf-dat ( -- data ) 5 +suf ; + : suf-ce-lbn ( -- lbn ) 4 +suf xl@ ; + : suf-ce-offset ( -- offset ) d# 12 +suf xl@ ; + : suf-ce-len ( -- len ) d# 20 +suf xl@ ; + + : init-sua ( -- ) + dir-file$ + /w roundup to sua-ptr + dir-sualen to sua-len + ; + + : next-suf ( -- ) + sua-len suf-len - to sua-len + suf-len +suf to sua-ptr + ; + + : end-sua ( -- end? ) + sua-len 4 < + ; + + : suf-nm$ ( -- adr len ) suf-dat suf-len 5 - ; + + \ Continuation suffix handling. When a 'CE' suffix is seen, + \ record the CE parameters (logical block#, offset and length + \ of continuation). We process the CE continuation only after + \ we've finished processing the current SUA area. + instance variable ce-lbn + instance variable ce-offset + instance variable ce-len + : suf-ce-set ( -- ) + suf-ce-lbn ce-lbn ! + suf-ce-offset ce-offset ! + suf-ce-len ce-len ! + ; + + : suf-ce-process ( -- error? ) + ce-lbn @ 0= if + true + else + sua-buf ce-len @ ce-lbn @ read-fs-blocks + sua-buf to sua-ptr + ce-len @ to sua-len + 0 ce-len ! 0 ce-lbn ! 0 ce-offset ! + false + then + ; + + /buf-len instance buffer: suf-sl-buf + false instance value symlink-need-sep + + \ Format of Rock Ridge symlinks needs to be munged to unix-style + \ name. Format is: <flag><nbytes>file-name<flag><nbytes>filename... + \ where \ <flag> is flag byte (0=filename, 2=current dir, 4=parent + \ dir, 8=root dir) and <nbytes> is one-byte byte count (zero for + \ !filename). + : suf-copy-to-symlinkbuf ( name$ -- ) + false to symlink-need-sep + suf-sl-buf -rot bounds do ( dst ) + symlink-need-sep if + ascii / over c! char+ + then + true to symlink-need-sep + i c@ dup 2 = if ( dst 2 ) + \ CURRENT (".") + drop ascii . over c! char+ 2 ( dst' inc ) + else dup 4 = if ( dst 4 ) + \ PARENT ("..") + drop " .." 2 pick swap move ( dst ) + wa1+ 2 ( dst' inc ) + else dup 8 = if ( dst 8 ) + \ ROOT ("/") + drop ascii / over c! char+ 2 ( dst' inc ) + false to symlink-need-sep + else dup 0<> if + ." unknown SL flag: " .x cr abort + else ( dst c ) + drop ( dst ) + i char+ dup c@ >r ( dst src+1 R:nbytes ) + char+ over r@ move ( dst R:nbytes ) + r@ + ( dst' R:nbytes ) + r> wa1+ ( dst' inc ) + then then then then + +loop ( dst ) + 0 swap c! + ; + + \ Saved 'NM' prefix buffer. + /buf-len instance buffer: suf-nm-buf + 0 instance value suf-nm-size + + \ Return the Rock Ridge file name associated with the current + \ dirent ('NM' suffix). Otherwise returns standard iso filename. + \ Marks whether returned filename is a symbolic link ('SL' suffix) + \ and also processes continuations ('CE' suffix). + : rr-file$ ( -- adr len ) + false to symlink? + 0 to suf-nm-size + + \ select start of sua, record sua offset + init-sua + begin + end-sua if + suf-ce-process if + suf-nm-size if + suf-nm-buf suf-nm-size + else + dir-file$ + then + exit + then + then + suf-sig ( sig-adr sig-len ) + 2dup " NM" $= if + suf-nm$ to suf-nm-size ( sig-adr sig-len suf-nm-adr ) + suf-nm-buf suf-nm-size move + then ( sig-adr sig-len ) + 2dup " SL" $= if + true to symlink? + suf-nm$ suf-copy-to-symlinkbuf + then + 2dup " CE" $= if + suf-ce-set + then ( sig-adr sig-len ) + 2drop next-suf ( ) + again + ; + + \ + \ HSFS high-level routines + \ + + \ Used for rescanning current directory for symbolic links. + + \ Initializes current directory settings from current directory + \ entry pointer or for rescan. If it's not a rescan, we have + \ access to the actual directory entry, so we can check whether + \ it's a directory or not here. + : init-dent ( -- error? ) + cdir-rescan if + false to cdir-rescan + cdir-blk0 @ cdir-blk ! + else + dir-isdir? 0= if + true exit + then + dir-block0 dup cdir-blk ! cdir-blk0 ! + dir-filesize cdir-size ! + then ( blk0 size ) + 0 cdir-offset ! + false + ; + + : get-dent ( -- error? ) + begin + \ Check for end of directory, return true if we're past the EOF. + cdir-offset @ cdir-size @ >= if + true exit + then + + \ If we're at a block boundary, get the next block. Otherwise + \ increment the directory pointer. + cdir-offset @ byte>blkoff 0= if + get-dirblk + dir-buf cdir-ptr ! + else + dir-entrylen cdir-ptr +! + then + + \ If dir-entrylen is not zero, increment the current directory + \ file offset. Otherwise, a dir-entrylen of zero indicates + \ the end of a dir block, so round up cdir-offset to fetch the + \ next one + dir-entrylen ?dup if + cdir-offset +! true + else + cdir-offset @ /block roundup cdir-offset ! + false + then + until false + ; + + \ directory stack + struct + /x field >dirs-size + /x field >dirs-block0 + constant /dirs-stack + + d# 10 constant #dirs-stack + #dirs-stack /dirs-stack * instance buffer: dirs-stack + instance variable dirs-stackp + + : dirs-init ( -- ) + dirs-stack dirs-stackp ! + ; + : dirs-push ( -- ) + dir-isdir? if + dirs-stackp @ + cdir-blk0 @ over >dirs-block0 ! + cdir-size @ over >dirs-size ! + /dirs-stack + dirs-stackp ! + then + ; + : dirs-pop ( -- ) + dirs-stackp @ dup dirs-stack = if + froot exit + then + /dirs-stack - + dup >dirs-block0 @ dir-block0! + dup >dirs-size @ dir-filesize! + dirs-stackp ! + dir-setdir + ; + + \ Look through current directory for file name 'file$'. + \ Will leave current directory entry (cdir-ptr) pointing + \ to matched entry on success. + : dirlook ( file$ -- error? ) + init-dent if + true exit + then + 2dup " .." $= if + 2drop dirs-pop false exit + then + 2dup " ." $= if + 2drop true to cdir-rescan false exit + then + + begin get-dent 0= while ( file$ ) + 2dup rr-file$ $= if ( file$ ) + 2drop dirs-push false exit ( succeeded ) + then ( file$ ) + repeat 2drop true ( failed ) + ; + + /buf-len instance buffer: symlink-buf + : symlink-buf$ ( -- path$ ) symlink-buf cscount ; + + : follow-symlink ( tail$ -- tail$' ) + + \ copy symlink value (plus null) to buf + suf-sl-buf cscount 1+ symlink-buf swap move + false to symlink? + + \ append to current path + ?dup if ( tail$ ) + " /" symlink-buf$ $append ( tail$ ) + symlink-buf$ $append ( ) + else drop then ( ) + symlink-buf$ ( path$ ) + over c@ ascii / = if ( path$ ) + froot str++ ( path$' ) + else + true to cdir-rescan + then ( path$ ) + ; + + : lookup ( path$ -- error? ) + dirs-init + over c@ ascii / = if + froot str++ ( path$' ) + then ( path$ ) + begin ( path$ ) + ascii / left-parse-string ( path$ file$ ) + dup while ( path$ file$ ) + dirlook if + 2drop true exit ( failed ) + then ( path$ ) + symlink? if + follow-symlink ( path$' ) + then ( path$ ) + repeat ( path$ file$ ) + 2drop 2drop false ( succeeded ) + ; + + + \ + \ HSFS installation routines + \ + + \ Allocate memory for necessary data structures. Need to + \ read volume desriptor sector in order to get /block value. + : initialize ( -- error? ) + /sector mem-alloc to vol-desc + get-vol-desc + /block mem-alloc to dir-buf + /block mem-alloc to sua-buf + /block mem-alloc to ce-buf + ; + + : release-buffers ( -- ) + ce-buf /block mem-free + sua-buf /block mem-free + dir-buf /block mem-free + vol-desc /sector mem-free + 0 to vol-desc + ; + + + \ HSFS file interface + struct + /x field >filesize + /x field >offset + /x field >block0 + constant /file-record + + d# 10 constant #opens + #opens /file-record * constant /file-records + + /file-records instance buffer: file-records + + -1 instance value current-fd + + : fd>record ( fd -- record ) /file-record * file-records + ; + + : set-fd ( fd -- error? ) + dup 0 #opens 1 - between 0= if + drop true exit + then + dup fd>record >block0 x@ 0= if + drop true exit + then + to current-fd false + ; + + : file-offset@ ( -- off ) + current-fd fd>record >offset x@ + ; + + : file-offset! ( off -- ) + current-fd fd>record >offset x! + ; + + : file-size@ ( -- size ) + current-fd fd>record >filesize x@ + ; + + : file-size! ( size -- ) + current-fd fd>record >filesize x! + ; + + : file-block0@ ( -- block0 ) + current-fd fd>record >block0 x@ + ; + + : file-block0! ( block0 -- ) + current-fd fd>record >block0 x! + ; + + : get-slot ( -- fd false | true ) + #opens 0 do + i fd>record >block0 x@ 0= if + i false unloop exit + then + loop true + ; + + : free-slot ( fd -- ) + set-fd 0= if + 0 file-offset! + 0 file-size! + 0 file-block0! + then + ; + + \ initializes the open structure with information from + \ the inode (on UFS) or directory entry (from HSFS). + : init-fd ( fd -- ) + to current-fd + dir-block0 file-block0! + dir-filesize file-size! + 0 file-offset! + ; + + external + + : open ( -- okay? ) + my-args dev-open dup 0= if ( 0 ) + exit ( failed ) + then to dev-ih + + initialize froot + file-records /file-records erase + true ( succeeded ) + ; + + : close ( -- ) + dev-ih dev-close + release-buffers + ; + + : open-file ( path$ -- fd true | false ) + get-slot if + 2drop false exit ( failed ) + then -rot ( fd path$ ) + + lookup if ( fd ) + drop false exit ( failed ) + then + + dup init-fd true ( fd success ) + ; + + : close-file ( fd -- ) + free-slot ( ) + ; + + : read-file ( adr len fd -- #read ) + + \ Check if fd is valid, if it is set current-fd. + set-fd if + 2drop 0 exit + then ( adr len ) + + \ Adjust len if less than len bytes remain. + file-size@ file-offset@ - min ( adr len' ) + + \ Check for invalid length read. + dup 0<= if 2drop 0 exit then + + \ Compute physical device byte offset. + tuck ( len adr len ) + file-block0@ /block * file-offset@ + ( len adr len off ) + dev-ih read-disk ( #read ) + ; + + : seek-file ( off fd -- error? ) + set-fd if ( off ) + drop false exit ( failed ) + then ( off ) + + dup file-size@ > if ( off ) + drop false exit ( failed ) + then ( off ) + dup file-offset! true ( off succeeded ) + ; + + : size-file ( fd -- size ) + set-fd if + 0 + else + file-size@ + then + ; + + \ we don't support compression (yet) + : cinfo-file ( fd -- bsize fsize comp? ) + set-fd if 0 0 0 else /block file-size@ 0 then + ; + + \ read ramdisk fcode at rd-offset + : get-rd ( adr len -- ) + rd-offset dev-ih read-disk + ; + + \ no additional props needed for hsfs + : bootprop ( -- ) false ; + + \ debug words + : chdir ( path$ -- ) + 2dup lookup if + type ." Not found" cr + else + dir-isdir? 0= if + type ." Not a directory" cr + else + type + ." blk0 " + cdir-blk0 @ .x + ." size " + cdir-size @ .x + cr + then + then + ; + + : dir ( -- ) + init-dent + begin get-dent 0= while + rr-file$ type + ." flags " dir-flags .x + ." blk0 " dir-block0 .x + ." size " dir-filesize .x + cr + repeat + true to cdir-rescan + ; + + +finish-device +pop-package + diff --git a/usr/src/psm/stand/bootblks/hsfs/sparc/Makefile b/usr/src/psm/stand/bootblks/hsfs/sparc/Makefile index 00d81e23f9..804c2997f2 100644 --- a/usr/src/psm/stand/bootblks/hsfs/sparc/Makefile +++ b/usr/src/psm/stand/bootblks/hsfs/sparc/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -22,7 +21,7 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright 1994, 2001-2002 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # psm/stand/bootblks/hsfs/sparc/Makefile @@ -31,7 +30,7 @@ BASEDIR = ../.. include $(BASEDIR)/hsfs/Makefile.hsfs -SUBDIRS = unix +SUBDIRS = sun4u sun4v all := TARGET= all install := TARGET= install diff --git a/usr/src/psm/stand/bootblks/hsfs/sparc/sun4u/Makefile b/usr/src/psm/stand/bootblks/hsfs/sparc/sun4u/Makefile new file mode 100644 index 0000000000..5103f063d8 --- /dev/null +++ b/usr/src/psm/stand/bootblks/hsfs/sparc/sun4u/Makefile @@ -0,0 +1,43 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# psm/stand/bootblks/hsfs/sparc/sun4u/Makefile +# + +# +# Platform specific Makefile for the boot block. +# +BASEDIR = ../../.. +PLATFORM = sun4u + +include $(BASEDIR)/hsfs/Makefile.hsfs +include $(BASEDIR)/Makefile.1275 + +.KEEP_STATE: + +all: $(PROG) + +include $(BASEDIR)/Makefile.targ diff --git a/usr/src/psm/stand/bootblks/hsfs/sparc/sun4v/Makefile b/usr/src/psm/stand/bootblks/hsfs/sparc/sun4v/Makefile new file mode 100644 index 0000000000..31a707e696 --- /dev/null +++ b/usr/src/psm/stand/bootblks/hsfs/sparc/sun4v/Makefile @@ -0,0 +1,43 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# psm/stand/bootblks/hsfs/sparc/sun4u/Makefile +# + +# +# Platform specific Makefile for the boot block. +# +BASEDIR = ../../.. +PLATFORM = sun4v + +include $(BASEDIR)/hsfs/Makefile.hsfs +include $(BASEDIR)/Makefile.1275 + +.KEEP_STATE: + +all: $(PROG) + +include $(BASEDIR)/Makefile.targ diff --git a/usr/src/psm/stand/bootblks/ufs/Makefile.ufs b/usr/src/psm/stand/bootblks/ufs/Makefile.ufs index 31c97a8635..116496a618 100644 --- a/usr/src/psm/stand/bootblks/ufs/Makefile.ufs +++ b/usr/src/psm/stand/bootblks/ufs/Makefile.ufs @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -22,14 +21,25 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright (c) 1994, by Sun Microsystems, Inc. -# All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # # psm/stand/bootblks/ufs/Makefile.ufs # include $(BASEDIR)/Makefile.com -include $(BASEDIR)/ufs/common/Makefile.com + +# +# Define FS dependent targets +# + +UFS_DIR = $(BASEDIR)/ufs/common + +FS_FCODE = boot-ufs.fcode +FS_BB = ufs.bb + +UFSBOOT_FTH = $(UFS_DIR)/boot-ufs.fth +UFS_FTH = $(UFS_DIR)/ufs.fth # # This program is used to install the boot block @@ -51,8 +61,15 @@ USR_SBIN_INSTALLBOOT = $(USR_SBIN)/$(INSTALLBOOT) INS.file.555 = $(RM) $@; $(INS) -s -m 555 -f $(@D) $< $(CH)INS.file.555 = $(INS) -s -m 555 -u $(OWNER) -g $(GROUP) -f $(@D) $< +%.fcode: $(UFS_DIR)/%.fth + $(TOKENIZE) $< + +$(FS_FCODE): $(UTIL_FTH) $(UFS_FTH) $(BOOT_FTH) + $(TOKENIZE) $(UFSBOOT_FTH) + # # install rules # $(USR_SBIN)/%: % $(USR_SBIN) $(INS.file.555) + diff --git a/usr/src/psm/stand/bootblks/ufs/common/boot-ufs.fth b/usr/src/psm/stand/bootblks/ufs/common/boot-ufs.fth new file mode 100644 index 0000000000..7deb242e70 --- /dev/null +++ b/usr/src/psm/stand/bootblks/ufs/common/boot-ufs.fth @@ -0,0 +1,45 @@ + + +\ ident "%Z%%M% %I% %E% SMI" +\ Copyright 2007 Sun Microsystems, Inc. All rights reserved. +\ Use is subject to license terms. +\ +\ CDDL HEADER START +\ +\ The contents of this file are subject to the terms of the +\ Common Development and Distribution License (the "License"). +\ You may not use this file except in compliance with the License. +\ +\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ or http://www.opensolaris.org/os/licensing. +\ See the License for the specific language governing permissions +\ and limitations under the License. +\ +\ When distributing Covered Code, include this CDDL HEADER in each +\ file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ If applicable, add the following below this CDDL HEADER, with the +\ fields enclosed by brackets "[]" replaced with your own identifying +\ information: Portions Copyright [yyyy] [name of copyright owner] +\ +\ CDDL HEADER END +\ + + +id: %Z%%M% %I% %E% SMI +purpose: UFS bootblock for sun4u platforms +copyright: Copyright 2006 Sun Microsystems, Inc. All Rights Reserved + +\ add headers +create doheaders + +: fs-pkg$ " ufs-file-system" ; +: fs-type$ " ufs" ; + +\ load common words +fload ../../../common/util.fth + +\ load fs reader +fload ../../common/ufs.fth + +\ load booter +fload ../../../common/boot.fth diff --git a/usr/src/psm/stand/bootblks/ufs/common/ufs.fth b/usr/src/psm/stand/bootblks/ufs/common/ufs.fth new file mode 100644 index 0000000000..25531ecd78 --- /dev/null +++ b/usr/src/psm/stand/bootblks/ufs/common/ufs.fth @@ -0,0 +1,584 @@ + +\ ident "%Z%%M% %I% %E% SMI" +\ Copyright 2007 Sun Microsystems, Inc. All rights reserved. +\ Use is subject to license terms. +\ +\ CDDL HEADER START +\ +\ The contents of this file are subject to the terms of the +\ Common Development and Distribution License (the "License"). +\ You may not use this file except in compliance with the License. +\ +\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ or http://www.opensolaris.org/os/licensing. +\ See the License for the specific language governing permissions +\ and limitations under the License. +\ +\ When distributing Covered Code, include this CDDL HEADER in each +\ file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ If applicable, add the following below this CDDL HEADER, with the +\ fields enclosed by brackets "[]" replaced with your own identifying +\ information: Portions Copyright [yyyy] [name of copyright owner] +\ +\ CDDL HEADER END +\ +\ + + +id: %Z%%M% %I% %E% SMI +purpose: UFS file system support package +copyright: Copyright 1995 Sun Microsystems, Inc. All Rights Reserved + +headers +" /packages" get-package push-package + +new-device + fs-pkg$ device-name diag-cr? + + \ + \ UFS low-level block routines + \ + + h# 2000 constant /max-bsize + d# 512 constant /disk-block + + 0 instance value dev-ih + 0 instance value temp-block + + : blk>byte ( block# -- byte# ) /disk-block * ; + + : read-disk-blocks ( adr len dev-block# -- ) + blk>byte dev-ih read-disk + ; + + + \ + \ UFS superblock routines + \ + + d# 512 constant /super-block + d# 16 constant super-block# + 0 instance value super-block + + : +sb ( index -- value ) super-block swap la+ l@ ; + : iblkno ( -- n ) d# 04 +sb ; + : cgoffset ( -- n ) d# 06 +sb ; + : cgmask ( -- n ) d# 07 +sb ; + : bsize ( -- n ) d# 12 +sb ; + : fragshift ( -- n ) d# 24 +sb ; + : fsbtodbc ( -- n ) d# 25 +sb ; + : inopb ( -- n ) d# 30 +sb ; + : ipg ( -- n ) d# 46 +sb ; + : fpg ( -- n ) d# 47 +sb ; + + : /frag ( -- fragsize ) bsize fragshift rshift ; + + : get-super-block ( -- ) + super-block /super-block super-block# read-disk-blocks + ; + + : cgstart ( cg -- block# ) + dup cgmask invert and cgoffset * swap fpg * + + ; + : cgimin ( cg -- block# ) cgstart iblkno + ; + : blkstofrags ( #blocks -- #frags ) fragshift lshift ; + : lblkno ( byte-off -- lblk# ) bsize / ; + : blkoff ( byte-off -- blk-off ) bsize mod ; + : fsbtodb ( fs-blk# -- dev-blk# ) fsbtodbc lshift ; + + : read-fs-blocks ( adr len fs-blk# -- ) fsbtodb read-disk-blocks ; + + + \ + \ UFS inode routines + \ + + h# 80 constant /inode + 0 instance value inode + 0 instance value iptr + + : itoo ( i# -- offset ) inopb mod ; + : itog ( i# -- group ) ipg / ; + : itod ( i# -- block# ) + dup itog cgimin swap ipg mod inopb / blkstofrags + + ; + + : +i ( n -- adr ) iptr + ; + + : ftype ( -- n ) 0 +i w@ h# f000 and ; + : dir? ( -- flag ) ftype h# 4000 = ; + : symlink? ( -- flag ) ftype h# a000 = ; + : regular? ( -- flag ) ftype h# 8000 = ; + + : file-size ( -- n ) 8 +i x@ ; + : direct0 ( -- adr ) d# 40 +i ; + : indirect0 ( -- adr ) d# 88 +i ; + : indirect1 ( -- adr ) d# 92 +i ; + : indirect2 ( -- adr ) d# 96 +i ; + : comp? ( -- flag ) d# 100 +i l@ 4 and 0<> ; + + 0 instance value current-file + : iget ( i# -- ) + dup temp-block bsize rot itod ( i# adr len blk# ) + read-fs-blocks + dup itoo /inode * temp-block + inode /inode move + inode to iptr + to current-file ( ) + ; + + : l@++ ( ptr -- value ) dup @ l@ /l rot +! ; + + d# 12 constant #direct + : #blk-addr/blk bsize /l / ; + : #sgl-addr #blk-addr/blk ; + : #dbl-addr #sgl-addr #blk-addr/blk * ; +\ : #tri-addr #dbl-addr #blk-addr/blk * ; + + : >1-idx ( blk# -- idx ) #blk-addr/blk mod ; + : >2-idx ( blk# -- idx ) #sgl-addr / >1-idx ; +\ : >3-idx ( blk# -- idx ) #dbl-addr / >1-idx ; + + \ + \ indirect block cache + \ we assume reads will mostly be sequential, and only + \ cache the current indirect block tree + \ + : get-indir ( fs-blk# var adr -- adr ) + -rot dup >r @ over = if ( adr fs-blk# r: var ) + r> 2drop exit ( adr ) + then ( adr fs-blk# r: var ) + 2dup bsize swap read-fs-blocks ( adr fs-blk# r: var ) + r> ! ( adr ) + ; + + 0 instance value indir0-adr + instance variable cur-indir0 + : get-indir0 ( fs-blk# -- adr ) + cur-indir0 indir0-adr get-indir + ; + + 0 instance value indir1-adr + instance variable cur-indir1 + : get-indir1 ( fs-blk# -- adr ) + cur-indir1 indir1-adr get-indir + ; + + \ + \ blkptr and blklim point to an array of blk#s, + \ whether in the inode direct block array or in + \ an indirect block + \ + instance variable blkptr + instance variable blklim + + : (bmap) ( lblk# -- ) + dup #direct < if ( lblk# ) + direct0 swap la+ blkptr ! ( ) + direct0 #direct la+ blklim ! + exit + then ( lblk# ) + + #direct - ( lblk#' ) + dup #sgl-addr < if + indirect0 l@ get-indir0 ( lblk# adr ) + tuck swap >1-idx la+ blkptr ! ( adr ) + #blk-addr/blk la+ blklim ! + exit + then ( lblk# ) + + #sgl-addr - ( lblk#' ) + dup #dbl-addr < if + indirect1 l@ get-indir0 ( lblk# adr ) + over >2-idx la+ l@ get-indir1 ( lblk# adr' ) + tuck swap >1-idx la+ blkptr ! ( adr ) + #blk-addr/blk la+ blklim ! ( ) + exit + then ( lblk# ) + +\ #dbl-addr - ( lblk#' ) +\ dup #tri-addr < if +\ indirect2 l@ get-indir0 ( lblk# adr ) +\ over >3-idx la+ l@ get-indir1 ( lblk# adr' ) +\ over >2-idx la+ l@ get-indir2 ( lblk# adr' ) +\ tuck swap >1-idx la+ blkptr ! ( adr ) +\ #blk-addr/blk la+ blklim ! ( ) +\ exit +\ then ( lblk# ) + ." file too large" cr drop true ( failed ) + ; + + 0 instance value cur-blk + : bmap ( lblk# -- fs-blk# ) + dup cur-blk <> blkptr @ blklim @ = or if ( lblk# ) + dup (bmap) ( lblk# ) + then ( lblk# ) + 1+ to cur-blk ( ) + blkptr l@++ ( fs-blk# ) + ; + + : read-one-block ( adr block# -- ) + bmap ?dup if + bsize swap read-fs-blocks + else + bsize erase + then + ; + + : read-partial-block ( adr len off block# -- ) + bmap ?dup if + fsbtodb blk>byte + ( adr len byte# ) + dev-ih read-disk + else + drop erase + then + ; + + \ + \ UFS directory routines + \ + + instance variable dir-blk + instance variable totoff + instance variable dirptr + 0 instance value dir-buf + + : get-dirblk ( -- ) + dir-buf bsize dir-blk @ bmap ( adr len fs-blk# ) + read-fs-blocks ( ) + 1 dir-blk +! + ; + + 2 constant rootino + + : +d ( n -- adr ) dirptr @ + ; + + : dir-ino ( -- adr ) 0 +d l@ ; + : reclen ( -- adr ) 4 +d w@ ; + : namelen ( -- adr ) 6 +d w@ ; + : dir-name ( -- adr ) 8 +d ; + : dir-name$ ( -- file$ ) dir-name namelen ; + + + \ + \ UFS high-level routines + \ + \ After this point, the code should be independent of the disk format! + + 0 instance value search-dir + : init-dent + 0 totoff ! 0 dir-blk ! + current-file to search-dir + ; + + : get-dent ( -- end-of-dir? ) + begin + totoff @ file-size >= if + true exit + then + totoff @ blkoff 0= if + get-dirblk + dir-buf dirptr ! + else + reclen dirptr +! + then + reclen totoff +! + dir-ino 0<> + until false + ; + + : dirlook ( file$ -- not-found? ) + init-dent + begin get-dent 0= while ( file$ ) + 2dup dir-name$ $= if ( file$ ) + dir-ino iget ( file$ ) + 2drop false exit ( found ) + then ( file$ ) + repeat 2drop true ( not-found ) + ; + + h# 200 constant /fpath-buf + /fpath-buf instance buffer: fpath-buf + : clr-fpath-buf ( -- ) fpath-buf /fpath-buf erase ; + : fpath-buf$ ( -- path$ ) fpath-buf cscount ; + + : follow-symlink ( tail$ -- tail$' ) + clr-fpath-buf ( tail$ ) + fpath-buf file-size 0 0 read-partial-block ( tail$ ) + ?dup if ( tail$ ) + " /" fpath-buf$ $append ( tail$ ) + fpath-buf$ $append ( ) + else drop then ( ) + fpath-buf$ ( path$ ) + over c@ ascii / = if ( path$ ) + str++ rootino ( path$' i# ) + else ( path$ ) + search-dir ( path$ i# ) + then ( path$ i# ) + iget ( path$ ) + ; + + : lookup ( path$ -- not-found? ) + over c@ ascii / = if + str++ rootino ( path$' i# ) + else + current-file ( path$ i# ) + then ( path$ i# ) + iget ( path$ ) + begin ( path$ ) + ascii / left-parse-string ( path$ file$ ) + dup while + dir? 0= if 2drop true exit then + dirlook if 2drop true exit then ( path$ ) + symlink? if + follow-symlink ( path$' ) + then ( path$ ) + repeat ( path$ file$ ) + 2drop 2drop false ( succeeded ) + ; + + : i#>name ( i# -- name$ ) + init-dent ( i# ) + begin get-dent 0= while ( i# ) + dup dir-ino = if ( i# ) + drop dir-name$ exit ( name$ ) + then ( i# ) + repeat drop " ???" ( name$ ) + ; + + + \ + \ UFS installation routines + \ + + /max-bsize 4 * + /super-block + + /inode + + constant alloc-size + + \ **** Allocate memory for necessary data structures + : allocate-buffers ( -- ) + alloc-size mem-alloc dup 0= if + ." no memory" abort + then ( adr ) + dup to temp-block /max-bsize + ( adr ) + dup to dir-buf /max-bsize + ( adr ) + dup to indir0-adr /max-bsize + ( adr ) + dup to indir1-adr /max-bsize + ( adr ) + dup to super-block /super-block + ( adr ) + to inode ( ) + ; + + : release-buffers ( -- ) + temp-block alloc-size mem-free + ; + + \ UFS file interface + + struct + /x field >busy + /x field >offset + /inode field >inode + constant /file-record + + d# 10 constant #opens + #opens /file-record * constant /file-records + + /file-records instance buffer: file-records + + -1 instance value current-fd + : fd>record ( fd -- record ) /file-record * file-records + ; + + + : file-offset@ ( -- off ) + current-fd fd>record >offset x@ + ; + + : file-offset! ( off -- ) + current-fd fd>record >offset x! + ; + + : get-slot ( -- fd false | true ) + #opens 0 do + i fd>record >busy x@ 0= if + i false unloop exit + then + loop true + ; + + : free-slot ( fd -- ) + 0 swap fd>record >busy x! + ; + + : init-fd ( fd -- ) + fd>record ( rec ) + dup >busy 1 swap x! + dup >inode inode swap /inode move + >offset 0 swap x! + ; + + : set-fd ( fd -- error? ) + dup fd>record dup >busy x@ 0= if ( fd rec ) + 2drop true exit ( failed ) + then + >inode to iptr ( fd ) + to current-fd false ( succeeded ) + ; + + + \ get current lblk# and offset within it + : file-blk+off ( -- off block# ) + file-offset@ dup blkoff swap lblkno + ; + + \ advance file io stack by n + : fio+ ( # adr len n -- #+n adr+n len-n ) + dup file-offset@ + file-offset! + dup >r - -rot ( len' # adr r: n ) + r@ + -rot ( adr' len' # r: n ) + r> + -rot ( #' adr' len' ) + ; + + : (cwd) ( i# -- ) tokenizer[ reveal ]tokenizer + dup rootino <> if + \ open parent, find current name + " .." lookup drop + i#>name ( name$ ) + \ recurse to print path components above + current-file (cwd) ( name$ ) + \ and print this component + type ( ) + else drop then ( ) + \ slash is both root name and separator + ." /" + ; + + external + + : open ( -- okay? ) + my-args dev-open dup 0= if ( 0 ) + exit ( failed ) + then to dev-ih + + allocate-buffers + get-super-block + file-records /file-records erase + true ( succeeded ) + ; + + : close ( -- ) + dev-ih dev-close + 0 to dev-ih + release-buffers + ; + + : open-file ( path$ -- fd true | false ) + get-slot if + 2drop false exit ( failed ) + then -rot ( fd path$ ) + + lookup if ( fd ) + drop false exit ( failed ) + then + + dup init-fd true ( fd succeeded ) + ; + + : close-file ( fd -- ) + free-slot ( ) + ; + + : size-file ( fd -- size ) + set-fd if 0 else file-size then + ; + + : seek-file ( off fd -- off true | false ) + set-fd if ( off ) + drop false exit ( failed ) + then ( off ) + + dup file-size > if ( off ) + drop false exit ( failed ) + then ( off ) + dup file-offset! true ( off succeeded ) + ; + + : read-file ( adr len fd -- #read ) + set-fd if ( adr len ) + 2drop 0 exit ( 0 ) + then ( adr len ) + + regular? 0= if 2drop 0 exit then + + \ adjust len if reading past eof + dup file-offset@ + file-size > if + dup file-offset@ + file-size - - + then + dup 0= if nip exit then + + 0 -rot ( #read adr len ) + + \ initial partial block + file-offset@ blkoff ?dup if ( #read adr len off ) + bsize swap - over min ( #read adr len len' ) + 3dup nip file-blk+off ( #read adr len len' adr len' off lblk# ) + read-partial-block ( #read adr len len ) + fio+ ( #read' adr' len' ) + then ( #read adr len ) + + dup lblkno 0 ?do ( #read adr len ) + over file-blk+off nip ( #read adr len adr lblk# ) + read-one-block ( #read adr len ) + bsize fio+ ( #read' adr' len' ) + loop ( #read adr len ) + + \ final partial block + dup if ( #read adr len ) + 2dup file-blk+off ( #read adr len adr len off lblk# ) + read-partial-block ( #read adr len ) + dup fio+ ( #read' adr' 0 ) + then 2drop ( #read ) + ; + + : cinfo-file ( fd -- bsize fsize comp? ) + set-fd if 0 0 0 else bsize file-size comp? then + ; + + \ read ramdisk fcode at rd-offset + : get-rd ( adr len -- ) + rd-offset dev-ih read-disk + ; + + \ no additional props needed for ufs + : bootprop ( -- ) false ; + + \ debug words + headers + + : chdir ( dir$ -- ) + current-file -rot ( i# dir$ ) + lookup if ( i# ) + to current-file ( ) + ." no such dir" cr exit + then ( i# ) + dir? 0= if ( i# ) + to current-file ( ) + ." not a dir" cr exit + then drop ( ) + ; + + : dir ( -- ) + current-file iget + init-dent + begin get-dent 0= while + dir-name$ type cr + repeat + ; + + : cwd ( -- ) + current-file ( i# ) + dup (cwd) cr ( i# ) + iget ( ) + ; + +finish-device +pop-package diff --git a/usr/src/psm/stand/bootblks/ufs/sparc/Makefile b/usr/src/psm/stand/bootblks/ufs/sparc/Makefile index 69ec178a4e..9679b0362c 100644 --- a/usr/src/psm/stand/bootblks/ufs/sparc/Makefile +++ b/usr/src/psm/stand/bootblks/ufs/sparc/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -22,7 +21,7 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # psm/stand/bootblks/ufs/sparc/Makefile @@ -30,9 +29,25 @@ BASEDIR = ../.. -include $(BASEDIR)/ufs/Makefile.ufs +include $(BASEDIR)/Makefile.com -SUBDIRS = unix sun4c sun4m sun4d sun4u sun4v +# +# This program is used to install the boot block +# +INSTALLBOOT = installboot + +USR = $(ROOT)/usr +USR_SBIN = $(USR)/sbin +USR_SBIN_INSTALLBOOT = $(USR_SBIN)/$(INSTALLBOOT) + +# +# Overrides for installing installboot. +# +INS.file.555 = $(RM) $@; $(INS) -s -m 555 -f $(@D) $< +$(CH)INS.file.555 = $(INS) -s -m 555 -u $(OWNER) -g $(GROUP) -f $(@D) $< + + +SUBDIRS = sun4u sun4v all := TARGET= all install := TARGET= install @@ -57,6 +72,12 @@ $(SUBDIRS): FRC FRC: # +# install rules +# +$(USR_SBIN)/%: % $(USR_SBIN) + $(INS.file.555) + +# # Pattern matching rules for source in this directory # %: %.sh diff --git a/usr/src/psm/stand/bootblks/zfs/Makefile b/usr/src/psm/stand/bootblks/zfs/Makefile new file mode 100644 index 0000000000..3e71e02fc4 --- /dev/null +++ b/usr/src/psm/stand/bootblks/zfs/Makefile @@ -0,0 +1,45 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# psm/stand/bootblks/zfs/Makefile +# +SUBDIRS = $(MACH) + +all := TARGET= all +install := TARGET= install +clean := TARGET= clean +clobber := TARGET= clobber +lint := TARGET= lint + +.KEEP_STATE: + +all install clean clobber lint : $(SUBDIRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: + diff --git a/usr/src/psm/stand/bootblks/zfs/Makefile.zfs b/usr/src/psm/stand/bootblks/zfs/Makefile.zfs new file mode 100644 index 0000000000..e0f1e0b52b --- /dev/null +++ b/usr/src/psm/stand/bootblks/zfs/Makefile.zfs @@ -0,0 +1,82 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# psm/stand/bootblks/zfs/Makefile.zfs +# + +include $(BASEDIR)/Makefile.com + +# +# Define FS dependent targets +# + +ZFS_DIR = $(BASEDIR)/zfs/common + +ZFSBOOT_FTH = $(ZFS_DIR)/boot-zfs.fth +ZFS_FTH = $(ZFS_DIR)/zfs.fth + +FS_FCODE = boot-zfs.fcode +FS_BB = zfs.bb + +ZFSDBGBOOT_FTH = $(ZFS_DIR)/debug-zfs.fth +ZFSDBG_FTH = $(ZFS_DIR)/big-zfs.fth + +DBGBOOT_FCODE = debug-zfs.fcode +DBGFS_FCODE = big-zfs.fcode + +DBGFS_BB = debugzfs.bb +DBGPROG = debugbb + +DBG_CLEAN += $(DBGBOOT_FCODE) $(DBGFS_FCODE) +DBG_CLOBBER += $(DBGPROG) $(DBGFS_BB) + +# +# Where and how stuff gets installed +# +USR_PSM_BOOTBLOCK = $(USR_PSM_LIB_ZFS_DIR)/$(PROG) + +%.fcode: $(BASEDIR)/zfs/common/%.fth + $(TOKENIZE) $< + +# make doesn't know fload +$(FS_FCODE): $(UTIL_FTH) $(ZFS_FTH) $(BOOT_FTH) + $(TOKENIZE) $(ZFSBOOT_FTH) + + +$(DBGBOOT_FCODE): $(UTIL_FTH) $(BOOT_FTH) + $(TOKENIZE) $(ZFSDBGBOOT_FTH) + +$(DBGFS_FCODE): $(UTIL_FTH) $(ZFS_FTH) + $(TOKENIZE) $(ZFSDBG_FTH) + +$(DBGFS_BB): $(MKBB) $(DBGBOOT_FCODE) $(DBGFS_FCODE) $(RD_FCODE) + $(MKBB) -e $(DBGFS_FCODE) $(DBGBOOT_FCODE) $(RD_FCODE) $(DBGFS_BB) + +$(DBGPROG): $(DBGFS_BB) + @-$(RM) $@ + cp -p $(DBGFS_BB) $@ + +debug: $(DBGPROG) diff --git a/usr/src/psm/stand/bootblks/zfs/common/big-zfs.fth b/usr/src/psm/stand/bootblks/zfs/common/big-zfs.fth new file mode 100644 index 0000000000..986dabf003 --- /dev/null +++ b/usr/src/psm/stand/bootblks/zfs/common/big-zfs.fth @@ -0,0 +1,43 @@ + + +\ ident "%Z%%M% %I% %E% SMI" +\ Copyright 2007 Sun Microsystems, Inc. All rights reserved. +\ Use is subject to license terms. +\ +\ CDDL HEADER START +\ +\ The contents of this file are subject to the terms of the +\ Common Development and Distribution License (the "License"). +\ You may not use this file except in compliance with the License. +\ +\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ or http://www.opensolaris.org/os/licensing. +\ See the License for the specific language governing permissions +\ and limitations under the License. +\ +\ When distributing Covered Code, include this CDDL HEADER in each +\ file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ If applicable, add the following below this CDDL HEADER, with the +\ fields enclosed by brackets "[]" replaced with your own identifying +\ information: Portions Copyright [yyyy] [name of copyright owner] +\ +\ CDDL HEADER END +\ + + +id: %Z%%M% %I% %E% SMI +purpose: ZFS debug fs reader +copyright: Copyright 2007 Sun Microsystems, Inc. All Rights Reserved + +\ add headers +create doheaders +create bigbootblk + +: fs-pkg$ " zfs-file-system" ; +: fs-type$ " zfs" ; + +\ load common words +fload ../../../common/util.fth + +\ load fs reader +fload ../../common/zfs.fth diff --git a/usr/src/psm/stand/bootblks/zfs/common/boot-zfs.fth b/usr/src/psm/stand/bootblks/zfs/common/boot-zfs.fth new file mode 100644 index 0000000000..69536d3c6a --- /dev/null +++ b/usr/src/psm/stand/bootblks/zfs/common/boot-zfs.fth @@ -0,0 +1,45 @@ + + +\ ident "%Z%%M% %I% %E% SMI" +\ Copyright 2007 Sun Microsystems, Inc. All rights reserved. +\ Use is subject to license terms. +\ +\ CDDL HEADER START +\ +\ The contents of this file are subject to the terms of the +\ Common Development and Distribution License (the "License"). +\ You may not use this file except in compliance with the License. +\ +\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ or http://www.opensolaris.org/os/licensing. +\ See the License for the specific language governing permissions +\ and limitations under the License. +\ +\ When distributing Covered Code, include this CDDL HEADER in each +\ file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ If applicable, add the following below this CDDL HEADER, with the +\ fields enclosed by brackets "[]" replaced with your own identifying +\ information: Portions Copyright [yyyy] [name of copyright owner] +\ +\ CDDL HEADER END +\ + + +id: %Z%%M% %I% %E% SMI +purpose: ZFS bootblock +copyright: Copyright 2006 Sun Microsystems, Inc. All Rights Reserved + +\ for [ifdef] zfs +create zfs + +: fs-pkg$ " zfs-file-system" ; +: fs-type$ " zfs" ; + +\ load common words +fload ../../../common/util.fth + +\ load fs reader +fload ../../common/zfs.fth + +\ load booter +fload ../../../common/boot.fth diff --git a/usr/src/psm/stand/bootblks/zfs/common/debug-zfs.fth b/usr/src/psm/stand/bootblks/zfs/common/debug-zfs.fth new file mode 100644 index 0000000000..296ea5a2a7 --- /dev/null +++ b/usr/src/psm/stand/bootblks/zfs/common/debug-zfs.fth @@ -0,0 +1,48 @@ + + +\ ident "%Z%%M% %I% %E% SMI" +\ Copyright 2007 Sun Microsystems, Inc. All rights reserved. +\ Use is subject to license terms. +\ +\ CDDL HEADER START +\ +\ The contents of this file are subject to the terms of the +\ Common Development and Distribution License (the "License"). +\ You may not use this file except in compliance with the License. +\ +\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ or http://www.opensolaris.org/os/licensing. +\ See the License for the specific language governing permissions +\ and limitations under the License. +\ +\ When distributing Covered Code, include this CDDL HEADER in each +\ file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ If applicable, add the following below this CDDL HEADER, with the +\ fields enclosed by brackets "[]" replaced with your own identifying +\ information: Portions Copyright [yyyy] [name of copyright owner] +\ +\ CDDL HEADER END +\ + + +id: %Z%%M% %I% %E% SMI +purpose: ZFS debug bootblock +copyright: Copyright 2007 Sun Microsystems, Inc. All Rights Reserved + +\ big bootblk +create doheaders +create bigbootblk +d# 8192 constant /fs-fcode +d# 8192 constant fs-offset + +\ for [ifdef] zfs +create zfs + +: fs-pkg$ " zfs-file-system" ; +: fs-type$ " zfs" ; + +\ load common words +fload ../../../common/util.fth + +\ load booter +fload ../../../common/boot.fth diff --git a/usr/src/psm/stand/bootblks/zfs/common/zfs.fth b/usr/src/psm/stand/bootblks/zfs/common/zfs.fth new file mode 100644 index 0000000000..50784d8839 --- /dev/null +++ b/usr/src/psm/stand/bootblks/zfs/common/zfs.fth @@ -0,0 +1,1221 @@ + +\ ident "%Z%%M% %I% %E% SMI" +\ Copyright 2007 Sun Microsystems, Inc. All rights reserved. +\ Use is subject to license terms. +\ +\ CDDL HEADER START +\ +\ The contents of this file are subject to the terms of the +\ Common Development and Distribution License (the "License"). +\ You may not use this file except in compliance with the License. +\ +\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ or http://www.opensolaris.org/os/licensing. +\ See the License for the specific language governing permissions +\ and limitations under the License. +\ +\ When distributing Covered Code, include this CDDL HEADER in each +\ file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ If applicable, add the following below this CDDL HEADER, with the +\ fields enclosed by brackets "[]" replaced with your own identifying +\ information: Portions Copyright [yyyy] [name of copyright owner] +\ +\ CDDL HEADER END +\ +\ + +[ifdef] doheaders +headers +[else] +headerless +[then] + + +id: %Z%%M% %I% %E% SMI +purpose: ZFS file system support package +copyright: Copyright 2006 Sun Microsystems, Inc. All Rights Reserved + +" /packages" get-package push-package + +new-device + fs-pkg$ device-name diag-cr? + + 0 instance value temp-space + + + \ 64b ops + \ fcode is still 32b on 64b sparc-v9, so + \ we need to override some arithmetic ops + \ stack ops and logical ops (dup, and, etc) are 64b + : xcmp ( x1 x2 -- -1|0|1 ) + xlsplit rot xlsplit ( x2.lo x2.hi x1.lo x1.hi ) + rot 2dup < if ( x2.lo x1.lo x1.hi x2.hi ) + 2drop 2drop -1 ( lt ) + else > if ( x2.lo x1.lo ) + 2drop 1 ( gt ) + else swap 2dup < if ( x1.lo x2.lo ) + 2drop -1 ( lt ) + else > if ( ) + 1 ( gt ) + else ( ) + 0 ( eq ) + then then then then ( -1|0|1 ) + ; + : x< ( x1 x2 -- <? ) xcmp -1 = ; + : x> ( x1 x2 -- >? ) xcmp 1 = ; +\ : x= ( x1 x2 -- =? ) xcmp 0= ; + : x<> ( x1 x2 -- <>? ) xcmp 0<> ; + : x0= ( x -- 0=? ) xlsplit 0= swap 0= and ; + + /buf-len instance buffer: numbuf + + : (xu.) ( u -- u$ ) + numbuf /buf-len + swap ( adr u ) + begin + d# 10 /mod swap ( adr u' rem ) + ascii 0 + ( adr u' c ) + rot 1- tuck c! ( u adr' ) + swap dup 0= ( adr u done? ) + until drop ( adr ) + dup numbuf - /buf-len swap - ( adr len ) + ; + + \ pool name + /buf-len instance buffer: bootprop-buf + : bootprop$ ( -- prop$ ) bootprop-buf cscount ; + + \ decompression + \ + \ uts/common/os/compress.c has a definitive theory of operation comment + \ on lzjb, but here's the reader's digest version: + \ + \ repeated phrases are replaced by referenced to the original + \ e.g., + \ y a d d a _ y a d d a _ y a d d a , _ b l a h _ b l a h _ b l a h + \ becomes + \ y a d d a _ 6 11 , _ b l a h 5 10 + \ where 6 11 means memmove(ptr, ptr - 6, 11) + \ + \ data is separated from metadata with embedded copymap entries + \ every 8 items e.g., + \ 0x40 y a d d a _ 6 11 , 0x20 _ b l a h 5 10 + \ the copymap has a set bit for copy refercences + \ and a clear bit for bytes to be copied directly + \ + \ the reference marks are encoded with match-bits and match-min + \ e.g., + \ byte[0] = ((mlen - MATCH_MIN) << (NBBY - MATCH_BITS) | (off >> NBBY) + \ byte[1] = (uint8_t)off + \ + + : pow2 ( n -- 2**n ) 1 swap lshift ; + + \ assume MATCH_BITS=6 and MATCH_MIN=3 + 6 constant mbits + 3 constant mmin + 8 mbits - constant mshift + d# 16 mbits - pow2 1- constant mmask + + : decode-src ( src -- mlen off ) + dup c@ swap 1+ c@ ( c[0] c[1] ) + over mshift rshift mmin + ( c[0] c[1] mlen ) + -rot swap bwjoin mmask and ( mlen off ) + ; + + \ equivalent of memmove(dst, dst - off, len) + \ src points to a copy reference to be decoded + : mcopy ( dend dst src -- dend dst' ) + decode-src ( dend dst mlen off ) + 2 pick swap - >r ( dent dst mlen r: cpy ) + begin + 1- dup 0>= ( dend dst mlen' any? r: cpy ) + 2over > and ( dend dst mlen !done? r : cpy ) + while ( dend dst mlen r: cpy ) + swap r> dup 1+ >r c@ ( dend mlen dst c r: cpy' ) + over c! 1+ swap ( dend dst' mlen r: cpy ) + repeat ( dend dst' mlen r: cpy ) + r> 2drop ( dend dst ) + ; + + + : lzjb ( src dst len -- ) + over + swap ( src dend dst ) + rot >r ( dend dst r: src ) + + \ setup mask so 1st while iteration fills map + 0 7 pow2 2swap ( map mask dend dst r: src ) + + begin 2dup > while + 2swap 1 lshift ( dend dst map mask' r: src ) + + dup 8 pow2 = if + \ fetch next copymap + 2drop ( dend dst r: src ) + r> dup 1+ >r c@ 1 ( dend dst map' mask' r: src' ) + then ( dend dst map mask r: src' ) + + \ if (map & mask) we hit a copy reference + \ else just copy 1 byte + 2swap 2over and if ( map mask dend dst r: src ) + r> dup 2+ >r ( map mask dend dst src r: src' ) + mcopy ( map mask dend dst' r: src ) + else + r> dup 1+ >r c@ ( map mask dend dst c r: src' ) + over c! 1+ ( map mask dend dst' r: src ) + then + repeat ( map mask dend dst r: src ) + 2drop 2drop r> drop ( ) + ; + + + \ + \ ZFS block (SPA) routines + \ + + 2 constant no-comp# + h# 2.0000 constant /max-bsize + d# 512 constant /disk-block + d# 128 constant /blkp + + : blk_offset ( bp -- n ) h# 8 + x@ -1 h# 8fff.ffff lxjoin and ; + : blk_gang ( bp -- n ) h# 8 + x@ xlsplit nip d# 31 rshift ; + : blk_comp ( bp -- n ) h# 33 + c@ ; + : blk_psize ( bp -- n ) h# 34 + w@ ; + : blk_lsize ( bp -- n ) h# 36 + w@ ; + : blk_birth ( bp -- n ) h# 50 + x@ ; + + 0 instance value dev-ih + 0 instance value blk-space + 0 instance value gang-space + + : foff>doff ( fs-off -- disk-off ) /disk-block * h# 40.0000 + ; + : fsz>dsz ( fs-size -- disk-size ) 1+ /disk-block * ; + + : bp-dsize ( bp -- dsize ) blk_psize fsz>dsz ; + : bp-lsize ( bp -- lsize ) blk_lsize fsz>dsz ; + + : (read-bp) ( adr len bp -- ) + blk_offset foff>doff dev-ih read-disk + ; + + : gang-read ( adr len bp -- ) + + \ read gang block + gang-space /disk-block rot ( adr len gb-adr gb-len bp ) + (read-bp) ( adr len ) + + \ read gang indirected blocks to blk-space + \ and copy requested len from there + blk-space gang-space ( adr len tmp-adr bp0 ) + dup /blkp 3 * + bounds do ( adr len tmp-adr ) + i blk_offset x0= ?leave + i bp-dsize ( adr len tmp-adr rd-len ) + 2dup i (read-bp) + + ( adr len tmp-adr' ) + /blkp +loop + drop ( adr len ) + blk-space -rot move ( ) + ; + + \ block read that check for holes, gangs, compression, etc + : read-bp ( adr len bp -- ) + \ sparse block? + dup blk_birth x0= if + drop erase exit ( ) + then + \ gang block? + dup blk_gang if + gang-read exit ( ) + then + \ compression? + dup blk_comp no-comp# <> if + blk-space over bp-dsize ( adr len bp b-adr rd-len ) + rot (read-bp) ( adr len ) + blk-space -rot lzjb exit ( ) + then + \ boring direct block + (read-bp) ( ) + ; + + \ + \ ZFS vdev routines + \ + + h# 1.c000 constant /nvpairs + h# 4000 constant nvpairs-off + + \ + \ xdr packed nvlist + \ + \ 12B header + \ array of xdr packed nvpairs + \ 4B encoded nvpair size + \ 4B decoded nvpair size + \ 4B name string size + \ name string + \ 4B data type + \ 4B # of data elements + \ data + \ 8B of 0 + \ + d# 12 constant /nvhead + + : >nvsize ( nv -- size ) l@ ; + : >nvname ( nv -- name$ ) + /l 2* + dup /l + swap l@ + ; + : >nvdata ( nv -- data ) + >nvname + /l roundup + ; + alias nvdata>$ >nvname + + : nv-lookup ( nv name$ -- nvdata false | true ) + rot /nvhead + ( name$ nvpair ) + begin dup >nvsize while + dup >r >nvname ( name$ nvname$ r: nvpair ) + 2over $= if ( name$ r: nvpair ) + 2drop r> >nvdata ( nvdata ) + false exit ( nvdata found ) + then ( name$ r: nvpair ) + r> dup >nvsize + ( name$ nvpair' ) + repeat + 3drop true ( not-found ) + ; + + : scan-vdev ( -- ) + temp-space /nvpairs nvpairs-off ( adr len off ) + dev-ih read-disk ( ) + temp-space " name" nv-lookup if + ." no name nvpair" abort + then nvdata>$ ( pool$ ) + bootprop-buf swap move ( ) + ; + + + \ + \ ZFS ueber-block routines + \ + + d# 1024 constant /uber-block + d# 128 constant #ub/label + #ub/label /uber-block * constant /ub-ring + h# 2.0000 constant ubring-off + + : ub_magic ( ub -- n ) x@ ; + : ub_txg ( ub -- n ) h# 10 + x@ ; + : ub_timestamp ( ub -- n ) h# 20 + x@ ; + : ub_rootbp ( ub -- p ) h# 28 + ; + + 0 instance value uber-block + + : ub-cmp ( ub1 ub2 -- best-ub ) + + \ ub1 wins if ub2 isn't valid + dup ub_magic h# 00bab10c x<> if + drop exit ( ub1 ) + then + + \ if ub1 is 0, ub2 wins by default + over 0= if nip exit then ( ub2 ) + + \ 2 valid ubs, compare transaction groups + over ub_txg over ub_txg ( ub1 ub2 txg1 txg2 ) + 2dup x< if + 2drop nip exit ( ub2 ) + then ( ub1 ub2 txg1 txg2 ) + x> if drop exit then ( ub1 ) + + \ same txg, check timestamps + over ub_timestamp over ub_timestamp x> if + nip ( ub2 ) + else + drop ( ub1 ) + then + ; + + \ find best uber-block in ring, and copy it to uber-block + : get-ub ( -- ) + temp-space /ub-ring ubring-off ( adr len off ) + dev-ih read-disk ( ) + 0 temp-space /ub-ring ( null-ub adr len ) + bounds do ( ub ) + i ub-cmp ( best-ub ) + /uber-block +loop + + \ make sure we found a valid ub + dup 0= if ." no ub found" abort then + + uber-block /uber-block move ( ) + ; + + + \ + \ ZFS dnode (DMU) routines + \ + + d# 512 constant /dnode + + : dn_indblkshift ( dn -- n ) h# 1 + c@ ; + : dn_nlevels ( dn -- n ) h# 2 + c@ ; + : dn_datablkszsec ( dn -- n ) h# 8 + w@ ; + : dn_blkptr ( dn -- p ) h# 40 + ; + : dn_bonus ( dn -- p ) h# c0 + ; + + 0 instance value dnode + + \ indirect cache + \ + \ ind-cache is a 1 block indirect block cache from dnode ic-dn + \ + \ ic-bp and ic-bplim point into the ic-dn's block ptr array, + \ either in dn_blkptr or in ind-cache ic-bp is the ic-blk#'th + \ block ptr, and ic-bplim is limit of the current bp array + \ + \ the assumption is that reads will be sequential, so we can + \ just increment ic-bp + \ + 0 instance value ind-cache + 0 instance value ic-dn + 0 instance value ic-blk# + 0 instance value ic-bp + 0 instance value ic-bplim + + : dn-bsize ( dn -- bsize ) dn_datablkszsec /disk-block * ; + : dn-indsize ( dn -- indsize ) dn_indblkshift pow2 ; + : dn-indmask ( dn -- mask ) dn-indsize 1- ; + + \ recursively climb the block tree from the leaf to the root + : blk@lvl>bp ( dn blk# lvl -- bp ) tokenizer[ reveal ]tokenizer + >r /blkp * over dn_nlevels ( dn bp-off #lvls r: lvl ) + + \ at top, just add dn_blkptr + r@ = if ( dn bp-off r: lvl ) + swap dn_blkptr + ( bp r: lvl ) + r> drop exit ( bp ) + then ( dn bp-off r: lvl ) + + \ shift bp-off down and find parent indir blk + 2dup over dn_indblkshift rshift ( dn bp-off dn blk# r: lvl ) + r> 1+ blk@lvl>bp ( dn bp-off bp ) + + \ read parent indir and index + rot tuck dn-indsize ( bp-off dn bp len ) + ind-cache swap rot read-bp ( bp-off dn ) + dn-indmask and ( bp-off' ) + ind-cache + ( bp ) + ; + + \ return end of current bp array + : bplim ( dn bp -- bp-lim ) + over dn_nlevels 1 = if + drop dn_blkptr ( bp0 ) + 3 /blkp * + ( bplim ) + else + 1+ swap dn-indsize ( bp+1 indsz ) + roundup ( bplim ) + then + ; + + \ return the lblk#'th block ptr from dnode + : lblk#>bp ( dn blk# -- bp ) + 2dup ( dn blk# dn blk# ) + ic-blk# <> swap ic-dn <> or ( dn blk# cache-miss? ) + ic-bp ic-bplim = ( dn blk# cache-miss? cache-empty? ) + or if ( dn blk# ) + 2dup 1 blk@lvl>bp ( dn blk# bp ) + dup to ic-bp ( dn blk# bp ) + swap to ic-blk# ( dn bp ) + 2dup bplim to ic-bplim ( dn bp ) + over to ic-dn + then 2drop ( ) + ic-blk# 1+ to ic-blk# + ic-bp dup /blkp + to ic-bp ( bp ) + ; + + + \ + \ ZFS attribute (ZAP) routines + \ + + 1 constant fzap# + 3 constant uzap# + + d# 64 constant /uzap + + d# 24 constant /lf-chunk + d# 21 constant /lf-arr + h# ffff constant chain-end# + + h# 100 constant /lf-buf + /lf-buf instance buffer: leaf-value + /lf-buf instance buffer: leaf-name + + : +le ( len off -- n ) + w@ ; + : le_next ( le -- n ) h# 2 +le ; + : le_name_chunk ( le -- n ) h# 4 +le ; + : le_name_length ( le -- n ) h# 6 +le ; + : le_value_chunk ( le -- n ) h# 8 +le ; + : le_value_length ( le -- n ) h# a +le ; + + : la_array ( la -- adr ) 1+ ; + : la_next ( la -- n ) h# 16 + w@ ; + + 0 instance value zap-space + + \ setup leaf hash bounds + : >leaf-hash ( dn lh -- hash-adr /hash ) + /lf-chunk 2* + ( dn hash-adr ) + \ size = (bsize / 32) * 2 + swap dn-bsize 4 rshift ( hash-adr /hash ) + ; + : >leaf-chunks ( lf -- ch0 ) >leaf-hash + ; + + \ convert chunk # to leaf chunk + : ch#>lc ( dn ch# -- lc ) + /lf-chunk * ( dn lc-off ) + swap zap-space >leaf-chunks ( lc-off ch0 ) + + ( lc ) + ; + + \ assemble chunk chain into single buffer + : get-chunk-data ( dn ch# adr -- ) + dup >r /lf-buf erase ( dn ch# r: adr ) + begin + 2dup ch#>lc nip ( dn la r: adr ) + dup la_array ( dn la la-arr r: adr ) + r@ /lf-arr move ( dn la r: adr ) + r> /lf-arr + >r ( dn la r: adr' ) + la_next dup chain-end# = ( dn la-ch# end? r: adr ) + until r> 3drop ( ) + ; + + \ get leaf entry's name + : entry-name$ ( dn le -- name$ ) + 2dup le_name_chunk ( dn le dn la-ch# ) + leaf-name get-chunk-data ( dn le ) + nip le_name_length ( len ) + leaf-name swap ( name$ ) + ; + + \ return entry value as int + : entry-int-val ( dn le -- n ) + le_value_chunk ( dn la-ch# ) + leaf-value get-chunk-data ( ) + leaf-value x@ ( n ) + ; + + +[ifdef] strlookup + \ get leaf entry's value as string + : entry-val$ ( dn le -- val$ ) + 2dup le_value_chunk ( dn le dn la-ch# ) + leaf-value get-chunk-data ( dn le ) + nip le_value_length ( len ) + leaf-value swap ( name$ ) + ; +[then] + + \ apply xt to entry + : entry-apply ( xt dn le -- xt dn false | ??? true ) + over >r ( xt dn le r: dn ) + rot dup >r execute if ( ??? r: xt dn ) + r> r> 2drop true ( ??? true ) + else ( ) + r> r> false ( xt dn false ) + then + ; + + \ apply xt to every entry in chain + : chain-apply ( xt dn ch# -- xt dn false | ??? true ) + begin + 2dup ch#>lc nip ( xt dn le ) + dup >r entry-apply if ( ??? r: le ) + r> drop true exit ( ??? found ) + then ( xt dn r: le ) + r> le_next ( xt dn ch# ) + dup chain-end# = ( xt dn ch# end? ) + until drop ( xt dn ) + false ( xt dn false ) + ; + + \ apply xt to every entry in leaf + : leaf-apply ( xt dn blk# -- xt dn false | ??? true ) + + \ read zap leaf into zap-space + 2dup lblk#>bp ( xt dn blk# bp ) + nip over dn-bsize zap-space ( xt dn bp len adr ) + swap rot read-bp ( xt dn ) + + \ call chunk-look for every valid chunk list + dup zap-space >leaf-hash ( xt dn hash-adr /hash ) + bounds do ( xt dn ) + i w@ dup chain-end# <> if ( xt dn ch# ) + chain-apply if ( ??? ) + unloop true exit ( ??? found ) + then ( xt dn ) + else drop then ( xt dn ) + /w +loop + false ( xt dn not-found ) + ; + + \ apply xt to every entry in fzap + : fzap-apply ( xt dn fz -- ??? not-found? ) + + \ blk# 1 is always the 1st leaf + >r 1 leaf-apply if ( ??? r: fz ) + r> drop false exit ( ??? found ) + then r> ( xt dn fz ) + + \ call leaf-apply on every non-duplicate hash entry + \ embedded hash is in 2nd half of fzap block + over dn-bsize tuck + ( xt dn bsize hash-eadr ) + swap 2dup 2/ - ( xt dn hash-eadr bsize hash-adr ) + nip do ( xt dn ) + i x@ dup 1 <> if ( xt dn blk# ) + leaf-apply if ( ??? ) + unloop true exit ( ??? found ) + then ( xt dn ) + else drop then ( xt dn ) + /x +loop + 2drop false ( not-found ) + ; + + : mze_value ( uz -- n ) x@ ; + : mze_name ( uz -- p ) h# e + ; + + : uzap-name$ ( uz -- name$ ) mze_name cscount ; + + \ apply xt to each entry in micro-zap + : uzap-apply ( xt uz len -- ??? not-found? ) + bounds do ( xt ) + i swap dup >r ( uz xt r: xt ) + execute if ( ??? r: xt ) + r> drop ( ??? ) + unloop true exit ( ??? found ) + then r> ( xt ) + /uzap +loop + drop false ( not-found ) + ; + + \ match by name + : fz-nmlook ( prop$ dn le -- prop$ false | prop$ dn le true ) + 2dup entry-name$ ( prop$ dn le name$ ) + 2rot 2swap ( dn le prop$ name$ ) + 2over $= if ( dn le prop$ ) + 2swap true ( prop$ dn le true ) + else ( dn le prop$ ) + 2swap 2drop false ( prop$ false ) + then ( prop$ false | prop$ dn le true ) + ; + + \ match by name + : uz-nmlook ( prop$ uz -- prop$ false | prop$ uz true ) + dup >r uzap-name$ ( prop$ name$ r: uz ) + 2over $= if ( prop$ r: uz ) + r> true ( prop$ uz true ) + else ( prop$ r: uz ) + r> drop false ( prop$ false ) + then ( prop$ false | prop$ uz true ) + ; + + : zap-type ( zp -- n ) h# 7 + c@ ; + : >uzap-ent ( adr -- ent ) h# 40 + ; + + \ read zap block into temp-space + : get-zap ( dn -- zp ) + dup 0 lblk#>bp ( dn bp ) + swap dn-bsize ( bp len ) + temp-space swap ( bp adr len ) + rot read-bp ( ) + temp-space ( zp ) + ; + + \ find prop in zap dnode + : zap-lookup ( dn prop$ -- [ n ] not-found? ) + rot dup get-zap ( prop$ dn zp ) + dup zap-type case + uzap# of + >uzap-ent swap dn-bsize ( prop$ uz len ) + ['] uz-nmlook -rot ( prop$ xt uz len ) + uzap-apply if ( prop$ uz ) + mze_value -rot 2drop ( n ) + false ( n found ) + else ( prop$ ) + 2drop true ( !found ) + then ( [ n ] not-found? ) + endof + fzap# of + ['] fz-nmlook -rot ( prop$ xt dn fz ) + fzap-apply if ( prop$ dn le ) + entry-int-val ( prop$ n ) + -rot 2drop false ( n found ) + else ( prop$ ) + 2drop true ( !found ) + then ( [ n ] not-found? ) + endof + 3drop 2drop true ( !found ) + endcase ( [ n ] not-found? ) + ; + +[ifdef] strlookup + : zap-lookup-str ( dn prop$ -- [ val$ ] not-found? ) + rot dup get-zap ( prop$ dn zp ) + dup zap-type fzap# <> if ( prop$ dn zp ) + 2drop 2drop true exit ( !found ) + then ( prop$ dn zp ) + ['] fz-nmlook -rot ( prop$ xt dn fz ) + fzap-apply if ( prop$ dn le ) + entry-val$ 2swap 2drop false ( val$ found ) + else ( prop$ ) + 2drop true ( !found ) + then ( [ val$ ] not-found? ) + ; +[then] + +[ifdef] bigbootblk + : fz-print ( dn le -- false ) + entry-name$ type cr false + ; + + : uz-print ( uz -- false ) + uzap-name$ type cr false + ; + + : zap-print ( dn -- ) + dup get-zap ( dn zp ) + dup zap-type case + uzap# of + >uzap-ent swap dn-bsize ( uz len ) + ['] uz-print -rot ( xt uz len ) + uzap-apply ( false ) + endof + fzap# of + ['] fz-print -rot ( xt dn fz ) + fzap-apply ( false ) + endof + 3drop false ( false ) + endcase ( false ) + drop ( ) + ; +[then] + + + \ + \ ZFS object set (DSL) routines + \ + + 1 constant pool-dir# + + : dd_head_dataset_obj ( dd -- n ) h# 8 + x@ ; + : dd_child_dir_zapobj ( dd -- n ) h# 20 + x@ ; + : ds_bp ( ds -- p ) h# 80 + ; + + 0 instance value mos-dn + 0 instance value obj-dir + 0 instance value root-dsl + 0 instance value root-dsl# + 0 instance value fs-dn + + \ dn-cache contains dc-dn's contents at dc-blk# + \ dc-dn will be either mos-dn or fs-dn + 0 instance value dn-cache + 0 instance value dc-dn + 0 instance value dc-blk# + + alias >dsl-dir dn_bonus + alias >dsl-ds dn_bonus + + : #dn/blk ( dn -- n ) dn-bsize /dnode / ; + + \ read block into dn-cache + : get-dnblk ( dn blk# -- ) + lblk#>bp dn-cache swap ( adr bp ) + dup bp-lsize swap read-bp ( ) + ; + + \ read obj# from objset dir dn into dnode + : get-dnode ( dn obj# -- ) + + \ check dn-cache + 2dup swap #dn/blk /mod ( dn obj# off# blk# ) + swap >r nip ( dn blk# r: off# ) + 2dup dc-blk# <> ( dn blk# dn !blk-hit? r: off# ) + swap dc-dn <> or if ( dn blk# r: off# ) + \ cache miss, fill from dir + 2dup get-dnblk + over to dc-dn + dup to dc-blk# + then ( dn blk# r: off# ) + + \ index and copy + 2drop r> /dnode * ( off ) + dn-cache + ( dn-adr ) + dnode /dnode move ( ) + ; + + \ read meta object set from uber-block + : get-mos ( -- ) + mos-dn /dnode ( adr len ) + uber-block ub_rootbp read-bp + ; + + : get-mos-dnode ( obj# -- ) + mos-dn swap get-dnode + ; + + \ get root dataset + : get-root-dsl ( -- ) + + \ read MOS + get-mos + + \ read object dir + pool-dir# get-mos-dnode + dnode obj-dir /dnode move + + \ read root dataset + obj-dir " root_dataset" zap-lookup if + ." no root_dataset" abort + then ( obj# ) + dup to root-dsl# + get-mos-dnode ( ) + dnode root-dsl /dnode move + ; + + \ look thru the dsl hierarchy for path + \ this looks almost exactly like a FS directory lookup + : dsl-lookup ( path$ -- [ ds-obj# ] not-found? ) + root-dsl >r ( path$ r: root-dn ) + begin + ascii / left-parse-string ( path$ file$ r: dn ) + dup while + + \ get child dir zap dnode + r> >dsl-dir dd_child_dir_zapobj ( path$ file$ obj# ) + get-mos-dnode ( path$ file$ ) + + \ search it + dnode -rot zap-lookup if ( path$ ) + \ not found + 2drop true exit ( not-found ) + then ( path$ obj# ) + get-mos-dnode ( path$ ) + dnode >r ( path$ r: dn ) + repeat ( path$ file$ r: dn) + 2drop 2drop r> drop ( ) + + \ found it, return dataset obj# + dnode >dsl-dir dd_head_dataset_obj ( ds-obj# ) + false ( ds-obj# found ) + ; + + \ get objset from dataset + : get-objset ( adr dn -- ) + >dsl-ds ds_bp /dnode swap read-bp + ; + + + \ + \ ZFS file-system (ZPL) routines + \ + + 1 constant master-node# + d# 264 constant /znode + d# 56 constant /zn-slink + + : zp_mode ( zn -- n ) h# 48 + x@ ; + : zp_size ( zn -- n ) h# 50 + x@ ; + : zp_parent ( zn -- n ) h# 58 + x@ ; + + 0 instance value bootfs-obj# + 0 instance value root-obj# + 0 instance value current-obj# + 0 instance value search-obj# + + alias >znode dn_bonus + + : fsize ( dn -- n ) >znode zp_size ; + : ftype ( dn -- n ) >znode zp_mode h# f000 and ; + : dir? ( dn -- flag ) ftype h# 4000 = ; + : regular? ( dn -- flag ) ftype h# 8000 = ; + : symlink? ( dn -- flag ) ftype h# a000 = ; + + \ read obj# from fs objset + : get-fs-dnode ( obj# -- ) + dup to current-obj# + fs-dn swap get-dnode ( ) + ; + + \ get root-obj# from dataset + : get-rootobj# ( ds-obj# -- fsroot-obj# ) + dup to bootfs-obj# + get-mos-dnode ( ) + fs-dn dnode get-objset + + \ get root obj# from master node + master-node# get-fs-dnode + dnode " ROOT" zap-lookup if + ." no ROOT" abort + then ( fsroot-obj# ) + ; + + : prop>rootobj# ( -- ) + obj-dir " pool_props" zap-lookup if + ." no pool_props" abort + then ( prop-obj# ) + get-mos-dnode ( ) + dnode " bootfs" zap-lookup if + ." no bootfs" abort + then ( ds-obj# ) + get-rootobj# ( fsroot-obj# ) + ; + + : fs>rootobj# ( fs$ -- root-obj# not-found? ) + + \ skip pool name + ascii / left-parse-string 2drop + + \ lookup fs in dsl + dsl-lookup if ( ) + true exit ( not-found ) + then ( ds-obj# ) + + get-rootobj# ( fsroot-obj# ) + false ( fsroot-obj# found ) + ; + + \ lookup file is current directory + : dirlook ( file$ dn -- not-found? ) + \ . and .. are magic + -rot 2dup " ." $= if ( dn file$ ) + 3drop false exit ( found ) + then + + 2dup " .." $= if + 2drop >znode zp_parent ( obj# ) + else ( dn file$ ) + \ search dir + current-obj# to search-obj# + zap-lookup if ( ) + true exit ( not-found ) + then ( obj# ) + then ( obj# ) + get-fs-dnode false ( found ) + ; + + /buf-len instance buffer: fpath-buf + : clr-fpath-buf ( -- ) fpath-buf /buf-len erase ; + + : fpath-buf$ ( -- path$ ) fpath-buf cscount ; + + \ copy symlink target to adr + : readlink ( dst dn -- ) + dup fsize tuck /zn-slink > if ( dst size dn ) + \ contents in 1st block + temp-space over dn-bsize ( dst size dn t-adr bsize ) + rot 0 lblk#>bp read-bp ( dst size ) + temp-space ( dst size src ) + else ( dst size dn ) + \ contents in dnode + >znode /znode + ( dst size src ) + then ( dst size src ) + -rot move ( ) + ; + + \ modify tail to account for symlink + : follow-symlink ( tail$ -- tail$' ) + clr-fpath-buf ( tail$ ) + fpath-buf dnode readlink + + \ append to current path + ?dup if ( tail$ ) + " /" fpath-buf$ $append ( tail$ ) + fpath-buf$ $append ( ) + else drop then ( ) + fpath-buf$ ( path$ ) + + \ get directory that starts changed path + over c@ ascii / = if ( path$ ) + str++ root-obj# ( path$' obj# ) + else ( path$ ) + search-obj# ( path$ obj# ) + then ( path$ obj# ) + get-fs-dnode ( path$ ) + ; + + \ open dnode at path + : lookup ( path$ -- not-found? ) + + \ get directory that starts path + over c@ ascii / = if + str++ root-obj# ( path$' obj# ) + else + current-obj# ( path$ obj# ) + then ( path$ obj# ) + get-fs-dnode ( path$ ) + + \ lookup each path component + begin ( path$ ) + ascii / left-parse-string ( path$ file$ ) + dup while + dnode dir? 0= if + 2drop true exit ( not-found ) + then ( path$ file$ ) + dnode dirlook if ( path$ ) + 2drop true exit ( not-found ) + then ( path$ ) + dnode symlink? if + follow-symlink ( path$' ) + then ( path$ ) + repeat ( path$ file$ ) + 2drop 2drop false ( found ) + ; + + \ + \ ZFS installation routines + \ + + \ ZFS file interface + struct + /x field >busy + /x field >offset + /dnode field >dnode + constant /file-record + + d# 10 constant #opens + #opens /file-record * constant /file-records + + /file-records instance buffer: file-records + + -1 instance value current-fd + + : fd>record ( fd -- rec ) /file-record * file-records + ; + : file-offset@ ( -- off ) current-fd fd>record >offset x@ ; + : file-offset! ( off -- ) current-fd fd>record >offset x! ; + : file-dnode ( -- dn ) current-fd fd>record >dnode ; + : file-size ( -- size ) file-dnode fsize ; + : file-bsize ( -- bsize ) file-dnode dn-bsize ; + + \ find free fd slot + : get-slot ( -- fd false | true ) + #opens 0 do + i fd>record >busy x@ 0= if + i false unloop exit + then + loop true + ; + + : free-slot ( fd -- ) + 0 swap fd>record >busy x! + ; + + \ init fd to offset 0 and copy dnode + : init-fd ( fd -- ) + fd>record ( rec ) + dup >busy 1 swap x! + dup >dnode dnode swap /dnode move + >offset 0 swap x! + ; + + \ make fd current + : set-fd ( fd -- error? ) + dup fd>record >busy x@ 0= if ( fd ) + drop true exit ( failed ) + then ( fd ) + to current-fd false ( succeeded ) + ; + + \ read next fs block + : file-bread ( adr -- ) + file-bsize ( adr len ) + file-offset@ over / ( adr len blk# ) + file-dnode swap lblk#>bp ( adr len bp ) + read-bp ( ) + ; + + \ advance file io stack by n + : fio+ ( # adr len n -- #+n adr+n len-n ) + dup file-offset@ + file-offset! + dup >r - -rot ( len' # adr r: n ) + r@ + -rot ( adr' len' # r: n ) + r> + -rot ( #' adr' len' ) + ; + + /max-bsize 5 * + /uber-block + + /dnode 5 * + + /disk-block + + constant alloc-size + + : allocate-buffers ( -- ) + alloc-size h# a0.0000 vmem-alloc dup 0= if + ." no memory" abort + then ( adr ) + dup to temp-space /max-bsize + ( adr ) + dup to dn-cache /max-bsize + ( adr ) + dup to blk-space /max-bsize + ( adr ) + dup to ind-cache /max-bsize + ( adr ) + dup to zap-space /max-bsize + ( adr ) + dup to uber-block /uber-block + ( adr ) + dup to mos-dn /dnode + ( adr ) + dup to obj-dir /dnode + ( adr ) + dup to root-dsl /dnode + ( adr ) + dup to fs-dn /dnode + ( adr ) + dup to dnode /dnode + ( adr ) + to gang-space ( ) + + \ zero instance buffers + file-records /file-records erase + bootprop-buf /buf-len erase + ; + + : release-buffers ( -- ) + temp-space alloc-size mem-free + ; + + external + + : open ( -- okay? ) + my-args dev-open dup 0= if + exit ( failed ) + then to dev-ih + + allocate-buffers + scan-vdev + get-ub + get-root-dsl + true + ; + + : open-fs ( fs$ -- okay? ) + fs>rootobj# if ( ) + false ( failed ) + else ( obj# ) + to root-obj# true ( succeeded ) + then ( okay? ) + ; + + : close ( -- ) + dev-ih dev-close + 0 to dev-ih + release-buffers + ; + + : open-file ( path$ -- fd true | false ) + + \ open default fs if no open-fs + root-obj# 0= if + prop>rootobj# to root-obj# + then + + get-slot if + 2drop false exit ( failed ) + then -rot ( fd path$ ) + + lookup if ( fd ) + drop false exit ( failed ) + then ( fd ) + + dup init-fd true ( fd succeeded ) + ; + + : close-file ( fd -- ) + free-slot ( ) + ; + + : size-file ( fd -- size ) + set-fd if 0 else file-size then + ; + + : seek-file ( off fd -- off true | false ) + set-fd if ( off ) + drop false exit ( failed ) + then ( off ) + + dup file-size > if ( off ) + drop false exit ( failed ) + then ( off ) + dup file-offset! true ( off succeeded ) + ; + + : read-file ( adr len fd -- #read ) + set-fd if ( adr len ) + 2drop 0 exit ( 0 ) + then ( adr len ) + + file-dnode regular? 0= if 2drop 0 exit then + + \ adjust len if reading past eof + dup file-offset@ + file-size > if + dup file-offset@ + file-size - - + then + dup 0= if nip exit then + + 0 -rot ( #read adr len ) + + \ initial partial block + file-offset@ file-bsize mod ?dup if ( #read adr len off ) + temp-space file-bread + 2dup file-bsize swap - min ( #read adr len off cpy-len ) + 2over drop -rot ( #read adr len adr off cpy-len ) + >r temp-space + swap ( #read adr len cpy-src adr r: cpy-len ) + r@ move r> fio+ ( #read' adr' len' ) + then ( #read adr len ) + + dup file-bsize / 0 ?do ( #read adr len ) + over file-bread + file-bsize fio+ ( #read' adr' len' ) + loop ( #read adr len ) + + \ final partial block + dup if ( #read adr len ) + temp-space file-bread + 2dup temp-space -rot move ( #read adr len ) + dup fio+ ( #read' adr' 0 ) + then 2drop ( #read ) + ; + + : cinfo-file ( fd -- bsize fsize comp? ) + set-fd if + 0 0 0 + else + file-bsize file-size ( bsize fsize ) + \ zfs does internal compression + 0 ( bsize fsize comp? ) + then + ; + + \ read ramdisk fcode at rd-offset + : get-rd ( adr len -- ) + rd-offset dev-ih read-disk + ; + + : bootprop + " /" bootprop$ $append + bootfs-obj# (xu.) bootprop$ $append + bootprop$ encode-string " zfs-bootfs" ( propval propname ) + true + ; + + +[ifdef] bigbootblk + : chdir ( dir$ -- ) + current-obj# -rot ( obj# dir$ ) + lookup if ( obj# ) + to current-obj# ( ) + ." no such dir" cr exit + then ( obj# ) + dnode dir? 0= if ( obj# ) + to current-obj# ( ) + ." not a dir" cr exit + then drop ( ) + ; + + : dir ( -- ) + current-obj# get-fs-dnode + dnode zap-print + ; +[then] + +finish-device +pop-package diff --git a/usr/src/psm/stand/bootblks/zfs/i386/Makefile b/usr/src/psm/stand/bootblks/zfs/i386/Makefile new file mode 100644 index 0000000000..a13453a764 --- /dev/null +++ b/usr/src/psm/stand/bootblks/zfs/i386/Makefile @@ -0,0 +1,43 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# psm/stand/bootblks/zfs/i386/Makefile +# +BASEDIR = ../.. + +include $(BASEDIR)/zfs/Makefile.zfs + +all := TARGET= all +install := TARGET= install +clean := TARGET= clean +clobber := TARGET= clobber +lint := TARGET= lint + +.KEEP_STATE: + +all install lint clean clobber: FRC + +FRC: diff --git a/usr/src/psm/stand/bootblks/zfs/sparc/Makefile b/usr/src/psm/stand/bootblks/zfs/sparc/Makefile new file mode 100644 index 0000000000..2a4c1e9b1f --- /dev/null +++ b/usr/src/psm/stand/bootblks/zfs/sparc/Makefile @@ -0,0 +1,48 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# psm/stand/bootblks/zfs/sparc/Makefile +# +BASEDIR = ../.. + +include $(BASEDIR)/zfs/Makefile.zfs + +SUBDIRS = sun4u sun4v + +all := TARGET= all +install := TARGET= install +clean := TARGET= clean +clobber := TARGET= clobber +lint := TARGET= lint + +.KEEP_STATE: + +all install lint clean clobber: $(SUBDIRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: diff --git a/usr/src/psm/stand/bootblks/zfs/sparc/sun4u/Makefile b/usr/src/psm/stand/bootblks/zfs/sparc/sun4u/Makefile new file mode 100644 index 0000000000..50e47d1f52 --- /dev/null +++ b/usr/src/psm/stand/bootblks/zfs/sparc/sun4u/Makefile @@ -0,0 +1,43 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# psm/stand/bootblks/zfs/sparc/sun4u/Makefile +# + +# +# Platform specific Makefile for the boot block. +# +BASEDIR = ../../.. +PLATFORM = sun4u + +include $(BASEDIR)/zfs/Makefile.zfs +include $(BASEDIR)/Makefile.1275 + +.KEEP_STATE: + +all: $(PROG) + +include $(BASEDIR)/Makefile.targ diff --git a/usr/src/psm/stand/bootblks/zfs/sparc/sun4v/Makefile b/usr/src/psm/stand/bootblks/zfs/sparc/sun4v/Makefile new file mode 100644 index 0000000000..7fff7f49de --- /dev/null +++ b/usr/src/psm/stand/bootblks/zfs/sparc/sun4v/Makefile @@ -0,0 +1,43 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# psm/stand/bootblks/zfs/sparc/sun4v/Makefile +# + +# +# Platform specific Makefile for the boot block. +# +BASEDIR = ../../.. +PLATFORM = sun4v + +include $(BASEDIR)/zfs/Makefile.zfs +include $(BASEDIR)/Makefile.1275 + +.KEEP_STATE: + +all: $(PROG) + +include $(BASEDIR)/Makefile.targ diff --git a/usr/src/psm/stand/cpr/common/support.c b/usr/src/psm/stand/cpr/common/support.c index 268fcd4445..dfafa98865 100644 --- a/usr/src/psm/stand/cpr/common/support.c +++ b/usr/src/psm/stand/cpr/common/support.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -31,11 +30,8 @@ #include <sys/pte.h> #include <sys/promimpl.h> #include <sys/prom_plat.h> +#include "cprboot.h" -extern int cpr_ufs_close(int); -extern int cpr_ufs_open(char *, char *); -extern int cpr_ufs_read(int, char *, int); -extern int cpr_read(int, char *, size_t); extern void prom_unmap(caddr_t, uint_t); extern int cpr_debug; @@ -51,7 +47,7 @@ cpr_read_cprinfo(int fd, char *file_path, char *fs_path) { struct cprconfig cf; - if (cpr_ufs_read(fd, (char *)&cf, sizeof (cf)) != sizeof (cf) || + if (cpr_fs_read(fd, (char *)&cf, sizeof (cf)) != sizeof (cf) || cf.cf_magic != CPR_CONFIG_MAGIC) return (-1); @@ -71,12 +67,11 @@ int cpr_locate_statefile(char *file_path, char *fs_path) { int fd; - char *boot_path = prom_bootpath(); int rc; - if ((fd = cpr_ufs_open(CPR_CONFIG, boot_path)) != -1) { + if ((fd = cpr_fs_open(CPR_CONFIG)) != -1) { rc = cpr_read_cprinfo(fd, file_path, fs_path); - (void) cpr_ufs_close(fd); + (void) cpr_fs_close(fd); } else rc = -1; @@ -95,7 +90,7 @@ cpr_locate_statefile(char *file_path, char *fs_path) int cpr_reset_properties(void) { - char *str, *boot_path, *default_path; + char *str, *default_path; int fd, len, rc, prop_errors; cprop_t *prop, *tail; cdef_t cdef; @@ -103,16 +98,15 @@ cpr_reset_properties(void) str = "cpr_reset_properties"; default_path = CPR_DEFAULT; - boot_path = prom_bootpath(); - if ((fd = cpr_ufs_open(default_path, boot_path)) == -1) { - prom_printf("%s: unable to open %s on %s\n", - str, default_path, boot_path); + if ((fd = cpr_fs_open(default_path)) == -1) { + prom_printf("%s: unable to open %s\n", + str, default_path); return (-1); } rc = 0; - len = cpr_ufs_read(fd, (char *)&cdef, sizeof (cdef)); + len = cpr_fs_read(fd, (char *)&cdef, sizeof (cdef)); if (len != sizeof (cdef)) { prom_printf("%s: error reading %s\n", str, default_path); rc = -1; @@ -121,7 +115,7 @@ cpr_reset_properties(void) rc = -1; } - (void) cpr_ufs_close(fd); + (void) cpr_fs_close(fd); if (rc) return (rc); diff --git a/usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.c b/usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.c index 5881aa2fca..60ff9d8b96 100644 --- a/usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.c +++ b/usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.c @@ -84,7 +84,7 @@ static char cb_argbuf[CB_MAXPROP]; static char *cb_args[CB_MAXARGS]; static int reusable; -static char *specialstate; +char *specialstate; static int @@ -399,7 +399,10 @@ cb_read_statefile(void) cnt = 0; dtlb_index = cb_dents - 1; - (void) prom_seek(sfile.fd, specialstate ? CPR_SPEC_OFFSET : 0); + if (specialstate) + (void) prom_seek(sfile.fd, CPR_SPEC_OFFSET); + else + (void) cpr_fs_seek(sfile.fd, 0); CPR_DEBUG(CPR_DEBUG1, "%s: reading statefile... ", prog); for (resid = cdump.cdd_filesize; resid; resid -= len) { /* @@ -422,7 +425,7 @@ cb_read_statefile(void) cnt++; len = min(PROM_MAX_READ, resid); - nread = prom_read(sfile.fd, dst_virt, len, 0, 0); + nread = cpr_read(sfile.fd, dst_virt, len); if (nread != (ssize_t)len) { prom_printf("\n%s: prom read error, " "expect %ld, got %ld\n", str, len, nread); @@ -469,9 +472,11 @@ cb_read_statefile(void) */ static int (*first_worklist[])(void) = { cb_intro, + cb_mountroot, cb_startup, cb_get_props, cb_usb_setup, + cb_unmountroot, cb_open_sf, cb_read_statefile, cb_close_sf, diff --git a/usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.h b/usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.h index 2102820146..4ceb64ba83 100644 --- a/usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.h +++ b/usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.h @@ -225,11 +225,18 @@ extern pfn_t cpr_vatopfn(caddr_t); extern int prom_remap(size_t, caddr_t, physaddr_t); extern void install_remap(void); extern int cb_alloc(size_t, uint_t, caddr_t *, physaddr_t *); +extern int cb_mountroot(void); +extern int cb_unmountroot(void); extern int cb_get_props(void); extern void cb_mapin(caddr_t, pfn_t, uint_t, uint_t, uint_t); extern int cb_usb_setup(void); extern void cb_enter_mon(void); extern void cb_exit_to_mon(void); +extern int cpr_fs_close(int); +extern int cpr_fs_open(char *); +extern int cpr_fs_read(int, char *, int); +extern int cpr_fs_seek(int, offset_t); +extern int cpr_read(int, char *, size_t); /* * cb_srt0.s diff --git a/usr/src/psm/stand/cpr/sparcv9/sun4u/util.c b/usr/src/psm/stand/cpr/sparcv9/sun4u/util.c index d59258c8db..e739d31d46 100644 --- a/usr/src/psm/stand/cpr/sparcv9/sun4u/util.c +++ b/usr/src/psm/stand/cpr/sparcv9/sun4u/util.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -31,11 +30,15 @@ #include "cprboot.h" +static ihandle_t cb_rih; +static pnode_t chosen; + +static int statefile_special; + static int reset_input = 0; static char kbd_input[] = "keyboard input"; static char null_input[] = "\" /nulldev\" input"; - /* * Ask prom to open a disk file given either the OBP device path, or the * device path representing the target drive/partition and the fs-relative @@ -44,113 +47,149 @@ static char null_input[] = "\" /nulldev\" input"; */ /* ARGSUSED */ int -cpr_statefile_open(char *path, char *fs) +cpr_statefile_open(char *path, char *fs_dev) { - char full_path[OBP_MAXPATHLEN]; - char *fp; + int plen, dlen; int handle; - int c; + char fs_pkg[OBP_MAXPATHLEN]; + char fs_name[OBP_MAXDRVNAME]; /* * instead of using specialstate, we use fs as the flag */ - if (*fs == '\0') { /* device open */ + if (*fs_dev == '\0') { /* device open */ + statefile_special = 1; handle = prom_open(path); /* IEEE1275 prom_open returns 0 on failure; we return -1 */ return (handle ? handle : -1); } /* - * IEEE 1275 prom needs "device-path,|file-path" where - * file-path can have embedded |'s. + * No cif for $open-package, so we have to use interpret */ - fp = full_path; - (void) prom_strcpy(fp, fs); - fp += prom_strlen(fp); - *fp++ = ','; - *fp++ = '|'; - - /* Skip a leading slash in file path -- we provided for it above. */ - if (*path == '/') - path++; - - /* Copy file path and convert separators. */ - while ((c = *path++) != '\0') - if (c == '/') - *fp++ = '|'; - else - *fp++ = c; - *fp = '\0'; - - handle = prom_open(full_path); - if (verbose) { - if (fp = prom_strrchr(full_path, '/')) - fp++; - else - fp = full_path; - prom_printf("cso: prom_open(\"%s\") = 0x%x\n", fp, handle); + if (prom_getprop(chosen, "fs-package", fs_pkg) == -1) { + prom_printf("Missing fs-package name\n"); + return (-1); + } + plen = prom_strlen(fs_pkg); + dlen = prom_strlen(fs_dev); + prom_interpret("$open-package swap l!", plen, (uintptr_t)fs_pkg, + dlen, (uintptr_t)fs_dev, (uintptr_t)&cb_rih); + if (cb_rih == OBP_BADNODE || cb_rih == 0) { + prom_printf("Can't open %s\n", fs_pkg); + return (-1); } /* - * IEEE1275 prom_open returns 0 on failure; we return -1 + * Prepend '/' if it's not there already */ - return (handle ? handle : -1); + if (*path != '/') { + (void) prom_sprintf(fs_name, "/%s", path); + return (cpr_fs_open(fs_name)); + } else + return (cpr_fs_open(path)); } - /* - * Ask prom to open a disk file given the device path representing - * the target drive/partition and the fs-relative path of the file. - * Handle file pathnames with or without leading '/'. if fs points - * to a null char, it indicates that we are opening a device. + * Mount root fs so we can read statefile, etc + * + * sets global + * cb_rih */ -/* ARGSUSED */ int -cpr_ufs_open(char *path, char *fs) +cb_mountroot() { - CB_VENTRY(cpr_ufs_open); - /* - * screen invalid state, then just use the other code rather than - * duplicating it - */ - if (*fs == '\0') { /* device open */ - prom_printf("cpr_ufs_open: NULL fs, path %s\n", path); + chosen = prom_chosennode(); + if (chosen == OBP_BADNODE) { + prom_printf("Missing chosen node\n"); return (ERR); } - return (cpr_statefile_open(path, fs)); + if (prom_getprop(chosen, "bootfs", (caddr_t)&cb_rih) == -1) { + prom_printf("Missing bootfs ihandle\n"); + return (ERR); + } + return (0); +} + +/* + * Unmount root + */ +int +cb_unmountroot() +{ + (void) prom_close(cb_rih); + cb_rih = OBP_BADNODE; + return (0); +} + +/* + * Ask prom to open a disk file. + */ +/* ARGSUSED */ +int +cpr_fs_open(char *path) +{ + + CB_VENTRY(cpr_fs_open); + + if (cb_rih == OBP_BADNODE) + return (-1); + return (prom_fopen(cb_rih, path)); } /* - * On sun4u there's no difference here, since prom groks ufs directly + * Direct read if using block special, + * otherwise use fs read */ int cpr_read(int fd, caddr_t buf, size_t len) { - return (prom_read(fd, buf, len, 0, 0)); + if (!statefile_special) + return (cpr_fs_read(fd, buf, len)); + else + return (prom_read(fd, buf, len, 0, 0)); } int -cpr_ufs_read(int fd, caddr_t buf, int len) +cpr_fs_read(int fd, caddr_t buf, int len) { - return (prom_read(fd, buf, len, 0, 0)); + if (cb_rih == OBP_BADNODE) + return (-1); + return (prom_fread(cb_rih, fd, buf, len)); } int -cpr_ufs_close(int fd) +cpr_fs_close(int fd) +{ + CB_VPRINTF(("cpr_fs_close 0x%x\n", fd)); + + if (cb_rih == OBP_BADNODE) + return (-1); + prom_fclose(cb_rih, fd); + return (0); +} + +int +cpr_fs_seek(int fd, offset_t off) { - CB_VPRINTF(("cpr_ufs_close 0x%x\n", fd)); - return (prom_close(fd)); + if (cb_rih == OBP_BADNODE) + return (-1); + return (prom_fseek(cb_rih, fd, off)); } int cpr_statefile_close(int fd) { - return (prom_close(fd)); + if (statefile_special) { + statefile_special = 0; + return (prom_close(fd)); + } else + return (cpr_fs_close(fd)); } diff --git a/usr/src/psm/stand/lib/boot/sparc/Makefile.com b/usr/src/psm/stand/lib/boot/sparc/Makefile.com index 495ca3d0ed..d7b224b644 100644 --- a/usr/src/psm/stand/lib/boot/sparc/Makefile.com +++ b/usr/src/psm/stand/lib/boot/sparc/Makefile.com @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -64,7 +63,7 @@ CPPINCS += -I$(ROOT)/usr/include/$(ARCHVERS) CPPINCS += -I$(ROOT)/usr/platform/$(PLATFORM)/include CPPINCS += -I$(PSMSYSHDRDIR) CPPFLAGS = $(CPPINCS) $(CCYFLAG)$(PSMSYSHDRDIR) -CPPFLAGS += -D_KERNEL -D_BOOT +CPPFLAGS += -D_KERNEL -D_BOOT -D_MACHDEP ASFLAGS = -P -D__STDC__ -D_ASM $(CPPINCS) CFLAGS += $(CCVERBOSE) diff --git a/usr/src/psm/stand/lib/boot/sparcv9/Makefile.com b/usr/src/psm/stand/lib/boot/sparcv9/Makefile.com index f160c1405e..7f8dcdd49f 100644 --- a/usr/src/psm/stand/lib/boot/sparcv9/Makefile.com +++ b/usr/src/psm/stand/lib/boot/sparcv9/Makefile.com @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -22,7 +21,7 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # psm/stand/lib/boot/sparcv9/Makefile.com @@ -64,7 +63,7 @@ CPPINCS += -I$(ROOT)/usr/include/$(ARCHVERS) CPPINCS += -I$(ROOT)/usr/platform/$(PLATFORM)/include CPPINCS += -I$(PSMSYSHDRDIR) CPPFLAGS = $(CPPINCS) $(CCYFLAG)$(PSMSYSHDRDIR) -CPPFLAGS += -D_KERNEL +CPPFLAGS += -D_KERNEL -D_MACHDEP ASFLAGS = -P -D__STDC__ -D_ASM $(CPPINCS) CFLAGS += $(CCVERBOSE) diff --git a/usr/src/psm/stand/lib/names/sparc/common/uname-i.c b/usr/src/psm/stand/lib/names/sparc/common/uname-i.c index 6e7e9401f0..c91fdedb4b 100644 --- a/usr/src/psm/stand/lib/names/sparc/common/uname-i.c +++ b/usr/src/psm/stand/lib/names/sparc/common/uname-i.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -183,24 +182,13 @@ open_platform_file( char *filename, int (*openfn)(char *, void *), void *arg, - char *fullpath, - char *given_iarch) + char *fullpath) { char *ia; int fd; enum ia_state_mach state = STATE_NAME; /* - * First try the impl_arch_name hint. - * - * This is only here to support the -I flag to boot. - */ - if (given_iarch != NULL) { - make_platform_path(fullpath, given_iarch, filename); - return ((*openfn)(fullpath, arg)); - } - - /* * Hunt the filesystem for one that works .. */ while ((ia = get_impl_arch_name(&state, 1)) != NULL) { diff --git a/usr/src/psm/stand/lib/promif/sparcv9/ieee1275/sun4u/Makefile b/usr/src/psm/stand/lib/promif/sparcv9/ieee1275/sun4u/Makefile index 0d47a6ef89..2a4cb99393 100644 --- a/usr/src/psm/stand/lib/promif/sparcv9/ieee1275/sun4u/Makefile +++ b/usr/src/psm/stand/lib/promif/sparcv9/ieee1275/sun4u/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # psm/stand/boot/sparcv9/ieee1275/sun4u/Makefile @@ -54,6 +53,7 @@ PLAT_PFILES = \ PLAT_PSUN4FILES = \ prom_alloc.c \ prom_cpuctl.c \ + prom_fio.c \ prom_getunum.c \ prom_idprom.c \ prom_init.c \ @@ -61,7 +61,8 @@ PLAT_PSUN4FILES = \ prom_map.c \ prom_mem.c \ prom_retain.c \ - prom_sparc.c + prom_sparc.c \ + prom_vername.c KARCH = sun4u MMU = sfmmu diff --git a/usr/src/psm/stand/lib/promif/sparcv9/ieee1275/sun4v/Makefile b/usr/src/psm/stand/lib/promif/sparcv9/ieee1275/sun4v/Makefile index c02f97839c..e10d2c36c6 100644 --- a/usr/src/psm/stand/lib/promif/sparcv9/ieee1275/sun4v/Makefile +++ b/usr/src/psm/stand/lib/promif/sparcv9/ieee1275/sun4v/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # psm/stand/boot/sparcv9/ieee1275/sun4v/Makefile @@ -59,7 +58,8 @@ PLAT_PSUN4FILES = \ prom_map.c \ prom_mem.c \ prom_retain.c \ - prom_sparc.c + prom_sparc.c \ + prom_vername.c KARCH = sun4v MMU = sfmmu diff --git a/usr/src/psm/stand/sys/platnames.h b/usr/src/psm/stand/sys/platnames.h index e63b357104..cf3152f2cb 100644 --- a/usr/src/psm/stand/sys/platnames.h +++ b/usr/src/psm/stand/sys/platnames.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,8 +19,8 @@ * CDDL HEADER END */ /* - * Copyright (c) 1994-1999 by Sun Microsystems, Inc. - * All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. */ #ifndef _SYS_PLATNAMES_H @@ -39,7 +38,7 @@ extern "C" { extern char *get_mfg_name(void); extern int find_platform_dir(int (*)(char *), char *, int); extern int open_platform_file(char *, - int (*)(char *, void *), void *, char *, char *); + int (*)(char *, void *), void *, char *); extern void mod_path_uname_m(char *, char *); #ifdef __cplusplus diff --git a/usr/src/stand/lib/fs/hsfs/hsfsops.c b/usr/src/stand/lib/fs/hsfs/hsfsops.c index c8a98b4780..0c515740f5 100644 --- a/usr/src/stand/lib/fs/hsfs/hsfsops.c +++ b/usr/src/stand/lib/fs/hsfs/hsfsops.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 1994-2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -146,7 +145,7 @@ opendir(fileid_t *filep, ino_t inode) filep->fi_blocknum = hdbtodb(inode); if (inode != root_ino) - return (0); + return (0); if ((int)(parse_dir(filep, 0, &hsdep)) > 0) { hs_seti(filep, &hsdep, inode); @@ -168,7 +167,7 @@ find(fileid_t *filep, char *path) } if ((boothowto & RB_DEBUG) && (boothowto & RB_VERBOSE)) - printf("find(): path=<%s>\n", path); + printf("find(): path=<%s>\n", path); /* Read the ROOT directory */ if (opendir(filep, inode = root_ino)) { @@ -464,7 +463,7 @@ boot_hsfs_mountroot(char *str) char *bufp; if ((boothowto & RB_DEBUG) && (boothowto & RB_VERBOSE)) - printf("mountroot()\n"); + printf("mountroot()\n"); /* * If already mounted, just return success. @@ -595,7 +594,7 @@ boot_hsfs_open(char *filename, int flags) inode = find(filep, filename); if (inode == (ino_t)0) { if ((boothowto & RB_DEBUG) && (boothowto & RB_VERBOSE)) - printf("open(%s) ENOENT\n", filename); + printf("open(%s) ENOENT\n", filename); (void) boot_hsfs_close(filep->fi_filedes); return (-1); } @@ -604,7 +603,7 @@ boot_hsfs_open(char *filename, int flags) filep->fi_offset = filep->fi_count = 0; if ((boothowto & RB_DEBUG) && (boothowto & RB_VERBOSE)) - printf("open(%s) fd=%d\n", filename, filep->fi_filedes); + printf("open(%s) fd=%d\n", filename, filep->fi_filedes); return (filep->fi_filedes); } @@ -679,7 +678,7 @@ boot_hsfs_close(int fd) fileid_t *filep; if ((boothowto & RB_DEBUG) && (boothowto & RB_VERBOSE)) - printf("close(%d)\n", fd); + printf("close(%d)\n", fd); if (filep = find_fp(fd)) { /* Clear the ranks */ @@ -702,6 +701,7 @@ boot_hsfs_close(int fd) } } +/* closeall is now idempotent */ /*ARGSUSED*/ static void boot_hsfs_closeall(int flag) @@ -709,11 +709,18 @@ boot_hsfs_closeall(int flag) fileid_t *filep = head; extern int verbosemode; + if (devp == NULL) { + if (head) + prom_panic("boot_hsfs_closeall: head != NULL.\n"); + return; + } + while ((filep = filep->fi_forw) != head) if (filep->fi_taken) if (boot_hsfs_close(filep->fi_filedes)) prom_panic("Filesystem may be inconsistent.\n"); + release_cache(devp->di_dcookie); (void) prom_close(devp->di_dcookie); devp->di_taken = 0; @@ -722,6 +729,8 @@ boot_hsfs_closeall(int flag) bkmem_free((char *)devp, sizeof (devid_t)); bkmem_free((char *)head, sizeof (fileid_t)); root_ino = 0; + devp = NULL; + head = NULL; } static uint_t @@ -796,52 +805,53 @@ parse_dir(fileid_t *filep, int offset, struct hs_direct *hsdep) ce_len = IDE_SUA_LEN(bufp); ce_lbn = 0; if ((int)(ce_len) > 0) { - ce_lbn = parse_susp((char *)IDE_sys_use_area(bufp), &ce_len, hsdep); - while (ce_lbn) { - daddr_t save_blocknum = filep->fi_blocknum; - daddr_t save_offset = filep->fi_offset; - caddr_t save_memp = filep->fi_memp; - uint_t save_count = filep->fi_count; + ce_lbn = parse_susp((char *)IDE_sys_use_area(bufp), + &ce_len, hsdep); + while (ce_lbn) { + daddr_t save_blocknum = filep->fi_blocknum; + daddr_t save_offset = filep->fi_offset; + caddr_t save_memp = filep->fi_memp; + uint_t save_count = filep->fi_count; #ifdef noisy - print_io_req(filep, "parse_dir(): [I]"); + print_io_req(filep, "parse_dir(): [I]"); #endif /* noisy */ - filep->fi_blocknum = hdbtodb(ce_lbn); - filep->fi_offset = 0; - filep->fi_count = ISO_SECTOR_SIZE; + filep->fi_blocknum = hdbtodb(ce_lbn); + filep->fi_offset = 0; + filep->fi_count = ISO_SECTOR_SIZE; #ifdef noisy - print_io_req(filep, "parse_dir(): [0]"); + print_io_req(filep, "parse_dir(): [0]"); #endif /* noisy */ - if ((filep->fi_memp = get_bcache(filep)) == 0) - ret_code = set_bcache(filep); + if ((filep->fi_memp = get_bcache(filep)) == 0) + ret_code = set_bcache(filep); #ifdef noisy - print_io_req(filep, "parse_dir(): [1]"); + print_io_req(filep, "parse_dir(): [1]"); #endif /* noisy */ - if (ret_code) { - filep->fi_blocknum = save_blocknum; - filep->fi_offset = save_offset; - filep->fi_memp = save_memp; - filep->fi_count = save_count; - printf("parse_dir(): set_bcache() failed (%d)\n", - ret_code); - break; - } - ce_lbn = parse_susp(filep->fi_memp, &ce_len, hsdep); - - filep->fi_blocknum = save_blocknum; - filep->fi_offset = save_offset; - filep->fi_memp = save_memp; - filep->fi_count = save_count; + if (ret_code) { + filep->fi_blocknum = save_blocknum; + filep->fi_offset = save_offset; + filep->fi_memp = save_memp; + filep->fi_count = save_count; + printf("parse_dir(): " + "set_bcache() failed (%d)\n", ret_code); + break; + } + ce_lbn = parse_susp(filep->fi_memp, &ce_len, hsdep); + + filep->fi_blocknum = save_blocknum; + filep->fi_offset = save_offset; + filep->fi_memp = save_memp; + filep->fi_count = save_count; #ifdef noisy - print_io_req(filep, "parse_dir(): [2]"); + print_io_req(filep, "parse_dir(): [2]"); #endif /* noisy */ - } + } } return (udp->d_reclen); @@ -859,75 +869,84 @@ parse_susp(char *bufp, uint_t *ce_len, struct hs_direct *hsdep) uint_t i; while (cur_off < blk_len) { - susp = (uchar_t *)(bufp + cur_off); - if (susp[0] == '\0' || susp[1] == '\0') - break; - susp_len = SUF_LEN(susp); - if (susp_len == 0) - break; - for (i = 0; i < hsfs_num_sig; i++) { - if (strncmp(hsfs_sig_tab[i], (char *)susp, SUF_SIG_LEN) == 0) { + susp = (uchar_t *)(bufp + cur_off); + if (susp[0] == '\0' || susp[1] == '\0') + break; + susp_len = SUF_LEN(susp); + if (susp_len == 0) + break; + for (i = 0; i < hsfs_num_sig; i++) { + if (strncmp(hsfs_sig_tab[i], + (char *)susp, SUF_SIG_LEN) == 0) { #ifdef noisy - if ((boothowto & RB_DEBUG) && (boothowto & RB_VERBOSE)) - printf(" SUSP_%c%c %d\n", susp[0], susp[1], susp_len); + if ((boothowto & RB_DEBUG) && + (boothowto & RB_VERBOSE)) + printf(" SUSP_%c%c %d\n", + susp[0], susp[1], susp_len); #endif /* noisy */ - switch (i) { - case SUSP_SP_IX: - if (CHECK_BYTES_OK(susp)) { - sua_offset = SP_SUA_OFFSET(susp); + switch (i) { + case SUSP_SP_IX: + if (CHECK_BYTES_OK(susp)) { + sua_offset = + SP_SUA_OFFSET(susp); #ifdef lint - /* Like the man said, this may not be needed */ - i = (int)sua_offset; + /* this may not be needed */ + i = (int)sua_offset; #endif /* lint */ - } - break; + } + break; - case SUSP_CE_IX: - ce_lbn = CE_BLK_LOC(susp); - *ce_len = CE_CONT_LEN(susp); + case SUSP_CE_IX: + ce_lbn = CE_BLK_LOC(susp); + *ce_len = CE_CONT_LEN(susp); #ifdef noisy - if ((boothowto & RB_DEBUG) && - (boothowto & RB_VERBOSE)) - printf("parse_susp(): " - "CE: ce_lbn = %d ce_len=%d\n", - ce_lbn, *ce_len); + if ((boothowto & RB_DEBUG) && + (boothowto & RB_VERBOSE)) + printf("parse_susp(): " + "CE: ce_lbn = %d " + "ce_len=%d\n", + ce_lbn, *ce_len); #endif /* noisy */ - break; + break; - case SUSP_ST_IX: - printf("parse_susp(): ST: returning %d\n", ce_lbn); - return (ce_lbn); + case SUSP_ST_IX: + printf("parse_susp(): ST: returning " + "%d\n", ce_lbn); + return (ce_lbn); - case RRIP_SL_IX: + case RRIP_SL_IX: #ifdef noisy - if ((boothowto & RB_DEBUG) && - (boothowto & RB_VERBOSE)) - printf("parse_susp(): ******* SL *******\n"); + if ((boothowto & RB_DEBUG) && + (boothowto & RB_VERBOSE)) + printf("parse_susp(): " + "******* SL *******\n"); #endif /* noisy */ - break; - - case RRIP_RR_IX: - break; - - case RRIP_NM_IX: - if (!RRIP_NAME_FLAGS(susp)) { - udp->d_namlen = RRIP_NAME_LEN(susp); - bcopy((char *)RRIP_name(susp), - (char *)udp->d_name, - udp->d_namlen); - udp->d_name[udp->d_namlen] = '\0'; - } - break; - } - cur_off += susp_len; - break; + break; + + case RRIP_RR_IX: + break; + + case RRIP_NM_IX: + if (!RRIP_NAME_FLAGS(susp)) { + udp->d_namlen = + RRIP_NAME_LEN(susp); + bcopy((char *)RRIP_name(susp), + (char *)udp->d_name, + udp->d_namlen); + udp->d_name + [udp->d_namlen] = '\0'; + } + break; + } + cur_off += susp_len; + break; + } + } + if (i > hsfs_num_sig) { + printf("parse_susp(): Bad SUSP\n"); + cur_off = blk_len; + break; } - } - if (i > hsfs_num_sig) { - printf("parse_susp(): Bad SUSP\n"); - cur_off = blk_len; - break; - } } return (ce_lbn); } @@ -962,11 +981,11 @@ static void print_io_req(fileid_t *filep, char *str) { printf("%s o=%d b=%d c=%d m=%x\n", - str, - filep->fi_offset, - filep->fi_blocknum, - filep->fi_count, - (uint_t)filep->fi_memp); + str, + filep->fi_offset, + filep->fi_blocknum, + filep->fi_count, + (uint_t)filep->fi_memp); } #endif /* noisy */ diff --git a/usr/src/stand/lib/fs/nfs/nfsops.c b/usr/src/stand/lib/fs/nfs/nfsops.c index 2adf856fc0..3da57391ab 100644 --- a/usr/src/stand/lib/fs/nfs/nfsops.c +++ b/usr/src/stand/lib/fs/nfs/nfsops.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Simple nfs ops - open, close, read, and lseek. @@ -104,6 +103,11 @@ boot_nfs_closeall(int flag) printf("boot_nfs_closeall(%x)\n", flag); #endif + if (nfs_files->file.version == 0 && + nfs_files->desc == 0 && + nfs_files->next == NULL) + return; + /* delete any dynamically allocated entries */ while ((filep = nfs_files->next) != NULL) { nfs_files->next = filep->next; @@ -211,7 +215,7 @@ boot_nfs_open(char *path, int flags) #ifdef NFS_OPS_DEBUG if ((boothowto & DBFLAGS) == DBFLAGS) printf("boot_nfs_open(): '%s' successful, fd = 0x%x\n", - path, filep->desc); + path, filep->desc); #endif return (filep->desc); } @@ -283,7 +287,7 @@ boot_nfs_read(int fd, char *buf, size_t size) break; default: printf("boot_nfs_read: NFS Version %d not supported\n", - filep->file.version); + filep->file.version); count = -1; break; } @@ -382,8 +386,8 @@ boot_nfs_fstat(int fd, struct bootstat *stp) return (-1); bzero((char *)&va, sizeof (va)); - va.va_mask = AT_TYPE | AT_SIZE | AT_MODE | AT_NODEID | \ - AT_ATIME | AT_CTIME | AT_MTIME; + va.va_mask = AT_TYPE | AT_SIZE | AT_MODE | AT_NODEID | + AT_ATIME | AT_CTIME | AT_MTIME; switch (filep->file.version) { case NFS_VERSION: @@ -397,7 +401,7 @@ boot_nfs_fstat(int fd, struct bootstat *stp) break; default: printf("boot_nfs_fstat: NFS Version %d not supported\n", - filep->file.version); + filep->file.version); status = -1; break; } @@ -455,7 +459,7 @@ boot_nfs_getdents(int fd, struct dirent *dep, unsigned size) break; default: printf("boot_nfs_getdents: NFS Version %d not supported\n", - filep->file.version); + filep->file.version); status = -1; } diff --git a/usr/src/stand/lib/fs/ufs/ufsops.c b/usr/src/stand/lib/fs/ufs/ufsops.c index 8e3cab1f03..8a53f92627 100644 --- a/usr/src/stand/lib/fs/ufs/ufsops.c +++ b/usr/src/stand/lib/fs/ufs/ufsops.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -125,7 +125,7 @@ openi(fileid_t *filep, ino_t inode) /* Nope, not there so lets read it off the disk. */ filep->fi_offset = 0; filep->fi_blocknum = fsbtodb(&devp->un_fs.di_fs, - itod(&devp->un_fs.di_fs, inode)); + itod(&devp->un_fs.di_fs, inode)); /* never more than 1 disk block */ filep->fi_count = devp->un_fs.di_fs.fs_bsize; @@ -147,7 +147,7 @@ openi(fileid_t *filep, ino_t inode) dp[itoo(&devp->un_fs.di_fs, inode)].di_un.di_icom; filep->fi_inode->i_number = inode; if (set_ricache(devp->di_dcookie, inode, (void *)filep->fi_inode, - sizeof (struct inode))) + sizeof (struct inode))) filep->fi_inode->i_flag = FI_NOCACHE; return (0); } @@ -210,8 +210,8 @@ find(fileid_t *filep, char *path) filep->fi_inode->i_db[0]); filep->fi_count = DEV_BSIZE; /* check the block cache */ - if ((filep->fi_memp = get_bcache(filep)) - == NULL) { + if ((filep->fi_memp = + get_bcache(filep)) == NULL) { if (set_bcache(filep)) return ((ino_t)0); lufs_merge_deltas(filep); @@ -385,7 +385,7 @@ dlook(fileid_t *filep, char *path) continue; if (set_rdcache(devp->di_dcookie, dp->d_name, ip->i_number, - dp->d_ino)) { + dp->d_ino)) { ip->i_flag &= ~FI_CACHED; ip->i_flag |= FI_PARTIAL_CACHE; #ifdef DEBUG @@ -825,17 +825,25 @@ boot_ufs_close(int fd) } } +/* closeall is now idempotent */ /*ARGSUSED*/ static void boot_ufs_closeall(int flag) { fileid_t *filep = head; + if (ufs_devp == NULL) { + if (head) + prom_panic("boot_ufs_closeall: head != NULL.\n"); + return; + } + while ((filep = filep->fi_forw) != head) if (filep->fi_taken) if (boot_ufs_close(filep->fi_filedes)) prom_panic("Filesystem may be inconsistent.\n"); + release_cache(ufs_devp->di_dcookie); (void) prom_close(ufs_devp->di_dcookie); ufs_devp->di_taken = 0; @@ -896,7 +904,7 @@ boot_ufs_getdents(int fd, struct dirent *dep, unsigned size) } } - if ((fp->fi_inode->i_smode & IFMT) == IFDIR) { + if ((fp->fi_inode->i_smode & IFMT) == IFDIR) { /* * If target file is a directory, go ahead * and read it. This consists of making diff --git a/usr/src/stand/lib/sa/stddef.h b/usr/src/stand/lib/sa/stddef.h index c9709aa373..82a497f4d1 100644 --- a/usr/src/stand/lib/sa/stddef.h +++ b/usr/src/stand/lib/sa/stddef.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -42,7 +41,9 @@ extern "C" { #define NULL 0 #endif +#ifndef offsetof #define offsetof(s, m) (size_t)(&(((s *)0)->m)) +#endif #ifdef __cplusplus } diff --git a/usr/src/tools/findunref/exception_list b/usr/src/tools/findunref/exception_list index e0ab7dd900..070af00ac3 100644 --- a/usr/src/tools/findunref/exception_list +++ b/usr/src/tools/findunref/exception_list @@ -262,13 +262,6 @@ ./src/lib/libresolv2/include/err.h # -# Ignore ufs unix version of the boot block, useful for testing. -# -./src/psm/stand/bootblks/ufs/common/iob.h -./src/psm/stand/bootblks/ufs/common/ufs.c -./src/psm/stand/bootblks/obp-c/common/cbootblk.h - -# # Ignore mont_mulf.c. It is used as a starting point for some hand optimized # assembly files. We keep it around for future reference. # diff --git a/usr/src/tools/scripts/Install.sh b/usr/src/tools/scripts/Install.sh index f491412c46..b9ed32064b 100644 --- a/usr/src/tools/scripts/Install.sh +++ b/usr/src/tools/scripts/Install.sh @@ -489,9 +489,9 @@ copy_kernel() { done # - # on x86, add the glommed kernel name to the root archive + # Add the glommed kernel name to the root archive # - if [[ $MACH = "i386" && $GLOM == "yes" ]]; + if [[ $GLOM == "yes" ]]; then filelist="$INSTALL_FILES/etc/boot/solaris/filelist.ramdisk" mkdir -p `dirname $filelist` diff --git a/usr/src/tools/scripts/bfu.sh b/usr/src/tools/scripts/bfu.sh index 26fb0ad277..560e06d722 100644 --- a/usr/src/tools/scripts/bfu.sh +++ b/usr/src/tools/scripts/bfu.sh @@ -339,9 +339,7 @@ superfluous_nonglobal_zone_files=" platform/sun4u/lib/sparcv9/libwrsmconf.so platform/sun4u/lib/sparcv9/libwrsmconf.so.1 platform/sun4u/sbin - platform/sun4u/ufsboot platform/sun4u/wanboot - platform/sun4v/ufsboot platform/sun4v/wanboot sbin/metadb sbin/metadevadm @@ -2358,6 +2356,15 @@ if $ZCAT $cpiodir/generic.root$ZFIX | cpio -it 2>/dev/null | \ new_dladm=yes fi +# +# Check whether the build is boot-archive or ufsboot sparc +# boot based on the existence of a generic.boot archive +# +newboot_sparc=no +if [ $target_isa = sparc -a -f $cpiodir/generic.boot$ZFIX ]; then + newboot_sparc=yes +fi + time_ref=/tmp/bfu.time_ref.$$ rm -f $time_ref touch $time_ref || fail "$time_ref: Unable to create time reference." @@ -4712,7 +4719,8 @@ get_rootdev_list() elif [[ $metadev = /dev/md/rdsk/* ]]; then metavol=`echo "$metadev" | sed -e "s#/dev/md/rdsk/##"` rootdevlist=`metastat -p $metavol |\ - grep -v "^$metavol[ ]" | nawk '{print $4}'` + grep -v "^$metavol[ ]" |\ + nawk '{print $4}' | sed -e "s#/dev/rdsk/##"` fi for rootdev in $rootdevlist do @@ -5093,6 +5101,39 @@ EOF chmod +x $rootprefix/bfu.conflicts/lib/svc/method/boot-archive } +# +# Install failsafe archive on a sparc machine if not present. +# Use a well-known server for the archive if we need it. +# +install_sparc_failsafe() +{ + # check if failsafe already installed + if [ -f $rootprefix/platform/$karch/failsafe ]; then + return + fi + if [ -z "$FAILSAFE_SERVER" ]; then + FAILSAFE_SERVER="netinstall.sfbay" + fi + if [ -z "$FAILSAFE_IMAGE" ]; then + FAILSAFE_IMAGE="export/nv/s/latest" + fi + fs_wos_image="/net/${FAILSAFE_SERVER}/${FAILSAFE_IMAGE}" + fs_archive="${fs_wos_image}/boot/sparc.miniroot" + if [ ! -d $fs_wos_image ] || [ ! -f $fs_archive ]; then + # XXX Remove this fallback to a known good archive once real + # XXX images with boot archives become available. + fs_wos_image="/net/netinstall.sfbay/export/setje/nbs-latest" + fs_archive="${fs_wos_image}/boot/sparc.miniroot" + fi + if [ ! -d $fs_wos_image ] || [ ! -f $fs_archive ]; then + echo "no failsafe archive, but can't find one to install" + return + fi + + echo "Installing failsafe archive from $fs_wos_image" + cp $fs_archive $rootprefix/platform/$karch/failsafe +} + disable_boot_service() { svccfg -s system/boot-archive setprop start/exec = true @@ -7017,6 +7058,14 @@ mondo_loop() { print "Installing boot block on $rootslice." cd $usr/platform/$karch/lib/fs/ufs installboot ./bootblk $rootslice + elif [[ "$rootslice" = /dev/md/rdsk/* ]]; then + print "Detected SVM root." + cd $usr/platform/$karch/lib/fs/ufs + get_rootdev_list | while read physlice + do + print "Installing bootblk on $physlice." + installboot ./bootblk $physlice + done fi ;; i386) @@ -7044,6 +7093,8 @@ mondo_loop() { extract_archives root generic $archlist if [ $target_isa = i386 ]; then extract_boot_archives boot $archlist + elif [ $newboot_sparc = yes ]; then + extract_boot_archives boot generic fi else export PATH=/tmp/bfubin @@ -7064,6 +7115,8 @@ mondo_loop() { # .root archives. # extract_boot_archives boot $rootarchs + elif [ $newboot_sparc = yes ]; then + extract_boot_archives boot generic fi else dir_is_inherited usr || @@ -7344,6 +7397,16 @@ mondo_loop() { check_boot_env fi + # + # update boot archives for new boot sparc + # + if [ $newboot_sparc = yes ] && \ + [[ $rootslice = /dev/rdsk/* || + $rootslice = /dev/md/rdsk/* ]]; then + build_boot_archive + install_sparc_failsafe + fi + # Check for damage due to CR 6379341. This was actually fixed # back in snv_24, but users BFUing from an S10 build up to # Nevada can still encounter it. diff --git a/usr/src/tools/scripts/mkbfu.sh b/usr/src/tools/scripts/mkbfu.sh index 963eb4b246..c5980fd645 100644 --- a/usr/src/tools/scripts/mkbfu.sh +++ b/usr/src/tools/scripts/mkbfu.sh @@ -197,8 +197,13 @@ do done if [ -d boot ]; then - ( find boot -depth -print | create_archive $CLASS boot ) \ - 2>$CPIODIR/${CLASS}.boot.err & + if [ "$CLASS" = "i86pc" ]; then + ARCHIVECLASS="$CLASS" + else + ARCHIVECLASS="generic" + fi + ( find boot -depth -print | create_archive $ARCHIVECLASS boot ) \ + 2>$CPIODIR/$ARCHIVECLASS.boot.err & bgcheck fi diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files index 52ba4b0bf2..1dec324b2f 100644 --- a/usr/src/uts/common/Makefile.files +++ b/usr/src/uts/common/Makefile.files @@ -214,6 +214,7 @@ GENUNIX_OBJS += \ nvpair.o \ nvpair_alloc_system.o \ nvpair_alloc_fixed.o \ + octet.o \ open.o \ p_online.o \ pathconf.o \ @@ -836,6 +837,8 @@ CACHEFS_OBJS += cachefs_cnode.o cachefs_cod.o \ cachefs_subr.o cachefs_vfsops.o \ cachefs_vnops.o +DCFS_OBJS += dc_vnops.o + DEVFS_OBJS += devfs_subr.o devfs_vfsops.o devfs_vnops.o DEV_OBJS += sdev_subr.o sdev_vfsops.o sdev_vnops.o \ @@ -1372,23 +1375,12 @@ DES_OBJS += des_crypt.o des_cbc_crypt.o des_impl.o des_ks.o des_soft.o DLBOOT_OBJS += bootparam_xdr.o nfs_dlinet.o scan.o -sparc_KRTLD_OBJS = \ - kobj_subr.o - -i386_KRTLD_OBJS = - -COMMON_KRTLD_OBJS = \ - kobj_bootflags.o \ - getoptstr.o \ - kobj.o \ - kobj_kdi.o \ - kobj_lm.o - -KRTLD_OBJS += $(COMMON_KRTLD_OBJS) $($(MACH)_KRTLD_OBJS) +KRTLD_OBJS += kobj_bootflags.o getoptstr.o \ + kobj.o kobj_kdi.o kobj_lm.o kobj_subr.o MOD_OBJS += modctl.o modsubr.o modsysfile.o modconf.o modhash.o -STRPLUMB_OBJS += strplumb.o octet.o +STRPLUMB_OBJS += strplumb.o CPR_OBJS += cpr_driver.o cpr_dump.o \ cpr_main.o cpr_misc.o cpr_mod.o cpr_stat.o \ diff --git a/usr/src/uts/common/Makefile.rules b/usr/src/uts/common/Makefile.rules index 5f47d597de..d33fcc7bc0 100644 --- a/usr/src/uts/common/Makefile.rules +++ b/usr/src/uts/common/Makefile.rules @@ -178,6 +178,10 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/common/fs/cachefs/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) +$(OBJS_DIR)/%.o: $(UTSBASE)/common/fs/dcfs/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + $(OBJS_DIR)/%.o: $(UTSBASE)/common/fs/devfs/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) @@ -907,6 +911,22 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/common/ktli/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) +# +# krtld must refer to its own bzero/bcopy until the kernel is fully linked +# +$(OBJS_DIR)/bootrd.o := CPPFLAGS += -DKOBJ_OVERRIDES +$(OBJS_DIR)/doreloc.o := CPPFLAGS += -DKOBJ_OVERRIDES +$(OBJS_DIR)/kobj.o := CPPFLAGS += -DKOBJ_OVERRIDES +$(OBJS_DIR)/kobj_boot.o := CPPFLAGS += -DKOBJ_OVERRIDES +$(OBJS_DIR)/kobj_bootflags.o := CPPFLAGS += -DKOBJ_OVERRIDES +$(OBJS_DIR)/kobj_convrelstr.o := CPPFLAGS += -DKOBJ_OVERRIDES +$(OBJS_DIR)/kobj_isa.o := CPPFLAGS += -DKOBJ_OVERRIDES +$(OBJS_DIR)/kobj_kdi.o := CPPFLAGS += -DKOBJ_OVERRIDES +$(OBJS_DIR)/kobj_lm.o := CPPFLAGS += -DKOBJ_OVERRIDES +$(OBJS_DIR)/kobj_reloc.o := CPPFLAGS += -DKOBJ_OVERRIDES +$(OBJS_DIR)/kobj_stubs.o := CPPFLAGS += -DKOBJ_OVERRIDES +$(OBJS_DIR)/kobj_subr.o := CPPFLAGS += -DKOBJ_OVERRIDES + $(OBJS_DIR)/%.o: $(UTSBASE)/common/krtld/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) @@ -1142,6 +1162,9 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/common/fs/ctfs/%.c $(LINTS_DIR)/%.ln: $(UTSBASE)/common/fs/doorfs/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) +$(LINTS_DIR)/%.ln: $(UTSBASE)/common/fs/dcfs/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + $(LINTS_DIR)/%.ln: $(UTSBASE)/common/fs/devfs/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) diff --git a/usr/src/uts/common/fs/dcfs/dc_vnops.c b/usr/src/uts/common/fs/dcfs/dc_vnops.c new file mode 100644 index 0000000000..8b2f2875fb --- /dev/null +++ b/usr/src/uts/common/fs/dcfs/dc_vnops.c @@ -0,0 +1,1110 @@ + +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + +/* + * University Copyright- Copyright (c) 1982, 1986, 1988 + * The Regents of the University of California + * All Rights Reserved + * + * University Acknowledgment- Portions of this document are derived from + * software developed by the University of California, Berkeley, and its + * contributors. + */ + + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> +#include <sys/thread.h> +#include <sys/t_lock.h> +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bitmap.h> +#include <sys/buf.h> +#include <sys/cmn_err.h> +#include <sys/conf.h> +#include <sys/ddi.h> +#include <sys/debug.h> +#include <sys/errno.h> +#include <sys/time.h> +#include <sys/fcntl.h> +#include <sys/flock.h> +#include <sys/file.h> +#include <sys/kmem.h> +#include <sys/mman.h> +#include <sys/vmsystm.h> +#include <sys/open.h> +#include <sys/swap.h> +#include <sys/sysmacros.h> +#include <sys/uio.h> +#include <sys/vfs.h> +#include <sys/vfs_opreg.h> +#include <sys/vnode.h> +#include <sys/stat.h> +#include <sys/poll.h> +#include <sys/zmod.h> +#include <sys/fs/decomp.h> + +#include <vm/hat.h> +#include <vm/as.h> +#include <vm/page.h> +#include <vm/pvn.h> +#include <vm/seg_vn.h> +#include <vm/seg_kmem.h> +#include <vm/seg_map.h> + +#include <fs/fs_subr.h> + +/* + * dcfs - A filesystem for automatic decompressing of fiocompressed files + * + * This filesystem is a layered filesystem that sits on top of a normal + * persistent filesystem and provides automatic decompression of files + * that have been previously compressed and stored on the host file system. + * This is a pseudo filesystem in that it does not persist data, rather it + * intercepts file lookup requests on the host filesystem and provides + * transparent decompression of those files. Currently the only supported + * host filesystem is ufs. + * + * A file is compressed via a userland utility (currently cmd/boot/fiocompress) + * and marked by fiocompress as a compressed file via a flag in the on-disk + * inode (set via a ufs ioctl() - see `ufs_vnops.c`ufs_ioctl()`_FIO_COMPRESSED + * ufs_lookup checks for this flag and if set, passes control to decompvp + * a function defined in this (dcfs) filesystem. decomvp uncompresses the file + * and returns a dcfs vnode to the VFS layer. + * + * dcfs is layered on top of ufs and passes requests involving persistence + * to the underlying ufs filesystem. The compressed files currently cannot be + * written to. + */ + + +/* + * Define data structures within this file. + */ +#define DCSHFT 5 +#define DCTABLESIZE 16 + +#if ((DCTABLESIZE & (DCTABLESIZE - 1)) == 0) +#define DCHASH(vp) (((uintptr_t)(vp) >> DCSHFT) & (DCTABLESIZE - 1)) +#else +#define DCHASH(vp) (((uintptr_t)(vp) >> DCSHFT) % DTABLESIZEC) +#endif + +#define DCLRUSIZE 16 + +#define DCCACHESIZE 4 + +#define rounddown(x, y) ((x) & ~((y) - 1)) + +struct dcnode *dctable[DCTABLESIZE]; + +struct dcnode *dclru; +static int dclru_len; + +kmutex_t dctable_lock; + +dev_t dcdev; +struct vfs dc_vfs; + +struct kmem_cache *dcnode_cache; +struct kmem_cache *dcbuf_cache[DCCACHESIZE]; + +kmutex_t dccache_lock; + +static int dcinit(int, char *); + +static struct dcnode *dcnode_alloc(void); +static void dcnode_free(struct dcnode *); +static void dcnode_recycle(struct dcnode *); + +static void dcinsert(struct dcnode *); +static void dcdelete(struct dcnode *); +static struct dcnode *dcfind(struct vnode *); +static void dclru_add(struct dcnode *); +static void dclru_sub(struct dcnode *); + + +/* + * This is the loadable module wrapper. + */ +#include <sys/modctl.h> + +struct vfsops *dc_vfsops; + +static vfsdef_t vfw = { + VFSDEF_VERSION, + "dcfs", + dcinit, + 0, + NULL +}; + +/* + * Module linkage information for the kernel. + */ +extern struct mod_ops mod_fsops; + +static struct modlfs modlfs = { + &mod_fsops, "compressed filesystem", &vfw +}; + +static struct modlinkage modlinkage = { + MODREV_1, (void *)&modlfs, NULL +}; + +int +_init() +{ + return (mod_install(&modlinkage)); +} + +int +_info(struct modinfo *modinfop) +{ + return (mod_info(&modlinkage, modinfop)); +} + + +static int dc_open(struct vnode **, int, struct cred *, caller_context_t *); +static int dc_close(struct vnode *, int, int, offset_t, + struct cred *, caller_context_t *); +static int dc_read(struct vnode *, struct uio *, int, struct cred *, + struct caller_context *); +static int dc_getattr(struct vnode *, struct vattr *, int, + struct cred *, caller_context_t *); +static int dc_setattr(struct vnode *, struct vattr *, int, struct cred *, + struct caller_context *); +static int dc_access(struct vnode *, int, int, + struct cred *, caller_context_t *); +static int dc_fsync(struct vnode *, int, struct cred *, caller_context_t *); +static void dc_inactive(struct vnode *, struct cred *, caller_context_t *); +static int dc_fid(struct vnode *, struct fid *, caller_context_t *); +static int dc_seek(struct vnode *, offset_t, offset_t *, caller_context_t *); +static int dc_frlock(struct vnode *, int, struct flock64 *, int, offset_t, + struct flk_callback *, struct cred *, caller_context_t *); +static int dc_getpage(struct vnode *, offset_t, size_t, uint_t *, + struct page **, size_t, struct seg *, caddr_t, enum seg_rw, + struct cred *, caller_context_t *); +static int dc_putpage(struct vnode *, offset_t, size_t, int, + struct cred *, caller_context_t *); +static int dc_map(struct vnode *, offset_t, struct as *, caddr_t *, size_t, + uchar_t, uchar_t, uint_t, struct cred *, caller_context_t *); +static int dc_addmap(struct vnode *, offset_t, struct as *, caddr_t, size_t, + uchar_t, uchar_t, uint_t, struct cred *, caller_context_t *); +static int dc_delmap(struct vnode *, offset_t, struct as *, caddr_t, size_t, + uint_t, uint_t, uint_t, struct cred *, caller_context_t *); + +struct vnodeops *dc_vnodeops; + +const fs_operation_def_t dc_vnodeops_template[] = { + VOPNAME_OPEN, { .vop_open = dc_open }, + VOPNAME_CLOSE, { .vop_close = dc_close }, + VOPNAME_READ, { .vop_read = dc_read }, + VOPNAME_GETATTR, { .vop_getattr = dc_getattr }, + VOPNAME_SETATTR, { .vop_setattr = dc_setattr }, + VOPNAME_ACCESS, { .vop_access = dc_access }, + VOPNAME_FSYNC, { .vop_fsync = dc_fsync }, + VOPNAME_INACTIVE, { .vop_inactive = dc_inactive }, + VOPNAME_FID, { .vop_fid = dc_fid }, + VOPNAME_SEEK, { .vop_seek = dc_seek }, + VOPNAME_FRLOCK, { .vop_frlock = dc_frlock }, + VOPNAME_GETPAGE, { .vop_getpage = dc_getpage }, + VOPNAME_PUTPAGE, { .vop_putpage = dc_putpage }, + VOPNAME_MAP, { .vop_map = dc_map }, + VOPNAME_ADDMAP, { .vop_addmap = dc_addmap }, + VOPNAME_DELMAP, { .vop_delmap = dc_delmap }, + NULL, NULL +}; + +/*ARGSUSED*/ +static int +dc_open(struct vnode **vpp, int flag, struct cred *cr, caller_context_t *ctp) +{ + return (0); +} + +/*ARGSUSED*/ +static int +dc_close(struct vnode *vp, int flag, int count, offset_t off, + struct cred *cr, caller_context_t *ctp) +{ + (void) cleanlocks(vp, ttoproc(curthread)->p_pid, 0); + cleanshares(vp, ttoproc(curthread)->p_pid); + return (0); +} + +/*ARGSUSED*/ +static int +dc_read(struct vnode *vp, struct uio *uiop, int ioflag, struct cred *cr, + struct caller_context *ct) +{ + struct dcnode *dp = VTODC(vp); + size_t rdsize = MAX(MAXBSIZE, dp->dc_hdr->ch_blksize); + size_t fsize = dp->dc_hdr->ch_fsize; + int error; + + /* + * Loop through file with segmap, decompression will occur + * in dc_getapage + */ + do { + caddr_t base; + size_t n; + offset_t mapon; + + /* + * read to end of block or file + */ + mapon = uiop->uio_loffset & (rdsize - 1); + n = MIN(rdsize - mapon, uiop->uio_resid); + n = MIN(n, fsize - uiop->uio_loffset); + if (n == 0) + return (0); /* at EOF */ + + base = segmap_getmapflt(segkmap, vp, uiop->uio_loffset, n, 1, + S_READ); + error = uiomove(base + mapon, n, UIO_READ, uiop); + if (!error) { + uint_t flags; + + if (n + mapon == rdsize || uiop->uio_loffset == fsize) + flags = SM_DONTNEED; + else + flags = 0; + error = segmap_release(segkmap, base, flags); + } else + (void) segmap_release(segkmap, base, 0); + } while (!error && uiop->uio_resid); + + return (error); +} + +static int +dc_getattr(struct vnode *vp, struct vattr *vap, int flags, + cred_t *cred, caller_context_t *ctp) +{ + struct dcnode *dp = VTODC(vp); + struct vnode *subvp = dp->dc_subvp; + int error; + + error = VOP_GETATTR(subvp, vap, flags, cred, ctp); + + /* substitute uncompressed size */ + vap->va_size = dp->dc_hdr->ch_fsize; + return (error); +} + +static int +dc_setattr(struct vnode *vp, struct vattr *vap, int flags, cred_t *cred, + caller_context_t *ctp) +{ + struct dcnode *dp = VTODC(vp); + struct vnode *subvp = dp->dc_subvp; + + return (VOP_SETATTR(subvp, vap, flags, cred, ctp)); +} + +static int +dc_access(struct vnode *vp, int mode, int flags, + cred_t *cred, caller_context_t *ctp) +{ + struct dcnode *dp = VTODC(vp); + struct vnode *subvp = dp->dc_subvp; + + return (VOP_ACCESS(subvp, mode, flags, cred, ctp)); +} + +/*ARGSUSED*/ +static int +dc_fsync(vnode_t *vp, int syncflag, cred_t *cred, caller_context_t *ctp) +{ + return (0); +} + +/*ARGSUSED*/ +static void +dc_inactive(struct vnode *vp, cred_t *cr, caller_context_t *ctp) +{ + struct dcnode *dp = VTODC(vp); + + mutex_enter(&dctable_lock); + mutex_enter(&vp->v_lock); + ASSERT(vp->v_count >= 1); + if (--vp->v_count != 0) { + /* + * Somebody accessed the dcnode before we got a chance to + * remove it. They will remove it when they do a vn_rele. + */ + mutex_exit(&vp->v_lock); + mutex_exit(&dctable_lock); + return; + } + mutex_exit(&vp->v_lock); + + dcnode_free(dp); + + mutex_exit(&dctable_lock); +} + +static int +dc_fid(struct vnode *vp, struct fid *fidp, caller_context_t *ctp) +{ + struct dcnode *dp = VTODC(vp); + struct vnode *subvp = dp->dc_subvp; + + return (VOP_FID(subvp, fidp, ctp)); +} + +static int +dc_seek(struct vnode *vp, offset_t oof, offset_t *noffp, caller_context_t *ctp) +{ + struct dcnode *dp = VTODC(vp); + struct vnode *subvp = dp->dc_subvp; + + return (VOP_SEEK(subvp, oof, noffp, ctp)); +} + +static int +dc_frlock(struct vnode *vp, int cmd, struct flock64 *bfp, int flag, + offset_t offset, struct flk_callback *flk_cbp, + cred_t *cr, caller_context_t *ctp) +{ + struct dcnode *dp = VTODC(vp); + + /* + * If file is being mapped, disallow frlock. + */ + if (dp->dc_mapcnt > 0) + return (EAGAIN); + + return (fs_frlock(vp, cmd, bfp, flag, offset, flk_cbp, cr, ctp)); +} + +/*ARGSUSED*/ +static int +dc_getblock_miss(struct vnode *vp, offset_t off, size_t len, struct page **ppp, + struct seg *seg, caddr_t addr, enum seg_rw rw, struct cred *cr) +{ + struct dcnode *dp = VTODC(vp); + struct comphdr *hdr = dp->dc_hdr; + struct page *pp; + struct buf *bp; + caddr_t saddr; + off_t cblkno; + size_t rdoff, rdsize, dsize; + long xlen; + int error, zerr; + + ASSERT(len == hdr->ch_blksize); + /* + * Get destination pages and make them addressable + */ + pp = page_create_va(vp, off, len, PG_WAIT, seg, addr); + bp = pageio_setup(pp, len, vp, B_READ); + bp_mapin(bp); + + /* + * read compressed data from subordinate vnode + */ + saddr = kmem_cache_alloc(dp->dc_bufcache, KM_SLEEP); + cblkno = off / len; + rdoff = hdr->ch_blkmap[cblkno]; + rdsize = hdr->ch_blkmap[cblkno + 1] - rdoff; + error = vn_rdwr(UIO_READ, dp->dc_subvp, saddr, rdsize, rdoff, + UIO_SYSSPACE, 0, 0, cr, NULL); + if (error) + goto cleanup; + + /* + * Uncompress + */ + dsize = len; + zerr = z_uncompress(bp->b_un.b_addr, &dsize, saddr, dp->dc_zmax); + if (zerr != Z_OK) { + error = EIO; + goto cleanup; + } + + /* + * Handle EOF + */ + xlen = hdr->ch_fsize - off; + if (xlen < len) { + bzero(bp->b_un.b_addr + xlen, len - xlen); + if (dsize != xlen) + error = EIO; + } else if (dsize != len) + error = EIO; + + /* + * Clean up + */ +cleanup: + kmem_cache_free(dp->dc_bufcache, saddr); + pageio_done(bp); + *ppp = pp; + return (error); +} + +static int +dc_getblock(struct vnode *vp, offset_t off, size_t len, struct page **ppp, + struct seg *seg, caddr_t addr, enum seg_rw rw, struct cred *cr) +{ + struct page *pp, *plist = NULL; + offset_t pgoff; + int rdblk; + + /* + * pvn_read_kluster() doesn't quite do what we want, since it + * thinks sub block reads are ok. Here we always decompress + * a full block. + */ + + /* + * Check page cache + */ + rdblk = 0; + for (pgoff = off; pgoff < off + len; pgoff += PAGESIZE) { + pp = page_lookup(vp, pgoff, SE_EXCL); + if (pp == NULL) { + rdblk = 1; + break; + } + page_io_lock(pp); + page_add(&plist, pp); + plist = plist->p_next; + } + if (!rdblk) { + *ppp = plist; + return (0); /* all pages in cache */ + } + + /* + * Undo any locks so getblock_miss has an open field + */ + if (plist != NULL) + pvn_io_done(plist); + + return (dc_getblock_miss(vp, off, len, ppp, seg, addr, rw, cr)); +} + +/*ARGSUSED10*/ +static int +dc_getpage(struct vnode *vp, offset_t off, size_t len, uint_t *protp, + struct page *pl[], size_t plsz, struct seg *seg, caddr_t addr, + enum seg_rw rw, struct cred *cr, caller_context_t *ctp) +{ + struct dcnode *dp = VTODC(vp); + struct comphdr *hdr = dp->dc_hdr; + struct page *pp, *plist = NULL; + caddr_t vp_baddr; + offset_t vp_boff, vp_bend; + size_t bsize = hdr->ch_blksize; + int nblks, error; + + /* does not support write */ + if (rw == S_WRITE) { + panic("write attempt on compressed file"); + /*NOTREACHED*/ + } + + if (protp) + *protp = PROT_ALL; + /* + * We don't support asynchronous operation at the moment, so + * just pretend we did it. If the pages are ever actually + * needed, they'll get brought in then. + */ + if (pl == NULL) + return (0); + + /* + * Calc block start and end offsets + */ + vp_boff = rounddown(off, bsize); + vp_bend = roundup(off + len, bsize); + vp_baddr = (caddr_t)rounddown((uintptr_t)addr, bsize); + + nblks = (vp_bend - vp_boff) / bsize; + while (nblks--) { + error = dc_getblock(vp, vp_boff, bsize, &pp, seg, vp_baddr, + rw, cr); + page_list_concat(&plist, &pp); + vp_boff += bsize; + vp_baddr += bsize; + } + if (!error) + pvn_plist_init(plist, pl, plsz, off, len, rw); + else + pvn_read_done(plist, B_ERROR); + return (error); +} + +/* + * This function should never be called. We need to have it to pass + * it as an argument to other functions. + */ +/*ARGSUSED*/ +static int +dc_putapage(struct vnode *vp, struct page *pp, u_offset_t *offp, size_t *lenp, + int flags, struct cred *cr) +{ + /* should never happen */ + cmn_err(CE_PANIC, "dcfs: dc_putapage: dirty page"); + /*NOTREACHED*/ + return (0); +} + + +/* + * The only flags we support are B_INVAL, B_FREE and B_DONTNEED. + * B_INVAL is set by: + * + * 1) the MC_SYNC command of memcntl(2) to support the MS_INVALIDATE flag. + * 2) the MC_ADVISE command of memcntl(2) with the MADV_DONTNEED advice + * which translates to an MC_SYNC with the MS_INVALIDATE flag. + * + * The B_FREE (as well as the B_DONTNEED) flag is set when the + * MADV_SEQUENTIAL advice has been used. VOP_PUTPAGE is invoked + * from SEGVN to release pages behind a pagefault. + */ +/*ARGSUSED5*/ +static int +dc_putpage(struct vnode *vp, offset_t off, size_t len, int flags, + struct cred *cr, caller_context_t *ctp) +{ + int error = 0; + + if (vp->v_count == 0) { + panic("dcfs_putpage: bad v_count"); + /*NOTREACHED*/ + } + + if (vp->v_flag & VNOMAP) + return (ENOSYS); + + if (!vn_has_cached_data(vp)) /* no pages mapped */ + return (0); + + if (len == 0) /* from 'off' to EOF */ + error = pvn_vplist_dirty(vp, off, dc_putapage, flags, cr); + else { + offset_t io_off; + se_t se = (flags & (B_INVAL | B_FREE)) ? SE_EXCL : SE_SHARED; + + for (io_off = off; io_off < off + len; io_off += PAGESIZE) { + page_t *pp; + + /* + * We insist on getting the page only if we are + * about to invalidate, free or write it and + * the B_ASYNC flag is not set. + */ + if ((flags & B_INVAL) || ((flags & B_ASYNC) == 0)) + pp = page_lookup(vp, io_off, se); + else + pp = page_lookup_nowait(vp, io_off, se); + + if (pp == NULL) + continue; + /* + * Normally pvn_getdirty() should return 0, which + * impies that it has done the job for us. + * The shouldn't-happen scenario is when it returns 1. + * This means that the page has been modified and + * needs to be put back. + * Since we can't write to a dcfs compressed file, + * we fake a failed I/O and force pvn_write_done() + * to destroy the page. + */ + if (pvn_getdirty(pp, flags) == 1) { + cmn_err(CE_NOTE, "dc_putpage: dirty page"); + pvn_write_done(pp, flags | + B_ERROR | B_WRITE | B_INVAL | B_FORCE); + } + } + } + return (error); +} + +static int +dc_map(struct vnode *vp, offset_t off, struct as *as, caddr_t *addrp, + size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, + struct cred *cred, caller_context_t *ctp) +{ + struct vattr vattr; + struct segvn_crargs vn_a; + int error; + + if (vp->v_flag & VNOMAP) + return (ENOSYS); + + if (off < (offset_t)0 || (offset_t)(off + len) < (offset_t)0) + return (ENXIO); + + /* + * If file is being locked, disallow mapping. + */ + if (error = VOP_GETATTR(VTODC(vp)->dc_subvp, &vattr, 0, cred, ctp)) + return (error); + if (vn_has_mandatory_locks(vp, vattr.va_mode)) + return (EAGAIN); + + as_rangelock(as); + + if ((flags & MAP_FIXED) == 0) { + map_addr(addrp, len, off, 1, flags); + if (*addrp == NULL) { + as_rangeunlock(as); + return (ENOMEM); + } + } else { + /* + * User specified address - blow away any previous mappings + */ + (void) as_unmap(as, *addrp, len); + } + + vn_a.vp = vp; + vn_a.offset = off; + vn_a.type = flags & MAP_TYPE; + vn_a.prot = prot; + vn_a.maxprot = maxprot; + vn_a.flags = flags & ~MAP_TYPE; + vn_a.cred = cred; + vn_a.amp = NULL; + vn_a.szc = 0; + vn_a.lgrp_mem_policy_flags = 0; + + error = as_map(as, *addrp, len, segvn_create, &vn_a); + as_rangeunlock(as); + return (error); +} + +/*ARGSUSED*/ +static int +dc_addmap(struct vnode *vp, offset_t off, struct as *as, caddr_t addr, + size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, + struct cred *cr, caller_context_t *ctp) +{ + struct dcnode *dp; + + if (vp->v_flag & VNOMAP) + return (ENOSYS); + + dp = VTODC(vp); + mutex_enter(&dp->dc_lock); + dp->dc_mapcnt += btopr(len); + mutex_exit(&dp->dc_lock); + return (0); +} + +/*ARGSUSED*/ +static int +dc_delmap(struct vnode *vp, offset_t off, struct as *as, caddr_t addr, + size_t len, uint_t prot, uint_t maxprot, uint_t flags, + struct cred *cr, caller_context_t *ctp) +{ + struct dcnode *dp; + + if (vp->v_flag & VNOMAP) + return (ENOSYS); + + dp = VTODC(vp); + mutex_enter(&dp->dc_lock); + dp->dc_mapcnt -= btopr(len); + ASSERT(dp->dc_mapcnt >= 0); + mutex_exit(&dp->dc_lock); + return (0); +} + +/* + * Constructor/destructor routines for dcnodes + */ +/*ARGSUSED1*/ +static int +dcnode_constructor(void *buf, void *cdrarg, int kmflags) +{ + struct dcnode *dp = buf; + struct vnode *vp; + + ASSERT(!(kmflags & KM_NOSLEEP)); + + vp = vn_alloc(KM_SLEEP); + vp->v_data = (caddr_t)dp; + vp->v_type = VREG; + vp->v_flag = VNOSWAP; + vp->v_vfsp = &dc_vfs; + vn_setops(vp, dc_vnodeops); + vn_exists(vp); + + dp->dc_vp = vp; + mutex_init(&dp->dc_lock, NULL, MUTEX_DEFAULT, NULL); + dp->dc_mapcnt = 0; + dp->dc_lrunext = dp->dc_lruprev = NULL; + return (0); +} + +/*ARGSUSED*/ +static void +dcnode_destructor(void *buf, void *cdrarg) +{ + struct dcnode *dp = buf; + struct vnode *vp = DCTOV(dp); + + mutex_destroy(&dp->dc_lock); + + VERIFY(dp->dc_hdr == NULL); + VERIFY(dp->dc_subvp == NULL); + vn_invalid(vp); + vn_free(vp); +} + +static struct dcnode * +dcnode_alloc(void) +{ + struct dcnode *dp; + + /* + * If the free list is above DCLRUSIZE + * re-use one from it + */ + mutex_enter(&dctable_lock); + if (dclru_len < DCLRUSIZE) { + mutex_exit(&dctable_lock); + dp = kmem_cache_alloc(dcnode_cache, KM_SLEEP); + } else { + ASSERT(dclru != NULL); + dp = dclru; + dclru_sub(dp); + dcdelete(dp); + mutex_exit(&dctable_lock); + dcnode_recycle(dp); + } + return (dp); +} + +static void +dcnode_free(struct dcnode *dp) +{ + struct vnode *vp = DCTOV(dp); + + ASSERT(MUTEX_HELD(&dctable_lock)); + + /* + * If no cached pages, no need to put it on lru + */ + if (!vn_has_cached_data(vp)) { + dcdelete(dp); + dcnode_recycle(dp); + kmem_cache_free(dcnode_cache, dp); + return; + } + + /* + * Add to lru, if it's over the limit, free from head + */ + dclru_add(dp); + if (dclru_len > DCLRUSIZE) { + dp = dclru; + dclru_sub(dp); + dcdelete(dp); + dcnode_recycle(dp); + kmem_cache_free(dcnode_cache, dp); + } +} + +static void +dcnode_recycle(struct dcnode *dp) +{ + struct vnode *vp; + + vp = DCTOV(dp); + + VN_RELE(dp->dc_subvp); + dp->dc_subvp = NULL; + (void) pvn_vplist_dirty(vp, 0, dc_putapage, B_INVAL, NULL); + kmem_free(dp->dc_hdr, dp->dc_hdrsize); + dp->dc_hdr = NULL; + dp->dc_hdrsize = dp->dc_zmax = 0; + dp->dc_bufcache = NULL; + dp->dc_mapcnt = 0; + vn_reinit(vp); + vp->v_type = VREG; + vp->v_flag = VNOSWAP; + vp->v_vfsp = &dc_vfs; +} + +static int +dcinit(int fstype, char *name) +{ + static const fs_operation_def_t dc_vfsops_template[] = { + NULL, NULL + }; + int error; + major_t dev; + + error = vfs_setfsops(fstype, dc_vfsops_template, &dc_vfsops); + if (error) { + cmn_err(CE_WARN, "dcinit: bad vfs ops template"); + return (error); + } + VFS_INIT(&dc_vfs, dc_vfsops, NULL); + dc_vfs.vfs_flag = VFS_RDONLY; + dc_vfs.vfs_fstype = fstype; + if ((dev = getudev()) == (major_t)-1) + dev = 0; + dcdev = makedevice(dev, 0); + dc_vfs.vfs_dev = dcdev; + + error = vn_make_ops(name, dc_vnodeops_template, &dc_vnodeops); + if (error != 0) { + (void) vfs_freevfsops_by_type(fstype); + cmn_err(CE_WARN, "dcinit: bad vnode ops template"); + return (error); + } + + mutex_init(&dctable_lock, NULL, MUTEX_DEFAULT, NULL); + mutex_init(&dccache_lock, NULL, MUTEX_DEFAULT, NULL); + dcnode_cache = kmem_cache_create("dcnode_cache", sizeof (struct dcnode), + 0, dcnode_constructor, dcnode_destructor, NULL, NULL, NULL, 0); + + return (0); +} + +/* + * Return shadow vnode with the given vp as its subordinate + */ +struct vnode * +decompvp(struct vnode *vp, cred_t *cred, caller_context_t *ctp) +{ + struct dcnode *dp, *ndp; + struct comphdr thdr, *hdr; + struct kmem_cache **cpp; + struct vattr vattr; + size_t hdrsize, bsize; + int error; + + /* + * See if we have an existing shadow + * If none, we have to manufacture one + */ + mutex_enter(&dctable_lock); + dp = dcfind(vp); + mutex_exit(&dctable_lock); + if (dp != NULL) + return (DCTOV(dp)); + + /* + * Make sure it's a valid compressed file + */ + hdr = &thdr; + error = vn_rdwr(UIO_READ, vp, (caddr_t)hdr, sizeof (struct comphdr), 0, + UIO_SYSSPACE, 0, 0, cred, NULL); + if (error || hdr->ch_magic != CH_MAGIC || + hdr->ch_version != CH_VERSION || hdr->ch_algorithm != CH_ALG_ZLIB || + hdr->ch_fsize == 0 || hdr->ch_blksize < PAGESIZE || + hdr->ch_blksize > ptob(DCCACHESIZE) || + (hdr->ch_blksize & (hdr->ch_blksize - 1)) != 0) + return (NULL); + + /* get underlying file size */ + if (VOP_GETATTR(vp, &vattr, 0, cred, ctp) != 0) + return (NULL); + + /* + * Re-read entire header + */ + hdrsize = hdr->ch_blkmap[0] + sizeof (uint64_t); + hdr = kmem_alloc(hdrsize, KM_SLEEP); + error = vn_rdwr(UIO_READ, vp, (caddr_t)hdr, hdrsize, 0, UIO_SYSSPACE, + 0, 0, cred, NULL); + if (error) { + kmem_free(hdr, hdrsize); + return (NULL); + } + + /* + * add extra blkmap entry to make dc_getblock()'s + * life easier + */ + bsize = hdr->ch_blksize; + hdr->ch_blkmap[((hdr->ch_fsize-1) / bsize) + 1] = vattr.va_size; + + ndp = dcnode_alloc(); + ndp->dc_subvp = vp; + VN_HOLD(vp); + ndp->dc_hdr = hdr; + ndp->dc_hdrsize = hdrsize; + + /* + * Allocate kmem cache if none there already + */ + ndp->dc_zmax = ZMAXBUF(bsize); + cpp = &dcbuf_cache[btop(bsize)]; + mutex_enter(&dccache_lock); + if (*cpp == NULL) + *cpp = kmem_cache_create("dcbuf_cache", ndp->dc_zmax, 0, NULL, + NULL, NULL, NULL, NULL, 0); + mutex_exit(&dccache_lock); + ndp->dc_bufcache = *cpp; + + /* + * Recheck table in case someone else created shadow + * while we were blocked above. + */ + mutex_enter(&dctable_lock); + dp = dcfind(vp); + if (dp != NULL) { + mutex_exit(&dctable_lock); + dcnode_recycle(ndp); + kmem_cache_free(dcnode_cache, ndp); + return (DCTOV(dp)); + } + dcinsert(ndp); + mutex_exit(&dctable_lock); + + return (DCTOV(ndp)); +} + + +/* + * dcnode lookup table + * These routines maintain a table of dcnodes hashed by their + * subordinate vnode so that they can be found if they already + * exist in the vnode cache + */ + +/* + * Put a dcnode in the table. + */ +static void +dcinsert(struct dcnode *newdp) +{ + int idx = DCHASH(newdp->dc_subvp); + + ASSERT(MUTEX_HELD(&dctable_lock)); + newdp->dc_hash = dctable[idx]; + dctable[idx] = newdp; +} + +/* + * Remove a dcnode from the hash table. + */ +void +dcdelete(struct dcnode *deldp) +{ + int idx = DCHASH(deldp->dc_subvp); + struct dcnode *dp, *prevdp; + + ASSERT(MUTEX_HELD(&dctable_lock)); + dp = dctable[idx]; + if (dp == deldp) + dctable[idx] = dp->dc_hash; + else { + for (prevdp = dp, dp = dp->dc_hash; dp != NULL; + prevdp = dp, dp = dp->dc_hash) { + if (dp == deldp) { + prevdp->dc_hash = dp->dc_hash; + break; + } + } + } + ASSERT(dp != NULL); +} + +/* + * Find a shadow vnode in the dctable hash list. + */ +static struct dcnode * +dcfind(struct vnode *vp) +{ + struct dcnode *dp; + + ASSERT(MUTEX_HELD(&dctable_lock)); + for (dp = dctable[DCHASH(vp)]; dp != NULL; dp = dp->dc_hash) + if (dp->dc_subvp == vp) { + VN_HOLD(DCTOV(dp)); + if (dp->dc_lrunext) + dclru_sub(dp); + return (dp); + } + return (NULL); +} + +#ifdef DEBUG +static int +dclru_count(void) +{ + struct dcnode *dp; + int i = 0; + + if (dclru == NULL) + return (0); + for (dp = dclru; dp->dc_lrunext != dclru; dp = dp->dc_lrunext) + i++; + return (i + 1); +} +#endif + +static void +dclru_add(struct dcnode *dp) +{ + /* + * Add to dclru as double-link chain + */ + ASSERT(MUTEX_HELD(&dctable_lock)); + if (dclru == NULL) { + dclru = dp; + dp->dc_lruprev = dp->dc_lrunext = dp; + } else { + struct dcnode *last = dclru->dc_lruprev; + + dclru->dc_lruprev = dp; + last->dc_lrunext = dp; + dp->dc_lruprev = last; + dp->dc_lrunext = dclru; + } + dclru_len++; + ASSERT(dclru_len == dclru_count()); +} + +static void +dclru_sub(struct dcnode *dp) +{ + ASSERT(MUTEX_HELD(&dctable_lock)); + dp->dc_lrunext->dc_lruprev = dp->dc_lruprev; + dp->dc_lruprev->dc_lrunext = dp->dc_lrunext; + if (dp == dclru) + dclru = dp->dc_lrunext == dp ? NULL : dp->dc_lrunext; + dp->dc_lrunext = dp->dc_lruprev = NULL; + dclru_len--; + ASSERT(dclru_len == dclru_count()); +} diff --git a/usr/src/uts/common/fs/nfs/nfs_dlinet.c b/usr/src/uts/common/fs/nfs/nfs_dlinet.c index 253312588e..632a5b29a7 100644 --- a/usr/src/uts/common/fs/nfs/nfs_dlinet.c +++ b/usr/src/uts/common/fs/nfs/nfs_dlinet.c @@ -951,7 +951,7 @@ getfile(char *fileid, } /* - * If the boot property "bootp-response" exists, then inetboot performed a + * If the boot property "bootp-response" exists, then OBP performed a * successful DHCP lease acquisition for us and left the resultant ACK packet * encoded at that location. * @@ -968,8 +968,6 @@ dhcpinit(void) DHCP_OPT *doptp; TIUSER *tiptr; struct sockaddr_in *sin; - int true_dhcacklen; - char *ackp; static int once_only = 0; if (once_only == 1) { @@ -981,45 +979,24 @@ dhcpinit(void) return (-1); } - ackp = (char *)(dhcack + IFNAMSIZ); - true_dhcacklen = strlen(ackp); - - /* - * Since we expect the "bootp-response" property to have - * been encoded via octet_to_hexascii(), its length should - * always be even. - */ - ASSERT((true_dhcacklen % 2) == 0); - if (dldebug) { printf("dhcp: dhcack %p, len %d\n", (void *)dhcack, - true_dhcacklen + IFNAMSIZ); + dhcacklen); } pl = kmem_alloc(sizeof (PKT_LIST), KM_SLEEP); - pl->len = true_dhcacklen / 2; + pl->len = dhcacklen; pl->pkt = kmem_alloc(pl->len, KM_SLEEP); + bcopy(dhcack, pl->pkt, dhcacklen); /* - * Store our interface name in the reserved block at the - * head of our packet. For x86, ifname is not initialized + * For x86, ifname is not initialized * in the netinstall case and dhcack interface name is * set in strplumb(). So we only copy the name if ifname * is set properly. */ if (ifname[0]) - (void) strncpy(dhcack, ifname, IFNAMSIZ - 1); - - /* skip over the interface name section */ - if (hexascii_to_octet(ackp, true_dhcacklen, (uchar_t *)pl->pkt, - &(pl->len)) != 0) { - cmn_err(CE_WARN, - "dhcp: boot dhcp cache is corrupted."); - kmem_free(pl->pkt, pl->len); - kmem_free(pl, sizeof (PKT_LIST)); - pl = NULL; - return (-1); - } + (void) strlcpy(dhcifname, ifname, sizeof (dhcifname)); /* remember the server_ip in dhcack */ bcopy((uchar_t *)pl->pkt + 20, dhcp_server_ip, 4); diff --git a/usr/src/uts/common/fs/ufs/ufs_filio.c b/usr/src/uts/common/fs/ufs/ufs_filio.c index 04a68104ff..c02fd89748 100644 --- a/usr/src/uts/common/fs/ufs/ufs_filio.c +++ b/usr/src/uts/common/fs/ufs/ufs_filio.c @@ -693,3 +693,24 @@ ufs_fio_holey(vnode_t *vp, int cmd, offset_t *off) *off = noff; return (error); } + +int +ufs_mark_compressed(struct vnode *vp) +{ + struct inode *ip = VTOI(vp); + struct ufsvfs *ufsvfsp = ip->i_ufsvfs; + + if (vp->v_type != VREG) + return (EINVAL); + + rw_enter(&ip->i_contents, RW_WRITER); + ip->i_cflags |= ICOMPRESS; + TRANS_INODE(ufsvfsp, ip); + ip->i_flag |= (ICHG|ISEQ); + ip->i_seq++; + if (!TRANS_ISTRANS(ufsvfsp)) + ufs_iupdat(ip, I_ASYNC); + rw_exit(&ip->i_contents); + + return (0); +} diff --git a/usr/src/uts/common/fs/ufs/ufs_vnops.c b/usr/src/uts/common/fs/ufs/ufs_vnops.c index 1274789e2d..5f4136afa3 100644 --- a/usr/src/uts/common/fs/ufs/ufs_vnops.c +++ b/usr/src/uts/common/fs/ufs/ufs_vnops.c @@ -98,6 +98,8 @@ #include <fs/fs_subr.h> +#include <sys/fs/decomp.h> + static struct instats ins; static int ufs_getpage_ra(struct vnode *, u_offset_t, struct seg *, caddr_t); @@ -177,7 +179,6 @@ static int ufs_getsecattr(struct vnode *, vsecattr_t *, int, struct cred *, caller_context_t *); static int ufs_setsecattr(struct vnode *, vsecattr_t *, int, struct cred *, caller_context_t *); - extern int as_map_locked(struct as *, caddr_t, size_t, int ((*)()), void *); /* @@ -860,7 +861,7 @@ wrip(struct inode *ip, struct uio *uio, int ioflag, struct cred *cr) */ if ((type == IFSHAD) || (rw_owner(&ufsvfsp->vfs_dqrwlock) == curthread)) { - do_dqrwlock = 0; + do_dqrwlock = 0; } else { do_dqrwlock = 1; } @@ -1508,7 +1509,7 @@ out: */ if (ioflag & FRSYNC) { if (TRANS_ISTRANS(ufsvfsp) && ((ip->i_mode & IFMT) == IFDIR)) { - doupdate = 0; + doupdate = 0; } if (doupdate) { if ((ioflag & FSYNC) || @@ -1929,11 +1930,53 @@ ufs_ioctl( return (EFAULT); return (0); + case _FIO_COMPRESSED: + { + /* + * This is a project private ufs ioctl() to mark + * the inode as that belonging to a compressed + * file. This is used to mark individual + * files in a miniroot archive for SPARC boot. + * The files compressed in this manner are + * automatically decompressed by the dcfs filesystem + * (via an interception in ufs_lookup - see decompvp()) + * which is layered on top of ufs on a system running + * the new archive booted SPARC system. See + * uts/common/fs/dcfs for details. + * This ioctl only marks the file as compressed - the + * actual compression is done by fiocompress (a + * userland utility) which invokes this ioctl(). + */ + struct inode *ip = VTOI(vp); + + error = ufs_lockfs_begin(ufsvfsp, &ulp, + ULOCKFS_SETATTR_MASK); + if (error) + return (error); + + if (ulp) { + TRANS_BEGIN_ASYNC(ufsvfsp, TOP_IUPDAT, + TOP_IUPDAT_SIZE(ip)); + } + + error = ufs_mark_compressed(vp); + + if (ulp) { + TRANS_END_ASYNC(ufsvfsp, TOP_IUPDAT, + TOP_IUPDAT_SIZE(ip)); + ufs_lockfs_end(ulp); + } + + return (error); + + } + default: return (ENOTTY); } } + /* ARGSUSED */ static int ufs_getattr(struct vnode *vp, struct vattr *vap, int flags, @@ -2812,6 +2855,18 @@ fastpath: error = ENOSYS; else *vpp = newvp; + } else if (ip->i_cflags & ICOMPRESS) { + struct vnode *newvp; + + /* + * Compressed file, substitute dcfs vnode + */ + newvp = decompvp(*vpp, cr, ct); + VN_RELE(*vpp); + if (newvp == NULL) + error = ENOSYS; + else + *vpp = newvp; } } if (ulp) { diff --git a/usr/src/uts/common/fs/zfs/zfs_vfsops.c b/usr/src/uts/common/fs/zfs/zfs_vfsops.c index 4440d7b13b..d55dee5ae3 100644 --- a/usr/src/uts/common/fs/zfs/zfs_vfsops.c +++ b/usr/src/uts/common/fs/zfs/zfs_vfsops.c @@ -859,6 +859,9 @@ zfs_mountroot(vfs_t *vfsp, enum whymountroot why) znode_t *zp = NULL; vnode_t *vp = NULL; char *zfs_bootpath; +#if defined(_OBP) + int proplen; +#endif ASSERT(vfsp); @@ -870,6 +873,18 @@ zfs_mountroot(vfs_t *vfsp, enum whymountroot why) if (zfsrootdone++) return (EBUSY); +#if defined(_OBP) + proplen = BOP_GETPROPLEN(bootops, "zfs-bootfs"); + if (proplen == 0) + return (EIO); + zfs_bootpath = kmem_zalloc(proplen, KM_SLEEP); + if (BOP_GETPROP(bootops, "zfs-bootfs", zfs_bootpath) == -1) { + kmem_free(zfs_bootpath, proplen); + return (EIO); + } + error = parse_bootpath(zfs_bootpath, rootfs.bo_name); + kmem_free(zfs_bootpath, proplen); +#else if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), DDI_PROP_DONTPASS, "zfs-bootfs", &zfs_bootpath) != DDI_SUCCESS) @@ -877,6 +892,7 @@ zfs_mountroot(vfs_t *vfsp, enum whymountroot why) error = parse_bootpath(zfs_bootpath, rootfs.bo_name); ddi_prop_free(zfs_bootpath); +#endif if (error) return (error); diff --git a/usr/src/uts/common/inet/ip/ip_if.c b/usr/src/uts/common/inet/ip/ip_if.c index dba1cf5e00..eb52e897e9 100644 --- a/usr/src/uts/common/inet/ip/ip_if.c +++ b/usr/src/uts/common/inet/ip/ip_if.c @@ -19971,11 +19971,11 @@ ill_dl_up(ill_t *ill, ipif_t *ipif, mblk_t *mp, queue_t *q) * and miniroot network configuration is driven from userland * these things still need to be set. This situation can be detected * by comparing the interface being configured here to the one - * dhcack was set to reference by the boot loader. Once sysid is + * dhcifname was set to reference by the boot loader. Once sysid is * converted to use dhcp_ipc_getinfo() this call can go away. */ - if ((ipif->ipif_flags & IPIF_DHCPRUNNING) && (dhcack != NULL) && - (strcmp(ill->ill_name, dhcack) == 0) && + if ((ipif->ipif_flags & IPIF_DHCPRUNNING) && + (strcmp(ill->ill_name, dhcifname) == 0) && (strlen(srpc_domain) == 0)) { if (dhcpinit() != 0) cmn_err(CE_WARN, "no cached dhcp response"); diff --git a/usr/src/uts/common/io/ramdisk.c b/usr/src/uts/common/io/ramdisk.c index 66ea7fa77a..36ad87c369 100644 --- a/usr/src/uts/common/io/ramdisk.c +++ b/usr/src/uts/common/io/ramdisk.c @@ -391,6 +391,7 @@ rd_phys_free(page_t **ppa, pgcnt_t npages) static void rd_unmap_window(rd_devstate_t *rsp) { + ASSERT(rsp->rd_window_obp == 0); if (rsp->rd_window_base != RD_WINDOW_NOT_MAPPED) { hat_unload(kas.a_hat, rsp->rd_window_virt, rsp->rd_window_size, HAT_UNLOAD_UNLOCK); @@ -574,7 +575,7 @@ rd_dealloc_resources(rd_devstate_t *rsp) char namebuf[RD_NAME_LEN + 5]; dev_t fulldev; - if (rsp->rd_window_virt != NULL) { + if (rsp->rd_window_obp == 0 && rsp->rd_window_virt != NULL) { if (rsp->rd_window_base != RD_WINDOW_NOT_MAPPED) { rd_unmap_window(rsp); } @@ -624,7 +625,7 @@ rd_dealloc_resources(rd_devstate_t *rsp) * to a ramdisk. */ static rd_devstate_t * -rd_alloc_resources(char *name, size_t size, dev_info_t *dip) +rd_alloc_resources(char *name, uint_t addr, size_t size, dev_info_t *dip) { minor_t minor; rd_devstate_t *rsp; @@ -648,12 +649,20 @@ rd_alloc_resources(char *name, size_t size, dev_info_t *dip) * Allocate virtual window onto ramdisk. */ mutex_init(&rsp->rd_device_lock, NULL, MUTEX_DRIVER, NULL); - rsp->rd_window_base = RD_WINDOW_NOT_MAPPED; - rsp->rd_window_size = PAGESIZE; - rsp->rd_window_virt = vmem_alloc(heap_arena, - rsp->rd_window_size, VM_SLEEP); - if (rsp->rd_window_virt == NULL) { - goto create_failed; + if (addr == 0) { + rsp->rd_window_obp = 0; + rsp->rd_window_base = RD_WINDOW_NOT_MAPPED; + rsp->rd_window_size = PAGESIZE; + rsp->rd_window_virt = vmem_alloc(heap_arena, + rsp->rd_window_size, VM_SLEEP); + if (rsp->rd_window_virt == NULL) { + goto create_failed; + } + } else { + rsp->rd_window_obp = 1; + rsp->rd_window_base = 0; + rsp->rd_window_size = size; + rsp->rd_window_virt = (caddr_t)((ulong_t)addr); } /* @@ -779,7 +788,7 @@ rd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { char *name; rd_existing_t *ep = NULL; - uint_t nep, i; + uint_t obpaddr = 0, nep, i; size_t size = 0; rd_devstate_t *rsp; @@ -825,32 +834,39 @@ rd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) * property; get and check it. */ if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, RD_EXISTING_PROP_NAME, - (uchar_t **)&ep, &nep) != DDI_SUCCESS) { - cmn_err(CE_CONT, - "%s: " RD_EXISTING_PROP_NAME - " property missing\n", name); - goto attach_failed; - } - if (nep == 0 || (nep % sizeof (*ep)) != 0) { - cmn_err(CE_CONT, - "%s: " RD_EXISTING_PROP_NAME - " illegal size\n", name); + DDI_PROP_DONTPASS, OBP_EXISTING_PROP_NAME, + (uchar_t **)&ep, &nep) == DDI_SUCCESS) { + + if (nep == 0 || (nep % sizeof (*ep)) != 0) { + cmn_err(CE_CONT, + "%s: " OBP_EXISTING_PROP_NAME + " illegal size\n", name); + goto attach_failed; + } + nep /= sizeof (*ep); + + /* + * Calculate the size of the ramdisk. + */ + for (i = 0; i < nep; ++i) { + size += ep[i].size; + } + } else if ((obpaddr = ddi_prop_get_int(DDI_DEV_T_ANY, + dip, DDI_PROP_DONTPASS, OBP_ADDRESS_PROP_NAME, + 0)) != 0) { + + size = ddi_prop_get_int(DDI_DEV_T_ANY, dip, + DDI_PROP_DONTPASS, OBP_SIZE_PROP_NAME, 0); + } else { + cmn_err(CE_CONT, "%s: missing OBP properties\n", + name); goto attach_failed; } - nep /= sizeof (*ep); - - /* - * Calculate the size of the ramdisk. - */ - for (i = 0; i < nep; ++i) { - size += ep[i].size; - } /* * Allocate driver resources for the ramdisk. */ - if ((rsp = rd_alloc_resources(name, size, + if ((rsp = rd_alloc_resources(name, obpaddr, size, dip)) == NULL) { goto attach_failed; } @@ -1164,7 +1180,7 @@ rd_create_disk(dev_t dev, struct rd_ioctl *urip, int mode, int *rvalp) return (EEXIST); } - rsp = rd_alloc_resources(kri.ri_name, size, rd_dip); + rsp = rd_alloc_resources(kri.ri_name, 0, size, rd_dip); if (rsp == NULL) { mutex_exit(&rd_lock); return (EAGAIN); @@ -1337,7 +1353,7 @@ extern struct mod_ops mod_driverops; static struct modldrv modldrv = { &mod_driverops, - "ramdisk driver v%I%", + "ramdisk driver", &rd_ops }; diff --git a/usr/src/uts/common/io/strplumb.c b/usr/src/uts/common/io/strplumb.c index 8243f9263f..80f4850622 100644 --- a/usr/src/uts/common/io/strplumb.c +++ b/usr/src/uts/common/io/strplumb.c @@ -96,7 +96,7 @@ int strplumbdebug = 0; /* * Module linkage information for the kernel. */ -#define STRPLUMB_IDENT "STREAMS Plumbing Module v%I%" +#define STRPLUMB_IDENT "STREAMS Plumbing Module" static struct modlmisc modlmisc = { &mod_miscops, @@ -339,10 +339,22 @@ resolve_boot_path(void) dev_info_t *dip; const char *driver; int instance; +#ifdef _OBP + char stripped_path[OBP_MAXPATHLEN]; +#endif +#ifdef _OBP + /* + * OBP passes options e.g, "net:dhcp" + * remove them here + */ + if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) { + prom_strip_options(rootfs.bo_name, stripped_path); + devpath = stripped_path; + } +#else if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) devpath = rootfs.bo_name; -#ifndef __sparc else devpath = strplumb_get_netdev_path(); #endif @@ -614,7 +626,7 @@ done: /* multiboot: diskless boot interface discovery */ -#ifndef __sparc +#ifndef _OBP static uchar_t boot_macaddr[16]; static int boot_maclen; @@ -625,15 +637,15 @@ int dl_bind(ldi_handle_t lh, uint_t sap, uint_t max_conn, uint_t service, uint_t conn_mgmt); int dl_phys_addr(ldi_handle_t lh, struct ether_addr *eaddr); -#endif /* !__sparc */ +#endif /* !_OBP */ char * strplumb_get_netdev_path(void) { -#ifndef __sparc +#ifndef _OBP char *macstr, *devpath = NULL; uchar_t *bootp; - uint_t bootp_len, len; + uint_t bootp_len; if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), DDI_PROP_DONTPASS, BP_BOOT_MAC, &macstr) == DDI_SUCCESS) { @@ -658,14 +670,12 @@ strplumb_get_netdev_path(void) */ boot_maclen = *(bootp + 2); ASSERT(boot_maclen <= 16); - (void) bcopy(bootp + 28, boot_macaddr, boot_maclen); - - /* encode to ascii string to match what sparc OBP exports */ - dhcack = kmem_zalloc(bootp_len * 2 + IFNAMSIZ + 2, KM_SLEEP); - len = bootp_len * 2 + 2; - (void) octet_to_hexascii(bootp, bootp_len, dhcack + IFNAMSIZ, - &len); - ASSERT(len < bootp_len * 2 + 2); + bcopy(bootp + 28, boot_macaddr, boot_maclen); + + dhcack = kmem_alloc(bootp_len, KM_SLEEP); + bcopy(bootp, dhcack, bootp_len); + dhcacklen = bootp_len; + ddi_prop_free(bootp); } else return (NULL); @@ -675,10 +685,10 @@ strplumb_get_netdev_path(void) #else return (NULL); -#endif /* !__sparc */ +#endif /* !_OBP */ } -#ifndef __sparc +#ifndef _OBP /* * Get boot path from the boot_mac address @@ -726,10 +736,11 @@ matchmac(dev_info_t *dip, void *arg) *devpathp = kmem_alloc(MAXPATHLEN, KM_SLEEP); (void) ddi_pathname(dip, *devpathp); - /* fill in the name portion of dhcack */ - if (dhcack) - (void) snprintf(dhcack, IFNAMSIZ, "%s%d", + /* fill in dhcifname */ + if (dhcack) { + (void) snprintf(dhcifname, IFNAMSIZ, "%s%d", ddi_driver_name(dip), i_ddi_devi_get_ppa(dip)); + } return (DDI_WALK_TERMINATE); } @@ -812,7 +823,7 @@ getmacaddr(dev_info_t *dip, int *maclenp) return (macaddr); } -#endif /* !__sparc */ +#endif /* !_OBP */ int dl_attach(ldi_handle_t lh, int unit) diff --git a/usr/src/uts/common/krtld/kobj.c b/usr/src/uts/common/krtld/kobj.c index deffd012bd..64a3648741 100644 --- a/usr/src/uts/common/krtld/kobj.c +++ b/usr/src/uts/common/krtld/kobj.c @@ -61,16 +61,18 @@ #include <sys/varargs.h> #include <sys/kstat.h> #include <sys/kobj_impl.h> +#include <sys/fs/decomp.h> #include <sys/callb.h> #include <sys/cmn_err.h> #include <sys/tnf_probe.h> +#include <sys/zmod.h> -#include <reloc.h> -#include <kobj_kdi.h> +#include <krtld/reloc.h> +#include <krtld/kobj_kdi.h> #include <sys/sha1.h> #include <sys/crypto/elfsign.h> -#if !defined(__sparc) +#if !defined(_OBP) #include <sys/bootvfs.h> #endif @@ -80,7 +82,10 @@ #define DOSYM_UNDEF -1 /* undefined symbol */ #define DOSYM_UNSAFE -2 /* MT-unsafe driver symbol */ +#if !defined(_OBP) static void synthetic_bootaux(char *, val_t *); +#endif + static struct module *load_exec(val_t *, char *); static void load_linker(val_t *); static struct modctl *add_primary(const char *filename, int); @@ -104,19 +109,20 @@ static void attr_val(val_t *); static char *find_libmacro(char *); static char *expand_libmacro(char *, char *, char *); static int read_bootflags(void); +static int kobj_comp_setup(struct _buf *, struct compinfo *); +static int kobj_uncomp_blk(struct _buf *, caddr_t, uint_t); +static int kobj_read_blks(struct _buf *, caddr_t, uint_t, uint_t); static int kobj_boot_open(char *, int); static int kobj_boot_close(int); static int kobj_boot_seek(int, off_t, off_t); static int kobj_boot_read(int, caddr_t, size_t); static int kobj_boot_fstat(int, struct bootstat *); +static int kobj_boot_compinfo(int, struct compinfo *); static Sym *lookup_one(struct module *, const char *); static void sym_insert(struct module *, char *, symid_t); static Sym *sym_lookup(struct module *, Sym *); -/*PRINTFLIKE2*/ -static void kprintf(void *, const char *, ...) __KPRINTFLIKE(2); - static struct kobjopen_tctl *kobjopen_alloc(char *filename); static void kobjopen_free(struct kobjopen_tctl *ltp); static void kobjopen_thread(struct kobjopen_tctl *ltp); @@ -125,13 +131,22 @@ extern int kcopy(const void *, void *, size_t); extern int elf_mach_ok(Ehdr *); extern int alloc_gottable(struct module *, caddr_t *, caddr_t *); -static void tnf_unsplice_probes(unsigned int, struct modctl *); +#if !defined(_OBP) +extern int kobj_boot_mountroot(void); +#endif + +static void tnf_unsplice_probes(uint_t, struct modctl *); +extern tnf_probe_control_t *__tnf_probe_list_head; +extern tnf_tag_data_t *__tnf_tag_list_head; extern int modrootloaded; extern int swaploaded; extern int bop_io_quiesced; extern int last_module_id; +extern char stubs_base[]; +extern char stubs_end[]; + #ifdef KOBJ_DEBUG /* * Values that can be or'd in to kobj_debug and their effects: @@ -198,10 +213,6 @@ struct lib_macro_info { char *boot_cpu_compatible_list; /* make $CPU available */ -#ifdef MPSAS -void sas_prisyms(struct modctl_list *); -void sas_syms(struct module *); -#endif char *kobj_module_path; /* module search path */ vmem_t *text_arena; /* module text arena */ @@ -256,17 +267,6 @@ int tnf_changed_probe_list = 0; */ const char *sdt_prefix = "__dtrace_probe_"; -#if defined(__sparc) -/* - * Some PROMs return SUNW,UltraSPARC when they actually have - * SUNW,UltraSPARC-II cpus. SInce we're now filtering out all - * SUNW,UltraSPARC systems during the boot phase, we can safely - * point the auxv CPU value at SUNW,UltraSPARC-II. This is what - * we point it at. - */ -const char *ultra_2 = "SUNW,UltraSPARC-II"; -#endif - /* * Beginning and end of the kernel's dynamic text/data segments. */ @@ -275,14 +275,21 @@ static caddr_t _etext; static caddr_t _data; /* - * XXX Hmm. The sparc linker fails to define this symbol. + * The sparc linker doesn't create a memory location + * for a variable named _edata, so _edata can only be + * referred to, not modified. krtld needs a static + * variable to modify it - within krtld, of course - + * outside of krtld, e_data is used in all kernels. */ -#if !defined(__sparc) -extern +#if defined(__sparc) +static caddr_t _edata; +#else +extern caddr_t _edata; #endif -caddr_t _edata; -static Addr dynseg = 0; /* load address of "dynamic" segment */ +Addr dynseg = 0; /* load address of "dynamic" segment */ +size_t dynsize; /* "dynamic" segment size */ + int standalone = 1; /* an unwholey kernel? */ int use_iflush; /* iflush after relocations */ @@ -297,6 +304,17 @@ int use_iflush; /* iflush after relocations */ */ void (*_kobj_printf)(void *, const char *, ...); /* printf routine */ +/* + * Standalone function pointers for use within krtld. + * Many platforms implement optimized platmod versions of + * utilities such as bcopy and any such are not yet available + * until the kernel is more completely stitched together. + * See kobj_impl.h + */ +void (*kobj_bcopy)(const void *, void *, size_t); +void (*kobj_bzero)(void *, size_t); +size_t (*kobj_strlcat)(char *, const char *, size_t); + static kobj_stat_t kobj_stat; #define MINALIGN 8 /* at least a double-word */ @@ -359,39 +377,9 @@ kobj_init( dbvec = dvec; ops = bootvec; -#if defined(__i386) || defined(__amd64) - _kobj_printf = (void (*)(void *, const char *, ...))ops->bsys_printf; -#else - _kobj_printf = (void (*)(void *, const char *, ...))bop_putsarg; -#endif - KOBJ_MARK("Entered kobj_init()"); - -#if defined(__sparc) - /* XXXQ should suppress this test on sun4v */ - if (bootaux[BA_CPU].ba_ptr) { - if (strcmp("SUNW,UltraSPARC", bootaux[BA_CPU].ba_ptr) == 0) { - bootaux[BA_CPU].ba_ptr = (void *) ultra_2; - } - } -#endif + kobj_setup_standalone_vectors(); - /* - * Check bootops version. - */ - if (BOP_GETVERSION(ops) != BO_VERSION) { - _kobj_printf(ops, "Warning: Using boot version %d, ", - BOP_GETVERSION(ops)); - _kobj_printf(ops, "expected %d\n", BO_VERSION); - } -#ifdef KOBJ_DEBUG - else if (kobj_debug & D_DEBUG) { - /* - * Say -something- so we know we got this far .. - */ - _kobj_printf(ops, "krtld: Using boot version %d.\n", - BOP_GETVERSION(ops)); - } -#endif + KOBJ_MARK("Entered kobj_init()"); (void) BOP_GETPROP(ops, "whoami", filename); @@ -410,10 +398,21 @@ kobj_init( goto fail; } -#ifndef __sparc +#if defined(_OBP) + /* + * OBP allows us to read both the ramdisk and + * the underlying root fs when root is a disk. + * This can lower incidences of unbootable systems + * when the archive is out-of-date with the /etc + * state files. + */ + if (BOP_MOUNTROOT() != BOOT_SVC_OK) { + _kobj_printf(ops, "can't mount boot fs\n"); + goto fail; + } +#else { /* on x86, we always boot with a ramdisk */ - extern int kobj_boot_mountroot(void); (void) kobj_boot_mountroot(); /* @@ -422,11 +421,10 @@ kobj_init( */ boot_prop_finish(); } -#endif #if !defined(_UNIX_KRTLD) /* - * If 'unix' is linked together with 'krtld' into one executable, + * 'unix' is linked together with 'krtld' into one executable and * the early boot code does -not- hand us any of the dynamic metadata * about the executable. In particular, it does not read in, map or * otherwise look at the program headers. We fake all that up now. @@ -434,10 +432,15 @@ kobj_init( * We do this early as DTrace static probes and tnf probes both call * undefined references. We have to process those relocations before * calling any of them. + * + * OBP tells kobj_start() where the ELF image is in memory, so it + * synthesized bootaux before kobj_init() was called */ if (bootaux[BA_PHDR].ba_ptr == NULL) synthetic_bootaux(filename, bootaux); -#endif + +#endif /* !_UNIX_KRTLD */ +#endif /* _OBP */ /* * Save the interesting attribute-values @@ -476,15 +479,6 @@ kobj_init( entry = bootaux[BA_ENTRY].ba_val; -#ifdef __sparc - /* - * On sparcv9, boot scratch memory is running out. - * Free the temporary allocations here to allow boot - * to continue. - */ - kobj_tmp_free(); -#endif - /* * Get the boot flags */ @@ -503,9 +497,6 @@ kobj_init( /* * Post setup. */ -#ifdef MPSAS - sas_prisyms(kobj_lm_lookup(KOBJ_LM_PRIMARY)); -#endif s_text = _text; e_text = _etext; s_data = _data; @@ -534,17 +525,28 @@ kobj_init( standalone = 0; -#ifdef __sparc +#ifdef KOBJ_DEBUG + if (kobj_debug & D_DEBUG) + _kobj_printf(ops, + "krtld: really transferring control to: 0x%p\n", entry); +#endif + + /* restore printf/bcopy/bzero vectors before returning */ + kobj_restore_vectors(); + +#if defined(_DBOOT) /* - * On sparcv9, boot scratch memory is running out. - * Free the temporary allocations here to allow boot - * to continue. + * krtld was called from a dboot ELF section, the embedded + * dboot code contains the real entry via bootaux */ - kobj_tmp_free(); + exitto((caddr_t)entry); +#else + /* + * krtld was directly called from startup + */ + return; #endif - _kobj_printf = kprintf; - exitto((caddr_t)entry); fail: _kobj_printf(ops, "krtld: error during initial load/link phase\n"); @@ -563,9 +565,10 @@ fail: #endif } -#if !defined(_UNIX_KRTLD) +#if !defined(_UNIX_KRTLD) && !defined(_OBP) /* - * Synthesize additional metadata that describes the executable. + * Synthesize additional metadata that describes the executable if + * krtld's caller didn't do it. * * (When the dynamic executable has an interpreter, the boot program * does all this for us. Where we don't have an interpreter, (or a @@ -627,7 +630,7 @@ synthetic_bootaux(char *filename, val_t *bootaux) } KOBJ_MARK("synthetic_bootaux() done"); } -#endif +#endif /* !_UNIX_KRTLD && !_OBP */ /* * Set up any global information derived @@ -652,14 +655,22 @@ attr_val(val_t *bootaux) for (i = 0; i < phnum; i++) { phdr = (Phdr *)(bootaux[BA_PHDR].ba_val + i * phsize); - if (phdr->p_type != PT_LOAD) + if (phdr->p_type != PT_LOAD) { continue; + } /* * Bounds of the various segments. */ if (!(phdr->p_flags & PF_X)) { -#if defined(_UNIX_KRTLD) +#if defined(_RELSEG) + /* + * sparc kernel puts the dynamic info + * into a separate segment, which is + * free'd in bop_fini() + */ + ASSERT(phdr->p_vaddr != 0); dynseg = phdr->p_vaddr; + dynsize = phdr->p_memsz; #else ASSERT(phdr->p_vaddr == 0); #endif @@ -699,11 +710,7 @@ load_exec(val_t *bootaux, char *filename) Sym *sp; int i, lsize, osize, nsize, allocsize; char *libname, *tmp; - - /* - * Set the module search path. - */ - kobj_module_path = getmodpath(filename); + char path[MAXPATHLEN]; #ifdef KOBJ_DEBUG if (kobj_debug & D_DEBUG) @@ -745,17 +752,14 @@ load_exec(val_t *bootaux, char *filename) dyn->d_tag != DT_NULL; dyn++) { switch (dyn->d_tag) { case DT_SYMTAB: - dyn->d_un.d_ptr += dynseg; mp->symspace = mp->symtbl = (char *)dyn->d_un.d_ptr; mp->symhdr->sh_addr = dyn->d_un.d_ptr; break; case DT_HASH: - dyn->d_un.d_ptr += dynseg; mp->nsyms = *((uint_t *)dyn->d_un.d_ptr + 1); mp->hashsize = *(uint_t *)dyn->d_un.d_ptr; break; case DT_STRTAB: - dyn->d_un.d_ptr += dynseg; mp->strings = (char *)dyn->d_un.d_ptr; mp->strhdr->sh_addr = dyn->d_un.d_ptr; break; @@ -785,7 +789,7 @@ load_exec(val_t *bootaux, char *filename) libname = mp->strings + dyn->d_un.d_val; if (strchr(libname, '$') != NULL) { if ((_lib = expand_libmacro(libname, - filename, filename)) != NULL) + path, path)) != NULL) libname = _lib; else _kobj_printf(ops, "krtld: " @@ -863,7 +867,7 @@ load_exec(val_t *bootaux, char *filename) if (sp->st_name == 0 || sp->st_shndx == SHN_UNDEF) continue; -#ifdef __sparc +#if defined(__sparc) /* * Register symbols are ignored in the kernel */ @@ -1063,67 +1067,21 @@ kobj_notify(int type, struct modctl *modp) } /* - * Ask boot for the module path. + * Create the module path. */ -/*ARGSUSED*/ static char * getmodpath(const char *filename) { - char *path; - int len; - -#if defined(_UNIX_KRTLD) - /* - * The boot program provides the module name when it detects - * that the executable has an interpreter, thus we can ask - * it directly in this case. - */ - if ((len = BOP_GETPROPLEN(ops, MODPATH_PROPNAME)) == -1) - return (MOD_DEFPATH); - - path = kobj_zalloc(len, KM_WAIT); - - (void) BOP_GETPROP(ops, MODPATH_PROPNAME, path); - - return (*path ? path : MOD_DEFPATH); - -#else + char *path = kobj_zalloc(MAXPATHLEN, KM_WAIT); /* - * Construct the directory path from the filename. + * Platform code gets first crack, then add + * the default components */ - - char *p; - const char isastr[] = "/amd64"; - size_t isalen = strlen(isastr); - - if ((p = strrchr(filename, '/')) == NULL) - return (MOD_DEFPATH); - - while (p > filename && *(p - 1) == '/') - p--; /* remove trailing '/' characters */ - if (p == filename) - p++; /* so "/" -is- the modpath in this case */ - - /* - * Remove optional isa-dependent directory name - the module - * subsystem will put this back again (!) - */ - len = p - filename; - if (len > isalen && - strncmp(&filename[len - isalen], isastr, isalen) == 0) - p -= isalen; - - /* - * "/platform/mumblefrotz" + " " + MOD_DEFPATH - */ - len += (p - filename) + 1 + strlen(MOD_DEFPATH) + 1; - - path = kobj_zalloc(len, KM_WAIT); - (void) strncpy(path, filename, p - filename); - (void) strcat(path, " "); + mach_modpath(path, filename); + if (*path != '\0') + (void) strcat(path, " "); return (strcat(path, MOD_DEFPATH)); -#endif } static struct modctl * @@ -1230,13 +1188,11 @@ bind_primary(val_t *bootaux, int lmid) break; case DT_RELA: shtype = SHT_RELA; - rela = (char *)(dyn->d_un.d_ptr + - dynseg); + rela = (char *)dyn->d_un.d_ptr; break; case DT_REL: shtype = SHT_REL; - rela = (char *)(dyn->d_un.d_ptr + - dynseg); + rela = (char *)dyn->d_un.d_ptr; break; } } @@ -2105,9 +2061,6 @@ kobj_load_module(struct modctl *modp, int use_path) /* sync_instruction_memory */ kobj_sync_instruction_memory(mp->text, mp->text_size); -#ifdef MPSAS - sas_syms(mp); -#endif kobj_export_module(mp); kobj_notify(KOBJ_NOTIFY_MODLOADED, modp); } @@ -2312,9 +2265,9 @@ get_progbits(struct module *mp, struct _buf *file) uint_t shn; int err = -1; - tp = kobj_zalloc(sizeof (struct proginfo), KM_WAIT); - dp = kobj_zalloc(sizeof (struct proginfo), KM_WAIT); - sdp = kobj_zalloc(sizeof (struct proginfo), KM_WAIT); + tp = kobj_zalloc(sizeof (struct proginfo), KM_WAIT|KM_TMP); + dp = kobj_zalloc(sizeof (struct proginfo), KM_WAIT|KM_TMP); + sdp = kobj_zalloc(sizeof (struct proginfo), KM_WAIT|KM_TMP); /* * loop through sections to find out how much space we need * for text, data, (also bss that is already assigned) @@ -2513,7 +2466,6 @@ get_syms(struct module *mp, struct _buf *file) Sym *sp, *ksp; char *symname; int dosymtab = 0; - extern char stubs_base[], stubs_end[]; /* * Find the interesting sections. @@ -2534,6 +2486,8 @@ get_syms(struct module *mp, struct _buf *file) */ if (shp->sh_addr) continue; + + /* KM_TMP since kobj_free'd in do_relocations */ shp->sh_addr = (Addr) kobj_alloc(shp->sh_size, KM_WAIT|KM_TMP); @@ -3028,7 +2982,7 @@ do_symbols(struct module *mp, Elf64_Addr bss_base) name = mp->strings + sp->st_name; if (sp->st_shndx != SHN_UNDEF && sp->st_shndx != SHN_COMMON) continue; -#ifdef __sparc +#if defined(__sparc) /* * Register symbols are ignored in the kernel */ @@ -3127,7 +3081,7 @@ do_symbols(struct module *mp, Elf64_Addr bss_base) uint_t kobj_hash_name(const char *p) { - unsigned int g; + uint_t g; uint_t hval; hval = 0; @@ -3661,7 +3615,7 @@ kobjopen_free(struct kobjopen_tctl *ltp) } int -kobj_read(intptr_t descr, char *buf, unsigned size, unsigned offset) +kobj_read(intptr_t descr, char *buf, uint_t size, uint_t offset) { int stat; ssize_t resid; @@ -3755,6 +3709,7 @@ struct _buf * kobj_open_file(char *name) { struct _buf *file; + struct compinfo cbuf; intptr_t fd; if ((fd = kobj_open(name)) == -1) { @@ -3764,25 +3719,80 @@ kobj_open_file(char *name) file = kobj_zalloc(sizeof (struct _buf), KM_WAIT|KM_TMP); file->_fd = fd; file->_name = kobj_alloc(strlen(name)+1, KM_WAIT|KM_TMP); - file->_base = kobj_zalloc(MAXBSIZE, KM_WAIT|KM_TMP); file->_cnt = file->_size = file->_off = 0; file->_ln = 1; file->_ptr = file->_base; (void) strcpy(file->_name, name); + + /* + * Before root is mounted, we must check + * for a compressed file and do our own + * buffering. + */ + if (_modrootloaded) { + file->_base = kobj_zalloc(MAXBSIZE, KM_WAIT); + file->_bsize = MAXBSIZE; + } else { + if (kobj_boot_compinfo(fd, &cbuf) != 0) { + kobj_close_file(file); + return ((struct _buf *)-1); + } + file->_iscmp = cbuf.iscmp; + if (file->_iscmp) { + if (kobj_comp_setup(file, &cbuf) != 0) { + kobj_close_file(file); + return ((struct _buf *)-1); + } + } else { + file->_base = kobj_zalloc(cbuf.blksize, KM_WAIT|KM_TMP); + file->_bsize = cbuf.blksize; + } + } return (file); } +static int +kobj_comp_setup(struct _buf *file, struct compinfo *cip) +{ + struct comphdr *hdr; + + /* + * read the compressed image into memory, + * so we can deompress from there + */ + file->_dsize = cip->fsize; + file->_dbuf = kobj_alloc(cip->fsize, KM_WAIT|KM_TMP); + if (kobj_read(file->_fd, file->_dbuf, cip->fsize, 0) != cip->fsize) { + kobj_free(file->_dbuf, cip->fsize); + return (-1); + } + + hdr = kobj_comphdr(file); + if (hdr->ch_magic != CH_MAGIC || hdr->ch_version != CH_VERSION || + hdr->ch_algorithm != CH_ALG_ZLIB || hdr->ch_fsize == 0 || + (hdr->ch_blksize & (hdr->ch_blksize - 1)) != 0) { + kobj_free(file->_dbuf, cip->fsize); + return (-1); + } + file->_base = kobj_alloc(hdr->ch_blksize, KM_WAIT|KM_TMP); + file->_bsize = hdr->ch_blksize; + return (0); +} + void kobj_close_file(struct _buf *file) { kobj_close(file->_fd); - kobj_free(file->_base, MAXBSIZE); + if (file->_base != NULL) + kobj_free(file->_base, file->_bsize); + if (file->_dbuf != NULL) + kobj_free(file->_dbuf, file->_dsize); kobj_free(file->_name, strlen(file->_name)+1); kobj_free(file, sizeof (struct _buf)); } int -kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off) +kobj_read_file(struct _buf *file, char *buf, uint_t size, uint_t off) { int b_size, c_size; int b_off; /* Offset into buffer for start of bcopy */ @@ -3796,7 +3806,7 @@ kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off) } while (size) { - page_addr = F_PAGE(off); + page_addr = F_PAGE(file, off); b_size = file->_size; /* * If we have the filesystem page the caller's referring to @@ -3804,7 +3814,7 @@ kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off) * satisfy as much of the request from the buffer as we can. */ if (page_addr == file->_off && b_size > 0) { - b_off = B_OFFSET(off); + b_off = B_OFFSET(file, off); c_size = b_size - b_off; /* * If there's nothing to copy, we're at EOF. @@ -3835,15 +3845,15 @@ kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off) * read directly into the caller's buffer. */ if (page_addr == off && - (c_size = F_PAGE(size)) && buf) { - c_size = kobj_read(file->_fd, buf, c_size, + (c_size = F_BLKS(file, size)) && buf) { + c_size = kobj_read_blks(file, buf, c_size, page_addr); if (c_size < 0) { count = -1; break; } count += c_size; - if (c_size != F_PAGE(size)) + if (c_size != F_BLKS(file, size)) break; size -= c_size; off += c_size; @@ -3854,8 +3864,8 @@ kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off) */ } else { file->_off = page_addr; - c_size = kobj_read(file->_fd, file->_base, - MAXBSIZE, page_addr); + c_size = kobj_read_blks(file, file->_base, + file->_bsize, page_addr); file->_ptr = file->_base; file->_cnt = c_size; file->_size = c_size; @@ -3877,10 +3887,56 @@ kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off) return (count); } +static int +kobj_read_blks(struct _buf *file, char *buf, uint_t size, uint_t off) +{ + int ret; + + ASSERT(B_OFFSET(file, size) == 0 && B_OFFSET(file, off) == 0); + if (file->_iscmp) { + uint_t blks; + int nret; + + ret = 0; + for (blks = size / file->_bsize; blks != 0; blks--) { + nret = kobj_uncomp_blk(file, buf, off); + if (nret == -1) + return (-1); + buf += nret; + off += nret; + ret += nret; + if (nret < file->_bsize) + break; + } + } else + ret = kobj_read(file->_fd, buf, size, off); + return (ret); +} + +static int +kobj_uncomp_blk(struct _buf *file, char *buf, uint_t off) +{ + struct comphdr *hdr = kobj_comphdr(file); + ulong_t dlen, slen; + caddr_t src; + int i; + + dlen = file->_bsize; + i = off / file->_bsize; + src = file->_dbuf + hdr->ch_blkmap[i]; + if (i == hdr->ch_fsize / file->_bsize) + slen = hdr->ch_fsize - hdr->ch_blkmap[i]; + else + slen = hdr->ch_blkmap[i + 1] - hdr->ch_blkmap[i]; + if (z_uncompress(buf, &dlen, src, slen) != Z_OK) + return (-1); + return (dlen); +} + int kobj_filbuf(struct _buf *f) { - if (kobj_read_file(f, NULL, MAXBSIZE, f->_off + f->_size) > 0) + if (kobj_read_file(f, NULL, f->_bsize, f->_off + f->_size) > 0) return (kobj_getc(f)); return (-1); } @@ -3919,23 +3975,10 @@ kobj_alloc(size_t size, int flag) * permanently using the dynamic data segment. */ if (standalone) { -#ifdef __sparc - if (flag & KM_TMP) { - return (kobj_tmp_alloc(size)); - } else if (flag & KM_SCRATCH) { - void *buf = kobj_bs_alloc(size); - - if (buf != NULL) - return (buf); -#ifdef KOBJ_DEBUG - if (kobj_debug & D_DEBUG) { - _kobj_printf(ops, "krtld: failed scratch alloc " - "of %lu bytes -- falling back\n", size); - } -#endif - } - -#else /* x86 */ +#if defined(_OBP) + if (flag & (KM_TMP | KM_SCRATCH)) + return (bop_temp_alloc(size, MINALIGN)); +#else if (flag & (KM_TMP | KM_SCRATCH)) return (BOP_ALLOC(ops, 0, size, MINALIGN)); #endif @@ -4068,6 +4111,19 @@ kobj_get_filesize(struct _buf *file, uint64_t *size) return (EIO); *size = bst.st_size; } else { + +#if defined(_OBP) + struct bootstat bsb; + + if (file->_iscmp) { + struct comphdr *hdr = kobj_comphdr(file); + + *size = hdr->ch_fsize; + } else if (kobj_boot_fstat(file->_fd, &bsb) != 0) + return (EIO); + else + *size = bsb.st_size; +#else char *buf; int count; uint64_t offset = 0; @@ -4084,6 +4140,7 @@ kobj_get_filesize(struct _buf *file, uint64_t *size) kmem_free(buf, MAXBSIZE); *size = offset; +#endif } return (0); @@ -4103,17 +4160,6 @@ basename(char *s) return (q ? q + 1 : s); } -/*ARGSUSED*/ -static void -kprintf(void *op, const char *fmt, ...) -{ - va_list adx; - - va_start(adx, fmt); - vprintf(fmt, adx); - va_end(adx); -} - void kobj_stat_get(kobj_stat_t *kp) { @@ -4327,10 +4373,8 @@ tnf_add_notifyunload(kobj_notify_f *fp) /* ARGSUSED */ static void -tnf_unsplice_probes(unsigned int what, struct modctl *mod) +tnf_unsplice_probes(uint_t what, struct modctl *mod) { - extern tnf_probe_control_t *__tnf_probe_list_head; - extern tnf_tag_data_t *__tnf_tag_list_head; tnf_probe_control_t **p; tnf_tag_data_t **q; struct module *mp = mod->mod_mp; @@ -4397,7 +4441,9 @@ tnf_splice_probes(int boot_load, tnf_probe_control_t *plist, return (result); } -#if defined(__x86) +char *kobj_file_buf; +int kobj_file_bufsize; + /* * This code is for the purpose of manually recording which files * needs to go into the boot archive on any given system. @@ -4408,15 +4454,10 @@ tnf_splice_probes(int boot_load, tnf_probe_control_t *plist, static void kobj_record_file(char *filename) { - extern char *kobj_file_buf; - extern int kobj_file_bufsize; static char *buf; static int size = 0; int n; - if (standalone) /* kernel symbol not available */ - return; - if (kobj_file_bufsize == 0) /* don't bother */ return; @@ -4431,12 +4472,11 @@ kobj_record_file(char *filename) size -= n; buf += n; } -#endif /* __x86 */ static int kobj_boot_fstat(int fd, struct bootstat *stp) { -#if defined(__sparc) +#if defined(_OBP) if (!standalone && _ioquiesced) return (-1); return (BOP_FSTAT(ops, fd, stp)); @@ -4445,14 +4485,11 @@ kobj_boot_fstat(int fd, struct bootstat *stp) #endif } -/* - * XXX these wrappers should go away when sparc is converted - * boot from ramdisk - */ static int kobj_boot_open(char *filename, int flags) { -#if defined(__sparc) +#if defined(_OBP) + /* * If io via bootops is quiesced, it means boot is no longer * available to us. We make it look as if we can't open the @@ -4461,7 +4498,8 @@ kobj_boot_open(char *filename, int flags) if (!standalone && _ioquiesced) return (-1); - return (BOP_OPEN(ops, filename, flags)); + kobj_record_file(filename); + return (BOP_OPEN(filename, flags)); #else /* x86 */ kobj_record_file(filename); return (BRD_OPEN(bfs_ops, filename, flags)); @@ -4471,11 +4509,11 @@ kobj_boot_open(char *filename, int flags) static int kobj_boot_close(int fd) { -#if defined(__sparc) +#if defined(_OBP) if (!standalone && _ioquiesced) return (-1); - return (BOP_CLOSE(ops, fd)); + return (BOP_CLOSE(fd)); #else /* x86 */ return (BRD_CLOSE(bfs_ops, fd)); #endif @@ -4485,8 +4523,8 @@ kobj_boot_close(int fd) static int kobj_boot_seek(int fd, off_t hi, off_t lo) { -#if defined(__sparc) - return (BOP_SEEK(ops, fd, hi, lo)); +#if defined(_OBP) + return (BOP_SEEK(fd, lo) == -1 ? -1 : 0); #else return (BRD_SEEK(bfs_ops, fd, lo, SEEK_SET)); #endif @@ -4495,9 +4533,15 @@ kobj_boot_seek(int fd, off_t hi, off_t lo) static int kobj_boot_read(int fd, caddr_t buf, size_t size) { -#if defined(__sparc) - return (BOP_READ(ops, fd, buf, size)); +#if defined(_OBP) + return (BOP_READ(fd, buf, size)); #else return (BRD_READ(bfs_ops, fd, buf, size)); #endif } + +static int +kobj_boot_compinfo(int fd, struct compinfo *cb) +{ + return (boot_compinfo(fd, cb)); +} diff --git a/usr/src/uts/common/krtld/kobj_bootflags.c b/usr/src/uts/common/krtld/kobj_bootflags.c index 68cc7a41b4..681f80e362 100644 --- a/usr/src/uts/common/krtld/kobj_bootflags.c +++ b/usr/src/uts/common/krtld/kobj_bootflags.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -51,25 +51,37 @@ bootflags(struct bootops *ops) int c; char scratch[BOOTARGS_MAX]; - if (BOP_GETPROP(ops, "boot-args", kern_bootargs) != 0) { + if (BOP_GETPROP(ops, "bootargs", kern_bootargs) == -1) { boothowto |= RB_ASKNAME; return; } cp = kern_bootargs; -#if !defined(__i386) && !defined(__amd64) +#if defined(_OBP) /* * x86: The boot scripts (i.e., /etc/bootrc) don't prepend the kernel * name to the boot arguments. (And beware making it do so: if the * run-kernel command returns, it will loop, and you will end up with * multiple copies of the kernel name.) */ - SKIP_WORD(cp); /* Skip the kernel's filename. */ + if (cp[0] != '-') { + /* if user booted kadb or kmdb, load kmdb */ + if (cp[0] == 'k' && (cp[1] == 'a' || cp[1] == 'm') && + cp[2] == 'd' && cp[3] == 'b' && + (cp[4] == ' ' || cp[4] == ' ' || cp[4] == 0)) + boothowto |= RB_KMDB; + SKIP_WORD(cp); /* Skip the kernel's filename. */ + } #endif SKIP_SPC(cp); +#if defined(_OBP) + /* skip bootblk args */ + params.gos_opts = "abcdDF:gGHhi:km:o:O:rsvVwx"; +#else params.gos_opts = "abcdgGhi:km:O:rsvwx"; +#endif params.gos_strp = cp; getoptstr_init(¶ms); while ((c = getoptstr(¶ms)) != -1) { @@ -87,6 +99,11 @@ bootflags(struct bootops *ops) case 'd': boothowto |= RB_DEBUGENTER; break; +#if defined(_OBP) + case 'D': + case 'F': + break; +#endif case 'g': boothowto |= RB_FORTHDEBUG; break; @@ -96,6 +113,10 @@ bootflags(struct bootops *ops) case 'h': boothowto |= RB_HALT; break; +#if defined(_OBP) + case 'H': + break; +#endif case 'i': if (params.gos_optarglen + 1 > sizeof (initname)) { _kobj_printf(ops, "krtld: initname too long. " @@ -122,9 +143,15 @@ bootflags(struct bootops *ops) params.gos_optarglen); scratch[params.gos_optarglen] = '\0'; (void) strlcat(initargs, "-m ", sizeof (initargs)); - (void) strlcat(initargs, scratch, sizeof (initargs)); + (void) strlcat(initargs, scratch, + sizeof (initargs)); (void) strlcat(initargs, " ", sizeof (initargs)); break; +#if defined(_OBP) + /* Ignore argument meant for wanboot standalone */ + case 'o': + break; +#endif case 'O': { char **str = &kobj_kmdb_argv[num_O_opt]; @@ -169,6 +196,10 @@ bootflags(struct bootops *ops) boothowto |= RB_VERBOSE; (void) strlcat(initargs, "-v ", sizeof (initargs)); break; +#if defined(_OBP) + case 'V': + break; +#endif case 'w': boothowto |= RB_WRITABLE; break; diff --git a/usr/src/uts/common/krtld/kobj_kdi.c b/usr/src/uts/common/krtld/kobj_kdi.c index c094e30d06..f843158535 100644 --- a/usr/src/uts/common/krtld/kobj_kdi.c +++ b/usr/src/uts/common/krtld/kobj_kdi.c @@ -76,7 +76,7 @@ #include <sys/reboot.h> #include <sys/kdi_impl.h> -#include <kobj_kdi.h> +#include <krtld/kobj_kdi.h> #define KOBJ_KDI_MOD_IDLE 0 #define KOBJ_KDI_MOD_CHANGING 1 diff --git a/usr/src/uts/common/krtld/kobj_subr.c b/usr/src/uts/common/krtld/kobj_subr.c index a949922fe0..761c8b69f6 100644 --- a/usr/src/uts/common/krtld/kobj_subr.c +++ b/usr/src/uts/common/krtld/kobj_subr.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -29,93 +29,61 @@ #include <sys/param.h> #include <sys/systm.h> -/* - * Standalone copies of some basic routines. Note that these routines - * are transformed via Makefile -D flags into krtld_* routines. So, - * this version of strcmp() will become krtld_strcmp() when built. - * - * This dubious practice is so that krtld can have its own private - * versions of these routines suitable for use during early boot, - * when kernel-based routines might not work. Make sure to use 'nm' - * on your krtld to make sure it is calling the appropriate routines. - */ - -int -strcmp(const char *s1, const char *s2) -{ - if (s1 == s2) - return (0); - while (*s1 == *s2++) - if (*s1++ == '\0') - return (0); - return (*s1 - s2[-1]); -} +#include <sys/bootconf.h> +#include <sys/kobj_impl.h> +#include <sys/cmn_err.h> /* - * Compare strings (at most n bytes): return *s1-*s2 for the last - * characters in s1 and s2 which were compared. + * Standalone utility functions for use within krtld. + * Many platforms implement optimized platmod versions of + * utilities such as bcopy and any such are not yet available + * until the kernel is more completely stitched together. + * These standalones are referenced through vectors + * kobj_bzero, etc. Throughout krtld, the usual utility + * is redefined to reference through the corresponding + * vector so that krtld may simply refer to bzero etc. + * as usual. See kobj_impl.h. */ -int -strncmp(const char *s1, const char *s2, size_t n) -{ - if (s1 == s2) - return (0); - n++; - while (--n != 0 && *s1 == *s2++) - if (*s1++ == '\0') - return (0); - return ((n == 0) ? 0 : *s1 - *--s2); -} -size_t -strlen(const char *s) +/*ARGSUSED*/ +static void +kprintf(void *op, const char *fmt, ...) { - const char *s0 = s + 1; + va_list adx; - while (*s++ != '\0') - ; - return (s - s0); + va_start(adx, fmt); + vprintf(fmt, adx); + va_end(adx); } -char * -strcpy(char *s1, const char *s2) +static void +stand_bzero(void *p_arg, size_t count) { - char *os1 = s1; + char zero = 0; + caddr_t p = p_arg; - while (*s1++ = *s2++) - ; - return (os1); + while (count != 0) + *p++ = zero, count--; } -char * -strncpy(char *s1, const char *s2, size_t n) +static void +stand_bcopy(const void *src_arg, void *dest_arg, size_t count) { - char *os1 = s1; - - n++; - while ((--n != 0) && ((*s1++ = *s2++) != '\0')) - ; - if (n != 0) - while (--n != 0) - *s1++ = '\0'; - return (os1); -} + caddr_t src = (caddr_t)src_arg; + caddr_t dest = dest_arg; -char * -strcat(char *s1, const char *s2) -{ - char *os1 = s1; - - while (*s1++) - ; - --s1; - while (*s1++ = *s2++) - ; - return (os1); + if (src < dest && (src + count) > dest) { + /* overlap copy */ + while (--count != -1) + *(dest + count) = *(src + count); + } else { + while (--count != -1) + *dest++ = *src++; + } } -size_t -strlcat(char *dst, const char *src, size_t dstsize) +static size_t +stand_strlcat(char *dst, const char *src, size_t dstsize) { char *df = dst; size_t left = dstsize; @@ -135,39 +103,36 @@ strlcat(char *dst, const char *src, size_t dstsize) return (l1 + l2); } -char * -strchr(const char *sp, int c) -{ - - do { - if (*sp == (char)c) - return ((char *)sp); - } while (*sp++); - return (NULL); -} - +/* + * Set up the krtld standalone utilty vectors + */ void -bzero(void *p_arg, size_t count) +kobj_setup_standalone_vectors() { - char zero = 0; - caddr_t p = p_arg; - - while (count != 0) - *p++ = zero, count--; /* Avoid clr for 68000, still... */ + _kobj_printf = (void (*)(void *, const char *, ...))bop_printf; + kobj_bcopy = stand_bcopy; + kobj_bzero = stand_bzero; + kobj_strlcat = stand_strlcat; } +/* + * Restore the kprintf/bcopy/bzero kobj vectors. + * We need to undefine the override macros to + * accomplish this. + * + * Do NOT add new code after the point or at least + * certainly not code using bcopy or bzero which would + * need to be vectored to the krtld equivalents. + */ +#undef bcopy +#undef bzero +#undef strlcat + void -bcopy(const void *src_arg, void *dest_arg, size_t count) +kobj_restore_vectors() { - caddr_t src = (caddr_t)src_arg; - caddr_t dest = dest_arg; - - if (src < dest && (src + count) > dest) { - /* overlap copy */ - while (--count != -1) - *(dest + count) = *(src + count); - } else { - while (--count != -1) - *dest++ = *src++; - } + _kobj_printf = kprintf; + kobj_bcopy = bcopy; + kobj_bzero = bzero; + kobj_strlcat = strlcat; } diff --git a/usr/src/uts/common/os/autoconf.c b/usr/src/uts/common/os/autoconf.c index 2adffdd7b0..0bd34a64a9 100644 --- a/usr/src/uts/common/os/autoconf.c +++ b/usr/src/uts/common/os/autoconf.c @@ -48,6 +48,7 @@ #include <sys/sysevent_impl.h> #include <sys/sunldi_impl.h> #include <sys/disp.h> +#include <sys/bootconf.h> #include <sys/fm/util.h> extern dev_info_t *top_devinfo; @@ -126,7 +127,6 @@ impl_create_root_class(void) major_t major; size_t size; char *cp; - extern struct bootops *bootops; /* * The name for the root nexus is exactly as the manufacturer diff --git a/usr/src/uts/common/os/instance.c b/usr/src/uts/common/os/instance.c index 08537f3372..7134d93c56 100644 --- a/usr/src/uts/common/os/instance.c +++ b/usr/src/uts/common/os/instance.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -195,7 +195,7 @@ e_ddi_instance_init(void) case PTI_REBUILD: cmn_err(CE_CONT, - "?Using default device instance data\n"); + "?Using default device instance data\n"); break; } @@ -245,14 +245,14 @@ in_preassign_instance() static int in_get_infile(char *filename) { - intptr_t file; + struct _buf *file; int return_val; char buf[PTI_MAGIC_STR_LEN]; /* * Try to open the file. */ - if ((file = kobj_open(filename)) == -1) { + if ((file = kobj_open_file(filename)) == (struct _buf *)-1) { return (PTI_NOT_FOUND); } return_val = PTI_FOUND; @@ -263,7 +263,7 @@ in_get_infile(char *filename) * in the file, then assume file is correct and no magic string * and move on. */ - switch (kobj_read(file, buf, PTI_MAGIC_STR_LEN, 0)) { + switch (kobj_read_file(file, buf, PTI_MAGIC_STR_LEN, 0)) { case PTI_MAGIC_STR_LEN: /* @@ -285,7 +285,7 @@ in_get_infile(char *filename) break; } - kobj_close(file); + kobj_close_file(file); return (return_val); } @@ -1360,13 +1360,13 @@ i_log_devfs_instance_mod(void) return; ev = sysevent_alloc(EC_DEVFS, ESC_DEVFS_INSTANCE_MOD, EP_DDI, - SE_NOSLEEP); + SE_NOSLEEP); if (ev == NULL) { return; } if (log_sysevent(ev, SE_NOSLEEP, &eid) != 0) { cmn_err(CE_WARN, "i_log_devfs_instance_mod: failed to post " - "event"); + "event"); } else { sent_one = 1; } diff --git a/usr/src/uts/common/os/modsysfile.c b/usr/src/uts/common/os/modsysfile.c index 07076f02dd..5ba026e22e 100644 --- a/usr/src/uts/common/os/modsysfile.c +++ b/usr/src/uts/common/os/modsysfile.c @@ -64,7 +64,7 @@ static char class_file[] = CLASSFILE; static char dafile[] = DAFILE; static char dacffile[] = DACFFILE; -char *systemfile = "etc/system"; /* name of ascii system file */ +char *systemfile = "/etc/system"; /* name of ascii system file */ static struct sysparam *sysparam_hd; /* head of parameters list */ static struct sysparam *sysparam_tl; /* tail of parameters list */ diff --git a/usr/src/uts/common/os/space.c b/usr/src/uts/common/os/space.c index d21630cb22..08384fab47 100644 --- a/usr/src/uts/common/os/space.c +++ b/usr/src/uts/common/os/space.c @@ -106,15 +106,12 @@ struct var v; */ struct vnode *rootvp; /* vnode of the root device */ dev_t rootdev; /* dev_t of the root device */ -int root_is_svm; /* root is a mirrored device flag */ - -int netboot; -int obpdebug; -char *dhcack; /* Used to cache ascii form of DHCPACK handed up by boot */ -char *netdev_path; /* Used to cache the netdev_path handed up by boot */ +boolean_t root_is_svm; /* root is a mirrored device flag */ +boolean_t root_is_ramdisk; /* root is ramdisk */ +uint32_t ramdisk_size; /* (KB) currently set only for sparc netboots */ /* - * Data from arp.c that must be resident. + * dhcp */ #include <sys/socket.h> #include <sys/errno.h> @@ -123,6 +120,17 @@ char *netdev_path; /* Used to cache the netdev_path handed up by boot */ #include <sys/stropts.h> #include <sys/dlpi.h> #include <net/if.h> + +int netboot; +int obpdebug; +char *dhcack; /* dhcp response packet */ +int dhcacklen; +char *netdev_path; /* Used to cache the netdev_path handed up by boot */ +char dhcifname[IFNAMSIZ]; + +/* + * Data from arp.c that must be resident. + */ #include <net/if_arp.h> #include <netinet/in.h> #include <netinet/in_var.h> @@ -130,6 +138,7 @@ char *netdev_path; /* Used to cache the netdev_path handed up by boot */ ether_addr_t etherbroadcastaddr = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + /* * Data from timod that must be resident */ @@ -260,7 +269,7 @@ static void store_fetch_initspace() { space_hash = mod_hash_create_strhash(space_hash_name, - space_hash_nchains, mod_hash_null_valdtor); + space_hash_nchains, mod_hash_null_valdtor); ASSERT(space_hash); } @@ -288,7 +297,7 @@ space_store(char *key, uintptr_t ptr) bcopy(key, s, l); rval = mod_hash_insert(space_hash, - (mod_hash_key_t)s, (mod_hash_val_t)ptr); + (mod_hash_key_t)s, (mod_hash_val_t)ptr); switch (rval) { case 0: diff --git a/usr/src/uts/common/os/swapgeneric.c b/usr/src/uts/common/os/swapgeneric.c index 23fe002d2f..33ce90b489 100644 --- a/usr/src/uts/common/os/swapgeneric.c +++ b/usr/src/uts/common/os/swapgeneric.c @@ -91,7 +91,7 @@ static boolean_t netboot_over_ib(char *bootpath); * Module linkage information for the kernel. */ static struct modlmisc modlmisc = { - &mod_miscops, "root and swap configuration %I%" + &mod_miscops, "root and swap configuration" }; static struct modlinkage modlinkage = { @@ -308,7 +308,7 @@ loadrootmodules(void) char *name; int err; /* ONC_PLUS EXTRACT END */ - int i, proplen, dhcacklen; + int i, proplen; extern char *impl_module_list[]; extern char *platform_module_list[]; @@ -415,23 +415,19 @@ loop: * ("bootp-response" boot property exists). If so, then before * bootops disappears we need to save the value of this property * such that the userland dhcpagent can adopt the DHCP management - * of our primary network interface. We leave room at the beginning of - * saved property to cache the interface name we used to boot the - * client. This context is necessary for the user land dhcpagent - * to do its job properly on a multi-homed system. + * of our primary network interface. */ proplen = BOP_GETPROPLEN(bootops, "bootp-response"); if (proplen > 0) { - dhcacklen = proplen + IFNAMSIZ; - dhcack = kmem_zalloc(dhcacklen, KM_SLEEP); - if (BOP_GETPROP(bootops, "bootp-response", - (uchar_t *)&dhcack[IFNAMSIZ]) == -1) { + dhcack = kmem_zalloc(proplen, KM_SLEEP); + if (BOP_GETPROP(bootops, "bootp-response", dhcack) == -1) { cmn_err(CE_WARN, "BOP_GETPROP of " "\"bootp-response\" failed\n"); kmem_free(dhcack, dhcacklen); dhcack = NULL; goto out; } + dhcacklen = proplen; /* * Fetch the "netdev-path" boot property (if it exists), and @@ -522,6 +518,36 @@ out: } /* ONC_PLUS EXTRACT END */ +static int +get_bootpath_prop(char *bootpath) +{ + if (root_is_ramdisk) { + if (BOP_GETPROP(bootops, "bootarchive", bootpath) == -1) + return (-1); + (void) strlcat(bootpath, ":a", BO_MAXOBJNAME); + } else { + /* + * Look for the 1275 compliant name 'bootpath' first, + * but make certain it has a non-NULL value as well. + */ + if ((BOP_GETPROP(bootops, "bootpath", bootpath) == -1) || + strlen(bootpath) == 0) { + if (BOP_GETPROP(bootops, + "boot-path", bootpath) == -1) + return (-1); + } + } + return (0); +} + +static int +get_fstype_prop(char *fstype) +{ + char *prop = (root_is_ramdisk) ? "archive-fstype" : "fstype"; + + return (BOP_GETPROP(bootops, prop, fstype)); +} + /* * Get the name of the root or swap filesystem type, and return * the corresponding entry in the vfs switch. @@ -558,7 +584,7 @@ getfstype(char *askfor, char *fsname, size_t fsnamelen) int root = 0; if (strcmp(askfor, "root") == 0) { - (void) BOP_GETPROP(bootops, "fstype", defaultfs); + (void) get_fstype_prop(defaultfs); root++; } else { (void) strcpy(defaultfs, "swapfs"); @@ -628,16 +654,8 @@ getphysdev(char *askfor, char *name, size_t namelen) * ease-of-use .. */ if (strcmp(askfor, "root") == 0) { - /* - * Look for the 1275 compliant name 'bootpath' first, - * but make certain it has a non-NULL value as well. - */ - if ((BOP_GETPROP(bootops, "bootpath", defaultpath) == -1) || - strlen(defaultpath) == 0) { - if (BOP_GETPROP(bootops, - "boot-path", defaultpath) == -1) - boothowto |= RB_ASKNAME | RB_VERBOSE; - } + if (get_bootpath_prop(defaultpath) == -1) + boothowto |= RB_ASKNAME | RB_VERBOSE; } else { (void) strcpy(defaultpath, rootfs.bo_name); defaultpath[strlen(defaultpath) - 1] = 'b'; diff --git a/usr/src/uts/common/os/vfs_conf.c b/usr/src/uts/common/os/vfs_conf.c index fec5cc998f..b15c834fbe 100644 --- a/usr/src/uts/common/os/vfs_conf.c +++ b/usr/src/uts/common/os/vfs_conf.c @@ -80,6 +80,7 @@ struct vfssw vfssw[] = { { "ctfs" }, /* CONTRACTFS */ { "objfs" }, /* OBJFS */ { "sharefs" }, /* SHAREFS */ + { "dcfs" }, /* DCFS */ { "" }, /* reserved for loadable fs */ { "" }, { "" }, diff --git a/usr/src/uts/common/sys/Makefile b/usr/src/uts/common/sys/Makefile index adf32df9d7..c46d01b321 100644 --- a/usr/src/uts/common/sys/Makefile +++ b/usr/src/uts/common/sys/Makefile @@ -731,6 +731,7 @@ FSHDRS= \ cachefs_fscache.h \ cachefs_ioctl.h \ cachefs_log.h \ + decomp.h \ dv_node.h \ sdev_impl.h \ sdev_node.h \ diff --git a/usr/src/uts/common/sys/bootstat.h b/usr/src/uts/common/sys/bootstat.h index b972d1419e..437f74d1c0 100644 --- a/usr/src/uts/common/sys/bootstat.h +++ b/usr/src/uts/common/sys/bootstat.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -65,6 +64,18 @@ struct bootstat { char st_fstype[_ST_FSTYPSZ]; }; +/* + * Special struct for compressed files. + * Only used by kobj to decompress files before + * root is mounted. Afterwards, dcfs will take + * over decompression. + */ +struct compinfo { + int iscmp; + size_t fsize; + size_t blksize; +}; + #ifdef __cplusplus } #endif diff --git a/usr/src/uts/common/sys/filio.h b/usr/src/uts/common/sys/filio.h index 8d13c2e483..cbd98af97e 100644 --- a/usr/src/uts/common/sys/filio.h +++ b/usr/src/uts/common/sys/filio.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -133,6 +132,11 @@ extern "C" { #define _FIO_SEEK_DATA _IO('f', 97) /* SEEK_DATA */ #define _FIO_SEEK_HOLE _IO('f', 98) /* SEEK_HOLE */ +/* + * boot archive compression + */ +#define _FIO_COMPRESSED _IO('f', 99) /* mark file as compressed */ + #ifdef __cplusplus } #endif diff --git a/usr/src/uts/common/sys/fs/decomp.h b/usr/src/uts/common/sys/fs/decomp.h new file mode 100644 index 0000000000..035a5ab6c8 --- /dev/null +++ b/usr/src/uts/common/sys/fs/decomp.h @@ -0,0 +1,78 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_DECOMP_H +#define _SYS_DECOMP_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#define CH_MAGIC 0x5a636d70 /* Zcmp */ + +#define CH_VERSION 1 + +#define CH_ALG_ZLIB 1 + +struct comphdr { + uint64_t ch_magic; + uint64_t ch_version; + uint64_t ch_algorithm; + uint64_t ch_fsize; + uint64_t ch_blksize; + uint64_t ch_blkmap[1]; +}; + +#define ZMAXBUF(n) ((n) + ((n) / 1000) + 12) + +#ifdef _KERNEL + +struct dcnode { + struct vnode *dc_vp; + struct vnode *dc_subvp; + struct kmem_cache *dc_bufcache; + kmutex_t dc_lock; + struct dcnode *dc_hash; + struct dcnode *dc_lrunext; + struct dcnode *dc_lruprev; + struct comphdr *dc_hdr; + size_t dc_hdrsize; + size_t dc_zmax; + int dc_mapcnt; +}; + +#define VTODC(vp) ((struct dcnode *)(vp)->v_data) +#define DCTOV(dp) ((dp)->dc_vp) + +struct vnode *decompvp(struct vnode *, struct cred *, caller_context_t *); + +#endif + +#ifdef __cplusplus +} +#endif +#endif /* _SYS_DECOMP_H */ diff --git a/usr/src/uts/common/sys/fs/ufs_filio.h b/usr/src/uts/common/sys/fs/ufs_filio.h index d97d765dd8..052be12ef4 100644 --- a/usr/src/uts/common/sys/fs/ufs_filio.h +++ b/usr/src/uts/common/sys/fs/ufs_filio.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -103,6 +102,7 @@ extern int ufs_fiologenable(vnode_t *, fiolog_t *, cred_t *, int); extern int ufs_fiologdisable(vnode_t *, fiolog_t *, cred_t *, int); extern int ufs_fioislog(vnode_t *, uint32_t *, cred_t *, int); extern int ufs_fio_holey(vnode_t *, int, offset_t *); +extern int ufs_mark_compressed(struct vnode *vp); #endif /* defined(_KERNEL) && defined(__STDC__) */ diff --git a/usr/src/uts/common/sys/fs/ufs_inode.h b/usr/src/uts/common/sys/fs/ufs_inode.h index effc5aa9f6..ec0ecdc766 100644 --- a/usr/src/uts/common/sys/fs/ufs_inode.h +++ b/usr/src/uts/common/sys/fs/ufs_inode.h @@ -369,6 +369,8 @@ struct dinode { /* cflags */ #define IXATTR 0x0001 /* extended attribute */ #define IFALLOCATE 0x0002 /* fallocate'd file */ +#define ICOMPRESS 0x0004 /* compressed for dcfs - see */ + /* `ufs_ioctl()`_FIO_COMPRESSED */ /* modes */ #define IFMT 0170000 /* type of file */ diff --git a/usr/src/uts/common/sys/isa_defs.h b/usr/src/uts/common/sys/isa_defs.h index 08fcbd02e5..005c0f6eef 100644 --- a/usr/src/uts/common/sys/isa_defs.h +++ b/usr/src/uts/common/sys/isa_defs.h @@ -206,6 +206,9 @@ * This indicates that the implementation uses a dynamically * linked unix + krtld to form the core kernel image at boot * time, or (in the absence of this symbol) a prelinked kernel image. + * + * _OBP + * This indicates the firmware interface is OBP. */ #ifdef __cplusplus @@ -402,7 +405,7 @@ extern "C" { #define _DMA_USES_VIRTADDR #define _NO_FDISK_PRESENT #define _HAVE_TEM_FIRMWARE -#define _UNIX_KRTLD +#define _OBP /* * The following set of definitions characterize the implementation of diff --git a/usr/src/uts/common/sys/kobj.h b/usr/src/uts/common/sys/kobj.h index 6c8fde02b4..8537430ed0 100644 --- a/usr/src/uts/common/sys/kobj.h +++ b/usr/src/uts/common/sys/kobj.h @@ -122,10 +122,14 @@ struct _buf { char *_ptr; char *_base; char *_name; + char *_dbuf; int _size; int _cnt; int _off; int _ln; + int _bsize; + int _iscmp; + int _dsize; }; @@ -144,9 +148,15 @@ typedef struct { #define kobj_newline(p) ((p)->_ln++) #define kobj_getc(p) (--(p)->_cnt >= 0 ? ((int)*(p)->_ptr++):kobj_filbuf(p)) #define kobj_ungetc(p) (++(p)->_cnt > (p)->_size ? -1 : ((int)*(--(p)->_ptr))) +#define kobj_comphdr(p) ((struct comphdr *)(p)->_dbuf) -#define B_OFFSET(f_offset) (f_offset & (MAXBSIZE-1)) /* Offset into buffer */ -#define F_PAGE(f_offset) (f_offset & ~(MAXBSIZE-1)) /* Start of page */ +/* Offset into buffer */ +#define B_OFFSET(file, off) (off % (file)->_bsize) + +/* Start of page */ +#define F_PAGE(file, off) (off - B_OFFSET(file, off)) + +#define F_BLKS(file, size) ((size / (file)->_bsize) * (file)->_bsize) #if defined(_KERNEL) diff --git a/usr/src/uts/common/sys/kobj_impl.h b/usr/src/uts/common/sys/kobj_impl.h index 363cf5a5ca..1dd7da9ee7 100644 --- a/usr/src/uts/common/sys/kobj_impl.h +++ b/usr/src/uts/common/sys/kobj_impl.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -136,8 +135,20 @@ extern int kobj_debug; /* different than moddebug */ #define KM_WAIT 0x0 /* wait for it */ #define KM_NOWAIT 0x1 /* return immediately */ -#define KM_TMP 0x1000 /* freed before kobj_init return */ -#define KM_SCRATCH 0x2000 /* not freed until boot unmap */ +#define KM_TMP 0x1000 /* freed before kobj_init returns */ +#define KM_SCRATCH 0x2000 /* not freed until kobj_sync */ + +#ifdef KOBJ_OVERRIDES +/* + * Until the kernel is fully linked, all code running in the + * context of krtld/kobj using bcopy or bzero must be directed + * to the kobj equivalents. All (ok, most) references to bcopy + * or bzero are thus so vectored. + */ +#define bcopy(s, d, n) kobj_bcopy((s), (d), (n)) +#define bzero(p, n) kobj_bzero((p), (n)) +#define strlcat(s, d, n) kobj_strlcat((s), (d), (n)) +#endif extern kdi_t kobj_kdi; @@ -155,7 +166,6 @@ extern int kobj_notify_add(kobj_notify_list_t *); extern int kobj_notify_remove(kobj_notify_list_t *); extern int do_relocations(struct module *); extern int do_relocate(struct module *, char *, Word, int, int, Addr); -extern void (*_kobj_printf)(void *, const char *fmt, ...); extern struct bootops *ops; extern void exitto(caddr_t); extern void kobj_sync_instruction_memory(caddr_t, size_t); @@ -170,15 +180,15 @@ extern Sym *kobj_lookup_kernel(const char *); extern struct modctl *kobj_boot_mod_lookup(const char *); extern void kobj_export_module(struct module *); extern int kobj_load_primary_module(struct modctl *); +extern int boot_compinfo(int, struct compinfo *); +extern void mach_modpath(char *, const char *); -#ifdef __sparc -extern void *kobj_bs_alloc(size_t); - -extern void *kobj_tmp_alloc(size_t); -extern void kobj_tmp_free(void); -#else -extern void kobj_boot_unmountroot(void); -#endif +extern void kobj_setup_standalone_vectors(void); +extern void kobj_restore_vectors(void); +extern void (*_kobj_printf)(void *, const char *fmt, ...); +extern void (*kobj_bcopy)(const void *, void *, size_t); +extern void (*kobj_bzero)(void *, size_t); +extern size_t (*kobj_strlcat)(char *, const char *, size_t); #define KOBJ_LM_PRIMARY 0x0 #define KOBJ_LM_DEBUGGER 0x1 diff --git a/usr/src/uts/common/sys/ramdisk.h b/usr/src/uts/common/sys/ramdisk.h index a33e2d1cb1..a750336d37 100644 --- a/usr/src/uts/common/sys/ramdisk.h +++ b/usr/src/uts/common/sys/ramdisk.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -164,7 +163,11 @@ struct rd_ioctl { * ranges; these are described by the 'existing' property, whose value * is a (corresponding) number of {phys,size} pairs. */ -#define RD_EXISTING_PROP_NAME "existing" +#define OBP_EXISTING_PROP_NAME "existing" +#define OBP_ADDRESS_PROP_NAME "address" +#define OBP_SIZE_PROP_NAME "size" + +#define RD_EXISTING_PROP_NAME "existing" /* for x86 */ typedef struct { uint64_t phys; /* Phys addr of range */ @@ -199,6 +202,7 @@ typedef struct rd_devstate { * giving the offset within the ramdisk of the window, its size, * and its virtual address (in the kernel heap). */ + uint_t rd_window_obp; /* using OBP's vaddr */ offset_t rd_window_base; uint64_t rd_window_size; caddr_t rd_window_virt; diff --git a/usr/src/uts/common/sys/systm.h b/usr/src/uts/common/sys/systm.h index b34d7ed304..df834a88ec 100644 --- a/usr/src/uts/common/sys/systm.h +++ b/usr/src/uts/common/sys/systm.h @@ -90,7 +90,9 @@ extern pgcnt_t freemem; /* Current free memory. */ extern dev_t rootdev; /* device of the root */ extern struct vnode *rootvp; /* vnode of root device */ -extern int root_is_svm; /* root is a mirrored device flag */ +extern boolean_t root_is_svm; /* root is a mirrored device flag */ +extern boolean_t root_is_ramdisk; /* root is boot_archive ramdisk */ +extern uint32_t ramdisk_size; /* (KB) set only for sparc netboots */ extern char *volatile panicstr; /* panic string pointer */ extern va_list panicargs; /* panic arguments */ diff --git a/usr/src/uts/common/syscall/systeminfo.c b/usr/src/uts/common/syscall/systeminfo.c index dd3dade3c5..5094294188 100644 --- a/usr/src/uts/common/syscall/systeminfo.c +++ b/usr/src/uts/common/syscall/systeminfo.c @@ -47,6 +47,7 @@ #include <sys/promif.h> #include <sys/zone.h> #include <sys/model.h> +#include <netinet/inetutil.h> static void get_netif_name(char *, char *); @@ -91,7 +92,7 @@ systeminfo(int command, char *buf, long count) break; case SI_ARCHITECTURE_NATIVE: kstr = get_udatamodel() == DATAMODEL_NATIVE ? - architecture : architecture_32; + architecture : architecture_32; break; #else case SI_ARCHITECTURE_K: @@ -141,6 +142,7 @@ systeminfo(int command, char *buf, long count) case SI_DHCP_CACHE: { char *tmp; + unsigned int tlen, octlen; if (dhcack == NULL) { tmp = ""; @@ -157,37 +159,53 @@ systeminfo(int command, char *buf, long count) } /* * If the interface name has not yet been resolved - * (first IFNAMSIZ bytes of dhcack[]) and a valid - * netdev_path[] was stashed by loadrootmodules in - * swapgeneric.c, or established above, resolve - * the interface name now. + * and a validnetdev_path[] was stashed by + * loadrootmodules in swapgeneric.c, or established + * above, resolve the interface name now. */ - if (dhcack[0] == '\0' && + if (dhcifname[0] == '\0' && netdev_path != NULL && netdev_path[0] != '\0') { - get_netif_name(netdev_path, dhcack); + get_netif_name(netdev_path, dhcifname); } - tmp = dhcack; - strcnt = IFNAMSIZ + strlen(&tmp[IFNAMSIZ]); + /* + * Form reply: + * IFNAMESIZ array of dhcp i/f + * hexascii representation of dhcp reply + */ + octlen = dhcacklen * 2 + 1; + tlen = octlen + IFNAMSIZ; + tmp = kmem_alloc(tlen, KM_SLEEP); + (void) strncpy(tmp, dhcifname, IFNAMSIZ); + if (octet_to_hexascii(dhcack, dhcacklen, + &tmp[IFNAMSIZ], &octlen) != 0) { + kmem_free(tmp, tlen); + error = EINVAL; + break; + } else { + strcnt = IFNAMSIZ + octlen; + } } if (count > 0) { if (count <= strcnt) { getcnt = count - 1; - if (subyte((buf + getcnt), 0) < 0) { - error = EFAULT; - break; - } + if (subyte((buf + getcnt), 0) < 0) + goto fail; } else { getcnt = strcnt + 1; } - if (copyout(tmp, buf, getcnt)) { - error = EFAULT; - break; - } + if (copyout(tmp, buf, getcnt)) + goto fail; } - + if (strcnt != 0) + kmem_free(tmp, tlen); return (strcnt + 1); +fail: + if (strcnt != 0) + kmem_free(tmp, tlen); + error = EFAULT; + break; } case SI_SET_HOSTNAME: diff --git a/usr/src/uts/i86pc/os/ddi_impl.c b/usr/src/uts/i86pc/os/ddi_impl.c index 1ddc6aa0f7..e001a30f78 100644 --- a/usr/src/uts/i86pc/os/ddi_impl.c +++ b/usr/src/uts/i86pc/os/ddi_impl.c @@ -86,7 +86,6 @@ struct pci_bus_resource *pci_bus_res; size_t dma_max_copybuf_size = 0x101000; /* 1M + 4K */ -extern int root_is_svm; uint64_t ramdisk_start, ramdisk_end; /* @@ -2557,7 +2556,7 @@ getrootdev(void) /* * Precedence given to rootdev if set in /etc/system */ - if (root_is_svm) { + if (root_is_svm == B_TRUE) { return (ddi_pathname_to_dev_t(svm_bootpath)); } diff --git a/usr/src/uts/i86pc/os/fakebop.c b/usr/src/uts/i86pc/os/fakebop.c index dc4de9eb30..622097c84e 100644 --- a/usr/src/uts/i86pc/os/fakebop.c +++ b/usr/src/uts/i86pc/os/fakebop.c @@ -383,7 +383,7 @@ bsetpropsi(char *name, int value) */ /*ARGSUSED*/ int -do_bsys_getproplen(bootops_t *bop, char *name) +do_bsys_getproplen(bootops_t *bop, const char *name) { bootprop_t *b; @@ -400,7 +400,7 @@ do_bsys_getproplen(bootops_t *bop, char *name) */ /*ARGSUSED*/ int -do_bsys_getprop(bootops_t *bop, char *name, void *value) +do_bsys_getprop(bootops_t *bop, const char *name, void *value) { bootprop_t *b; @@ -698,7 +698,7 @@ done: /*PRINTFLIKE2*/ /*ARGSUSED*/ void -bop_printf(bootops_t *bop, char *fmt, ...) +bop_printf(bootops_t *bop, const char *fmt, ...) { va_list ap; @@ -717,7 +717,7 @@ bop_printf(bootops_t *bop, char *fmt, ...) */ /*PRINTFLIKE1*/ void -bop_panic(char *fmt, ...) +bop_panic(const char *fmt, ...) { va_list ap; @@ -1216,8 +1216,11 @@ build_boot_properties(void) /* * set boot-args property + * 1275 name is bootargs, so set + * that too */ bsetprops("boot-args", boot_args); + bsetprops("bootargs", boot_args); #ifndef __xpv /* @@ -2029,3 +2032,12 @@ usbser_init(size_t size) &p, sizeof (p)); return (p); } + +/*ARGSUSED*/ +int +boot_compinfo(int fd, struct compinfo *cbp) +{ + cbp->iscmp = 0; + cbp->blksize = MAXBSIZE; + return (0); +} diff --git a/usr/src/uts/i86pc/os/mlsetup.c b/usr/src/uts/i86pc/os/mlsetup.c index 2c23519515..3f5705bbc6 100644 --- a/usr/src/uts/i86pc/os/mlsetup.c +++ b/usr/src/uts/i86pc/os/mlsetup.c @@ -347,3 +347,40 @@ mlsetup(struct regs *rp) if (workaround_errata(CPU) != 0) panic("critical workaround(s) missing for boot cpu"); } + + +void +mach_modpath(char *path, const char *filename) +{ + /* + * Construct the directory path from the filename. + */ + + int len; + char *p; + const char isastr[] = "/amd64"; + size_t isalen = strlen(isastr); + + if ((p = strrchr(filename, '/')) == NULL) + return; + + while (p > filename && *(p - 1) == '/') + p--; /* remove trailing '/' characters */ + if (p == filename) + p++; /* so "/" -is- the modpath in this case */ + + /* + * Remove optional isa-dependent directory name - the module + * subsystem will put this back again (!) + */ + len = p - filename; + if (len > isalen && + strncmp(&filename[len - isalen], isastr, isalen) == 0) + p -= isalen; + + /* + * "/platform/mumblefrotz" + " " + MOD_DEFPATH + */ + len += (p - filename) + 1 + strlen(MOD_DEFPATH) + 1; + (void) strncpy(path, filename, p - filename); +} diff --git a/usr/src/uts/intel/Makefile.rules b/usr/src/uts/intel/Makefile.rules index 105e2873bd..c1b13870f5 100644 --- a/usr/src/uts/intel/Makefile.rules +++ b/usr/src/uts/intel/Makefile.rules @@ -258,6 +258,11 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/intel/$(SUBARCH_DIR)/krtld/%.c $(COMPILE.c) $(KRTLD_INC_PATH) $(KRTLD_CPPFLAGS) -o $@ $< $(CTFCONVERT_O) +# +# _DBOOT indicates that krtld is called from a dboot ELF section +# +$(OBJS_DIR)/kobj.o := CPPFLAGS += -D_DBOOT + $(OBJS_DIR)/%.o: $(UTSBASE)/intel/$(SUBARCH_DIR)/krtld/%.s $(COMPILE.s) $(KRTLD_INC_PATH) $(KRTLD_CPPFLAGS) -o $@ $< $(CTFCONVERT_O) @@ -432,3 +437,4 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/intel/$(SUBARCH_DIR)/krtld/%.s $(LINTS_DIR)/%.ln: $(SRC)/common/util/$(SUBARCH_DIR)/%.c @($(LHEAD) $(LINT.c) $(KRTLD_INC_PATH) $(KRTLD_CPPFLAGS) $< $(LTAIL)) +$(OBJS_DIR)/kobj.ln := CPPFLAGS += -D_DBOOT diff --git a/usr/src/uts/intel/amd64/krtld/kobj_boot.c b/usr/src/uts/intel/amd64/krtld/kobj_boot.c index bdd6779d01..b63486fd69 100644 --- a/usr/src/uts/intel/amd64/krtld/kobj_boot.c +++ b/usr/src/uts/intel/amd64/krtld/kobj_boot.c @@ -35,8 +35,8 @@ #include <sys/auxv.h> #include <sys/kobj.h> #include <sys/bootsvcs.h> -#include <sys/kobj_impl.h> #include <vm/kboot_mmu.h> +#include <sys/kobj_impl.h> /* * the kernel's entry point (from locore.s) diff --git a/usr/src/uts/intel/ia32/krtld/kobj_boot.c b/usr/src/uts/intel/ia32/krtld/kobj_boot.c index a65721d82c..83fceab7d0 100644 --- a/usr/src/uts/intel/ia32/krtld/kobj_boot.c +++ b/usr/src/uts/intel/ia32/krtld/kobj_boot.c @@ -35,8 +35,8 @@ #include <sys/auxv.h> #include <sys/kobj.h> #include <sys/bootsvcs.h> -#include <sys/kobj_impl.h> #include <vm/kboot_mmu.h> +#include <sys/kobj_impl.h> /* * the kernel's entry point (from locore.s) diff --git a/usr/src/uts/intel/ia32/ml/modstubs.s b/usr/src/uts/intel/ia32/ml/modstubs.s index d6f06c6e1f..7cee20312e 100644 --- a/usr/src/uts/intel/ia32/ml/modstubs.s +++ b/usr/src/uts/intel/ia32/ml/modstubs.s @@ -739,6 +739,15 @@ fcnname/**/_info: \ #endif /* + * Stubs for dcfs + */ +#ifndef DCFS_MODULE + MODULE(dcfs,fs); + STUB(dcfs, decompvp, 0); + END_MODULE(dcfs); +#endif + +/* * Stubs for namefs */ #ifndef NAMEFS_MODULE diff --git a/usr/src/uts/intel/sys/bootconf.h b/usr/src/uts/intel/sys/bootconf.h index 4da7f8c3cb..89b38435cd 100644 --- a/usr/src/uts/intel/sys/bootconf.h +++ b/usr/src/uts/intel/sys/bootconf.h @@ -35,9 +35,10 @@ #include <sys/types.h> #include <sys/bootregs.h> /* for struct bop_regs */ #include <sys/bootstat.h> -#include <sys/dirent.h> /* for struct dirent */ +#include <sys/dirent.h> /* for struct dirent */ #include <sys/memlist.h> #include <sys/obpdefs.h> +#include <net/if.h> /* for IFNAMSIZ */ #ifdef __cplusplus extern "C" { @@ -108,12 +109,12 @@ typedef struct bootops { /* * to find the size of the buffer to allocate */ - int (*bsys_getproplen)(struct bootops *, char *name); + int (*bsys_getproplen)(struct bootops *, const char *); /* * get the value associated with this name */ - int (*bsys_getprop)(struct bootops *, char *name, void *value); + int (*bsys_getprop)(struct bootops *, const char *, void *); /* * get the name of the next property in succession @@ -124,7 +125,7 @@ typedef struct bootops { /* * print formatted output */ - void (*bsys_printf)(struct bootops *, char *, ...); + void (*bsys_printf)(struct bootops *, const char *, ...); /* * Do a real mode interrupt @@ -222,15 +223,16 @@ extern char *kobj_module_path; extern char *default_path; extern char *dhcack; extern int dhcacklen; +extern char dhcifname[IFNAMSIZ]; extern char *netdev_path; extern void bop_no_more_mem(void); /*PRINTFLIKE2*/ -extern void bop_printf(struct bootops *, char *, ...) +extern void bop_printf(struct bootops *, const char *, ...) __KPRINTFLIKE(2); /*PRINTFLIKE1*/ -extern void bop_panic(char *, ...) +extern void bop_panic(const char *, ...) __KPRINTFLIKE(1); extern void boot_prop_finish(void); @@ -240,8 +242,8 @@ extern void boot_prop_finish(void); */ extern paddr_t do_bop_phys_alloc(uint64_t, uint64_t); -extern int do_bsys_getproplen(bootops_t *, char *); -extern int do_bsys_getprop(bootops_t *, char *, void *); +extern int do_bsys_getproplen(bootops_t *, const char *); +extern int do_bsys_getprop(bootops_t *, const char *, void *); #endif /* _KERNEL && !_BOOT */ diff --git a/usr/src/uts/sparc/Makefile.files b/usr/src/uts/sparc/Makefile.files index 7d4c036a18..fccd7341e3 100644 --- a/usr/src/uts/sparc/Makefile.files +++ b/usr/src/uts/sparc/Makefile.files @@ -79,13 +79,9 @@ CORE_OBJS += prmachdep.o # # misc modules # -KRTLD_BOOT_OBJS += kobj_boot.o KRTLD_OBJS += \ - bootops.o \ doreloc.o \ - kobj_alloc.o \ kobj_convrelstr.o \ - kobj_crt.o \ kobj_isa.o \ kobj_reloc.o @@ -110,6 +106,7 @@ SDT_OBJS += sdt.o # LINT_DEFS += -Dsparc INC_PATH += -I$(UTSBASE)/sparc +INC_PATH += -I$(UTSBASE)/sparc/krtld # # Since assym.h is a derived file, the dependency must be explicit for diff --git a/usr/src/uts/sparc/Makefile.rules b/usr/src/uts/sparc/Makefile.rules index b693acfa37..b7978200ad 100644 --- a/usr/src/uts/sparc/Makefile.rules +++ b/usr/src/uts/sparc/Makefile.rules @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 1991-2003 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -63,6 +62,14 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/sparc/krtld/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) +# +# _RELSEG indicates that the dynamic syms are put in a separate ELF +# section so they can be freed later. +# +$(OBJS_DIR)/kobj_bootflags.o := CPPFLAGS += -I$(SRC)/common +$(OBJS_DIR)/kobj.o := CPPFLAGS += -DMODDIR_SUFFIX=\"sparcv9\" +$(OBJS_DIR)/kobj.o := CPPFLAGS += -D_RELSEG + $(OBJS_DIR)/%.o: $(UTSBASE)/sparc/krtld/%.s $(COMPILE.s) -o $@ $< @@ -98,6 +105,10 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/sparc/fs/proc/%.c $(LINTS_DIR)/%.ln: $(UTSBASE)/sparc/krtld/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) +$(OBJS_DIR)/kobj_bootflags.ln := CPPFLAGS += -I$(SRC)/common +$(OBJS_DIR)/kobj.ln := CPPFLAGS += -DMODDIR_SUFFIX=\"sparcv9\" +$(OBJS_DIR)/kobj.ln := CPPFLAGS += -D_RELSEG + $(LINTS_DIR)/%.ln: $(UTSBASE)/sparc/krtld/%.s @($(LHEAD) $(LINT.s) $< $(LTAIL)) diff --git a/usr/src/uts/sparc/Makefile.sparc.shared b/usr/src/uts/sparc/Makefile.sparc.shared index 2db72ddc3f..58d69a0d61 100644 --- a/usr/src/uts/sparc/Makefile.sparc.shared +++ b/usr/src/uts/sparc/Makefile.sparc.shared @@ -340,7 +340,7 @@ SCHED_KMODS += RT TS RT_DPTBL TS_DPTBL IA FSS FX FX_DPTBL # FS_KMODS += dev devfs fdfs fifofs hsfs lofs namefs nfs pcfs tmpfs zfs FS_KMODS += specfs udfs ufs autofs cachefs procfs sockfs mntfs -FS_KMODS += ctfs objfs sharefs +FS_KMODS += ctfs objfs sharefs dcfs # # Streams Modules (/kernel/strmod): @@ -368,7 +368,6 @@ SYS_KMODS += doorfs pset acctctl portfs MISC_KMODS += amsrc2 audiosup diaudio mixer MISC_KMODS += consconfig gld ipc nfs_dlboot nfssrv scsi MISC_KMODS += strplumb swapgeneric tlimod -MISC_KMODS += krtld MISC_KMODS += rpcsec rpcsec_gss kgssapi kmech_dummy MISC_KMODS += kmech_krb5 MISC_KMODS += fssnap_if diff --git a/usr/src/uts/sparc/dcfs/Makefile b/usr/src/uts/sparc/dcfs/Makefile new file mode 100644 index 0000000000..ca4be87faf --- /dev/null +++ b/usr/src/uts/sparc/dcfs/Makefile @@ -0,0 +1,88 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# uts/sparc/dcfs/Makefile +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# This makefile drives the production of the dcfs file system +# kernel module. +# +# sparc architecture dependent +# + +# +# Path to the base of the uts directory tree (usually /usr/src/uts). +# +UTSBASE = ../.. + +# +# Define the module and object file sets. +# +MODULE = dcfs +OBJECTS = $(DCFS_OBJS:%=$(OBJS_DIR)/%) +LINTS = $(DCFS_OBJS:%.o=$(LINTS_DIR)/%.ln) +ROOTMODULE = $(ROOT_FS_DIR)/$(MODULE) + +# +# Include common rules. +# +include $(UTSBASE)/sparc/Makefile.sparc + +# +# Define targets +# +ALL_TARGET = $(BINARY) +LINT_TARGET = $(MODULE).lint +INSTALL_TARGET = $(BINARY) $(ROOTMODULE) + +# +# Overrides. +# +CFLAGS += $(CCVERBOSE) + +# +# Default build targets. +# +.KEEP_STATE: + +def: $(DEF_DEPS) + +all: $(ALL_DEPS) + +clean: $(CLEAN_DEPS) + +clobber: $(CLOBBER_DEPS) + +lint: $(LINT_DEPS) + +modlintlib: $(MODLINTLIB_DEPS) + +clean.lint: $(CLEAN_LINT_DEPS) + +install: $(INSTALL_DEPS) + +# +# Include common targets. +# +include $(UTSBASE)/sparc/Makefile.targ diff --git a/usr/src/uts/sparc/krtld/doreloc.c b/usr/src/uts/sparc/krtld/doreloc.c index ff9864ae84..b044fbac43 100644 --- a/usr/src/uts/sparc/krtld/doreloc.c +++ b/usr/src/uts/sparc/krtld/doreloc.c @@ -28,7 +28,7 @@ #if defined(_KERNEL) #include <sys/types.h> -#include "reloc.h" +#include "krtld/reloc.h" #else #include <stdio.h> #include "sgs.h" @@ -450,7 +450,7 @@ do_reloc_rtld(uchar_t rtype, uchar_t *off, Xword *value, const char *sym, */ if (re_flags & FLG_RE_WDISP16) { uvalue = ((basevalue & 0x300000) >> 6) | - (basevalue & 0x3fff); + (basevalue & 0x3fff); basevalue &= ~0x303fff; } else { uvalue = sigbit_mask & basevalue; @@ -533,7 +533,7 @@ do_reloc_rtld(uchar_t rtype, uchar_t *off, Xword *value, const char *sym, */ if (re_flags & FLG_RE_WDISP16) uvalue = ((uvalue & 0xc000) << 6) | - (uvalue & 0x3fff); + (uvalue & 0x3fff); else uvalue &= sigbit_mask; /* diff --git a/usr/src/uts/sparc/krtld/kobj_convrelstr.c b/usr/src/uts/sparc/krtld/kobj_convrelstr.c index 93f02bb716..8bac7172b3 100644 --- a/usr/src/uts/sparc/krtld/kobj_convrelstr.c +++ b/usr/src/uts/sparc/krtld/kobj_convrelstr.c @@ -20,13 +20,13 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include <sys/types.h> -#include "reloc.h" +#include "krtld/reloc.h" static const char *rels[R_SPARC_NUM] = { "R_SPARC_NONE", "R_SPARC_8", diff --git a/usr/src/uts/sparc/krtld/kobj_reloc.c b/usr/src/uts/sparc/krtld/kobj_reloc.c index eda18f35a1..05e207810a 100644 --- a/usr/src/uts/sparc/krtld/kobj_reloc.c +++ b/usr/src/uts/sparc/krtld/kobj_reloc.c @@ -44,7 +44,7 @@ #include <sys/tnf_probe.h> #include <sys/sdt.h> -#include "reloc.h" +#include "krtld/reloc.h" /* diff --git a/usr/src/uts/sparc/ml/modstubs.s b/usr/src/uts/sparc/ml/modstubs.s index 5424c4cce7..db9f9d954f 100644 --- a/usr/src/uts/sparc/ml/modstubs.s +++ b/usr/src/uts/sparc/ml/modstubs.s @@ -627,6 +627,15 @@ stubs_base: #endif /* + * Stubs for dcfs + */ +#ifndef DCFS_MODULE + MODULE(dcfs,fs); + STUB(dcfs, decompvp, 0); + END_MODULE(dcfs); +#endif + +/* * Stubs for namefs */ #ifndef NAMEFS_MODULE diff --git a/usr/src/uts/sparc/os/archdep.c b/usr/src/uts/sparc/os/archdep.c index ceeee3ef44..a1964308ed 100644 --- a/usr/src/uts/sparc/os/archdep.c +++ b/usr/src/uts/sparc/os/archdep.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -386,7 +385,7 @@ exec_set_sp(size_t stksize) void * boot_virt_alloc(void *addr, size_t size) { - return (BOP_ALLOC_VIRT(bootops, (caddr_t)addr, size)); + return (BOP_ALLOC_VIRT((caddr_t)addr, size)); } diff --git a/usr/src/uts/sparc/os/bootops.c b/usr/src/uts/sparc/os/bootops.c index f01c0f8f65..b0231cae13 100644 --- a/usr/src/uts/sparc/os/bootops.c +++ b/usr/src/uts/sparc/os/bootops.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -35,670 +34,518 @@ */ #include <sys/types.h> +#include <sys/systm.h> #include <sys/reboot.h> #include <sys/param.h> #include <sys/varargs.h> #include <sys/obpdefs.h> -#include <sys/promif.h> +#include <sys/promimpl.h> +#include <sys/prom_plat.h> #include <sys/bootconf.h> #include <sys/bootstat.h> +#include <sys/kobj_impl.h> -/* - * Implementation of the "version" boot service. - * Return the compiled version number of this implementation. - * - * Note: An individual service can be tested for and versioned with - * bop_serviceavail(); - * - * Calling spec: - * args[0] Service name string - * args[1] #argument cells - * args[2] #result cells - * args[3] Res0: returned version number - */ -uint_t -bop_getversion(struct bootops *bop) +struct bootops *bootops; +struct bootops kbootops; + +pnode_t chosennode; + +#define FAKE_ROOT (pnode_t)1 + +struct fakeprop { + char *bootname; + pnode_t promnode; + char *promname; +} fakeprops[] = { + { "mfg-name", FAKE_ROOT, "name" }, + { NULL, 0, NULL } +}; + +static void +fakelook_init(void) { - return (bop->bsys_version); + struct fakeprop *fpp = fakeprops; + + while (fpp->bootname != NULL) { + switch (fpp->promnode) { + case FAKE_ROOT: + fpp->promnode = prom_rootnode(); + break; + } + fpp++; + } +} + +static struct fakeprop * +fakelook(const char *prop) +{ + struct fakeprop *fpp = fakeprops; + + while (fpp->bootname != NULL) { + if (strcmp(prop, fpp->bootname) == 0) + return (fpp); + fpp++; + } + return (NULL); } +ihandle_t bfs_ih = OBP_BADNODE; +ihandle_t afs_ih = OBP_BADNODE; + +void +bop_init(void) +{ + chosennode = prom_chosennode(); + + fakelook_init(); + + /* fake bootops - it needs to point to non-NULL */ + bootops = &kbootops; +} + +#define MAXPROMFD 16 + +static ihandle_t prom_ihs[MAXPROMFD]; +int filter_etc = 1; /* * Implementation of the "open" boot service. - * - * Calling spec: - * args[0] Service name string - * args[1] #argument cells - * args[2] #result cells - * args[3] filename string - * args[4] flags - * args[5] Res0: returned result - * */ +/*ARGSUSED*/ int -bop_open(struct bootops *bop, char *name, int flags) +bop_open(const char *name, int flags) +{ + int fd = -1, layered; + ihandle_t ih; + + /* + * Only look underneath archive for /etc files + */ + layered = filter_etc ? + strncmp(name, "/etc", sizeof ("/etc") - 1) == 0 : 1; + + if (afs_ih != OBP_BADNODE) { + ih = afs_ih; + fd = prom_fopen(ih, (char *)name); + if (fd == -1 && !layered) + return (BOOT_SVC_FAIL); + } + if (fd == -1 && bfs_ih != OBP_BADNODE) { + ih = bfs_ih; + fd = prom_fopen(ih, (char *)name); + } + if (fd == -1) + return (BOOT_SVC_FAIL); + ASSERT(fd < MAXPROMFD); + ASSERT(prom_ihs[fd] == 0); + prom_ihs[fd] = ih; + return (fd); +} + +static void +spinner(void) { - boot_cell_t args[6]; - int (*bsys_1275_call)(void *); - - /* use uintptr_t to suppress the gcc warning */ - bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; - args[0] = boot_ptr2cell("open"); - args[1] = 2; - args[2] = 1; - - args[3] = boot_ptr2cell(name); - args[4] = boot_int2cell(flags); - (void) (bsys_1275_call)(args); - return (boot_cell2int(args[5])); + static int pos; + static char ind[] = "|/-\\"; /* that's entertainment? */ + static int blks_read; + + if ((blks_read++ & 0x3) == 0) + prom_printf("%c\b", ind[pos++ & 3]); } /* * Implementation of the "read" boot service. - * - * Calling spec: - * args[0] Service name string - * args[1] #argument cells - * args[2] #result cells - * args[3] boot-opened file descriptor - * args[4] client's buffer - * args[5] size of read request - * args[6] Res0: returned result - * */ int -bop_read(struct bootops *bop, int fd, caddr_t buf, size_t size) +bop_read(int fd, caddr_t buf, size_t size) { - boot_cell_t args[7]; - int (*bsys_1275_call)(void *); - - /* use uintptr_t to suppress the gcc warning */ - bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; - args[0] = boot_ptr2cell("read"); - args[1] = 3; - args[2] = 1; - - args[3] = boot_int2cell(fd); - args[4] = boot_ptr2cell(buf); - args[5] = boot_uint2cell(size); - (void) (bsys_1275_call)(args); - return (boot_cell2int(args[6])); + ASSERT(prom_ihs[fd] != 0); + spinner(); + return (prom_fread(prom_ihs[fd], fd, buf, size)); } /* * Implementation of the "seek" boot service. - * - * Calling spec: - * args[0] Service name string - * args[1] #argument cells - * args[2] #result cells - * args[3] boot-opened file descriptor - * args[4] offset hi XXX just use one cell for offset? - * args[5] offset lo - * args[6] Res0: returned result */ int -bop_seek(struct bootops *bop, int fd, off_t hi, off_t lo) +bop_seek(int fd, off_t off) { - boot_cell_t args[7]; - int (*bsys_1275_call)(void *); - - /* use uintptr_t to suppress the gcc warning */ - bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; - args[0] = boot_ptr2cell("seek"); - args[1] = 3; - args[2] = 1; - - args[3] = boot_int2cell(fd); - args[4] = boot_offt2cell(hi); - args[5] = boot_offt2cell(lo); - (void) (bsys_1275_call)(args); - return (boot_cell2int(args[6])); + ASSERT(prom_ihs[fd] != 0); + return (prom_fseek(prom_ihs[fd], fd, off)); } /* * Implementation of the "close" boot service. - * - * Calling spec: - * args[0] Service name string - * args[1] #argument cells - * args[2] #result cells - * args[3] boot-opened file descriptor - * args[4] Res0: returned result */ int -bop_close(struct bootops *bop, int fd) +bop_close(int fd) { - boot_cell_t args[5]; - int (*bsys_1275_call)(void *); - - /* use uintptr_t to suppress the gcc warning */ - bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; - args[0] = boot_ptr2cell("close"); - args[1] = 1; - args[2] = 1; - - args[3] = boot_int2cell(fd); - (void) (bsys_1275_call)(args); - return (boot_cell2int(args[4])); + ASSERT(prom_ihs[fd] != 0); + prom_fclose(prom_ihs[fd], fd); + prom_ihs[fd] = 0; + return (0); } /* - * Implementation of the "alloc" boot service. + * Simple temp memory allocator * - * Calling spec: - * args[0] Service name string - * args[1] #argument cells - * args[2] #result cells - * args[3] virtual hint - * args[4] size to allocate - * args[5] alignment - * args[6] Res0: returned result + * >PAGESIZE allocations are gotten directly from prom at bighand + * smaller ones are satisfied from littlehand, which does a + * 1 page bighand allocation when it runs out of memory */ -caddr_t -bop_alloc(struct bootops *bop, caddr_t virthint, size_t size, int align) -{ - boot_cell_t args[7]; - int (*bsys_1275_call)(void *); - - /* use uintptr_t to suppress the gcc warning */ - bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; - args[0] = boot_ptr2cell("alloc"); - args[1] = 3; - args[2] = 1; - - args[3] = boot_ptr2cell(virthint); - args[4] = boot_size2cell(size); - args[5] = boot_int2cell(align); - (void) (bsys_1275_call)(args); - return ((caddr_t)(uintptr_t)boot_ptr2cell((uintptr_t)args[6])); -} +static caddr_t bighand = (caddr_t)BOOTTMPBASE; +static caddr_t littlehand = (caddr_t)BOOTTMPBASE; + +#define NTMPALLOC 128 + +static caddr_t temp_base[NTMPALLOC]; +static size_t temp_size[NTMPALLOC]; +static int temp_indx; + +#if defined(C_OBP) +void cobp_free_mem(caddr_t, size_t); +#endif /* C_OBP */ + /* - * Implementation of the "alloc_virt" boot service - * - * Calling spec: - * args[0] Service name string - * args[1] #argument cells - * args[2] #result cells - * args[3] virtual address - * args[4] size to allocate - * args[5] Resi: returned result + * temporary memory storage until bop_tmp_freeall is called + * (after the kernel heap is initialized) */ caddr_t -bop_alloc_virt(struct bootops *bop, caddr_t virt, size_t size) +bop_temp_alloc(size_t size, int align) { - boot_cell_t args[6]; - int (*bsys_1275_call)(void *); - - /* use uintptr_t to suppress the gcc warning */ - bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; - args[0] = boot_ptr2cell("alloc_virt"); - args[1] = 2; - args[2] = 1; - - args[3] = boot_ptr2cell(virt); - args[4] = boot_size2cell(size); - (void) (bsys_1275_call)(args); - return ((caddr_t)(uintptr_t)boot_ptr2cell((uintptr_t)args[5])); + caddr_t ret; + + /* + * OBP allocs 10MB to boot, which is where virthint = 0 + * memory was allocated from. Without boot, we allocate + * from BOOTTMPBASE and free when we're ready to take + * the machine from OBP + */ + if (size < PAGESIZE) { + size_t left = + ALIGN(littlehand, PAGESIZE) - (uintptr_t)littlehand; + + size = roundup(size, MAX(align, 8)); + if (size <= left) { + ret = littlehand; + littlehand += size; + return (ret); + } + littlehand = bighand + size; + } + size = roundup(size, PAGESIZE); + ret = prom_alloc(bighand, size, align); + if (ret == NULL) + prom_panic("boot temp overflow"); + bighand += size; + + /* log it for bop_fini() */ + temp_base[temp_indx] = ret; + temp_size[temp_indx] = size; + if (++temp_indx == NTMPALLOC) + prom_panic("out of bop temp space"); + + return (ret); } -/* - * Implementation of the "free" boot service. - * - * Calling spec: - * args[0] Service name string - * args[1] #argument cells - * args[2] #result cells - * args[3] virtual hint - * args[4] size to free - * args[5] Res0: returned result - */ -/*ARGSUSED*/ void -bop_free(struct bootops *bop, caddr_t virt, size_t size) +bop_temp_freeall(void) { - boot_cell_t args[6]; - int (*bsys_1275_call)(void *); - - /* use uintptr_t to suppress the gcc warning */ - bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; - args[0] = boot_ptr2cell("free"); - args[1] = 2; - args[2] = 1; - - args[3] = boot_ptr2cell(virt); - args[4] = boot_size2cell(size); - (void) (bsys_1275_call)(args); + int i; + + /* + * We have to call prom_free() with the same args + * as we used in prom_alloc() + */ + for (i = 0; i < NTMPALLOC; i++) { + if (temp_base[i] == NULL) + break; +#if !defined(C_OBP) + prom_free(temp_base[i], temp_size[i]); +#else /* !C_OBP */ + cobp_free_mem(temp_base[i], temp_size[i]); +#endif /* !C_OBP */ + } } + /* - * Implementation of the "map" boot service. - * - * Calling spec: - * args[0] Service name string - * args[1] #argument cells - * args[2] #result cells - * args[3] virtual address - * args[4] space of phys addr - * args[5] phys addr - * args[6] size - * args[7] Res0: returned result + * Implementation of the "alloc" boot service. */ -/*ARGSUSED*/ caddr_t -bop_map(struct bootops *bop, caddr_t virt, int space, - caddr_t phys, size_t size) +bop_alloc(caddr_t virthint, size_t size, int align) { - boot_cell_t args[8]; - int (*bsys_1275_call)(void *); - - /* use uintptr_t to suppress the gcc warning */ - bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; - args[0] = boot_ptr2cell("map"); - args[1] = 3; - args[2] = 1; - - args[3] = boot_ptr2cell(virt); - args[4] = boot_int2cell(space); - args[5] = boot_ptr2cell(phys); - args[6] = boot_size2cell(size); - (void) (bsys_1275_call)(args); - return ((caddr_t)boot_cell2ptr(args[7])); + if (virthint == NULL) + return (bop_temp_alloc(size, align)); + return (prom_alloc(virthint, size, align)); } /* - * Implementation of the "unmap" boot service. - * - * Calling spec: - * args[0] Service name string - * args[1] #argument cells - * args[2] #result cells - * args[3] virtual address - * args[4] size of chunk - * args[5] Res0: returned result + * Implementation of the "alloc_virt" boot service */ -/*ARGSUSED*/ -void -bop_unmap(struct bootops *bop, caddr_t virt, size_t size) +caddr_t +bop_alloc_virt(caddr_t virt, size_t size) { - boot_cell_t args[6]; - int (*bsys_1275_call)(void *); - - /* use uintptr_t to suppress the gcc warning */ - bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; - args[0] = boot_ptr2cell("unmap"); - args[1] = 2; - args[2] = 1; - - args[3] = boot_ptr2cell(virt); - args[4] = boot_size2cell(size); - (void) (bsys_1275_call)(args); + return (prom_claim_virt(size, virt)); } /* - * Implementation of the "quiesce" boot service. - * - * Calling spec: - * args[0] Service name string - * args[1] #argument cells - * args[2] #result cells - * args[3] Res0: returned result + * Implementation of the "free" boot service. */ /*ARGSUSED*/ void -bop_quiesce_io(struct bootops *bop) +bop_free(caddr_t virt, size_t size) { - boot_cell_t args[4]; - int (*bsys_1275_call)(void *); + prom_free(virt, size); +} - /* use uintptr_t to suppress the gcc warning */ - bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; - args[0] = boot_ptr2cell("quiesce"); - args[1] = 0; - args[2] = 1; - (void) (bsys_1275_call)(args); -} /* * Implementation of the "getproplen" boot service. - * - * Calling spec: - * args[0] Service name string - * args[1] #argument cells - * args[2] #result cells - * args[3] property name string - * args[4] Res0: returned result */ /*ARGSUSED*/ int -bop_getproplen(struct bootops *bop, char *name) +bop_getproplen(const char *name) { - boot_cell_t args[7]; - int (*bsys_1275_call)(void *); - - /* use uintptr_t to suppress the gcc warning */ - bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; - args[0] = boot_ptr2cell("getproplen"); - args[1] = 1; - args[2] = 1; - - args[3] = boot_ptr2cell(name); - (void) (bsys_1275_call)(args); - return (boot_cell2int(args[4])); + struct fakeprop *fpp; + pnode_t node; + char *prop; + + fpp = fakelook(name); + if (fpp != NULL) { + node = fpp->promnode; + prop = fpp->promname; + } else { + node = chosennode; + prop = (char *)name; + } + return (prom_getproplen(node, prop)); } /* * Implementation of the "getprop" boot service. - * - * Calling spec: - * args[0] Service name string - * args[1] #argument cells - * args[2] #result cells - * args[3] property name string - * args[4] buffer pointer to hold value of the property - * args[5] Res0: returned result */ /*ARGSUSED*/ int -bop_getprop(struct bootops *bop, char *name, void *value) +bop_getprop(const char *name, void *value) { - boot_cell_t args[6]; - int (*bsys_1275_call)(void *); - - /* use uintptr_t to suppress the gcc warning */ - bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; - args[0] = boot_ptr2cell("getprop"); - args[1] = 2; - args[2] = 1; - - args[3] = boot_ptr2cell(name); - args[4] = boot_ptr2cell(value); - (void) (bsys_1275_call)(args); - return (boot_cell2int(args[5])); + struct fakeprop *fpp; + pnode_t node; + char *prop; + + fpp = fakelook(name); + if (fpp != NULL) { + node = fpp->promnode; + prop = fpp->promname; + } else { + node = chosennode; + prop = (char *)name; + } + return (prom_getprop(node, prop, value)); } /* - * Implementation of the "nextprop" boot service. - * - * Calling spec: - * args[0] Service name string - * args[1] #argument cells - * args[2] #result cells - * args[3] previous property name string - * args[4] Res0: returned result + * Implementation of the "print" boot service. */ /*ARGSUSED*/ -char * -bop_nextprop(struct bootops *bop, char *prevprop) +void +bop_printf(void *ops, const char *fmt, ...) { - boot_cell_t args[5]; - int (*bsys_1275_call)(void *); - - /* use uintptr_t to suppress the gcc warning */ - bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; - args[0] = boot_ptr2cell("nextprop"); - args[1] = 1; - args[2] = 1; - - args[3] = boot_ptr2cell(prevprop); - (void) (bsys_1275_call)(args); - return ((char *)boot_cell2ptr(args[4])); + va_list adx; + + va_start(adx, fmt); + prom_vprintf(fmt, adx); + va_end(adx); } /* - * Implementation of the "puts" boot service. - * - * Calling spec: - * args[0] Service name string - * args[1] #argument cells - * args[2] #result cells - * args[3] string to print + * Special routine for kmdb */ -/*ARGSUSED*/ void -bop_puts(struct bootops *bop, char *string) +bop_putsarg(const char *fmt, char *arg) { - boot_cell_t args[6]; - int (*bsys_1275_call)(void *); - void (*bsys_printf)(struct bootops *, char *, ...); - - /* so new kernel, old boot can print a message before dying */ - if (!BOOTOPS_ARE_1275(bop)) { - /* use uintptr_t to suppress the gcc warning */ - bsys_printf = (void (*)(struct bootops *, char *, ...)) - (uintptr_t)bop->bsys_printf; - (*bsys_printf)(bop, string); - return; - } - - bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; - args[0] = boot_ptr2cell("puts"); - args[1] = 1; - args[2] = 0; - - args[3] = boot_ptr2cell(string); - (void) (bsys_1275_call)(args); - + prom_printf(fmt, arg); } /* - * Implementation of the "putsarg" boot service. - * - * Calling spec: - * args[0] Service name string - * args[1] #argument cells - * args[2] #result cells - * args[3] string to print (with '%*' format) - * args[4] 64-bit thing to print + * panic for krtld only */ -/*ARGSUSED*/ void -bop_putsarg(struct bootops *bop, const char *string, ...) +bop_panic(const char *s) { - boot_cell_t args[6]; - int (*bsys_1275_call)(void *); - void (*bsys_printf)(struct bootops *, char *, ...); - va_list ap; - const char *fmt = string; - int ells = 0; - uint64_t arg; - - /* - * We need to do the minimum printf-like stuff here to figure - * out the size of argument, if present. - */ - while (*fmt) { - if (*fmt++ != '%') - continue; - if (*fmt == '%') { - fmt++; - continue; - } - - while (*fmt >= '0' && *fmt <= '9') - fmt++; - for (ells = 0; *fmt == 'l'; fmt++) - ells++; - va_start(ap, string); - switch (*fmt) { - case 's': - /* use uintptr_t to suppress the gcc warning */ - arg = (uint64_t)(uintptr_t)va_arg(ap, char *); - break; - case 'p': - arg = (uint64_t)(uintptr_t)va_arg(ap, void *); - break; - case 'd': - case 'D': - case 'x': - case 'X': - case 'u': - case 'U': - case 'o': - case 'O': - if (ells == 0) - arg = (uint64_t)va_arg(ap, uint_t); - else if (ells == 1) - arg = (uint64_t)va_arg(ap, ulong_t); - else - arg = (uint64_t)va_arg(ap, uint64_t); - break; - default: - arg = (uint64_t)va_arg(ap, uint_t); - break; - } - va_end(ap); - break; - } - - /* so new kernel, old boot can print a message before dying */ - if (!BOOTOPS_ARE_1275(bop)) { - /* use uintptr_t to suppress the gcc warning */ - bsys_printf = (void (*)(struct bootops *, char *, ...)) - (uintptr_t)bop->bsys_printf; - (*bsys_printf)(bop, (char *)string, arg); - return; - } - - bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; - args[0] = boot_ptr2cell("putsarg"); - args[1] = 2; - args[2] = 0; - args[3] = boot_ptr2cell(string); - args[4] = boot_uint642cell(arg); - - (void) (bsys_1275_call)(args); + prom_panic((char *)s); } /* * Implementation of the "mount" boot service. * - * Calling spec: - * args[0] Service name string - * args[1] #argument cells - * args[2] #result cells - * args[3] pathname string - * args[4] Res0: returned result */ /*ARGSUSED*/ int -bop_mountroot(struct bootops *bop, char *path) +bop_mountroot(void) { - boot_cell_t args[5]; - int (*bsys_1275_call)(void *); - - /* use uintptr_t to suppress the gcc warning */ - bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; - args[0] = boot_ptr2cell("mountroot"); - args[1] = 2; - args[2] = 1; - - args[3] = boot_ptr2cell(path); - (void) (bsys_1275_call)(args); - return (boot_cell2int(args[4])); + (void) prom_getprop(chosennode, "bootfs", (caddr_t)&bfs_ih); + (void) prom_getprop(chosennode, "archfs", (caddr_t)&afs_ih); + return ((bfs_ih == -1 && afs_ih == -1) ? BOOT_SVC_FAIL : BOOT_SVC_OK); } /* * Implementation of the "unmountroot" boot service. - * - * Calling spec: - * args[0] Service name string - * args[1] #argument cells - * args[2] #result cells - * args[3] Res0: returned result */ /*ARGSUSED*/ int -bop_unmountroot(struct bootops *bop) +bop_unmountroot(void) { - boot_cell_t args[4]; - int (*bsys_1275_call)(void *); - - /* use uintptr_t to suppress the gcc warning */ - bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; - args[0] = boot_ptr2cell("unmountroot"); - args[1] = 0; - args[2] = 1; - (void) (bsys_1275_call)(args); - return (boot_cell2int(args[3])); + if (bfs_ih != OBP_BADNODE) { + (void) prom_close(bfs_ih); + bfs_ih = OBP_BADNODE; + } + if (afs_ih != OBP_BADNODE) { + (void) prom_close(afs_ih); + afs_ih = OBP_BADNODE; + } + return (BOOT_SVC_OK); } /* - * Implementation of the "serviceavail" boot service. - * - * Calling spec: - * args[0] Service name string - * args[1] #argument cells - * args[2] #result cells - * args[3] name string of service to be tested for - * args[4] Res0: returned version number or 0 + * Implementation of the "fstat" boot service. */ -/*ARGSUSED*/ int -bop_serviceavail(struct bootops *bop, char *name) +bop_fstat(int fd, struct bootstat *st) { - /* use uintptr_t to suppress the gcc warning */ - boot_cell_t args[5]; - int (*bsys_1275_call)(void *) = - (int (*)(void *))(uintptr_t)bop->bsys_1275_call; - - args[0] = boot_ptr2cell("serviceavail"); - args[1] = 1; - args[2] = 1; - - args[3] = boot_ptr2cell(name); - (void) (bsys_1275_call)(args); - return (boot_cell2int(args[4])); + ASSERT(prom_ihs[fd] != 0); + return (prom_fsize(prom_ihs[fd], fd, (size_t *)&st->st_size)); } +int +boot_compinfo(int fd, struct compinfo *cb) +{ + ASSERT(prom_ihs[fd] != 0); + return (prom_compinfo(prom_ihs[fd], fd, + &cb->iscmp, &cb->fsize, &cb->blksize)); +} + +void +bop_free_archive(void) +{ + char archive[OBP_MAXPATHLEN]; + pnode_t arph; + uint32_t arbase, arsize, alloc_size; + + /* + * If the ramdisk will eventually be root, or we weren't + * booted via the archive, then nothing to do here + */ + if (root_is_ramdisk == B_TRUE || + prom_getprop(chosennode, "bootarchive", archive) == -1) + return; + arph = prom_finddevice(archive); + if (arph == -1 || + prom_getprop(arph, OBP_ALLOCSIZE, (caddr_t)&alloc_size) == -1 || + prom_getprop(arph, OBP_SIZE, (caddr_t)&arsize) == -1 || + prom_getprop(arph, OBP_ADDRESS, (caddr_t)&arbase) == -1) + prom_panic("can't free boot archive"); + +#if !defined(C_OBP) + if (alloc_size == 0) + prom_free((caddr_t)(uintptr_t)arbase, arsize); + else { + uint32_t arend = arbase + arsize; + + while (arbase < arend) { + prom_free((caddr_t)(uintptr_t)arbase, + MIN(alloc_size, arend - arbase)); + arbase += alloc_size; + } + } +#else /* !C_OBP */ + cobp_free_mem((caddr_t)(uintptr_t)arbase, arsize); +#endif /* !C_OBP */ +} + +#if defined(C_OBP) /* - * Implementation of the "fstat" boot service. - * - * Calling spec: - * args[0] Service name string - * args[1] #argument cells - * args[2] #result cells - * args[3] fd - * args[4] client's stat structure + * Blech. The C proms have a bug when freeing areas that cross + * page sizes, so we have to break up the free into sections + * bounded by the various pagesizes. */ -int -bop_fstat(struct bootops *bop, int fd, struct bootstat *st) +void +cobp_free_mem(caddr_t base, size_t size) { - boot_cell_t args[6]; - int (*bsys_1275_call)(void *); - - /* use uintptr_t to suppress the gcc warning */ - bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; - args[0] = boot_ptr2cell("fstat"); - args[1] = 2; - args[2] = 1; - args[3] = boot_int2cell(fd); - args[4] = boot_ptr2cell(st); - (void) (bsys_1275_call)(args); - return (boot_cell2int(args[5])); + int i; + size_t len, pgsz; + + /* + * Large pages only used when size > 512k + */ + if (size < MMU_PAGESIZE512K || + ((uintptr_t)base & MMU_PAGEOFFSET512K) != 0) { + prom_free(base, size); + return; + } + for (i = 3; i >= 0; i--) { + pgsz = page_get_pagesize(i); + if (size < pgsz) + continue; + len = size & ~(pgsz - 1); + prom_free(base, len); + base += len; + size -= len; + } } +#endif /* C_OBP */ + /* * Implementation of the "enter_mon" boot service. - * - * Calling spec: - * args[0] Service name string - * args[1] #argument cells (0) - * args[2] #result cells (0) */ void -bop_enter_mon(struct bootops *bop) +bop_enter_mon(void) +{ + prom_enter_mon(); +} + +/* + * free elf info allocated by booter + */ +void +bop_free_elf(void) +{ + uint32_t eadr; + uint32_t esize; + extern Addr dynseg; + extern size_t dynsize; + + if (bop_getprop("elfheader-address", (caddr_t)&eadr) == -1 || + bop_getprop("elfheader-length", (caddr_t)&esize) == -1) + prom_panic("missing elfheader"); + prom_free((caddr_t)(uintptr_t)eadr, roundup(esize, PAGESIZE)); + + prom_free((caddr_t)(uintptr_t)dynseg, roundup(dynsize, PAGESIZE)); +} + + +/* Simple message to indicate that the bootops pointer has been zeroed */ +#ifdef DEBUG +int bootops_gone_on = 0; +#define BOOTOPS_GONE() \ + if (bootops_gone_on) \ + prom_printf("The bootops vec is zeroed now!\n"); +#else +#define BOOTOPS_GONE() +#endif /* DEBUG */ + +void +bop_fini(void) { - boot_cell_t args[4]; - int (*bsys_1275_call)(void *); - - /* use uintptr_t to suppress the gcc warning */ - bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; - args[0] = boot_ptr2cell("enter_mon"); - args[1] = 0; - args[2] = 0; - (void) (bsys_1275_call)(args); + bop_free_archive(); + (void) bop_unmountroot(); + bop_free_elf(); + bop_temp_freeall(); + + bootops = (struct bootops *)NULL; + BOOTOPS_GONE(); } diff --git a/usr/src/uts/sun/sys/bootconf.h b/usr/src/uts/sun/sys/bootconf.h index beaa49a17c..814b84ef61 100644 --- a/usr/src/uts/sun/sys/bootconf.h +++ b/usr/src/uts/sun/sys/bootconf.h @@ -33,8 +33,11 @@ */ #include <sys/types.h> +#include <sys/varargs.h> +#include <sys/sysmacros.h> #include <sys/memlist.h> #include <sys/bootstat.h> +#include <net/if.h> /* for IFNAMSIZ */ #ifdef __cplusplus extern "C" { @@ -72,26 +75,12 @@ typedef struct bootops { uint_t bsys_version; /* - * pointer to our parents bootops - */ - struct bootops *bsys_super; - - /* - * the area containing boot's memlists (non-LP64 boot) - */ - struct bsys_mem *boot_mem; - -#ifndef _LP64 - uint32_t bsys_pad2[2]; /* pointers above get larger */ -#endif - /* * The entry point to jump to for boot services. * Pass this routine the array of boot_cell_t's describing the * service requested. */ uint64_t bsys_1275_call; - uint32_t bsys_pad1[7]; /* * print formatted output - PRINTFLIKE1 * here (and maintained) so old kernels can fail with @@ -101,51 +90,43 @@ typedef struct bootops { uint32_t bsys_printf; } bootops_t; -extern uint_t bop_getversion(struct bootops *bootops); -extern int bop_open(struct bootops *bop, char *s, int flags); -extern int bop_read(struct bootops *bop, int fd, caddr_t buf, size_t size); -extern int bop_seek(struct bootops *bop, int fd, off_t hi, off_t lo); -extern int bop_close(struct bootops *bop, int fd); -extern caddr_t bop_alloc(struct bootops *bop, caddr_t virthint, size_t size, - int align); -extern caddr_t bop_alloc_virt(struct bootops *bop, caddr_t virt, size_t size); -extern void bop_free(struct bootops *bop, caddr_t virt, size_t size); -extern caddr_t bop_map(struct bootops *bop, caddr_t virt, int space, - caddr_t phys, size_t size); -extern void bop_unmap(struct bootops *bop, caddr_t virt, size_t size); -extern void bop_quiesce_io(struct bootops *bop); -extern int bop_getproplen(struct bootops *bop, char *name); -extern int bop_getprop(struct bootops *bop, char *name, void *value); -extern char *bop_nextprop(struct bootops *bop, char *prevprop); -extern int bop_mountroot(struct bootops *bop, char *path); -extern int bop_unmountroot(struct bootops *bop); -extern void bop_puts(struct bootops *, char *); -extern void bop_putsarg(struct bootops *, const char *, ...); -extern int bop_fstat(struct bootops *, int fd, struct bootstat *); -extern void bop_enter_mon(struct bootops *bop); - -#define BOP_GETVERSION(bop) bop_getversion(bop) -#define BOP_OPEN(bop, s, flags) bop_open(bop, s, flags) -#define BOP_READ(bop, fd, buf, size) bop_read(bop, fd, buf, size) -#define BOP_SEEK(bop, fd, hi, lo) bop_seek(bop, fd, hi, lo) -#define BOP_CLOSE(bop, fd) bop_close(bop, fd) +extern void bop_init(void); +extern int bop_open(const char *s, int flags); +extern int bop_read(int fd, caddr_t buf, size_t size); +extern int bop_seek(int fd, off_t off); +extern int bop_close(int fd); +extern caddr_t bop_alloc(caddr_t virthint, size_t size, int align); +extern caddr_t bop_alloc_virt(caddr_t virt, size_t size); +extern caddr_t bop_temp_alloc(size_t size, int align); +extern void bop_free(caddr_t virt, size_t size); +extern int bop_getproplen(const char *name); +extern int bop_getprop(const char *name, void *value); +extern int bop_mountroot(void); +extern int bop_unmountroot(void); +extern int bop_fstat(int fd, struct bootstat *st); +extern void bop_enter_mon(void); +extern void bop_fini(void); + +extern void bop_printf(void *ops, const char *fmt, ...); +extern void bop_putsarg(const char *fmt, char *arg); +extern void bop_panic(const char *s); + +#define BOP_OPEN(s, flags) bop_open(s, flags) +#define BOP_READ(fd, buf, size) bop_read(fd, buf, size) +#define BOP_SEEK(fd, off) bop_seek(fd, off) +#define BOP_CLOSE(fd) bop_close(fd) #define BOP_ALLOC(bop, virthint, size, align) \ - bop_alloc(bop, virthint, size, align) -#define BOP_ALLOC_VIRT(bop, virt, size) bop_alloc_virt(bop, virt, size) -#define BOP_FREE(bop, virt, size) bop_free(bop, virt, size) -#define BOP_MAP(bop, virt, space, phys, size) \ - bop_map(bop, virt, space, phys, size) -#define BOP_UNMAP(bop, virt, size) bop_unmap(bop, virt, size) -#define BOP_QUIESCE_IO(bop) bop_quiesce_io(bop) -#define BOP_GETPROPLEN(bop, name) bop_getproplen(bop, name) -#define BOP_GETPROP(bop, name, buf) bop_getprop(bop, name, buf) -#define BOP_NEXTPROP(bop, prev) bop_nextprop(bop, prev) -#define BOP_MOUNTROOT(bop, path) bop_mountroot(bop, path) -#define BOP_UNMOUNTROOT(bop) bop_unmountroot(bop) -#define BOP_PUTS(bop, msg) bop_puts(bop, msg) -#define BOP_PUTSARG(bop, msg, arg) bop_putsarg(bop, msg, arg) -#define BOP_FSTAT(bop, fd, st) bop_fstat(bop, fd, st) -#define BOP_ENTER_MON(bop) bop_enter_mon(bop) + bop_alloc(virthint, size, align) +#define BOP_ALLOC_VIRT(virt, size) bop_alloc_virt(virt, size) +#define BOP_FREE(bop, virt, size) bop_free(virt, size) +#define BOP_GETPROPLEN(bop, name) bop_getproplen(name) +#define BOP_GETPROP(bop, name, buf) bop_getprop(name, buf) +#define BOP_MOUNTROOT() bop_mountroot() +#define BOP_UNMOUNTROOT() bop_unmountroot() +#define BOP_FSTAT(bop, fd, st) bop_fstat(fd, st) + +/* special routine for kmdb only */ +#define BOP_PUTSARG(bop, fmt, arg) bop_putsarg(fmt, arg) /* * macros and declarations needed by clients of boot to @@ -243,6 +224,8 @@ extern char kern_bootargs[]; extern char *kobj_module_path; extern char *default_path; extern char *dhcack; +extern int dhcacklen; +extern char dhcifname[IFNAMSIZ]; extern char *netdev_path; extern char *strplumb_get_netdev_path(void); diff --git a/usr/src/uts/sun/sys/obpdefs.h b/usr/src/uts/sun/sys/obpdefs.h index d209af3d90..2a9fb15989 100644 --- a/usr/src/uts/sun/sys/obpdefs.h +++ b/usr/src/uts/sun/sys/obpdefs.h @@ -74,6 +74,8 @@ typedef phandle_t pnode_t; #define OBP_IPI "ipi3" #define OBP_CPU "cpu" #define OBP_ADDRESS "address" +#define OBP_SIZE "size" +#define OBP_ALLOCSIZE "alloc-size" /* * OBP status values defines diff --git a/usr/src/uts/sun/sys/promif.h b/usr/src/uts/sun/sys/promif.h index a31fa87f05..bd761e6fa0 100644 --- a/usr/src/uts/sun/sys/promif.h +++ b/usr/src/uts/sun/sys/promif.h @@ -312,6 +312,18 @@ extern pnode_t prom_findnode_bydevtype(pnode_t id, char *devtype); prom_enter_mon(); \ } +/* + * file IO + */ +extern int prom_fopen(ihandle_t, char *); +extern int prom_fseek(ihandle_t, int, unsigned long long); +extern int prom_fread(ihandle_t, int, caddr_t, size_t); +extern int prom_fsize(ihandle_t, int, size_t *); +extern int prom_compinfo(ihandle_t, int, int *, + size_t *, size_t *); +extern void prom_fclose(ihandle_t, int); + + #endif /* _KERNEL || _KMDB */ #ifdef _KERNEL diff --git a/usr/src/uts/sun4/conf/Mapfile b/usr/src/uts/sun4/conf/Mapfile index 1ed243344f..9a0dd0b984 100644 --- a/usr/src/uts/sun4/conf/Mapfile +++ b/usr/src/uts/sun4/conf/Mapfile @@ -1,13 +1,12 @@ # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -42,7 +41,11 @@ data | .data; data : $PROGBITS ?AW; data : $NOBITS ?AW; -reloc = LOAD ?RW V0x0; +# +# put reloc seg in space between text and data +# it will be freed by the kernel after use +# +reloc = LOAD ?RW V0x01402000; reloc : $DYNSYM; reloc : $HASH; reloc : .dynstr; diff --git a/usr/src/uts/sun4/os/forthdebug.c b/usr/src/uts/sun4/os/forthdebug.c index c2f9ab9f1e..244905d96e 100644 --- a/usr/src/uts/sun4/os/forthdebug.c +++ b/usr/src/uts/sun4/os/forthdebug.c @@ -96,7 +96,7 @@ forthdebug_init(void) char *fth_buf, *buf_p; ulong_t modsym; int i, sz; - struct bootstat bstat; + uint64_t fsz; struct _buf *file; if (!forthdebug_supported) { @@ -113,20 +113,20 @@ forthdebug_init(void) return; } - i = BOP_FSTAT(bootops, file->_fd, &bstat); - if (i || !bstat.st_size) { + i = kobj_get_filesize(file, &fsz); + if (i || !fsz) { cmn_err(CE_CONT, "Can't stat %s stat=%x sz=%llx\n", - FDEBUGFILE, i, (long long)bstat.st_size); + FDEBUGFILE, i, (long long)fsz); goto err_stat; } - fth_buf = (char *)kobj_zalloc(bstat.st_size + 1, KM_SLEEP); - sz = kobj_read_file(file, fth_buf, bstat.st_size, 0); /* entire file */ + fth_buf = (char *)kobj_zalloc(fsz + 1, KM_SLEEP); + sz = kobj_read_file(file, fth_buf, fsz, 0); /* entire file */ if (sz < 0) { cmn_err(CE_CONT, "Error(%d) reading %s\n", sz, FDEBUGFILE); goto done; } - ASSERT(bstat.st_size == sz); + ASSERT(fsz == sz); fth_buf[sz] = 0; /* resolve all essential symbols in basic_sym[] */ @@ -176,7 +176,7 @@ forthdebug_init(void) debug_enter("Defer breakpoint enabled. Add breakpoints, then"); } done: - kobj_free(fth_buf, bstat.st_size + 1); + kobj_free(fth_buf, fsz + 1); err_stat: kobj_close_file(file); diff --git a/usr/src/uts/sun4/os/memlist.c b/usr/src/uts/sun4/os/memlist.c index 9fbac7d65b..cbef1ec58d 100644 --- a/usr/src/uts/sun4/os/memlist.c +++ b/usr/src/uts/sun4/os/memlist.c @@ -86,6 +86,7 @@ #include <sys/memlist_plat.h> #include <sys/systeminfo.h> #include <sys/promif.h> +#include <sys/prom_plat.h> u_longlong_t spec_hole_start = 0x80000000000ull; u_longlong_t spec_hole_end = 0xfffff80000000000ull; @@ -102,29 +103,9 @@ num_phys_pages() return (npages); } -/* - * Count the number of available pages and the number of - * chunks in the list of available memory. - */ -void -size_physavail( - u_longlong_t *physavail, - size_t nelems, - pgcnt_t *npages, - int *memblocks) -{ - size_t i; - - *npages = 0; - *memblocks = 0; - for (i = 0; i < nelems; i += 2) { - *npages += (pgcnt_t)(physavail[i+1] >> PAGESHIFT); - (*memblocks)++; - } -} pgcnt_t -size_virtalloc(u_longlong_t *avail, size_t nelems) +size_virtalloc(prom_memlist_t *avail, size_t nelems) { u_longlong_t start, end; @@ -132,10 +113,10 @@ size_virtalloc(u_longlong_t *avail, size_t nelems) uint_t hole_allocated = 0; uint_t i; - for (i = 0; i < (nelems - 2); i += 2) { + for (i = 0; i < nelems - 1; i++) { - start = avail[i] + avail[i + 1]; - end = avail[i + 2]; + start = avail[i].addr + avail[i].size; + end = avail[i + 1].addr; /* * Notes: @@ -195,182 +176,197 @@ get_max_phys_size( } -/* - * Copy boot's physavail list deducting memory at "start" - * for "size" bytes. - */ -int -copy_physavail( - u_longlong_t *src, - size_t nelems, - struct memlist **dstp, - uint_t start, - uint_t size) -{ - struct memlist *dst, *prev; - uint_t end1; - int deducted = 0; - size_t i; - dst = *dstp; - prev = dst; - end1 = start + size; - - for (i = 0; i < nelems; i += 2) { - uint64_t addr, lsize, end2; - - addr = src[i]; - lsize = src[i+1]; - end2 = addr + lsize; - - if ((size != 0) && start >= addr && end1 <= end2) { - /* deducted range in this chunk */ - deducted = 1; - if (start == addr) { - /* abuts start of chunk */ - if (end1 == end2) - /* is equal to the chunk */ - continue; - dst->address = end1; - dst->size = lsize - size; - } else if (end1 == end2) { - /* abuts end of chunk */ - dst->address = addr; - dst->size = lsize - size; - } else { - /* in the middle of the chunk */ - dst->address = addr; - dst->size = start - addr; - dst->next = 0; - if (prev == dst) { - dst->prev = 0; - dst++; - } else { - dst->prev = prev; - prev->next = dst; - dst++; - prev++; - } - dst->address = end1; - dst->size = end2 - end1; - } - dst->next = 0; - if (prev == dst) { - dst->prev = 0; - dst++; - } else { - dst->prev = prev; - prev->next = dst; - dst++; - prev++; - } - } else { - dst->address = src[i]; - dst->size = src[i+1]; - dst->next = 0; - if (prev == dst) { - dst->prev = 0; - dst++; - } else { - dst->prev = prev; - prev->next = dst; - dst++; - prev++; - } - } - } +struct vnode prom_ppages; - *dstp = dst; - return (deducted); -} +static void +more_pages(uint64_t base, uint64_t len) +{ + void kphysm_add(); -struct vnode prom_ppages; + kphysm_add(base, len, 1); +} -/* - * Find the pages allocated by the prom by diffing the original - * phys_avail list and the current list. In the difference, the - * pages not locked belong to the PROM. (The kernel has already locked - * and removed all the pages it has allocated from the freelist, this - * routine removes the remaining "free" pages that really belong to the - * PROM and hashs them in on the 'prom_pages' vnode.) - */ -void -fix_prom_pages(struct memlist *orig, struct memlist *new) +static void +less_pages(uint64_t base, uint64_t len) { - struct memlist *list, *nlist; + uint64_t pa, end = base + len; extern int kcage_on; - nlist = new; - for (list = orig; list; list = list->next) { - uint64_t pa, end; + for (pa = base; pa < end; pa += PAGESIZE) { pfn_t pfnum; page_t *pp; - if (list->address == nlist->address && - list->size == nlist->size) { - nlist = nlist->next ? nlist->next : nlist; + pfnum = (pfn_t)(pa >> PAGESHIFT); + if ((pp = page_numtopp_nolock(pfnum)) == NULL) + cmn_err(CE_PANIC, "missing pfnum %lx", pfnum); + + /* + * must break up any large pages that may have + * constituent pages being utilized for + * prom_alloc()'s. page_reclaim() can't handle + * large pages. + */ + if (pp->p_szc != 0) + page_boot_demote(pp); + + if (!PAGE_LOCKED(pp) && pp->p_lckcnt == 0) { + /* + * Ahhh yes, a prom page, + * suck it off the freelist, + * lock it, and hashin on prom_pages vp. + */ + if (page_trylock(pp, SE_EXCL) == 0) + cmn_err(CE_PANIC, "prom page locked"); + + (void) page_reclaim(pp, NULL); + /* + * vnode offsets on the prom_ppages vnode + * are page numbers (gack) for >32 bit + * physical memory machines. + */ + (void) page_hashin(pp, &prom_ppages, + (offset_t)pfnum, NULL); + + if (kcage_on) { + ASSERT(pp->p_szc == 0); + PP_SETNORELOC(pp); + } + (void) page_pp_lock(pp, 0, 1); + } + } +} + +void +diff_memlists(struct memlist *proto, struct memlist *diff, void (*func)()) +{ + uint64_t p_base, p_end, d_base, d_end; + + while (proto != NULL) { + /* + * find diff item which may overlap with proto item + * if none, apply func to all of proto item + */ + while (diff != NULL && + proto->address >= diff->address + diff->size) + diff = diff->next; + if (diff == NULL) { + (*func)(proto->address, proto->size); + proto = proto->next; + continue; + } + if (proto->address == diff->address && + proto->size == diff->size) { + proto = proto->next; + diff = diff->next; continue; } + p_base = proto->address; + p_end = p_base + proto->size; + d_base = diff->address; + d_end = d_base + diff->size; /* - * Loop through the old list looking to - * see if each page is still in the new one. - * If a page is not in the new list then we - * check to see if it locked permanently. - * If so, the kernel allocated and owns it. - * If not, then the prom must own it. We - * remove any pages found to owned by the prom - * from the freelist. + * here p_base < d_end + * there are 5 cases */ - end = list->address + list->size; - for (pa = list->address; pa < end; pa += PAGESIZE) { - if (address_in_memlist(new, pa, PAGESIZE)) - continue; + /* + * d_end + * d_base + * p_end + * p_base + * + * apply func to all of proto item + */ + if (p_end <= d_base) { + (*func)(p_base, proto->size); + proto = proto->next; + continue; + } - pfnum = (pfn_t)(pa >> PAGESHIFT); - if ((pp = page_numtopp_nolock(pfnum)) == NULL) - cmn_err(CE_PANIC, "missing pfnum %lx", pfnum); + /* + * ... + * d_base + * p_base + * + * normalize by applying func from p_base to d_base + */ + if (p_base < d_base) + (*func)(p_base, d_base - p_base); + if (p_end <= d_end) { /* - * must break up any large pages that may have - * constituent pages being utilized for - * BOP_ALLOC()'s. page_reclaim() can't handle - * large pages. + * d_end + * p_end + * d_base + * p_base + * + * -or- + * + * d_end + * p_end + * p_base + * d_base + * + * any non-overlapping ranges applied above, + * so just continue */ - if (pp->p_szc != 0) - page_boot_demote(pp); - - if (!PAGE_LOCKED(pp) && pp->p_lckcnt == 0) { - /* - * Ahhh yes, a prom page, - * suck it off the freelist, - * lock it, and hashin on prom_pages vp. - */ - if (page_trylock(pp, SE_EXCL) == 0) - cmn_err(CE_PANIC, "prom page locked"); - - (void) page_reclaim(pp, NULL); - /* - * XXX vnode offsets on the prom_ppages vnode - * are page numbers (gack) for >32 bit - * physical memory machines. - */ - (void) page_hashin(pp, &prom_ppages, - (offset_t)pfnum, NULL); - - if (kcage_on) { - ASSERT(pp->p_szc == 0); - PP_SETNORELOC(pp); - } - (void) page_pp_lock(pp, 0, 1); - page_downgrade(pp); - } + proto = proto->next; + continue; + } + + /* + * p_end + * d_end + * d_base + * p_base + * + * -or- + * + * p_end + * d_end + * p_base + * d_base + * + * Find overlapping d_base..d_end ranges, and apply func + * where no overlap occurs. Stop when d_base is above + * p_end + */ + for (p_base = d_end, diff = diff->next; diff != NULL; + p_base = d_end, diff = diff->next) { + d_base = diff->address; + d_end = d_base + diff->size; + if (p_end <= d_base) { + (*func)(p_base, p_end - p_base); + break; + } else + (*func)(p_base, d_base - p_base); } - nlist = nlist->next ? nlist->next : nlist; + if (diff == NULL) + (*func)(p_base, p_end - p_base); + proto = proto->next; } } +void +sync_memlists(struct memlist *orig, struct memlist *new) +{ + + /* + * Find pages allocated via prom by looking for + * pages on orig, but no on new. + */ + diff_memlists(orig, new, less_pages); + + /* + * Find pages free'd via prom by looking for + * pages on new, but not on orig. + */ + diff_memlists(new, orig, more_pages); +} + + /* * Find the page number of the highest installed physical * page and the number of pages installed (one cannot be @@ -379,7 +375,7 @@ fix_prom_pages(struct memlist *orig, struct memlist *new) */ void installed_top_size_memlist_array( - u_longlong_t *list, /* base of array */ + prom_memlist_t *list, /* base of array */ size_t nelems, /* number of elements */ pfn_t *topp, /* return ptr for top value */ pgcnt_t *sumpagesp) /* return prt for sum of installed pages */ @@ -389,11 +385,11 @@ installed_top_size_memlist_array( pfn_t highp; /* high page in a chunk */ size_t i; - for (i = 0; i < nelems; i += 2) { - highp = (list[i] + list[i+1] - 1) >> PAGESHIFT; + for (i = 0; i < nelems; list++, i++) { + highp = (list->addr + list->size - 1) >> PAGESHIFT; if (top < highp) top = highp; - sumpages += (list[i+1] >> PAGESHIFT); + sumpages += (list->size >> PAGESHIFT); } *topp = top; @@ -406,7 +402,7 @@ installed_top_size_memlist_array( */ void copy_memlist( - u_longlong_t *src, + prom_memlist_t *src, size_t nelems, struct memlist **dstp) { @@ -416,9 +412,9 @@ copy_memlist( dst = *dstp; prev = dst; - for (i = 0; i < nelems; i += 2) { - dst->address = src[i]; - dst->size = src[i+1]; + for (i = 0; i < nelems; src++, i++) { + dst->address = src->addr; + dst->size = src->size; dst->next = 0; if (prev == dst) { dst->prev = 0; @@ -434,93 +430,176 @@ copy_memlist( *dstp = dst; } + static struct bootmem_props { - char *name; - u_longlong_t *ptr; + prom_memlist_t *ptr; size_t nelems; /* actual number of elements */ - size_t bufsize; /* length of allocated buffer */ -} bootmem_props[] = { - { "phys-installed", NULL, 0, 0 }, - { "phys-avail", NULL, 0, 0 }, - { "virt-avail", NULL, 0, 0 }, - { NULL, NULL, 0, 0 } -}; + size_t maxsize; /* max buffer */ +} bootmem_props[3]; #define PHYSINSTALLED 0 #define PHYSAVAIL 1 #define VIRTAVAIL 2 -void -copy_boot_memlists(u_longlong_t **physinstalled, size_t *physinstalled_len, - u_longlong_t **physavail, size_t *physavail_len, - u_longlong_t **virtavail, size_t *virtavail_len) +/* + * Comapct contiguous memory list elements + */ +static void +compact_promlist(struct bootmem_props *bpp) { - int align = BO_ALIGN_L3; - size_t len; - struct bootmem_props *tmp = bootmem_props; - -tryagain: - for (tmp = bootmem_props; tmp->name != NULL; tmp++) { - len = BOP_GETPROPLEN(bootops, tmp->name); - if (len == 0) { - panic("cannot get length of \"%s\" property", - tmp->name); - } - tmp->nelems = len / sizeof (u_longlong_t); - len = roundup(len, PAGESIZE); - if (len <= tmp->bufsize) - continue; - /* need to allocate more */ - if (tmp->ptr) { - BOP_FREE(bootops, (caddr_t)tmp->ptr, tmp->bufsize); - tmp->ptr = NULL; - tmp->bufsize = 0; + int i = 0, j; + struct prom_memlist *pmp = bpp->ptr; + + for (;;) { + if (pmp[i].addr + pmp[i].size == pmp[i+1].addr) { + pmp[i].size += pmp[i+1].size; + bpp->nelems--; + for (j = i + 1; j < bpp->nelems; j++) + pmp[j] = pmp[j+1]; + pmp[j].addr = 0; + } else + i++; + if (i == bpp->nelems) + break; + } +} + +/* + * Sort prom memory lists into ascending order + */ +static void +sort_promlist(struct bootmem_props *bpp) +{ + int i, j, min; + struct prom_memlist *pmp = bpp->ptr; + struct prom_memlist temp; + + for (i = 0; i < bpp->nelems; i++) { + min = i; + + for (j = i+1; j < bpp->nelems; j++) { + if (pmp[j].addr < pmp[min].addr) + min = j; } - tmp->bufsize = len; - tmp->ptr = (void *)BOP_ALLOC(bootops, 0, tmp->bufsize, align); - if (tmp->ptr == NULL) - panic("cannot allocate %lu bytes for \"%s\" property", - tmp->bufsize, tmp->name); + if (i != min) { + /* Swap pmp[i] and pmp[min] */ + temp = pmp[min]; + pmp[min] = pmp[i]; + pmp[i] = temp; + } } +} + +static int max_bootlist_sz; + +void +init_boot_memlists(void) +{ + size_t size, len; + char *start; + struct bootmem_props *tmp; + /* - * take the most current snapshot we can by calling mem-update + * These lists can get fragmented as the prom allocates + * memory, so generously round up. */ - if (BOP_GETPROPLEN(bootops, "memory-update") == 0) - (void) BOP_GETPROP(bootops, "memory-update", NULL); - - /* did the sizes change? */ - for (tmp = bootmem_props; tmp->name != NULL; tmp++) { - len = BOP_GETPROPLEN(bootops, tmp->name); - tmp->nelems = len / sizeof (u_longlong_t); - len = roundup(len, PAGESIZE); - if (len > tmp->bufsize) { - /* ick. Free them all and try again */ - for (tmp = bootmem_props; tmp->name != NULL; tmp++) { - BOP_FREE(bootops, (caddr_t)tmp->ptr, - tmp->bufsize); - tmp->ptr = NULL; - tmp->bufsize = 0; - } - goto tryagain; - } + size = prom_phys_installed_len() + prom_phys_avail_len() + + prom_virt_avail_len(); + size *= 4; + size = roundup(size, PAGESIZE); + start = prom_alloc(0, size, BO_NO_ALIGN); + + /* + * Get physinstalled + */ + tmp = &bootmem_props[PHYSINSTALLED]; + len = prom_phys_installed_len(); + if (len == 0) + panic("no \"reg\" in /memory"); + tmp->nelems = len / sizeof (struct prom_memlist); + tmp->maxsize = len; + tmp->ptr = (prom_memlist_t *)start; + start += len; + size -= len; + (void) prom_phys_installed((caddr_t)tmp->ptr); + sort_promlist(tmp); + compact_promlist(tmp); + + /* + * Start out giving each half of available space + */ + max_bootlist_sz = size; + len = size / 2; + tmp = &bootmem_props[PHYSAVAIL]; + tmp->maxsize = len; + tmp->ptr = (prom_memlist_t *)start; + start += len; + + tmp = &bootmem_props[VIRTAVAIL]; + tmp->maxsize = len; + tmp->ptr = (prom_memlist_t *)start; +} + + +void +copy_boot_memlists( + prom_memlist_t **physinstalled, size_t *physinstalled_len, + prom_memlist_t **physavail, size_t *physavail_len, + prom_memlist_t **virtavail, size_t *virtavail_len) +{ + size_t plen, vlen, move = 0; + struct bootmem_props *il, *pl, *vl; + + plen = prom_phys_avail_len(); + if (plen == 0) + panic("no \"available\" in /memory"); + vlen = prom_virt_avail_len(); + if (vlen == 0) + panic("no \"available\" in /virtual-memory"); + if (plen + vlen > max_bootlist_sz) + panic("ran out of prom_memlist space"); + + pl = &bootmem_props[PHYSAVAIL]; + vl = &bootmem_props[VIRTAVAIL]; + + /* + * re-adjust ptrs if needed + */ + if (plen > pl->maxsize) { + /* move virt avail up */ + move = plen - pl->maxsize; + pl->maxsize = plen; + vl->ptr += move / sizeof (struct prom_memlist); + vl->maxsize -= move; + } else if (vlen > vl->maxsize) { + /* move virt avail down */ + move = vlen - vl->maxsize; + vl->maxsize = vlen; + vl->ptr -= move / sizeof (struct prom_memlist); + pl->maxsize -= move; } + pl->nelems = plen / sizeof (struct prom_memlist); + vl->nelems = vlen / sizeof (struct prom_memlist); + /* now we can retrieve the properties */ - for (tmp = bootmem_props; tmp->name != NULL; tmp++) { - if (BOP_GETPROP(bootops, tmp->name, tmp->ptr) == -1) { - panic("cannot retrieve \"%s\" property", - tmp->name); - } - } - *physinstalled = bootmem_props[PHYSINSTALLED].ptr; - *physinstalled_len = bootmem_props[PHYSINSTALLED].nelems; + (void) prom_phys_avail((caddr_t)pl->ptr); + (void) prom_virt_avail((caddr_t)vl->ptr); + + /* .. and sort them */ + sort_promlist(pl); + sort_promlist(vl); + + il = &bootmem_props[PHYSINSTALLED]; + *physinstalled = il->ptr; + *physinstalled_len = il->nelems; - *physavail = bootmem_props[PHYSAVAIL].ptr; - *physavail_len = bootmem_props[PHYSAVAIL].nelems; + *physavail = pl->ptr; + *physavail_len = pl->nelems; - *virtavail = bootmem_props[VIRTAVAIL].ptr; - *virtavail_len = bootmem_props[VIRTAVAIL].nelems; + *virtavail = vl->ptr; + *virtavail_len = vl->nelems; } diff --git a/usr/src/uts/sun4/os/memnode.c b/usr/src/uts/sun4/os/memnode.c index cb21287ebd..b9d0fa3d56 100644 --- a/usr/src/uts/sun4/os/memnode.c +++ b/usr/src/uts/sun4/os/memnode.c @@ -185,7 +185,7 @@ mem_node_post_del_slice(pfn_t start, pfn_t end, int cancelled) } void -startup_build_mem_nodes(u_longlong_t *list, size_t nelems) +startup_build_mem_nodes(prom_memlist_t *list, size_t nelems) { size_t elem; pfn_t basepfn; @@ -200,13 +200,11 @@ startup_build_mem_nodes(u_longlong_t *list, size_t nelems) /* * Boot install lists are arranged <addr, len>, ... */ - for (elem = 0; elem < nelems; elem += 2) { - basepfn = btop(list[elem]); - npgs = btop(list[elem+1]); + for (elem = 0; elem < nelems; list++, elem++) { + basepfn = btop(list->addr); + npgs = btop(list->size); mem_node_add_slice(basepfn, basepfn + npgs - 1); } - mem_node_physalign = 0; - mem_node_pfn_shift = 0; } } diff --git a/usr/src/uts/sun4/os/mlsetup.c b/usr/src/uts/sun4/os/mlsetup.c index af8ab0ac17..6cefe6cc99 100644 --- a/usr/src/uts/sun4/os/mlsetup.c +++ b/usr/src/uts/sun4/os/mlsetup.c @@ -33,6 +33,8 @@ #include <sys/autoconf.h> #include <sys/promif.h> #include <sys/prom_plat.h> +#include <sys/promimpl.h> +#include <sys/platform_module.h> #include <sys/clock.h> #include <sys/pte.h> #include <sys/scb.h> @@ -66,6 +68,10 @@ #include <sys/sunddi.h> #include <sys/lgrp.h> #include <sys/traptrace.h> + +#include <sys/kobj_impl.h> +#include <sys/kdi_machimpl.h> + /* * External Routines: */ @@ -115,7 +121,7 @@ static void kern_splx_postprom(void); */ void -mlsetup(struct regs *rp, void *cif, kfpu_t *fp) +mlsetup(struct regs *rp, kfpu_t *fp) { struct machpcb *mpcb; @@ -128,6 +134,10 @@ mlsetup(struct regs *rp, void *cif, kfpu_t *fp) TRAP_TRACE_CTL *ctlp; #endif /* TRAPTRACE */ + /* drop into kmdb on boot -d */ + if (boothowto & RB_DEBUGENTER) + kmdb_enter(); + /* * initialize cpu_self */ @@ -205,10 +215,8 @@ mlsetup(struct regs *rp, void *cif, kfpu_t *fp) cpu_vm_data_init(CPU); - prom_init("kernel", cif); (void) prom_set_preprom(kern_splr_preprom); (void) prom_set_postprom(kern_splx_postprom); - PRM_INFO("mlsetup: now ok to call prom_printf"); mpcb->mpcb_pa = va_to_pa(t0.t_stk); @@ -298,3 +306,239 @@ kern_splx_postprom(void) { splx(saved_spl); } + + +/* + * WARNING + * The code fom here to the end of mlsetup.c runs before krtld has + * knitted unix and genunix together. It can call routines in unix, + * but calls into genunix will fail spectacularly. More specifically, + * calls to prom_*, bop_* and str* will work, everything else is + * caveat emptor. + * + * Also note that while #ifdef sun4u is generally a bad idea, they + * exist here to concentrate the dangerous code into a single file. + */ + +static char * +getcpulist(void) +{ + pnode_t node; + /* big enough for OBP_NAME and for a reasonably sized OBP_COMPATIBLE. */ + static char cpubuf[5 * OBP_MAXDRVNAME]; + int nlen, clen, i; +#ifdef sun4u + char dname[OBP_MAXDRVNAME]; +#endif + + node = prom_findnode_bydevtype(prom_rootnode(), OBP_CPU); + if (node != OBP_NONODE && node != OBP_BADNODE) { + if ((nlen = prom_getproplen(node, OBP_NAME)) <= 0 || + nlen > sizeof (cpubuf) || + prom_getprop(node, OBP_NAME, cpubuf) <= 0) + prom_panic("no name in cpu node"); + + /* nlen includes the terminating null character */ +#ifdef sun4v + if ((clen = prom_getproplen(node, OBP_COMPATIBLE)) > 0) { +#else /* sun4u */ + /* + * For the CMT case, need check the parent "core" + * node for the compatible property. + */ + if ((clen = prom_getproplen(node, OBP_COMPATIBLE)) > 0 || + ((node = prom_parentnode(node)) != OBP_NONODE && + node != OBP_BADNODE && + (clen = prom_getproplen(node, OBP_COMPATIBLE)) > 0 && + prom_getprop(node, OBP_DEVICETYPE, dname) > 0 && + strcmp(dname, "core") == 0)) { +#endif + if ((clen + nlen) > sizeof (cpubuf)) + prom_panic("cpu node \"compatible\" too long"); + /* read in compatible, leaving space for ':' */ + if (prom_getprop(node, OBP_COMPATIBLE, + &cpubuf[nlen]) != clen) + prom_panic("cpu node \"compatible\" error"); + clen += nlen; /* total length */ + /* convert all null characters to ':' */ + clen--; /* except the final one... */ + for (i = 0; i < clen; i++) + if (cpubuf[i] == '\0') + cpubuf[i] = ':'; + } +#ifdef sun4u + /* + * Some PROMs return SUNW,UltraSPARC when they actually have + * SUNW,UltraSPARC-II cpus. SInce we're now filtering out all + * SUNW,UltraSPARC systems during the boot phase, we can safely + * point the auxv CPU value at SUNW,UltraSPARC-II. + */ + if (strcmp("SUNW,UltraSPARC", cpubuf) == 0) + (void) strcpy(cpubuf, "SUNW,UltraSPARC-II"); +#endif + return (cpubuf); + } else + return (NULL); +} + +/* + * called immediately from _start to stich the + * primary modules together + */ +void +kobj_start(void *cif) +{ + Ehdr *ehdr; + Phdr *phdr; + uint32_t eadr, padr; + val_t bootaux[BA_NUM]; + int i; + + prom_init("kernel", cif); + bop_init(); +#ifdef DEBUG + if (bop_getproplen("stop-me") != -1) + prom_enter_mon(); +#endif + + if (bop_getprop("elfheader-address", (caddr_t)&eadr) == -1) + prom_panic("no ELF image"); + ehdr = (Ehdr *)(uintptr_t)eadr; + for (i = 0; i < BA_NUM; i++) + bootaux[i].ba_val = NULL; + bootaux[BA_PHNUM].ba_val = ehdr->e_phnum; + bootaux[BA_PHENT].ba_val = ehdr->e_phentsize; + bootaux[BA_LDNAME].ba_ptr = NULL; + + padr = eadr + ehdr->e_phoff; + bootaux[BA_PHDR].ba_ptr = (void *)(uintptr_t)padr; + for (i = 0; i < ehdr->e_phnum; i++) { + phdr = (Phdr *)((uintptr_t)padr + i * ehdr->e_phentsize); + if (phdr->p_type == PT_DYNAMIC) { + bootaux[BA_DYNAMIC].ba_ptr = (void *)phdr->p_vaddr; + break; + } + } + + bootaux[BA_LPAGESZ].ba_val = MMU_PAGESIZE4M; + bootaux[BA_PAGESZ].ba_val = MMU_PAGESIZE; + bootaux[BA_IFLUSH].ba_val = 1; + bootaux[BA_CPU].ba_ptr = getcpulist(); + bootaux[BA_MMU].ba_ptr = NULL; + + kobj_init(cif, NULL, bootops, bootaux); + + /* kernel stitched together; we can now test #pragma's */ + if (&plat_setprop_enter != NULL) { + prom_setprop_enter = &plat_setprop_enter; + prom_setprop_exit = &plat_setprop_exit; + ASSERT(prom_setprop_exit != NULL); + } + +} + +/* + * Create modpath from kernel name. + * If we booted: + * /platform/`uname -i`/kernel/sparcv9/unix + * or + * /platform/`uname -m`/kernel/sparcv9/unix + * + * then make the modpath: + * /platform/`uname -i`/kernel /platform/`uname -m`/kernel + * + * otherwise, make the modpath the dir the kernel was + * loaded from, minus any sparcv9 extension + * + * note the sparcv9 dir is optional since a unix -> sparcv9/unix + * symlink is available as a shortcut. + */ +void +mach_modpath(char *path, const char *fname) +{ + char *p; + int len, compat; + const char prefix[] = "/platform/"; + char platname[MAXPATHLEN]; +#ifdef sun4u + char defname[] = "sun4u"; +#else + char defname[] = "sun4v"; +#endif + const char suffix[] = "/kernel"; + const char isastr[] = "/sparcv9"; + + /* + * check for /platform + */ + p = (char *)fname; + if (strncmp(p, prefix, sizeof (prefix) - 1) != 0) + goto nopath; + p += sizeof (prefix) - 1; + + /* + * check for the default name or the platform name. + * also see if we used the 'compatible' name + * (platname == default) + */ + (void) bop_getprop("impl-arch-name", platname); + compat = strcmp(platname, defname) == 0; + len = strlen(platname); + if (strncmp(p, platname, len) == 0) + p += len; + else if (strncmp(p, defname, sizeof (defname) - 1) == 0) + p += sizeof (defname) - 1; + else + goto nopath; + + /* + * check for /kernel/sparcv9 or just /kernel + */ + if (strncmp(p, suffix, sizeof (suffix) - 1) != 0) + goto nopath; + p += sizeof (suffix) - 1; + if (strncmp(p, isastr, sizeof (isastr) - 1) == 0) + p += sizeof (isastr) - 1; + + /* + * check we're at the last component + */ + if (p != strrchr(fname, '/')) + goto nopath; + + /* + * everything is kosher; setup modpath + */ + (void) strcpy(path, "/platform/"); + (void) strcat(path, platname); + (void) strcat(path, "/kernel "); + if (!compat) { + (void) strcat(path, "/platform/"); + (void) strcat(path, defname); + (void) strcat(path, "/kernel "); + } + return; + +nopath: + /* + * Construct the directory path from the filename. + */ + if ((p = strrchr(fname, '/')) == NULL) + return; + + while (p > fname && *(p - 1) == '/') + p--; /* remove trailing '/' characters */ + if (p == fname) + p++; /* so "/" -is- the modpath in this case */ + + /* + * Remove optional isa-dependent directory name - the module + * subsystem will put this back again (!) + */ + len = p - fname; + if (len > sizeof (isastr) - 1 && + strncmp(&fname[len - (sizeof (isastr) - 1)], isastr, + sizeof (isastr) - 1) == 0) + p -= sizeof (isastr) - 1; + (void) strncpy(path, fname, p - fname); +} diff --git a/usr/src/uts/sun4/os/mp_startup.c b/usr/src/uts/sun4/os/mp_startup.c index 843e57f3d2..7d9eac0e18 100644 --- a/usr/src/uts/sun4/os/mp_startup.c +++ b/usr/src/uts/sun4/os/mp_startup.c @@ -56,7 +56,7 @@ uint64_t cpu_pa[NCPU]; /* pointers to all CPUs in PA */ cpu_core_t cpu_core[NCPU]; /* cpu_core structures */ #ifdef TRAPTRACE -caddr_t ttrace_buf; /* bop alloced traptrace for all cpus except 0 */ +caddr_t ttrace_buf; /* kmem64 traptrace for all cpus except 0 */ #endif /* TRAPTRACE */ /* bit mask of cpus ready for x-calls, protected by cpu_lock */ @@ -83,26 +83,15 @@ static void slave_startup(void); /* * This function sets traptrace buffers for all cpus * other than boot cpu. - * Note that the memory at base will be allocated later. */ -caddr_t -trap_trace_alloc(caddr_t base) +size_t +calc_traptrace_sz(void) { - caddr_t vaddr; - extern int max_ncpus; - - if (max_ncpus == 1) { - return (base); - } - - vaddr = (caddr_t)base; - - ttrace_buf = vaddr; - PRM_DEBUG(ttrace_buf); - return (vaddr + (TRAP_TSIZE * (max_ncpus - 1))); + return (TRAP_TSIZE * (max_ncpus - 1)); } #endif /* TRAPTRACE */ + /* * common slave cpu initialization code */ diff --git a/usr/src/uts/sun4/os/startup.c b/usr/src/uts/sun4/os/startup.c index f69b831007..2974299c1b 100644 --- a/usr/src/uts/sun4/os/startup.c +++ b/usr/src/uts/sun4/os/startup.c @@ -128,7 +128,6 @@ char *cache_mode = NULL; int use_mix = 1; int prom_debug = 0; -struct bootops *bootops = 0; /* passed in from boot in %o2 */ caddr_t boot_tba; /* %tba at boot - used by kmdb */ uint_t tba_taken_over = 0; @@ -149,10 +148,6 @@ caddr_t econtig32; /* end of first blk of contiguous kernel */ caddr_t ncbase; /* beginning of non-cached segment */ caddr_t ncend; /* end of non-cached segment */ -caddr_t sdata; /* beginning of data segment */ - -caddr_t extra_etva; /* beginning of unused nucleus text */ -pgcnt_t extra_etpg; /* number of pages of unused nucleus text */ size_t ndata_remain_sz; /* bytes from end of data to 4MB boundary */ caddr_t nalloc_base; /* beginning of nucleus allocation */ @@ -161,8 +156,8 @@ caddr_t valloc_base; /* beginning of kvalloc segment */ caddr_t kmem64_base; /* base of kernel mem segment in 64-bit space */ caddr_t kmem64_end; /* end of kernel mem segment in 64-bit space */ +size_t kmem64_sz; /* bytes in kernel mem segment, 64-bit space */ caddr_t kmem64_aligned_end; /* end of large page, overmaps 64-bit space */ -int kmem64_alignsize; /* page size for mem segment in 64-bit space */ int kmem64_szc; /* page size code */ uint64_t kmem64_pabase = (uint64_t)-1; /* physical address of kmem64_base */ @@ -170,6 +165,7 @@ uintptr_t shm_alignment; /* VAC address consistency modulus */ struct memlist *phys_install; /* Total installed physical memory */ struct memlist *phys_avail; /* Available (unreserved) physical memory */ struct memlist *virt_avail; /* Available (unmapped?) virtual memory */ +struct memlist *nopp_list; /* pages with no backing page structs */ struct memlist ndata; /* memlist of nucleus allocatable memory */ int memexp_flag; /* memory expansion card flag */ uint64_t ecache_flushaddr; /* physical address used for flushing E$ */ @@ -193,7 +189,7 @@ struct seg kmapseg; /* Segment used for generic kernel mappings */ struct seg kpmseg; /* Segment used for physical mapping */ struct seg kdebugseg; /* Segment used for the kernel debugger */ -uintptr_t kpm_pp_base; /* Base of system kpm_page array */ +void *kpm_pp_base; /* Base of system kpm_page array */ size_t kpm_pp_sz; /* Size of system kpm_page array */ pgcnt_t kpm_npages; /* How many kpm pages are managed */ @@ -221,8 +217,8 @@ const size_t kdi_segdebugsize = SEGDEBUGSIZE; */ struct seg kmem64; -struct memseg *memseg_base; -size_t memseg_sz; /* Used to translate a va to page */ +struct memseg *memseg_free; + struct vnode unused_pages_vp; /* @@ -239,11 +235,13 @@ size_t mpo_heap32_bufsz = 0; /* * Static Routines: */ -static void memlist_add(uint64_t, uint64_t, struct memlist **, - struct memlist **); -static void kphysm_init(page_t *, struct memseg *, pgcnt_t, uintptr_t, - pgcnt_t); +static int ndata_alloc_memseg(struct memlist *, size_t); +static void memlist_new(uint64_t, uint64_t, struct memlist **); +static void memlist_add(uint64_t, uint64_t, + struct memlist **, struct memlist **); +static void kphysm_init(void); static void kvm_init(void); +static void install_kmem64_tte(void); static void startup_init(void); static void startup_memlist(void); @@ -270,9 +268,6 @@ uint_t hblk1_min = H1MIN; int iam_positron(void); #pragma weak iam_positron static void do_prom_version_check(void); -static void kpm_init(void); -static void kpm_npages_setup(int); -static void kpm_memseg_init(void); /* * After receiving a thermal interrupt, this is the number of seconds @@ -339,51 +334,8 @@ printmemseg(struct memseg *memseg) #define MPRINTF3(str, a, b, c) #endif /* DEBUGGING_MEM */ -/* Simple message to indicate that the bootops pointer has been zeroed */ -#ifdef DEBUG -static int bootops_gone_on = 0; -#define BOOTOPS_GONE() \ - if (bootops_gone_on) \ - prom_printf("The bootops vec is zeroed now!\n"); -#else -#define BOOTOPS_GONE() -#endif /* DEBUG */ /* - * Monitor pages may not be where this says they are. - * and the debugger may not be there either. - * - * Note that 'pages' here are *physical* pages, which are 8k on sun4u. - * - * Physical memory layout - * (not necessarily contiguous) - * (THIS IS SOMEWHAT WRONG) - * /-----------------------\ - * | monitor pages | - * availmem -|-----------------------| - * | | - * | page pool | - * | | - * |-----------------------| - * | configured tables | - * | buffers | - * firstaddr -|-----------------------| - * | hat data structures | - * |-----------------------| - * | kernel data, bss | - * |-----------------------| - * | interrupt stack | - * |-----------------------| - * | kernel text (RO) | - * |-----------------------| - * | trap table (4k) | - * |-----------------------| - * page 1 | panicbuf | - * |-----------------------| - * page 0 | reclaimed | - * |_______________________| - * - * * * Kernel's Virtual Memory Layout. * /-----------------------\ @@ -425,6 +377,11 @@ static int bootops_gone_on = 0; * 0x000007FF.00000000 -|-----------------------|- hole_start ----- * : : ^ * : : | + * |-----------------------| | + * | | | + * | ecache flush area | | + * | (twice largest e$) | | + * | | | * 0x00000XXX.XXX00000 -|-----------------------|- kmem64_ | * | overmapped area | alignend_end | * | (kmem64_alignsize | | @@ -493,9 +450,12 @@ static int bootops_gone_on = 0; * | | * | segkmem32 segment | (SYSLIMIT32 - SYSBASE32 = * | | ~64MB) - * 0x00000000.78002000 -|-----------------------| + * 0x00000000.70002000 -|-----------------------| * | panicbuf | - * 0x00000000.78000000 -|-----------------------|- SYSBASE32 + * 0x00000000.70000000 -|-----------------------|- SYSBASE32 + * | boot-time | + * | temporary space | + * 0x00000000.4C000000 -|-----------------------|- BOOTTMPBASE * : : * : : * | | @@ -557,7 +517,7 @@ static int bootops_gone_on = 0; * | user data | * -|-----------------------|- * | user text | - * 0x00000000.00100000 -|-----------------------|- + * 0x00000000.01000000 -|-----------------------|- * | invalid | * 0x00000000.00000000 _|_______________________| */ @@ -698,8 +658,6 @@ startup_init(void) */ char bp[sizeof (sync_str) + 16 * 20]; - (void) check_boot_version(BOP_GETVERSION(bootops)); - /* * Initialize ptl1 stack for the 1st CPU. */ @@ -736,12 +694,111 @@ startup_init(void) add_vx_handler("sync", 1, (void (*)(cell_t *))sync_handler); } -static u_longlong_t *boot_physinstalled, *boot_physavail, *boot_virtavail; + +size_t +calc_pp_sz(pgcnt_t npages) +{ + + return (npages * sizeof (struct page)); +} + +size_t +calc_kpmpp_sz(pgcnt_t npages) +{ + + kpm_pgshft = (kpm_smallpages == 0) ? MMU_PAGESHIFT4M : MMU_PAGESHIFT; + kpm_pgsz = 1ull << kpm_pgshft; + kpm_pgoff = kpm_pgsz - 1; + kpmp2pshft = kpm_pgshft - PAGESHIFT; + kpmpnpgs = 1 << kpmp2pshft; + + if (kpm_smallpages == 0) { + /* + * Avoid fragmentation problems in kphysm_init() + * by allocating for all of physical memory + */ + kpm_npages = ptokpmpr(physinstalled); + return (kpm_npages * sizeof (kpm_page_t)); + } else { + kpm_npages = npages; + return (kpm_npages * sizeof (kpm_spage_t)); + } +} + +size_t +calc_pagehash_sz(pgcnt_t npages) +{ + + /* + * The page structure hash table size is a power of 2 + * such that the average hash chain length is PAGE_HASHAVELEN. + */ + page_hashsz = npages / PAGE_HASHAVELEN; + page_hashsz = 1 << highbit(page_hashsz); + return (page_hashsz * sizeof (struct page *)); +} + +void +alloc_kmem64(caddr_t base, caddr_t end) +{ + int i; + caddr_t aligned_end = NULL; + + /* + * Make one large memory alloc after figuring out the 64-bit size. This + * will enable use of the largest page size appropriate for the system + * architecture. + */ + ASSERT(mmu_exported_pagesize_mask & (1 << TTE8K)); + ASSERT(IS_P2ALIGNED(base, TTEBYTES(max_bootlp_tteszc))); + for (i = max_bootlp_tteszc; i >= TTE8K; i--) { + size_t alloc_size, alignsize; +#if !defined(C_OBP) + unsigned long long pa; +#endif /* !C_OBP */ + + if ((mmu_exported_pagesize_mask & (1 << i)) == 0) + continue; + alignsize = TTEBYTES(i); + kmem64_szc = i; + + /* limit page size for small memory */ + if (mmu_btop(alignsize) > (npages >> 2)) + continue; + + aligned_end = (caddr_t)roundup((uintptr_t)end, alignsize); + alloc_size = aligned_end - base; +#if !defined(C_OBP) + if (prom_allocate_phys(alloc_size, alignsize, &pa) == 0) { + if (prom_claim_virt(alloc_size, base) != (caddr_t)-1) { + kmem64_pabase = pa; + kmem64_aligned_end = aligned_end; + install_kmem64_tte(); + break; + } else { + prom_free_phys(alloc_size, pa); + } + } +#else /* !C_OBP */ + if (prom_alloc(base, alloc_size, alignsize) == base) { + kmem64_pabase = va_to_pa(kmem64_base); + kmem64_aligned_end = aligned_end; + break; + } +#endif /* !C_OBP */ + if (i == TTE8K) { + prom_panic("kmem64 allocation failure"); + } + } + ASSERT(aligned_end != NULL); +} + +static prom_memlist_t *boot_physinstalled, *boot_physavail, *boot_virtavail; static size_t boot_physinstalled_len, boot_physavail_len, boot_virtavail_len; -#define IVSIZE ((MAXIVNUM * sizeof (intr_vec_t *)) + \ - (MAX_RSVD_IV * sizeof (intr_vec_t)) + \ - (MAX_RSVD_IVX * sizeof (intr_vecx_t))) +#define IVSIZE roundup(((MAXIVNUM * sizeof (intr_vec_t *)) + \ + (MAX_RSVD_IV * sizeof (intr_vec_t)) + \ + (MAX_RSVD_IVX * sizeof (intr_vecx_t))), PAGESIZE) #if !defined(C_OBP) /* @@ -782,18 +839,18 @@ static size_t boot_physinstalled_len, boot_physavail_len, boot_virtavail_len; * } */ char kmem64_obp_str[] = - "h# %lx constant kmem64_base " - "h# %lx constant kmem64_end " - "h# %lx constant kmem64_pagemask " - "h# %lx constant kmem64_template " + "h# %lx constant kmem64-base " + "h# %lx constant kmem64-end " + "h# %lx constant kmem64-pagemask " + "h# %lx constant kmem64-template " ": kmem64-tte ( addr cnum -- false | tte-data true ) " " if ( addr ) " " drop false exit then ( false ) " - " dup kmem64_base kmem64_end within if ( addr ) " - " kmem64_pagemask and ( addr' ) " - " kmem64_base - ( addr' ) " - " kmem64_template + ( tte ) " + " dup kmem64-base kmem64-end within if ( addr ) " + " kmem64-pagemask and ( addr' ) " + " kmem64-base - ( addr' ) " + " kmem64-template + ( tte ) " " true ( tte true ) " " else ( addr ) " " pgmap@ ( tte ) " @@ -804,7 +861,7 @@ char kmem64_obp_str[] = "' kmem64-tte is va>tte-data " ; -void +static void install_kmem64_tte() { char b[sizeof (kmem64_obp_str) + (4 * 16)]; @@ -843,24 +900,19 @@ pgcnt_t tune_npages = (pgcnt_t) #pragma weak page_set_colorequiv_arr_cpu extern void page_set_colorequiv_arr_cpu(void); +extern void page_set_colorequiv_arr(void); + static void startup_memlist(void) { - size_t alloc_sz; - size_t ctrs_sz; + size_t hmehash_sz, pagelist_sz, tt_sz; + size_t psetable_sz; caddr_t alloc_base; - caddr_t ctrs_base, ctrs_end; caddr_t memspace; - caddr_t va; - int memblocks = 0; struct memlist *cur; size_t syslimit = (size_t)SYSLIMIT; size_t sysbase = (size_t)SYSBASE; - int alloc_alignsize = ecache_alignsize; - int i; - extern void page_coloring_init(void); - extern void page_set_colorequiv_arr(void); /* * Initialize enough of the system to allow kmem_alloc to work by @@ -896,12 +948,11 @@ startup_memlist(void) * handling operations. We align nalloc_base to a l2 cache * linesize because this is the line size the hardware uses to * maintain cache coherency. - * 256K is carved out for module data. + * 512K is carved out for module data. */ - nalloc_base = (caddr_t)roundup((uintptr_t)e_data, MMU_PAGESIZE); - moddata = nalloc_base; - e_moddata = nalloc_base + MODDATA; + moddata = (caddr_t)roundup((uintptr_t)e_data, MMU_PAGESIZE); + e_moddata = moddata + MODDATA; nalloc_base = e_moddata; nalloc_end = (caddr_t)roundup((uintptr_t)nalloc_base, MMU_PAGESIZE4M); @@ -910,12 +961,12 @@ startup_memlist(void) /* * Calculate the start of the data segment. */ - sdata = (caddr_t)((uintptr_t)e_data & MMU_PAGEMASK4M); + if (((uintptr_t)e_moddata & MMU_PAGEMASK4M) != (uintptr_t)s_data) + prom_panic("nucleus data overflow"); PRM_DEBUG(moddata); PRM_DEBUG(nalloc_base); PRM_DEBUG(nalloc_end); - PRM_DEBUG(sdata); /* * Remember any slop after e_text so we can give it to the modules. @@ -929,9 +980,11 @@ startup_memlist(void) PRM_DEBUG(modtext); PRM_DEBUG(modtext_sz); + init_boot_memlists(); copy_boot_memlists(&boot_physinstalled, &boot_physinstalled_len, &boot_physavail, &boot_physavail_len, &boot_virtavail, &boot_virtavail_len); + /* * Remember what the physically available highest page is * so that dumpsys works properly, and find out how much @@ -946,106 +999,39 @@ startup_memlist(void) startup_build_mem_nodes(boot_physinstalled, boot_physinstalled_len); /* - * Get the list of physically available memory to size - * the number of page structures needed. - */ - size_physavail(boot_physavail, boot_physavail_len, &npages, &memblocks); - /* - * This first snap shot of npages can represent the pages used - * by OBP's text and data approximately. This is used in the - * the calculation of the kernel size - */ - obp_pages = physinstalled - npages; - - - /* - * On small-memory systems (<MODTEXT_SM_SIZE MB, currently 256MB), the - * in-nucleus module text is capped to MODTEXT_SM_CAP bytes (currently - * 2MB) and any excess pages are put on physavail. The assumption is - * that small-memory systems will need more pages more than they'll - * need efficiently-mapped module texts. - */ - if ((physinstalled < mmu_btop(MODTEXT_SM_SIZE << 20)) && - modtext_sz > MODTEXT_SM_CAP) { - extra_etpg = mmu_btop(modtext_sz - MODTEXT_SM_CAP); - modtext_sz = MODTEXT_SM_CAP; - extra_etva = modtext + modtext_sz; - } - - PRM_DEBUG(extra_etpg); - PRM_DEBUG(modtext_sz); - PRM_DEBUG(extra_etva); - - /* - * Account for any pages after e_text and e_data. - */ - npages += extra_etpg; - npages += mmu_btopr(nalloc_end - nalloc_base); - PRM_DEBUG(npages); - - /* * npages is the maximum of available physical memory possible. * (ie. it will never be more than this) + * + * When we boot from a ramdisk, the ramdisk memory isn't free, so + * using phys_avail will underestimate what will end up being freed. + * A better initial guess is just total memory minus the kernel text */ + npages = physinstalled - btop(MMU_PAGESIZE4M); /* - * initialize the nucleus memory allocator. + * First allocate things that can go in the nucleus data page + * (fault status, TSBs, dmv, CPUs) */ ndata_alloc_init(&ndata, (uintptr_t)nalloc_base, (uintptr_t)nalloc_end); - /* - * Allocate mmu fault status area from the nucleus data area. - */ if ((&ndata_alloc_mmfsa != NULL) && (ndata_alloc_mmfsa(&ndata) != 0)) cmn_err(CE_PANIC, "no more nucleus memory after mfsa alloc"); - /* - * Allocate kernel TSBs from the nucleus data area. - */ if (ndata_alloc_tsbs(&ndata, npages) != 0) cmn_err(CE_PANIC, "no more nucleus memory after tsbs alloc"); - /* - * Allocate dmv dispatch table from the nucleus data area. - */ if (ndata_alloc_dmv(&ndata) != 0) cmn_err(CE_PANIC, "no more nucleus memory after dmv alloc"); - - page_coloring_init(); - - /* - * Allocate page_freelists bin headers for memnode 0 from the - * nucleus data area. - */ - if (ndata_alloc_page_freelists(&ndata, 0) != 0) + if (ndata_alloc_page_mutexs(&ndata) != 0) cmn_err(CE_PANIC, "no more nucleus memory after page free lists alloc"); - if (kpm_enable) { - kpm_init(); - /* - * kpm page space -- Update kpm_npages and make the - * same assumption about fragmenting as it is done - * for memseg_sz. - */ - kpm_npages_setup(memblocks + 4); - } - - /* - * Allocate hat related structs from the nucleus data area. - */ - if (ndata_alloc_hat(&ndata, npages, kpm_npages) != 0) + if (ndata_alloc_hat(&ndata, npages) != 0) cmn_err(CE_PANIC, "no more nucleus memory after hat alloc"); - /* - * We want to do the BOP_ALLOCs before the real allocation of page - * structs in order to not have to allocate page structs for this - * memory. We need to calculate a virtual address because we want - * the page structs to come before other allocations in virtual address - * space. This is so some (if not all) of page structs can actually - * live in the nucleus. - */ + if (ndata_alloc_memseg(&ndata, boot_physavail_len) != 0) + cmn_err(CE_PANIC, "no more nucleus memory after memseg alloc"); /* * WARNING WARNING WARNING WARNING WARNING WARNING WARNING @@ -1059,6 +1045,8 @@ startup_memlist(void) * WARNING WARNING WARNING WARNING WARNING WARNING WARNING */ alloc_base = (caddr_t)roundup((uintptr_t)nalloc_end, MMU_PAGESIZE); + PRM_DEBUG(alloc_base); + alloc_base = sfmmu_ktsb_alloc(alloc_base); alloc_base = (caddr_t)roundup((uintptr_t)alloc_base, ecache_alignsize); PRM_DEBUG(alloc_base); @@ -1068,11 +1056,15 @@ startup_memlist(void) * memory gets deducted from the PROM's physical memory list. */ alloc_base = iommu_tsb_init(alloc_base); - alloc_base = (caddr_t)roundup((uintptr_t)alloc_base, - ecache_alignsize); + alloc_base = (caddr_t)roundup((uintptr_t)alloc_base, ecache_alignsize); PRM_DEBUG(alloc_base); /* + * Allow for an early allocation of physically contiguous memory. + */ + alloc_base = contig_mem_prealloc(alloc_base, npages); + + /* * Platforms like Starcat and OPL need special structures assigned in * 32-bit virtual address space because their probing routines execute * FCode, and FCode can't handle 64-bit virtual addresses... @@ -1090,189 +1082,117 @@ startup_memlist(void) */ econtig32 = alloc_base; PRM_DEBUG(econtig32); - if (econtig32 > (caddr_t)KERNEL_LIMIT32) cmn_err(CE_PANIC, "econtig32 too big"); - /* - * To avoid memory allocation collisions in the 32-bit virtual address - * space, make allocations from this point forward in 64-bit virtual - * address space starting at syslimit and working up. - * - * All this is needed because on large memory systems, the default - * Solaris allocations will collide with SYSBASE32, which is hard - * coded to be at the virtual address 0x78000000. Therefore, on 64-bit - * kernels, move the allocations to a location in the 64-bit virtual - * address space space, allowing those structures to grow without - * worry. - * - * On current CPUs we'll run out of physical memory address bits before - * we need to worry about the allocations running into anything else in - * VM or the virtual address holes on US-I and II, as there's currently - * about 1 TB of addressable space before the US-I/II VA hole. - */ - kmem64_base = (caddr_t)syslimit; - PRM_DEBUG(kmem64_base); + pp_sz = calc_pp_sz(npages); + PRM_DEBUG(pp_sz); + if (kpm_enable) { + kpm_pp_sz = calc_kpmpp_sz(npages); + PRM_DEBUG(kpm_pp_sz); + } - /* - * Allocate addresses, but not physical memory. None of these locations - * can be touched until physical memory is allocated below. - */ - alloc_base = kmem64_base; + hmehash_sz = calc_hmehash_sz(npages); + PRM_DEBUG(hmehash_sz); - /* - * If KHME and/or UHME hash buckets won't fit in the nucleus, allocate - * them here. - */ - if (khme_hash == NULL || uhme_hash == NULL) { - /* - * alloc_hme_buckets() will align alloc_base properly before - * assigning the hash buckets, so we don't need to do it - * before the call... - */ - alloc_base = alloc_hme_buckets(alloc_base, alloc_alignsize); + pagehash_sz = calc_pagehash_sz(npages); + PRM_DEBUG(pagehash_sz); - PRM_DEBUG(alloc_base); - PRM_DEBUG(khme_hash); - PRM_DEBUG(uhme_hash); - } + pagelist_sz = calc_free_pagelist_sz(); + PRM_DEBUG(pagelist_sz); + +#ifdef TRAPTRACE + tt_sz = calc_traptrace_sz(); + PRM_DEBUG(tt_sz); +#else + tt_sz = 0; +#endif /* TRAPTRACE */ /* - * Allow for an early allocation of physically contiguous memory. + * Place the array that protects pp->p_selock in the kmem64 wad. */ - alloc_base = contig_mem_prealloc(alloc_base, npages); + pse_shift = size_pse_array(physmem, max_ncpus); + PRM_DEBUG(pse_shift); + pse_table_size = 1 << pse_shift; + PRM_DEBUG(pse_table_size); + psetable_sz = roundup( + pse_table_size * sizeof (pad_mutex_t), ecache_alignsize); + PRM_DEBUG(psetable_sz); /* - * Allocate the remaining page freelists. NUMA systems can - * have lots of page freelists, one per node, which quickly - * outgrow the amount of nucleus memory available. + * Now allocate the whole wad */ - if (max_mem_nodes > 1) { - int mnode; - - for (mnode = 1; mnode < max_mem_nodes; mnode++) { - alloc_base = alloc_page_freelists(mnode, alloc_base, - ecache_alignsize); - } - PRM_DEBUG(alloc_base); - } - - if (!mml_table) { - size_t mmltable_sz; - - /* - * We need to allocate the mml_table here because there - * was not enough space within the nucleus. - */ - mmltable_sz = sizeof (kmutex_t) * mml_table_sz; - alloc_sz = roundup(mmltable_sz, alloc_alignsize); - alloc_base = (caddr_t)roundup((uintptr_t)alloc_base, - alloc_alignsize); - mml_table = (kmutex_t *)alloc_base; - alloc_base += alloc_sz; - PRM_DEBUG(mml_table); - PRM_DEBUG(alloc_base); - } - - if (kpm_enable && !(kpmp_table || kpmp_stable)) { - size_t kpmptable_sz; - caddr_t table; - - /* - * We need to allocate either kpmp_table or kpmp_stable here - * because there was not enough space within the nucleus. - */ - kpmptable_sz = (kpm_smallpages == 0) ? - sizeof (kpm_hlk_t) * kpmp_table_sz : - sizeof (kpm_shlk_t) * kpmp_stable_sz; - - alloc_sz = roundup(kpmptable_sz, alloc_alignsize); - alloc_base = (caddr_t)roundup((uintptr_t)alloc_base, - alloc_alignsize); + kmem64_sz = pp_sz + kpm_pp_sz + hmehash_sz + pagehash_sz + + pagelist_sz + tt_sz + psetable_sz; + kmem64_sz = roundup(kmem64_sz, PAGESIZE); + kmem64_base = (caddr_t)syslimit; + kmem64_end = kmem64_base + kmem64_sz; + alloc_kmem64(kmem64_base, kmem64_end); + if (kmem64_aligned_end > (hole_start ? hole_start : kpm_vbase)) + cmn_err(CE_PANIC, "not enough kmem64 space"); + PRM_DEBUG(kmem64_base); + PRM_DEBUG(kmem64_end); + PRM_DEBUG(kmem64_aligned_end); - table = alloc_base; + /* + * ... and divy it up + */ + alloc_base = kmem64_base; + npages -= kmem64_sz / (PAGESIZE + sizeof (struct page)); + pp_base = (page_t *)alloc_base; + pp_sz = npages * sizeof (struct page); + alloc_base += pp_sz; + alloc_base = (caddr_t)roundup((uintptr_t)alloc_base, ecache_alignsize); + PRM_DEBUG(pp_base); + PRM_DEBUG(npages); + if (kpm_enable) { + kpm_pp_base = alloc_base; if (kpm_smallpages == 0) { - kpmp_table = (kpm_hlk_t *)table; - PRM_DEBUG(kpmp_table); + /* kpm_npages based on physinstalled, don't reset */ + kpm_pp_sz = kpm_npages * sizeof (kpm_page_t); } else { - kpmp_stable = (kpm_shlk_t *)table; - PRM_DEBUG(kpmp_stable); + kpm_npages = ptokpmpr(npages); + kpm_pp_sz = kpm_npages * sizeof (kpm_spage_t); } - - alloc_base += alloc_sz; - PRM_DEBUG(alloc_base); - } - - if (&ecache_init_scrub_flush_area) { - /* - * Pass alloc_base directly, as the routine itself is - * responsible for any special alignment requirements... - */ - alloc_base = ecache_init_scrub_flush_area(alloc_base); - PRM_DEBUG(alloc_base); + alloc_base += kpm_pp_sz; + alloc_base = + (caddr_t)roundup((uintptr_t)alloc_base, ecache_alignsize); + PRM_DEBUG(kpm_pp_base); } - /* - * Take the most current snapshot we can by calling mem-update. - */ - copy_boot_memlists(&boot_physinstalled, &boot_physinstalled_len, - &boot_physavail, &boot_physavail_len, - &boot_virtavail, &boot_virtavail_len); - - /* - * Reset npages and memblocks based on boot_physavail list. - */ - size_physavail(boot_physavail, boot_physavail_len, &npages, &memblocks); - PRM_DEBUG(npages); - - /* - * Account for extra memory after e_text. - */ - npages += extra_etpg; + alloc_base = alloc_hmehash(alloc_base); + alloc_base = (caddr_t)roundup((uintptr_t)alloc_base, ecache_alignsize); + PRM_DEBUG(alloc_base); - /* - * Calculate the largest free memory chunk in the nucleus data area. - * We need to figure out if page structs can fit in there or not. - * We also make sure enough page structs get created for any physical - * memory we might be returning to the system. - */ - ndata_remain_sz = ndata_maxsize(&ndata); - PRM_DEBUG(ndata_remain_sz); + page_hash = (page_t **)alloc_base; + alloc_base += pagehash_sz; + alloc_base = (caddr_t)roundup((uintptr_t)alloc_base, ecache_alignsize); + PRM_DEBUG(page_hash); - pp_sz = sizeof (struct page) * npages; + alloc_base = alloc_page_freelists(alloc_base); + alloc_base = (caddr_t)roundup((uintptr_t)alloc_base, ecache_alignsize); + PRM_DEBUG(alloc_base); - /* - * Here's a nice bit of code based on somewhat recursive logic: - * - * If the page array would fit within the nucleus, we want to - * add npages to cover any extra memory we may be returning back - * to the system. - * - * HOWEVER, the page array is sized by calculating the size of - * (struct page * npages), as are the pagehash table, ctrs and - * memseg_list, so the very act of performing the calculation below may - * in fact make the array large enough that it no longer fits in the - * nucleus, meaning there would now be a much larger area of the - * nucleus free that should really be added to npages, which would - * make the page array that much larger, and so on. - * - * This also ignores the memory possibly used in the nucleus for the - * the page hash, ctrs and memseg list and the fact that whether they - * fit there or not varies with the npages calculation below, but we - * don't even factor them into the equation at this point; perhaps we - * should or perhaps we should just take the approach that the few - * extra pages we could add via this calculation REALLY aren't worth - * the hassle... - */ - if (ndata_remain_sz > pp_sz) { - size_t spare = ndata_spare(&ndata, pp_sz, ecache_alignsize); +#ifdef TRAPTRACE + ttrace_buf = alloc_base; + alloc_base += tt_sz; + alloc_base = (caddr_t)roundup((uintptr_t)alloc_base, ecache_alignsize); + PRM_DEBUG(alloc_base); +#endif /* TRAPTRACE */ - npages += mmu_btop(spare); + pse_mutex = (pad_mutex_t *)alloc_base; + alloc_base += psetable_sz; + alloc_base = (caddr_t)roundup((uintptr_t)alloc_base, ecache_alignsize); + PRM_DEBUG(alloc_base); - pp_sz = npages * sizeof (struct page); + /* adjust kmem64_end to what we really allocated */ + kmem64_end = (caddr_t)roundup((uintptr_t)alloc_base, PAGESIZE); + kmem64_sz = kmem64_end - kmem64_base; - pp_base = ndata_alloc(&ndata, pp_sz, ecache_alignsize); + if (&ecache_init_scrub_flush_area) { + alloc_base = ecache_init_scrub_flush_area(kmem64_aligned_end); + ASSERT(alloc_base <= (hole_start ? hole_start : kpm_vbase)); } /* @@ -1284,283 +1204,52 @@ startup_memlist(void) physmem = npages; /* - * If pp_base is NULL that means the routines above have determined - * the page array will not fit in the nucleus; we'll have to - * BOP_ALLOC() ourselves some space for them. - */ - if (pp_base == NULL) { - alloc_base = (caddr_t)roundup((uintptr_t)alloc_base, - alloc_alignsize); - alloc_sz = roundup(pp_sz, alloc_alignsize); - - pp_base = (struct page *)alloc_base; - - alloc_base += alloc_sz; - } - - /* - * The page structure hash table size is a power of 2 - * such that the average hash chain length is PAGE_HASHAVELEN. - */ - page_hashsz = npages / PAGE_HASHAVELEN; - page_hashsz = 1 << highbit((ulong_t)page_hashsz); - pagehash_sz = sizeof (struct page *) * page_hashsz; - - /* - * We want to TRY to fit the page structure hash table, - * the page size free list counters, the memseg list and - * and the kpm page space in the nucleus if possible. + * root_is_ramdisk is set via /etc/system when the ramdisk miniroot + * is mounted as root. This memory is held down by OBP and unlike + * the stub boot_archive is never released. * - * alloc_sz counts how much memory needs to be allocated by - * BOP_ALLOC(). - */ - page_hash = ndata_alloc(&ndata, pagehash_sz, ecache_alignsize); - - alloc_sz = (page_hash == NULL ? pagehash_sz : 0); - - /* - * Size up per page size free list counters. - */ - ctrs_sz = page_ctrs_sz(); - ctrs_base = ndata_alloc(&ndata, ctrs_sz, ecache_alignsize); - - if (ctrs_base == NULL) - alloc_sz = roundup(alloc_sz, ecache_alignsize) + ctrs_sz; - - /* - * The memseg list is for the chunks of physical memory that - * will be managed by the vm system. The number calculated is - * a guess as boot may fragment it more when memory allocations - * are made before kphysm_init(). Currently, there are two - * allocations before then, so we assume each causes fragmen- - * tation, and add a couple more for good measure. - */ - memseg_sz = sizeof (struct memseg) * (memblocks + 4); - memseg_base = ndata_alloc(&ndata, memseg_sz, ecache_alignsize); - - if (memseg_base == NULL) - alloc_sz = roundup(alloc_sz, ecache_alignsize) + memseg_sz; - - - if (kpm_enable) { - /* - * kpm page space -- Update kpm_npages and make the - * same assumption about fragmenting as it is done - * for memseg_sz above. - */ - kpm_npages_setup(memblocks + 4); - kpm_pp_sz = (kpm_smallpages == 0) ? - kpm_npages * sizeof (kpm_page_t): - kpm_npages * sizeof (kpm_spage_t); - - kpm_pp_base = (uintptr_t)ndata_alloc(&ndata, kpm_pp_sz, - ecache_alignsize); - - if (kpm_pp_base == NULL) - alloc_sz = roundup(alloc_sz, ecache_alignsize) + - kpm_pp_sz; - } - - /* - * Allocate the array that protects pp->p_selock. - */ - pse_shift = size_pse_array(physmem, max_ncpus); - pse_table_size = 1 << pse_shift; - pse_mutex = ndata_alloc(&ndata, pse_table_size * sizeof (pad_mutex_t), - ecache_alignsize); - if (pse_mutex == NULL) - alloc_sz = roundup(alloc_sz, ecache_alignsize) + - pse_table_size * sizeof (pad_mutex_t); - - if (alloc_sz > 0) { - uintptr_t bop_base; - - /* - * We need extra memory allocated through BOP_ALLOC. - */ - alloc_base = (caddr_t)roundup((uintptr_t)alloc_base, - alloc_alignsize); - - alloc_sz = roundup(alloc_sz, alloc_alignsize); - - bop_base = (uintptr_t)alloc_base; - - alloc_base += alloc_sz; - - if (page_hash == NULL) { - page_hash = (struct page **)bop_base; - bop_base = roundup(bop_base + pagehash_sz, - ecache_alignsize); - } - - if (ctrs_base == NULL) { - ctrs_base = (caddr_t)bop_base; - bop_base = roundup(bop_base + ctrs_sz, - ecache_alignsize); - } - - if (memseg_base == NULL) { - memseg_base = (struct memseg *)bop_base; - bop_base = roundup(bop_base + memseg_sz, - ecache_alignsize); - } - - if (kpm_enable && kpm_pp_base == NULL) { - kpm_pp_base = (uintptr_t)bop_base; - bop_base = roundup(bop_base + kpm_pp_sz, - ecache_alignsize); - } - - if (pse_mutex == NULL) { - pse_mutex = (pad_mutex_t *)bop_base; - bop_base = roundup(bop_base + - pse_table_size * sizeof (pad_mutex_t), - ecache_alignsize); - } - - ASSERT(bop_base <= (uintptr_t)alloc_base); - } - - PRM_DEBUG(page_hash); - PRM_DEBUG(memseg_base); - PRM_DEBUG(kpm_pp_base); - PRM_DEBUG(kpm_pp_sz); - PRM_DEBUG(pp_base); - PRM_DEBUG(pp_sz); - PRM_DEBUG(alloc_base); - -#ifdef TRAPTRACE - alloc_base = trap_trace_alloc(alloc_base); - PRM_DEBUG(alloc_base); -#endif /* TRAPTRACE */ - - /* - * In theory it's possible that kmem64 chunk is 0 sized - * (on very small machines). Check for that. - */ - if (alloc_base == kmem64_base) { - kmem64_base = NULL; - kmem64_end = NULL; - kmem64_aligned_end = NULL; - goto kmem64_alloced; - } - - /* - * Allocate kmem64 memory. - * Round up to end of large page and overmap. - * kmem64_end..kmem64_aligned_end is added to memory list for reuse - */ - kmem64_end = (caddr_t)roundup((uintptr_t)alloc_base, - MMU_PAGESIZE); - - /* - * Make one large memory alloc after figuring out the 64-bit size. This - * will enable use of the largest page size appropriate for the system - * architecture. - */ - ASSERT(mmu_exported_pagesize_mask & (1 << TTE8K)); - ASSERT(IS_P2ALIGNED(kmem64_base, TTEBYTES(max_bootlp_tteszc))); - for (i = max_bootlp_tteszc; i >= TTE8K; i--) { - size_t asize; -#if !defined(C_OBP) - unsigned long long pa; -#endif /* !C_OBP */ - - if ((mmu_exported_pagesize_mask & (1 << i)) == 0) - continue; - kmem64_alignsize = TTEBYTES(i); - kmem64_szc = i; - - /* limit page size for small memory */ - if (mmu_btop(kmem64_alignsize) > (npages >> 2)) - continue; - - kmem64_aligned_end = (caddr_t)roundup((uintptr_t)kmem64_end, - kmem64_alignsize); - asize = kmem64_aligned_end - kmem64_base; -#if !defined(C_OBP) - if (prom_allocate_phys(asize, kmem64_alignsize, &pa) == 0) { - if (prom_claim_virt(asize, kmem64_base) != - (caddr_t)-1) { - kmem64_pabase = pa; - install_kmem64_tte(); - break; - } else { - prom_free_phys(asize, pa); - } - } -#else /* !C_OBP */ - if ((caddr_t)BOP_ALLOC(bootops, kmem64_base, asize, - kmem64_alignsize) == kmem64_base) { - kmem64_pabase = va_to_pa(kmem64_base); - break; - } -#endif /* !C_OBP */ - if (i == TTE8K) { - prom_panic("kmem64 allocation failure"); - } - } - - PRM_DEBUG(kmem64_base); - PRM_DEBUG(kmem64_end); - PRM_DEBUG(kmem64_aligned_end); - PRM_DEBUG(kmem64_alignsize); - - /* - * Now set pa using saved va from above. + * In order to get things sized correctly on lower memory + * machines (where the memory used by the ramdisk represents + * a significant portion of memory), physmem is adjusted. + * + * This is done by subtracting the ramdisk_size which is set + * to the size of the ramdisk (in Kb) in /etc/system at the + * time the miniroot archive is constructed. */ - if (&ecache_init_scrub_flush_area) { - (void) ecache_init_scrub_flush_area(NULL); - } - -kmem64_alloced: + if (root_is_ramdisk == B_TRUE) + physmem -= (ramdisk_size * 1024) / PAGESIZE; - /* - * Initialize per page size free list counters. - */ - ctrs_end = page_ctrs_alloc(ctrs_base); - ASSERT(ctrs_base + ctrs_sz >= ctrs_end); + if (kpm_enable && (ndata_alloc_kpm(&ndata, kpm_npages) != 0)) + cmn_err(CE_PANIC, "no more nucleus memory after kpm alloc"); /* - * Allocate space for the interrupt vector table and also for the - * reserved interrupt vector data structures. + * Allocate space for the interrupt vector table. */ - memspace = (caddr_t)BOP_ALLOC(bootops, (caddr_t)intr_vec_table, - IVSIZE, MMU_PAGESIZE); + memspace = prom_alloc((caddr_t)intr_vec_table, IVSIZE, MMU_PAGESIZE); if (memspace != (caddr_t)intr_vec_table) prom_panic("interrupt vector table allocation failure"); /* - * The memory lists from boot are allocated from the heap arena - * so that later they can be freed and/or reallocated. - */ - if (BOP_GETPROP(bootops, "extent", &memlist_sz) == -1) - prom_panic("could not retrieve property \"extent\""); - - /* * Between now and when we finish copying in the memory lists, * allocations happen so the space gets fragmented and the - * lists longer. Leave enough space for lists twice as long - * as what boot says it has now; roundup to a pagesize. - * Also add space for the final phys-avail copy in the fixup - * routine. - */ - va = (caddr_t)(sysbase + PAGESIZE + PANICBUFSIZE + - roundup(IVSIZE, MMU_PAGESIZE)); - memlist_sz *= 4; - memlist_sz = roundup(memlist_sz, MMU_PAGESIZE); - memspace = (caddr_t)BOP_ALLOC(bootops, va, memlist_sz, BO_NO_ALIGN); + * lists longer. Leave enough space for lists twice as + * long as we have now; then roundup to a pagesize. + */ + memlist_sz = sizeof (struct memlist) * (prom_phys_installed_len() + + prom_phys_avail_len() + prom_virt_avail_len()); + memlist_sz *= 2; + memlist_sz = roundup(memlist_sz, PAGESIZE); + memspace = ndata_alloc(&ndata, memlist_sz, ecache_alignsize); if (memspace == NULL) - halt("Boot allocation failed."); + cmn_err(CE_PANIC, "no more nucleus memory after memlist alloc"); memlist = (struct memlist *)memspace; memlist_end = (char *)memspace + memlist_sz; - PRM_DEBUG(memlist); PRM_DEBUG(memlist_end); + PRM_DEBUG(sysbase); PRM_DEBUG(syslimit); - kernelheap_init((void *)sysbase, (void *)syslimit, (caddr_t)sysbase + PAGESIZE, NULL, NULL); @@ -1572,7 +1261,7 @@ kmem64_alloced: &boot_virtavail, &boot_virtavail_len); /* - * Remove the space used by BOP_ALLOC from the kernel heap + * Remove the space used by prom_alloc from the kernel heap * plus the area actually used by the OBP (if any) * ignoring virtual addresses in virt_avail, above syslimit. */ @@ -1597,30 +1286,7 @@ kmem64_alloced: } phys_avail = memlist; - (void) copy_physavail(boot_physavail, boot_physavail_len, - &memlist, 0, 0); - - /* - * Add any unused kmem64 memory from overmapped page - * (Note: va_to_pa does not work for kmem64_end) - */ - if (kmem64_end < kmem64_aligned_end) { - uint64_t overlap_size = kmem64_aligned_end - kmem64_end; - uint64_t overlap_pa = kmem64_pabase + - (kmem64_end - kmem64_base); - - PRM_DEBUG(overlap_pa); - PRM_DEBUG(overlap_size); - memlist_add(overlap_pa, overlap_size, &memlist, &phys_avail); - } - - /* - * Add any extra memory after e_text to the phys_avail list, as long - * as there's at least a page to add. - */ - if (extra_etpg) - memlist_add(va_to_pa(extra_etva), mmu_ptob(extra_etpg), - &memlist, &phys_avail); + copy_memlist(boot_physavail, boot_physavail_len, &memlist); /* * Add any extra memory at the end of the ndata region if there's at @@ -1632,25 +1298,34 @@ kmem64_alloced: nalloc_base = nalloc_end; ndata_remain_sz = nalloc_end - nalloc_base; - if (ndata_remain_sz >= MMU_PAGESIZE) - memlist_add(va_to_pa(nalloc_base), - (uint64_t)ndata_remain_sz, &memlist, &phys_avail); + /* + * Copy physinstalled list into kernel space. + */ + phys_install = memlist; + copy_memlist(boot_physinstalled, boot_physinstalled_len, &memlist); - PRM_DEBUG(memlist); - PRM_DEBUG(memlist_sz); - PRM_DEBUG(memspace); + /* + * Create list of physical addrs we don't need pp's for: + * kernel text 4M page + * kernel data 4M page - ndata_remain_sz + * kmem64 pages + * + * NB if adding any pages here, make sure no kpm page + * overlaps can occur (see ASSERTs in kphysm_memsegs) + */ + nopp_list = memlist; + memlist_new(va_to_pa(s_text), MMU_PAGESIZE4M, &memlist); + memlist_add(va_to_pa(s_data), MMU_PAGESIZE4M - ndata_remain_sz, + &memlist, &nopp_list); + memlist_add(kmem64_pabase, kmem64_sz, &memlist, &nopp_list); if ((caddr_t)memlist > (memspace + memlist_sz)) prom_panic("memlist overflow"); - PRM_DEBUG(pp_base); - PRM_DEBUG(memseg_base); - PRM_DEBUG(npages); - /* * Initialize the page structures from the memory lists. */ - kphysm_init(pp_base, memseg_base, npages, kpm_pp_base, kpm_npages); + kphysm_init(); availrmem_initial = availrmem = freemem; PRM_DEBUG(availrmem); @@ -1703,26 +1378,12 @@ kmem64_alloced: static void startup_modules(void) { - int proplen, nhblk1, nhblk8; + int nhblk1, nhblk8; size_t nhblksz; pgcnt_t pages_per_hblk; size_t hme8blk_sz, hme1blk_sz; /* - * Log any optional messages from the boot program - */ - proplen = (size_t)BOP_GETPROPLEN(bootops, "boot-message"); - if (proplen > 0) { - char *msg; - size_t len = (size_t)proplen; - - msg = kmem_zalloc(len, KM_SLEEP); - (void) BOP_GETPROP(bootops, "boot-message", msg); - cmn_err(CE_CONT, "?%s\n", msg); - kmem_free(msg, len); - } - - /* * Let the platforms have a chance to change default * values before reading system file. */ @@ -1903,7 +1564,6 @@ startup_modules(void) static void startup_bop_gone(void) { - extern int bop_io_quiesced; /* * Destroy the MD initialized at startup @@ -1913,19 +1573,13 @@ startup_bop_gone(void) mach_descrip_startup_fini(); /* - * Call back into boot and release boots resources. + * We're done with prom allocations. */ - BOP_QUIESCE_IO(bootops); - bop_io_quiesced = 1; + bop_fini(); copy_boot_memlists(&boot_physinstalled, &boot_physinstalled_len, &boot_physavail, &boot_physavail_len, &boot_virtavail, &boot_virtavail_len); - /* - * Copy physinstalled list into kernel space. - */ - phys_install = memlist; - copy_memlist(boot_physinstalled, boot_physinstalled_len, &memlist); /* * setup physically contiguous area twice as large as the ecache. @@ -1947,9 +1601,6 @@ startup_bop_gone(void) virt_avail = memlist; copy_memlist(boot_virtavail, boot_virtavail_len, &memlist); - /* - * Last chance to ask our booter questions .. - */ } @@ -1979,8 +1630,7 @@ startup_fixup_physavail(void) * from the original list we copied earlier. */ cur = memlist; - (void) copy_physavail(boot_physavail, boot_physavail_len, - &memlist, 0, 0); + copy_memlist(boot_physavail, boot_physavail_len, &memlist); /* * Add any unused kmem64 memory from overmapped page @@ -1988,17 +1638,13 @@ startup_fixup_physavail(void) */ if (kmem64_overmap_size) { memlist_add(kmem64_pabase + (kmem64_end - kmem64_base), - kmem64_overmap_size, - &memlist, &cur); + kmem64_overmap_size, &memlist, &cur); } /* - * Add any extra memory after e_text we added to the phys_avail list + * Add any extra memory after e_data we added to the phys_avail list * back to the old list. */ - if (extra_etpg) - memlist_add(va_to_pa(extra_etva), mmu_ptob(extra_etpg), - &memlist, &cur); if (ndata_remain_sz >= MMU_PAGESIZE) memlist_add(va_to_pa(nalloc_base), (uint64_t)ndata_remain_sz, &memlist, &cur); @@ -2016,19 +1662,12 @@ startup_fixup_physavail(void) * the prom has allocated for it's own book-keeping, and remove * them from the freelist too. sigh. */ - fix_prom_pages(phys_avail, cur); + sync_memlists(phys_avail, cur); ASSERT(phys_avail != NULL); memlist_free_list(phys_avail); phys_avail = cur; - /* - * We're done with boot. Just after this point in time, boot - * gets unmapped, so we can no longer rely on its services. - * Zero the bootops to indicate this fact. - */ - bootops = (struct bootops *)NULL; - BOOTOPS_GONE(); } static void @@ -2088,13 +1727,6 @@ startup_vm(void) kvm_init(); /* - * XXX4U: previously, we initialized and turned on - * the caches at this point. But of course we have - * nothing to do, as the prom has already done this - * for us -- main memory must be E$able at all times. - */ - - /* * If the following is true, someone has patched * phsymem to be less than the number of pages that * the system actually has. Remove pages until system @@ -2595,6 +2227,17 @@ init_ptl1_thread(void) #endif /* PTL1_PANIC_DEBUG */ +static void +memlist_new(uint64_t start, uint64_t len, struct memlist **memlistp) +{ + struct memlist *new; + + new = *memlistp; + new->address = start; + new->size = len; + *memlistp = new + 1; +} + /* * Add to a memory list. * start = start of new memory segment @@ -2606,16 +2249,41 @@ static void memlist_add(uint64_t start, uint64_t len, struct memlist **memlistp, struct memlist **curmemlistp) { - struct memlist *new; - - new = *memlistp; - new->address = start; - new->size = len; - *memlistp = new + 1; + struct memlist *new = *memlistp; + memlist_new(start, len, memlistp); memlist_insert(new, curmemlistp); } +static int +ndata_alloc_memseg(struct memlist *ndata, size_t avail) +{ + int nseg; + size_t memseg_sz; + struct memseg *msp; + + /* + * The memseg list is for the chunks of physical memory that + * will be managed by the vm system. The number calculated is + * a guess as boot may fragment it more when memory allocations + * are made before kphysm_init(). + */ + memseg_sz = (avail + 10) * sizeof (struct memseg); + memseg_sz = roundup(memseg_sz, PAGESIZE); + nseg = memseg_sz / sizeof (struct memseg); + msp = ndata_alloc(ndata, memseg_sz, ecache_alignsize); + if (msp == NULL) + return (1); + PRM_DEBUG(memseg_free); + + while (nseg--) { + msp->next = memseg_free; + memseg_free = msp; + msp++; + } + return (0); +} + /* * In the case of architectures that support dynamic addition of * memory at run-time there are two cases where memsegs need to @@ -2687,132 +2355,207 @@ add_physmem_cb(page_t *pp, pfn_t pnum) } /* - * kphysm_init() tackles the problem of initializing physical memory. - * The old startup made some assumptions about the kernel living in - * physically contiguous space which is no longer valid. + * Find memseg with given pfn + */ +static struct memseg * +memseg_find(pfn_t base, pfn_t *next) +{ + struct memseg *seg; + + if (next != NULL) + *next = LONG_MAX; + for (seg = memsegs; seg != NULL; seg = seg->next) { + if (base >= seg->pages_base && base < seg->pages_end) + return (seg); + if (next != NULL && seg->pages_base > base && + seg->pages_base < *next) + *next = seg->pages_base; + } + return (NULL); +} + +extern struct vnode prom_ppages; + +/* + * Put page allocated by OBP on prom_ppages */ static void -kphysm_init(page_t *pp, struct memseg *memsegp, pgcnt_t npages, - uintptr_t kpm_pp, pgcnt_t kpm_npages) +kphysm_erase(uint64_t addr, uint64_t len) { - struct memlist *pmem; - struct memseg *msp; - pfn_t base; - pgcnt_t num; - pfn_t lastseg_pages_end = 0; - pgcnt_t nelem_used = 0; + struct page *pp; + struct memseg *seg; + pfn_t base = btop(addr), next; + pgcnt_t num = btop(len); - ASSERT(page_hash != NULL && page_hashsz != 0); + while (num != 0) { + pgcnt_t off, left; - msp = memsegp; - for (pmem = phys_avail; pmem && npages; pmem = pmem->next) { + seg = memseg_find(base, &next); + if (seg == NULL) { + if (next == LONG_MAX) + break; + left = MIN(next - base, num); + base += left, num -= left; + continue; + } + off = base - seg->pages_base; + pp = seg->pages + off; + left = num - MIN(num, (seg->pages_end - seg->pages_base) - off); + while (num != left) { + /* + * init it, lock it, and hashin on prom_pages vp. + * + * XXX vnode offsets on the prom_ppages vnode + * are page numbers (gack) for >32 bit + * physical memory machines. + */ + add_physmem_cb(pp, base); + if (page_trylock(pp, SE_EXCL) == 0) + cmn_err(CE_PANIC, "prom page locked"); + (void) page_hashin(pp, &prom_ppages, + (offset_t)base, NULL); + (void) page_pp_lock(pp, 0, 1); + pp++, base++, num--; + } + } +} + +static page_t *ppnext; +static pgcnt_t ppleft; + +static void *kpm_ppnext; +static pgcnt_t kpm_ppleft; + +/* + * Create a memseg + */ +static void +kphysm_memseg(uint64_t addr, uint64_t len) +{ + pfn_t base = btop(addr); + pgcnt_t num = btop(len); + struct memseg *seg; + seg = memseg_free; + memseg_free = seg->next; + ASSERT(seg != NULL); + + seg->pages = ppnext; + seg->epages = ppnext + num; + seg->pages_base = base; + seg->pages_end = base + num; + ppnext += num; + ppleft -= num; + + if (kpm_enable) { + pgcnt_t kpnum = ptokpmpr(num); + + if (kpnum > kpm_ppleft) + panic("kphysm_memseg: kpm_pp overflow"); + seg->pagespa = va_to_pa(seg->pages); + seg->epagespa = va_to_pa(seg->epages); + seg->kpm_pbase = kpmptop(ptokpmp(base)); + seg->kpm_nkpmpgs = kpnum; /* - * Build the memsegs entry + * In the kpm_smallpage case, the kpm array + * is 1-1 wrt the page array */ - num = btop(pmem->size); - if (num > npages) - num = npages; - npages -= num; - base = btop(pmem->address); - - msp->pages = pp; - msp->epages = pp + num; - msp->pages_base = base; - msp->pages_end = base + num; - - if (kpm_enable) { - pfn_t pbase_a; - pfn_t pend_a; - pfn_t prev_pend_a; - pgcnt_t nelem; - - msp->pagespa = va_to_pa(pp); - msp->epagespa = va_to_pa(pp + num); - pbase_a = kpmptop(ptokpmp(base)); - pend_a = kpmptop(ptokpmp(base + num - 1)) + kpmpnpgs; - nelem = ptokpmp(pend_a - pbase_a); - msp->kpm_nkpmpgs = nelem; - msp->kpm_pbase = pbase_a; - if (lastseg_pages_end) { - /* - * Assume phys_avail is in ascending order - * of physical addresses. - */ - ASSERT(base + num > lastseg_pages_end); - prev_pend_a = kpmptop( - ptokpmp(lastseg_pages_end - 1)) + kpmpnpgs; - - if (prev_pend_a > pbase_a) { - /* - * Overlap, more than one memseg may - * point to the same kpm_page range. - */ - if (kpm_smallpages == 0) { - msp->kpm_pages = - (kpm_page_t *)kpm_pp - 1; - kpm_pp = (uintptr_t) - ((kpm_page_t *)kpm_pp - + nelem - 1); - } else { - msp->kpm_spages = - (kpm_spage_t *)kpm_pp - 1; - kpm_pp = (uintptr_t) - ((kpm_spage_t *)kpm_pp - + nelem - 1); - } - nelem_used += nelem - 1; - - } else { - if (kpm_smallpages == 0) { - msp->kpm_pages = - (kpm_page_t *)kpm_pp; - kpm_pp = (uintptr_t) - ((kpm_page_t *)kpm_pp - + nelem); - } else { - msp->kpm_spages = - (kpm_spage_t *)kpm_pp; - kpm_pp = (uintptr_t) - ((kpm_spage_t *) - kpm_pp + nelem); - } - nelem_used += nelem; - } + if (kpm_smallpages) { + kpm_spage_t *kpm_pp = kpm_ppnext; - } else { - if (kpm_smallpages == 0) { - msp->kpm_pages = (kpm_page_t *)kpm_pp; - kpm_pp = (uintptr_t) - ((kpm_page_t *)kpm_pp + nelem); - } else { - msp->kpm_spages = (kpm_spage_t *)kpm_pp; - kpm_pp = (uintptr_t) - ((kpm_spage_t *)kpm_pp + nelem); - } - nelem_used = nelem; - } + kpm_ppnext = kpm_pp + kpnum; + seg->kpm_spages = kpm_pp; + seg->kpm_pagespa = va_to_pa(seg->kpm_spages); + } else { + kpm_page_t *kpm_pp = kpm_ppnext; + + kpm_ppnext = kpm_pp + kpnum; + seg->kpm_pages = kpm_pp; + seg->kpm_pagespa = va_to_pa(seg->kpm_pages); + /* ASSERT no kpm overlaps */ + ASSERT( + memseg_find(base - pmodkpmp(base), NULL) == NULL); + ASSERT(memseg_find( + roundup(base + num, kpmpnpgs) - 1, NULL) == NULL); + } + kpm_ppleft -= num; + } - if (nelem_used > kpm_npages) - panic("kphysm_init: kpm_pp overflow\n"); + memseg_list_add(seg); +} - msp->kpm_pagespa = va_to_pa(msp->kpm_pages); - lastseg_pages_end = msp->pages_end; - } +/* + * Add range to free list + */ +void +kphysm_add(uint64_t addr, uint64_t len, int reclaim) +{ + struct page *pp; + struct memseg *seg; + pfn_t base = btop(addr); + pgcnt_t num = btop(len); - memseg_list_add(msp); + seg = memseg_find(base, NULL); + ASSERT(seg != NULL); + pp = seg->pages + (base - seg->pages_base); + + if (reclaim) { + struct page *rpp = pp; + struct page *lpp = pp + num; /* - * add_physmem() initializes the PSM part of the page - * struct by calling the PSM back with add_physmem_cb(). - * In addition it coalesces pages into larger pages as - * it initializes them. + * page should be locked on prom_ppages + * unhash and unlock it */ - add_physmem(pp, num, base); - pp += num; - msp++; + while (rpp < lpp) { + ASSERT(PAGE_EXCL(rpp) && rpp->p_vnode == &prom_ppages); + page_pp_unlock(rpp, 0, 1); + page_hashout(rpp, NULL); + page_unlock(rpp); + rpp++; + } } + /* + * add_physmem() initializes the PSM part of the page + * struct by calling the PSM back with add_physmem_cb(). + * In addition it coalesces pages into larger pages as + * it initializes them. + */ + add_physmem(pp, num, base); +} + +/* + * kphysm_init() tackles the problem of initializing physical memory. + */ +static void +kphysm_init(void) +{ + struct memlist *pmem; + + ASSERT(page_hash != NULL && page_hashsz != 0); + + ppnext = pp_base; + ppleft = npages; + kpm_ppnext = kpm_pp_base; + kpm_ppleft = kpm_npages; + + /* + * installed pages not on nopp_memlist go in memseg list + */ + diff_memlists(phys_install, nopp_list, kphysm_memseg); + + /* + * Free the avail list + */ + for (pmem = phys_avail; pmem != NULL; pmem = pmem->next) + kphysm_add(pmem->address, pmem->size, 0); + + /* + * Erase pages that aren't available + */ + diff_memlists(phys_install, phys_avail, kphysm_erase); + build_pfn_hash(); } @@ -3201,25 +2944,6 @@ do_prom_version_check(void) cmn_err(CE_WARN, drev, " on one or more CPU boards", buf); } -static void -kpm_init() -{ - kpm_pgshft = (kpm_smallpages == 0) ? MMU_PAGESHIFT4M : MMU_PAGESHIFT; - kpm_pgsz = 1ull << kpm_pgshft; - kpm_pgoff = kpm_pgsz - 1; - kpmp2pshft = kpm_pgshft - PAGESHIFT; - kpmpnpgs = 1 << kpmp2pshft; - ASSERT(((uintptr_t)kpm_vbase & (kpm_pgsz - 1)) == 0); -} - -void -kpm_npages_setup(int memblocks) -{ - /* - * npages can be scattered in a maximum of 'memblocks' - */ - kpm_npages = ptokpmpr(npages) + memblocks; -} /* * Must be defined in platform dependent code. diff --git a/usr/src/uts/sun4/sys/memlist_plat.h b/usr/src/uts/sun4/sys/memlist_plat.h index 7bf901ce6c..6f98bcb28a 100644 --- a/usr/src/uts/sun4/sys/memlist_plat.h +++ b/usr/src/uts/sun4/sys/memlist_plat.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 1991-2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -40,23 +39,35 @@ extern "C" { #endif +/* + * The prom hands us an array of these + * as available and installed props + */ +typedef struct prom_memlist { + u_longlong_t addr; + u_longlong_t size; +} prom_memlist_t; + extern int check_boot_version(int); -extern int check_memexp(struct memlist *, uint_t); -extern void copy_memlist(u_longlong_t *, size_t, struct memlist **); -extern int copy_physavail(u_longlong_t *, size_t, struct memlist **, - uint_t, uint_t); -extern void size_physavail(u_longlong_t *physavail, size_t size, +extern void copy_memlist(prom_memlist_t *, size_t, struct memlist **); +extern void size_physavail(prom_memlist_t *physavail, size_t size, pgcnt_t *npages, int *memblocks); -extern pgcnt_t size_virtalloc(u_longlong_t *avail, size_t size); -extern void installed_top_size_memlist_array(u_longlong_t *, size_t, pfn_t *, +extern pgcnt_t size_virtalloc(prom_memlist_t *avail, size_t size); +extern void installed_top_size_memlist_array(prom_memlist_t *, size_t, pfn_t *, pgcnt_t *); extern void installed_top_size(struct memlist *, pfn_t *, pgcnt_t *); extern void fix_prom_pages(struct memlist *, struct memlist *); -extern void copy_boot_memlists(u_longlong_t **physinstalled, - size_t *physinstalled_len, u_longlong_t **physavail, size_t *physavail_len, - u_longlong_t **virtavail, size_t *virtavail_len); +extern void init_boot_memlists(void); +extern void copy_boot_memlists( + prom_memlist_t **physinstalled, size_t *physinstalled_len, + prom_memlist_t **physavail, size_t *physavail_len, + prom_memlist_t **virtavail, size_t *virtavail_len); extern void phys_install_has_changed(void); +extern void diff_memlists(struct memlist *, struct memlist *, + void (*)(uint64_t, uint64_t)); +extern void sync_memlists(struct memlist *, struct memlist *); + #ifdef __cplusplus } #endif diff --git a/usr/src/uts/sun4/sys/memnode.h b/usr/src/uts/sun4/sys/memnode.h index 745d03002f..e3bba09096 100644 --- a/usr/src/uts/sun4/sys/memnode.h +++ b/usr/src/uts/sun4/sys/memnode.h @@ -35,6 +35,7 @@ extern "C" { #ifdef _KERNEL #include <sys/lgrp.h> +#include <sys/memlist_plat.h> /* * This file defines the mappings between physical addresses and memory @@ -103,7 +104,7 @@ struct mem_node_conf { struct memlist; -extern void startup_build_mem_nodes(u_longlong_t *, size_t); +extern void startup_build_mem_nodes(prom_memlist_t *, size_t); extern void mem_node_add_slice(pfn_t, pfn_t); extern void mem_node_pre_del_slice(pfn_t, pfn_t); extern void mem_node_post_del_slice(pfn_t, pfn_t, int); diff --git a/usr/src/uts/sun4/sys/platform_module.h b/usr/src/uts/sun4/sys/platform_module.h index 8f96b014c7..1475816e52 100644 --- a/usr/src/uts/sun4/sys/platform_module.h +++ b/usr/src/uts/sun4/sys/platform_module.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -30,6 +30,7 @@ #include <sys/async.h> #include <sys/sunddi.h> +#include <sys/memlist_plat.h> #ifdef __cplusplus extern "C" { @@ -59,7 +60,7 @@ extern void load_platform_modules(void); extern int plat_cpu_poweron(struct cpu *cp); /* power on CPU */ extern int plat_cpu_poweroff(struct cpu *cp); /* power off CPU */ extern void plat_freelist_process(int mnode); -extern void plat_build_mem_nodes(u_longlong_t *, size_t); +extern void plat_build_mem_nodes(prom_memlist_t *, size_t); extern void plat_slice_add(pfn_t, pfn_t); extern void plat_slice_del(pfn_t, pfn_t); extern int plat_lpkmem_is_supported(void); diff --git a/usr/src/uts/sun4/vm/sfmmu.c b/usr/src/uts/sun4/vm/sfmmu.c index 78247431a3..8581f17d4d 100644 --- a/usr/src/uts/sun4/vm/sfmmu.c +++ b/usr/src/uts/sun4/vm/sfmmu.c @@ -514,37 +514,6 @@ ndata_maxsize(struct memlist *ndata) return (chunksize); } -/* - * This is a special function to figure out if the memory chunk needed - * for the page structs can fit in the nucleus or not. If it fits the - * function calculates and returns the possible remaining ndata size - * in the last element if the size needed for page structs would be - * allocated from the nucleus. - */ -size_t -ndata_spare(struct memlist *ndata, size_t wanted, size_t alignment) -{ - struct memlist *frlist; - uintptr_t base; - uintptr_t end; - - for (frlist = ndata; frlist != NULL; frlist = frlist->next) { - base = roundup(frlist->address, alignment); - end = roundup(base + wanted, ecache_alignsize); - - if (end <= frlist->address + frlist->size) { - if (frlist->next == NULL) - return (frlist->address + frlist->size - end); - - while (frlist->next != NULL) - frlist = frlist->next; - - return (frlist->size); - } - } - - return (0); -} /* * Allocate the last properly aligned memory chunk. @@ -876,27 +845,11 @@ ndata_alloc_tsbs(struct memlist *ndata, pgcnt_t npages) return (0); } -/* - * Allocate hat structs from the nucleus data memory. - */ -int -ndata_alloc_hat(struct memlist *ndata, pgcnt_t npages, pgcnt_t kpm_npages) +size_t +calc_hmehash_sz(pgcnt_t npages) { - size_t mml_alloc_sz; - size_t cb_alloc_sz; - int max_nucuhme_buckets = MAX_NUCUHME_BUCKETS; - int max_nuckhme_buckets = MAX_NUCKHME_BUCKETS; ulong_t hme_buckets; - if (enable_bigktsb) { - ASSERT((max_nucuhme_buckets + max_nuckhme_buckets) * - sizeof (struct hmehash_bucket) <= - TSB_BYTES(TSB_1M_SZCODE)); - - max_nucuhme_buckets *= 2; - max_nuckhme_buckets *= 2; - } - /* * The number of buckets in the hme hash tables * is a power of 2 such that the average hash chain length is @@ -925,27 +878,36 @@ ndata_alloc_hat(struct memlist *ndata, pgcnt_t npages, pgcnt_t kpm_npages) khmehash_num = 1 << highbit(khmehash_num - 1); khmehash_num = MAX(khmehash_num, MIN_KHME_BUCKETS); - if ((khmehash_num > max_nuckhme_buckets) || - (uhmehash_num > max_nucuhme_buckets)) { - khme_hash = NULL; - uhme_hash = NULL; - } else { - size_t hmehash_sz = (uhmehash_num + khmehash_num) * - sizeof (struct hmehash_bucket); + return ((uhmehash_num + khmehash_num) * sizeof (struct hmehash_bucket)); +} - if ((khme_hash = ndata_alloc(ndata, hmehash_sz, - ecache_alignsize)) != NULL) - uhme_hash = &khme_hash[khmehash_num]; - else - uhme_hash = NULL; +caddr_t +alloc_hmehash(caddr_t alloc_base) +{ + size_t khmehash_sz, uhmehash_sz; - PRM_DEBUG(hmehash_sz); - } + khme_hash = (struct hmehash_bucket *)alloc_base; + khmehash_sz = khmehash_num * sizeof (struct hmehash_bucket); + alloc_base += khmehash_sz; + + uhme_hash = (struct hmehash_bucket *)alloc_base; + uhmehash_sz = uhmehash_num * sizeof (struct hmehash_bucket); + alloc_base += uhmehash_sz; PRM_DEBUG(khme_hash); - PRM_DEBUG(khmehash_num); PRM_DEBUG(uhme_hash); - PRM_DEBUG(uhmehash_num); + + return (alloc_base); +} + +/* + * Allocate hat structs from the nucleus data memory. + */ +int +ndata_alloc_hat(struct memlist *ndata, pgcnt_t npages) +{ + size_t mml_alloc_sz; + size_t cb_alloc_sz; /* * For the page mapping list mutex array we allocate one mutex @@ -954,13 +916,6 @@ ndata_alloc_hat(struct memlist *ndata, pgcnt_t npages, pgcnt_t kpm_npages) * is rounded up (ie. 1 << highbit(npages * 1.5 / 128)) * * mml_shift is roughly log2(mml_table_sz) + 3 for MLIST_HASH - * - * It is not required that this be allocated from the nucleus, - * but it is desirable. So we first allocate from the nucleus - * everything that must be there. Having done so, if mml_table - * will fit within what remains of the nucleus then it will be - * allocated here. If not, set mml_table to NULL, which will cause - * startup_memlist() to BOP_ALLOC() space for it after our return... */ mml_table_sz = 1 << highbit((npages * 3) / 256); if (mml_table_sz < 64) @@ -975,92 +930,73 @@ ndata_alloc_hat(struct memlist *ndata, pgcnt_t npages, pgcnt_t kpm_npages) mml_alloc_sz = mml_table_sz * sizeof (kmutex_t); mml_table = ndata_alloc(ndata, mml_alloc_sz, ecache_alignsize); - + if (mml_table == NULL) + return (-1); PRM_DEBUG(mml_table); cb_alloc_sz = sfmmu_max_cb_id * sizeof (struct sfmmu_callback); PRM_DEBUG(cb_alloc_sz); sfmmu_cb_table = ndata_alloc(ndata, cb_alloc_sz, ecache_alignsize); + if (sfmmu_cb_table == NULL) + return (-1); PRM_DEBUG(sfmmu_cb_table); + return (0); +} + +int +ndata_alloc_kpm(struct memlist *ndata, pgcnt_t kpm_npages) +{ + size_t kpmp_alloc_sz; + /* * For the kpm_page mutex array we allocate one mutex every 16 * kpm pages (64MB). In smallpage mode we allocate one mutex * every 8K pages. The minimum is set to 64 entries and the * maximum to 8K entries. - * - * It is not required that this be allocated from the nucleus, - * but it is desirable. So we first allocate from the nucleus - * everything that must be there. Having done so, if kpmp_table - * or kpmp_stable will fit within what remains of the nucleus - * then it will be allocated here. If not, startup_memlist() - * will use BOP_ALLOC() space for it after our return... */ - if (kpm_enable) { - size_t kpmp_alloc_sz; - - if (kpm_smallpages == 0) { - kpmp_shift = highbit(sizeof (kpm_page_t)) - 1; - kpmp_table_sz = 1 << highbit(kpm_npages / 16); - kpmp_table_sz = (kpmp_table_sz < 64) ? 64 : - ((kpmp_table_sz > 8192) ? 8192 : kpmp_table_sz); - kpmp_alloc_sz = kpmp_table_sz * sizeof (kpm_hlk_t); - - kpmp_table = ndata_alloc(ndata, kpmp_alloc_sz, - ecache_alignsize); + if (kpm_smallpages == 0) { + kpmp_shift = highbit(sizeof (kpm_page_t)) - 1; + kpmp_table_sz = 1 << highbit(kpm_npages / 16); + kpmp_table_sz = (kpmp_table_sz < 64) ? 64 : + ((kpmp_table_sz > 8192) ? 8192 : kpmp_table_sz); + kpmp_alloc_sz = kpmp_table_sz * sizeof (kpm_hlk_t); + + kpmp_table = ndata_alloc(ndata, kpmp_alloc_sz, + ecache_alignsize); + if (kpmp_table == NULL) + return (-1); - PRM_DEBUG(kpmp_table); - PRM_DEBUG(kpmp_table_sz); + PRM_DEBUG(kpmp_table); + PRM_DEBUG(kpmp_table_sz); - kpmp_stable_sz = 0; - kpmp_stable = NULL; - } else { - ASSERT(kpm_pgsz == PAGESIZE); - kpmp_shift = highbit(sizeof (kpm_shlk_t)) + 1; - kpmp_stable_sz = 1 << highbit(kpm_npages / 8192); - kpmp_stable_sz = (kpmp_stable_sz < 64) ? 64 : - ((kpmp_stable_sz > 8192) ? 8192 : kpmp_stable_sz); - kpmp_alloc_sz = kpmp_stable_sz * sizeof (kpm_shlk_t); - - kpmp_stable = ndata_alloc(ndata, kpmp_alloc_sz, - ecache_alignsize); + kpmp_stable_sz = 0; + kpmp_stable = NULL; + } else { + ASSERT(kpm_pgsz == PAGESIZE); + kpmp_shift = highbit(sizeof (kpm_shlk_t)) + 1; + kpmp_stable_sz = 1 << highbit(kpm_npages / 8192); + kpmp_stable_sz = (kpmp_stable_sz < 64) ? 64 : + ((kpmp_stable_sz > 8192) ? 8192 : kpmp_stable_sz); + kpmp_alloc_sz = kpmp_stable_sz * sizeof (kpm_shlk_t); + + kpmp_stable = ndata_alloc(ndata, kpmp_alloc_sz, + ecache_alignsize); + if (kpmp_stable == NULL) + return (-1); - PRM_DEBUG(kpmp_stable); - PRM_DEBUG(kpmp_stable_sz); + PRM_DEBUG(kpmp_stable); + PRM_DEBUG(kpmp_stable_sz); - kpmp_table_sz = 0; - kpmp_table = NULL; - } - PRM_DEBUG(kpmp_shift); + kpmp_table_sz = 0; + kpmp_table = NULL; } + PRM_DEBUG(kpmp_shift); return (0); } /* - * Allocate virtual addresses at base with given alignment. - * Note that there is no physical memory behind the address yet. - */ -caddr_t -alloc_hme_buckets(caddr_t base, int alignsize) -{ - size_t hmehash_sz = (uhmehash_num + khmehash_num) * - sizeof (struct hmehash_bucket); - - ASSERT(khme_hash == NULL); - ASSERT(uhme_hash == NULL); - - base = (caddr_t)roundup((uintptr_t)base, alignsize); - hmehash_sz = roundup(hmehash_sz, alignsize); - - khme_hash = (struct hmehash_bucket *)base; - uhme_hash = (struct hmehash_bucket *)((caddr_t)khme_hash + - khmehash_num * sizeof (struct hmehash_bucket)); - base += hmehash_sz; - return (base); -} - -/* * This function bop allocs kernel TSBs. */ caddr_t @@ -1070,8 +1006,7 @@ sfmmu_ktsb_alloc(caddr_t tsbbase) if (enable_bigktsb) { ktsb_base = (caddr_t)roundup((uintptr_t)tsbbase, ktsb_sz); - vaddr = (caddr_t)BOP_ALLOC(bootops, ktsb_base, ktsb_sz, - ktsb_sz); + vaddr = prom_alloc(ktsb_base, ktsb_sz, ktsb_sz); if (vaddr != ktsb_base) cmn_err(CE_PANIC, "sfmmu_ktsb_alloc: can't alloc" " 8K bigktsb"); @@ -1275,7 +1210,8 @@ sfmmu_tsb_segkmem_alloc(vmem_t *vmp, size_t size, int vmflag) * to do this the hard way. */ for (lgrpid = 0; lgrpid < NLGRPS_MAX && - vmp != kmem_tsb_default_arena[lgrpid]; lgrpid++); + vmp != kmem_tsb_default_arena[lgrpid]; lgrpid++) + ; if (lgrpid == NLGRPS_MAX) lgrpid = LGRP_NONE; } diff --git a/usr/src/uts/sun4/vm/vm_dep.c b/usr/src/uts/sun4/vm/vm_dep.c index 763b3dc737..4b80603a8f 100644 --- a/usr/src/uts/sun4/vm/vm_dep.c +++ b/usr/src/uts/sun4/vm/vm_dep.c @@ -242,7 +242,7 @@ map_addr(caddr_t *addrp, size_t len, offset_t off, int vacalign, uint_t flags) { struct proc *p = curproc; caddr_t userlimit = flags & _MAP_LOW32 ? - (caddr_t)USERLIMIT32 : p->p_as->a_userlimit; + (caddr_t)USERLIMIT32 : p->p_as->a_userlimit; map_addr_proc(addrp, len, off, vacalign, userlimit, p, flags); } @@ -665,27 +665,33 @@ map_pgszcvec(caddr_t addr, size_t size, uintptr_t off, int flags, int type, int memcntl) { if (flags & MAP_TEXT) { - return (map_szcvec(addr, size, off, disable_auto_text_large_pages, + return (map_szcvec(addr, size, off, + disable_auto_text_large_pages, max_utext_lpsize, shm_lpg_min_physmem)); } else if (flags & MAP_INITDATA) { - return (map_szcvec(addr, size, off, disable_auto_data_large_pages, + return (map_szcvec(addr, size, off, + disable_auto_data_large_pages, max_uidata_lpsize, privm_lpg_min_physmem)); } else if (type == MAPPGSZC_SHM) { - return (map_szcvec(addr, size, off, disable_auto_data_large_pages, + return (map_szcvec(addr, size, off, + disable_auto_data_large_pages, max_shm_lpsize, shm_lpg_min_physmem)); } else if (type == MAPPGSZC_HEAP) { - return (map_szcvec(addr, size, off, disable_auto_data_large_pages, + return (map_szcvec(addr, size, off, + disable_auto_data_large_pages, max_uheap_lpsize, privm_lpg_min_physmem)); } else if (type == MAPPGSZC_STACK) { - return (map_szcvec(addr, size, off, disable_auto_data_large_pages, + return (map_szcvec(addr, size, off, + disable_auto_data_large_pages, max_ustack_lpsize, privm_lpg_min_physmem)); } else { - return (map_szcvec(addr, size, off, disable_auto_data_large_pages, + return (map_szcvec(addr, size, off, + disable_auto_data_large_pages, max_privmap_lpsize, privm_lpg_min_physmem)); } } @@ -734,119 +740,111 @@ page_t ***page_cachelists[MAX_MEM_TYPES]; kmutex_t *fpc_mutex[NPC_MUTEX]; kmutex_t *cpc_mutex[NPC_MUTEX]; -caddr_t -alloc_page_freelists(int mnode, caddr_t alloc_base, int alloc_align) +/* + * Calculate space needed for page freelists and counters + */ +size_t +calc_free_pagelist_sz(void) { - int mtype; - uint_t szc; + int szc; + size_t alloc_sz, cache_sz, free_sz; - alloc_base = (caddr_t)roundup((uintptr_t)alloc_base, alloc_align); + /* + * one cachelist per color, node, and type + */ + cache_sz = (page_get_pagecolors(0) * sizeof (page_t *)) + + sizeof (page_t **); + cache_sz *= max_mem_nodes * MAX_MEM_TYPES; + + /* + * one freelist per size, color, node, and type + */ + free_sz = sizeof (page_t **); + for (szc = 0; szc < mmu_page_sizes; szc++) + free_sz += sizeof (page_t *) * page_get_pagecolors(szc); + free_sz *= max_mem_nodes * MAX_MEM_TYPES; + + alloc_sz = cache_sz + free_sz + page_ctrs_sz(); + return (alloc_sz); +} + +caddr_t +alloc_page_freelists(caddr_t alloc_base) +{ + int mnode, mtype; + int szc, clrs; /* * We only support small pages in the cachelist. */ for (mtype = 0; mtype < MAX_MEM_TYPES; mtype++) { - page_cachelists[mtype][mnode] = (page_t **)alloc_base; - alloc_base += (sizeof (page_t *) * page_get_pagecolors(0)); - /* - * Allocate freelists bins for all - * supported page sizes. - */ - for (szc = 0; szc < mmu_page_sizes; szc++) { - page_freelists[szc][mtype][mnode] = - (page_t **)alloc_base; - alloc_base += ((sizeof (page_t *) * - page_get_pagecolors(szc))); + page_cachelists[mtype] = (page_t ***)alloc_base; + alloc_base += (max_mem_nodes * sizeof (page_t **)); + for (mnode = 0; mnode < max_mem_nodes; mnode++) { + page_cachelists[mtype][mnode] = (page_t **)alloc_base; + alloc_base += + (page_get_pagecolors(0) * sizeof (page_t *)); } } - alloc_base = (caddr_t)roundup((uintptr_t)alloc_base, alloc_align); + /* + * Allocate freelists bins for all + * supported page sizes. + */ + for (szc = 0; szc < mmu_page_sizes; szc++) { + clrs = page_get_pagecolors(szc); + for (mtype = 0; mtype < MAX_MEM_TYPES; mtype++) { + page_freelists[szc][mtype] = (page_t ***)alloc_base; + alloc_base += (max_mem_nodes * sizeof (page_t **)); + for (mnode = 0; mnode < max_mem_nodes; mnode++) { + page_freelists[szc][mtype][mnode] = + (page_t **)alloc_base; + alloc_base += (clrs * (sizeof (page_t *))); + } + } + } + alloc_base = page_ctrs_alloc(alloc_base); return (alloc_base); } /* - * Allocate page_freelists bin headers for a memnode from the - * nucleus data area. This is the first time that mmu_page_sizes is - * used during sun4u bootup, so check mmu_page_sizes initialization. + * Allocate page_freelists locks for a memnode from the nucleus data + * area. This is the first time that mmu_page_sizes is used during + * bootup, so check mmu_page_sizes initialization. */ int -ndata_alloc_page_freelists(struct memlist *ndata, int mnode) +ndata_alloc_page_mutexs(struct memlist *ndata) { size_t alloc_sz; caddr_t alloc_base; - caddr_t end; - int mtype; - uint_t szc; - int32_t allp = 0; + int i; + void page_coloring_init(); + page_coloring_init(); if (&mmu_init_mmu_page_sizes) { - if (!mmu_init_mmu_page_sizes(allp)) { + if (!mmu_init_mmu_page_sizes(0)) { cmn_err(CE_PANIC, "mmu_page_sizes %d not initialized", mmu_page_sizes); } } ASSERT(mmu_page_sizes >= DEFAULT_MMU_PAGE_SIZES); - /* first time called - allocate max_mem_nodes dimension */ - if (mnode == 0) { - int i; - - /* page_cachelists */ - alloc_sz = MAX_MEM_TYPES * max_mem_nodes * - sizeof (page_t **); - - /* page_freelists */ - alloc_sz += MAX_MEM_TYPES * mmu_page_sizes * max_mem_nodes * - sizeof (page_t **); - - /* fpc_mutex and cpc_mutex */ - alloc_sz += 2 * NPC_MUTEX * max_mem_nodes * sizeof (kmutex_t); - - alloc_base = ndata_alloc(ndata, alloc_sz, ecache_alignsize); - if (alloc_base == NULL) - return (-1); - - ASSERT(((uintptr_t)alloc_base & (ecache_alignsize - 1)) == 0); - - for (mtype = 0; mtype < MAX_MEM_TYPES; mtype++) { - page_cachelists[mtype] = (page_t ***)alloc_base; - alloc_base += (max_mem_nodes * sizeof (page_t **)); - for (szc = 0; szc < mmu_page_sizes; szc++) { - page_freelists[szc][mtype] = - (page_t ***)alloc_base; - alloc_base += (max_mem_nodes * - sizeof (page_t **)); - } - } - for (i = 0; i < NPC_MUTEX; i++) { - fpc_mutex[i] = (kmutex_t *)alloc_base; - alloc_base += (sizeof (kmutex_t) * max_mem_nodes); - cpc_mutex[i] = (kmutex_t *)alloc_base; - alloc_base += (sizeof (kmutex_t) * max_mem_nodes); - } - alloc_sz = 0; - } - - /* - * Calculate the size needed by alloc_page_freelists(). - */ - for (mtype = 0; mtype < MAX_MEM_TYPES; mtype++) { - alloc_sz += sizeof (page_t *) * page_get_pagecolors(0); - - for (szc = 0; szc < mmu_page_sizes; szc++) - alloc_sz += sizeof (page_t *) * - page_get_pagecolors(szc); - } + /* fpc_mutex and cpc_mutex */ + alloc_sz = 2 * NPC_MUTEX * max_mem_nodes * sizeof (kmutex_t); alloc_base = ndata_alloc(ndata, alloc_sz, ecache_alignsize); if (alloc_base == NULL) return (-1); - end = alloc_page_freelists(mnode, alloc_base, ecache_alignsize); - ASSERT((uintptr_t)end == roundup((uintptr_t)alloc_base + alloc_sz, - ecache_alignsize)); + ASSERT(((uintptr_t)alloc_base & (ecache_alignsize - 1)) == 0); + for (i = 0; i < NPC_MUTEX; i++) { + fpc_mutex[i] = (kmutex_t *)alloc_base; + alloc_base += (sizeof (kmutex_t) * max_mem_nodes); + cpc_mutex[i] = (kmutex_t *)alloc_base; + alloc_base += (sizeof (kmutex_t) * max_mem_nodes); + } return (0); } diff --git a/usr/src/uts/sun4u/boston/os/boston.c b/usr/src/uts/sun4u/boston/os/boston.c index f30ba9510f..39713603a2 100644 --- a/usr/src/uts/sun4u/boston/os/boston.c +++ b/usr/src/uts/sun4u/boston/os/boston.c @@ -191,7 +191,7 @@ load_platform_drivers(void) * updates to ALOM. */ rmc_req_now = (int (*)(rmc_comm_msg_t *, uint8_t)) - modgetsymvalue("rmc_comm_request_nowait", 0); + modgetsymvalue("rmc_comm_request_nowait", 0); } /* @@ -313,7 +313,7 @@ plat_nodename_set(void) * find the symbol for the mailbox routine */ rmc_req_res = (int (*)(rmc_comm_msg_t *, rmc_comm_msg_t *, time_t)) - modgetsymvalue("rmc_comm_request_response", 0); + modgetsymvalue("rmc_comm_request_response", 0); if (rmc_req_res == NULL) { return; @@ -385,7 +385,7 @@ cpu_sgn_update(ushort_t sig, uchar_t state, uchar_t sub_state, int cpuid) * find the symbol for the mailbox routine */ rmc_req_now = (int (*)(rmc_comm_msg_t *, uint8_t)) - modgetsymvalue("rmc_comm_request_nowait", 0); + modgetsymvalue("rmc_comm_request_nowait", 0); if (rmc_req_now == NULL) { return; } @@ -563,23 +563,6 @@ plat_fill_mc(pnode_t nodeid) plat_assign_lgrphand_to_mem_node((lgrp_handle_t)portid, portid); } -/* ARGSUSED */ -void -plat_build_mem_nodes(u_longlong_t *list, size_t nelems) -{ - size_t elem; - pfn_t basepfn; - pgcnt_t npgs; - - /* - * Boot install lists are arranged <addr, len>, <addr, len>, ... - */ - for (elem = 0; elem < nelems; elem += 2) { - basepfn = btop(list[elem]); - npgs = btop(list[elem+1]); - mem_node_add_slice(basepfn, basepfn + npgs - 1); - } -} /* * Common locking enter code diff --git a/usr/src/uts/sun4u/cherrystone/os/cherrystone.c b/usr/src/uts/sun4u/cherrystone/os/cherrystone.c index 0db042c464..cca3d056a8 100644 --- a/usr/src/uts/sun4u/cherrystone/os/cherrystone.c +++ b/usr/src/uts/sun4u/cherrystone/os/cherrystone.c @@ -144,7 +144,7 @@ load_platform_drivers(void) for (drv = boot_time_drivers; *drv; drv++) { if (i_ddi_attach_hw_nodes(*drv) != DDI_SUCCESS) cmn_err(CE_WARN, "Failed to install \"%s\" driver.", - *drv); + *drv); } /* @@ -156,7 +156,7 @@ load_platform_drivers(void) /* Gain access into the ssc050_get_port function */ cherry_ssc050_get_port_bit = (int (*) (dev_info_t *, int, int, - uint8_t *, int)) modgetsymvalue("ssc050_get_port_bit", 0); + uint8_t *, int)) modgetsymvalue("ssc050_get_port_bit", 0); if (cherry_ssc050_get_port_bit == NULL) { cmn_err(CE_WARN, "cannot find ssc050_get_port_bit"); return; @@ -199,7 +199,7 @@ cherry_dev_search(dev_info_t *dip, void *arg) return (DDI_WALK_CONTINUE); err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "reg", &dev_regs, &len); + DDI_PROP_DONTPASS, "reg", &dev_regs, &len); if (err != DDI_PROP_SUCCESS) { return (DDI_WALK_CONTINUE); } @@ -228,10 +228,10 @@ keyswitch_poll(void *arg) int err; err = cherry_ssc050_get_port_bit(dip, port, bit, - &port_byte, I2C_NOSLEEP); + &port_byte, I2C_NOSLEEP); if (err != 0) { cmn_err(CE_WARN, "keyswitch polling disabled: " - "errno=%d while reading ssc050", err); + "errno=%d while reading ssc050", err); return; } @@ -244,7 +244,7 @@ cherry_abort_seq_handler(char *msg) { if (key_locked_bit == 0) cmn_err(CE_CONT, "KEY in LOCKED position, " - "ignoring debug enter sequence"); + "ignoring debug enter sequence"); else { debug_enter(msg); } @@ -277,7 +277,7 @@ plat_discover_slice(pfn_t pfn, pfn_t *first, pfn_t *last) for (bd = 0; bd < CHERRYSTONE_SBD_SLOTS; bd++) { for (cpu = 0; cpu < CHERRYSTONE_CPUS_PER_BOARD; cpu++) { for (bank = 0; bank < CHERRYSTONE_BANKS_PER_MC; - bank++) { + bank++) { uint64_t *slice = slice_table[bd][cpu][bank]; uint64_t base = btop(slice[SLICE_PA]); uint64_t len = btop(slice[SLICE_SPAN]); @@ -437,7 +437,7 @@ plat_fill_mc(pnode_t nodeid) */ /* ARGSUSED */ void -plat_build_mem_nodes(u_longlong_t *list, size_t nelems) +plat_build_mem_nodes(prom_memlist_t *list, size_t nelems) { int slice; pfn_t basepfn; @@ -549,7 +549,7 @@ plat_get_mem_unum(int synd_code, uint64_t flt_addr, int flt_bus_id, { if (flt_in_memory && (p2get_mem_unum != NULL)) return (p2get_mem_unum(synd_code, P2ALIGN(flt_addr, 8), - buf, buflen, lenp)); + buf, buflen, lenp)); else return (ENOTSUP); } diff --git a/usr/src/uts/sun4u/chicago/os/chicago.c b/usr/src/uts/sun4u/chicago/os/chicago.c index 152f08f249..f1cfc84bfe 100644 --- a/usr/src/uts/sun4u/chicago/os/chicago.c +++ b/usr/src/uts/sun4u/chicago/os/chicago.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -320,24 +319,6 @@ plat_fill_mc(pnode_t nodeid) plat_assign_lgrphand_to_mem_node((lgrp_handle_t)portid, portid); } -/* ARGSUSED */ -void -plat_build_mem_nodes(u_longlong_t *list, size_t nelems) -{ - size_t elem; - pfn_t basepfn; - pgcnt_t npgs; - - /* - * Boot install lists are arranged <addr, len>, <addr, len>, ... - */ - for (elem = 0; elem < nelems; elem += 2) { - basepfn = btop(list[elem]); - npgs = btop(list[elem+1]); - mem_node_add_slice(basepfn, basepfn + npgs - 1); - } -} - /* * Common locking enter code */ diff --git a/usr/src/uts/sun4u/cpu/us3_cheetah.c b/usr/src/uts/sun4u/cpu/us3_cheetah.c index ce160b43c4..44fefd1ecf 100644 --- a/usr/src/uts/sun4u/cpu/us3_cheetah.c +++ b/usr/src/uts/sun4u/cpu/us3_cheetah.c @@ -667,36 +667,52 @@ uint64_t ecache_tl1_flushaddr = (uint64_t)-1; /* physaddr for E$ flushing */ /* * Allocate and initialize the exclusive displacement flush area. - * Called twice. The first time allocates virtual address. The second - * call looks up the physical address. */ caddr_t ecache_init_scrub_flush_area(caddr_t alloc_base) { - static caddr_t ecache_tl1_virtaddr; + unsigned size = 2 * CH_ECACHE_8M_SIZE; + caddr_t tmp_alloc_base = alloc_base; + caddr_t flush_alloc_base = + (caddr_t)roundup((uintptr_t)alloc_base, size); + caddr_t ecache_tl1_virtaddr; - if (alloc_base != NULL) { - /* - * Need to allocate an exclusive flush area that is twice the - * largest supported E$ size, physically contiguous, and - * aligned on twice the largest E$ size boundary. - */ - unsigned size = 2 * CH_ECACHE_8M_SIZE; - caddr_t va = (caddr_t)roundup((uintptr_t)alloc_base, size); + /* + * Allocate the physical memory for the exclusive flush area + * + * Need to allocate an exclusive flush area that is twice the + * largest supported E$ size, physically contiguous, and + * aligned on twice the largest E$ size boundary. + * + * Memory allocated via prom_alloc is included in the "cage" + * from the DR perspective and due to this, its physical + * address will never change and the memory will not be + * removed. + * + * prom_alloc takes 3 arguments: bootops, virtual address hint, + * size of the area to allocate, and alignment of the area to + * allocate. It returns zero if the allocation fails, or the + * virtual address for a successful allocation. Memory prom_alloc'd + * is physically contiguous. + */ + if ((ecache_tl1_virtaddr = + prom_alloc(flush_alloc_base, size, size)) != NULL) { - ecache_tl1_virtaddr = va; - alloc_base = va + size; + tmp_alloc_base = + (caddr_t)roundup((uintptr_t)(ecache_tl1_virtaddr + size), + ecache_alignsize); - } else { /* - * Get the physical address of the exclusive flush area. + * get the physical address of the exclusive flush area */ - ASSERT(ecache_tl1_virtaddr != NULL); ecache_tl1_flushaddr = va_to_pa(ecache_tl1_virtaddr); - ASSERT(ecache_tl1_flushaddr != ((uint64_t)-1)); + + } else { + ecache_tl1_virtaddr = (caddr_t)-1; + cmn_err(CE_NOTE, "!ecache_init_scrub_flush_area failed\n"); } - return (alloc_base); + return (tmp_alloc_base); } /* diff --git a/usr/src/uts/sun4u/daktari/os/daktari.c b/usr/src/uts/sun4u/daktari/os/daktari.c index f441ba787e..c6e3287636 100644 --- a/usr/src/uts/sun4u/daktari/os/daktari.c +++ b/usr/src/uts/sun4u/daktari/os/daktari.c @@ -153,7 +153,7 @@ load_platform_drivers(void) /* Gain access into the ssc050_get_port function */ daktari_ssc050_get_port_bit = (int (*) (dev_info_t *, int, int, - uint8_t *, int)) modgetsymvalue("ssc050_get_port_bit", 0); + uint8_t *, int)) modgetsymvalue("ssc050_get_port_bit", 0); if (daktari_ssc050_get_port_bit == NULL) { cmn_err(CE_WARN, "cannot find ssc050_get_port_bit"); return; @@ -181,14 +181,14 @@ daktari_dev_search(dev_info_t *dip, void *arg) int err; if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, - "compatible", &compatible) != DDI_PROP_SUCCESS) + "compatible", &compatible) != DDI_PROP_SUCCESS) return (DDI_WALK_CONTINUE); if (strcmp(compatible, "i2c-ssc050") == 0) { ddi_prop_free(compatible); err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "reg", &dev_regs, &len); + DDI_PROP_DONTPASS, "reg", &dev_regs, &len); if (err != DDI_PROP_SUCCESS) { return (DDI_WALK_CONTINUE); } @@ -220,10 +220,10 @@ keyswitch_poll(void *arg) int err; err = daktari_ssc050_get_port_bit(dip, port, bit, - &port_byte, I2C_NOSLEEP); + &port_byte, I2C_NOSLEEP); if (err != 0) { cmn_err(CE_WARN, "keyswitch polling disabled: " - "errno=%d while reading ssc050", err); + "errno=%d while reading ssc050", err); return; } @@ -236,7 +236,7 @@ daktari_abort_seq_handler(char *msg) { if (key_locked_bit == 0) cmn_err(CE_CONT, "KEY in LOCKED position, " - "ignoring debug enter sequence"); + "ignoring debug enter sequence"); else { debug_enter(msg); } @@ -430,7 +430,7 @@ plat_fill_mc(pnode_t nodeid) */ /* ARGSUSED */ void -plat_build_mem_nodes(u_longlong_t *list, size_t nelems) +plat_build_mem_nodes(prom_memlist_t *list, size_t nelems) { int slice; pfn_t basepfn; @@ -540,7 +540,7 @@ plat_get_mem_unum(int synd_code, uint64_t flt_addr, int flt_bus_id, { if (flt_in_memory && (p2get_mem_unum != NULL)) return (p2get_mem_unum(synd_code, P2ALIGN(flt_addr, 8), - buf, buflen, lenp)); + buf, buflen, lenp)); else return (ENOTSUP); } diff --git a/usr/src/uts/sun4u/enchilada/os/enchilada.c b/usr/src/uts/sun4u/enchilada/os/enchilada.c index 7415e77807..786228ee42 100644 --- a/usr/src/uts/sun4u/enchilada/os/enchilada.c +++ b/usr/src/uts/sun4u/enchilada/os/enchilada.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -367,21 +366,3 @@ plat_fill_mc(pnode_t nodeid) if (portid < max_mem_nodes) plat_assign_lgrphand_to_mem_node(portid, portid); } - -/* ARGSUSED */ -void -plat_build_mem_nodes(u_longlong_t *list, size_t nelems) -{ - size_t elem; - pfn_t basepfn; - pgcnt_t npgs; - - /* - * Boot install lists are arranged <addr, len>, <addr, len>, ... - */ - for (elem = 0; elem < nelems; elem += 2) { - basepfn = btop(list[elem]); - npgs = btop(list[elem+1]); - mem_node_add_slice(basepfn, basepfn + npgs - 1); - } -} diff --git a/usr/src/uts/sun4u/lw8/os/lw8_platmod.c b/usr/src/uts/sun4u/lw8/os/lw8_platmod.c index aeb275346a..70442879c1 100644 --- a/usr/src/uts/sun4u/lw8/os/lw8_platmod.c +++ b/usr/src/uts/sun4u/lw8/os/lw8_platmod.c @@ -412,7 +412,7 @@ plat_fill_mc(pnode_t nodeid) */ /* ARGSUSED */ void -plat_build_mem_nodes(u_longlong_t *list, size_t nelems) +plat_build_mem_nodes(prom_memlist_t *list, size_t nelems) { int slice; pfn_t basepfn; @@ -657,8 +657,7 @@ find_chosen_dip(void) dip = e_ddi_hold_devi_by_path(master_sbbc, 0); if ((dip == NULL) || (ddi_get_nodeid(dip) != tunnel)) { cmn_err(CE_PANIC, - "e_ddi_hold_devi_by_path(%x) failed for SBBC\n", - tunnel); + "e_ddi_hold_devi_by_path(%x) failed for SBBC\n", tunnel); } /* make sure devi_ref is ZERO */ @@ -824,7 +823,7 @@ plat_nodename_set(void) */ if (sg_mbox == NULL) sg_mbox = (int (*)(sbbc_msg_t *, sbbc_msg_t *, time_t)) - modgetsymvalue("sbbc_mbox_request_response", 0); + modgetsymvalue("sbbc_mbox_request_response", 0); if (sg_mbox == NULL) { cmn_err(CE_NOTE, "!plat_nodename_set: sg_mbox not found\n"); @@ -867,7 +866,7 @@ plat_nodename_set(void) cmn_err(CE_NOTE, "!plat_nodename_set: sg_mbox retval %d\n", rv); } else if (resp.msg_status != 0) { cmn_err(CE_NOTE, "!plat_nodename_set: msg_status %d\n", - resp.msg_status); + resp.msg_status); } else { DCMNERR(CE_NOTE, "!plat_nodename_set was successful\n"); @@ -1130,10 +1129,10 @@ plat_send_ecc_mailbox_msg(plat_ecc_message_type_t msg_type, void *datap) } msgp = (sbbc_ecc_mbox_t *)kmem_zalloc(sizeof (sbbc_ecc_mbox_t), - sleep_flag); + sleep_flag); if (msgp == NULL) { cmn_err(CE_NOTE, "!plat_send_ecc_mailbox_msg: " - "unable to allocate sbbc_ecc_mbox"); + "unable to allocate sbbc_ecc_mbox"); return (ENOMEM); } @@ -1150,7 +1149,7 @@ plat_send_ecc_mailbox_msg(plat_ecc_message_type_t msg_type, void *datap) if (msgp->ecc_req.msg_buf == NULL) { cmn_err(CE_NOTE, "!plat_send_ecc_mailbox_msg: " - "unable to allocate request msg_buf"); + "unable to allocate request msg_buf"); kmem_free((void *)msgp, sizeof (sbbc_ecc_mbox_t)); return (ENOMEM); } @@ -1274,11 +1273,11 @@ cpu_sgn_update(ushort_t sig, uchar_t state, uchar_t sub_state, int cpuid) " could not check current domain signature\n"); } else { (void) (*iosram_read_ptr)(SBBC_SIGBLCK_KEY, - SG_SGNBLK_DOMAINSIG_OFFSET, - (char *)¤t_sgn, sizeof (current_sgn)); + SG_SGNBLK_DOMAINSIG_OFFSET, + (char *)¤t_sgn, sizeof (current_sgn)); if (current_sgn.state_t.state == SIGST_EXIT) signature = CPU_SIG_BLD(sig, state, - SIGSUBST_PANIC_REBOOT); + SIGSUBST_PANIC_REBOOT); } } @@ -1287,17 +1286,17 @@ cpu_sgn_update(ushort_t sig, uchar_t state, uchar_t sub_state, int cpuid) */ if (cpuid >= 0) { (void) (*iosram_write_ptr)(SBBC_SIGBLCK_KEY, - SG_SGNBLK_CPUSIG_OFFSET(cpuid), (char *)&signature, - sizeof (signature)); + SG_SGNBLK_CPUSIG_OFFSET(cpuid), (char *)&signature, + sizeof (signature)); } else { for (i = 0; i < NCPU; i++) { if (cpu[i] == NULL || !(cpu[i]->cpu_flags & - (CPU_EXISTS|CPU_QUIESCED))) { + (CPU_EXISTS|CPU_QUIESCED))) { continue; } (void) (*iosram_write_ptr)(SBBC_SIGBLCK_KEY, - SG_SGNBLK_CPUSIG_OFFSET(i), (char *)&signature, - sizeof (signature)); + SG_SGNBLK_CPUSIG_OFFSET(i), (char *)&signature, + sizeof (signature)); } } @@ -1306,8 +1305,8 @@ cpu_sgn_update(ushort_t sig, uchar_t state, uchar_t sub_state, int cpuid) } (void) (*iosram_write_ptr)(SBBC_SIGBLCK_KEY, - SG_SGNBLK_DOMAINSIG_OFFSET, (char *)&signature, - sizeof (signature)); + SG_SGNBLK_DOMAINSIG_OFFSET, (char *)&signature, + sizeof (signature)); } void diff --git a/usr/src/uts/sun4u/ml/mach_locore.s b/usr/src/uts/sun4u/ml/mach_locore.s index 75aefc3bc7..9393dd2f7a 100644 --- a/usr/src/uts/sun4u/ml/mach_locore.s +++ b/usr/src/uts/sun4u/ml/mach_locore.s @@ -232,18 +232,22 @@ afsrbuf: ! Stash away our arguments in memory. ! sethi %hi(_local_p1275cis), %g1 - stn %o0, [%g1 + %lo(_local_p1275cis)] - sethi %hi(bootops), %g1 - stn %o1, [%g1 + %lo(bootops)] + stn %o4, [%g1 + %lo(_local_p1275cis)] ! ! Initialize CPU state registers ! wrpr %g0, PSTATE_KERN, %pstate wr %g0, %g0, %fprs - CLEARTICKNPT ! allow user rdtick ! + ! call krtld to link the world together + ! + call kobj_start + mov %o4, %o0 + + CLEARTICKNPT ! allow user rdtick + ! ! Get maxwin from %ver ! rdpr %ver, %g1 @@ -297,8 +301,8 @@ afsrbuf: set t0stacktop, %g1 ! setup kernel stack pointer sub %g1, SA(KFPUSIZE+GSR_SIZE), %g2 and %g2, 0x3f, %g3 - sub %g2, %g3, %o2 - sub %o2, SA(MPCBSIZE) + STACK_BIAS, %sp + sub %g2, %g3, %o1 + sub %o1, SA(MPCBSIZE) + STACK_BIAS, %sp ! ! Initialize global thread register. @@ -326,10 +330,7 @@ afsrbuf: ! ! Call mlsetup with address of prototype user registers. - ! and p1275cis pointers. - - sethi %hi(_local_p1275cis), %o1 - ldn [%o1 + %lo(_local_p1275cis)], %o1 + ! call mlsetup add %sp, REGOFF + STACK_BIAS, %o0 diff --git a/usr/src/uts/sun4u/opl/os/opl.c b/usr/src/uts/sun4u/opl/os/opl.c index b4c3e94c51..f2d3162a93 100644 --- a/usr/src/uts/sun4u/opl/os/opl.c +++ b/usr/src/uts/sun4u/opl/os/opl.c @@ -457,7 +457,7 @@ plat_pfn_to_mem_node(pfn_t pfn) /* ARGSUSED */ void -plat_build_mem_nodes(u_longlong_t *list, size_t nelems) +plat_build_mem_nodes(prom_memlist_t *list, size_t nelems) { size_t elem; pfn_t basepfn; @@ -475,9 +475,9 @@ plat_build_mem_nodes(u_longlong_t *list, size_t nelems) * Boot install lists are arranged <addr, len>, <addr, len>, ... */ ssize = (1ull << OPL_MC_MEMBOARD_SHIFT); - for (elem = 0; elem < nelems; elem += 2) { - low = (uint64_t)list[elem]; - high = low+(uint64_t)(list[elem+1]); + for (elem = 0; elem < nelems; list++, elem++) { + low = list->addr; + high = low + list->size; while (low < high) { boundary = roundup(low+1, ssize); boundary = MIN(high, boundary); diff --git a/usr/src/uts/sun4u/opl/unix/Makefile b/usr/src/uts/sun4u/opl/unix/Makefile index 0be4aed67f..b8b938ca51 100644 --- a/usr/src/uts/sun4u/opl/unix/Makefile +++ b/usr/src/uts/sun4u/opl/unix/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -48,13 +48,14 @@ LINTS = $(SPECIAL_OBJS:%.o=$(LINTS_DIR)/%.ln) \ $(MACH_NOT_YET_KMODS:%.o=$(LINTS_DIR)/%.ln) \ $(LINTS_DIR)/vers.ln \ $(LINTS_DIR)/modstubs.ln + +KRTLD_MAPFILE = $(UTSBASE)/sparc/krtld/mapfile +KRTLD_OBJECTS = $(KRTLD_OBJS:%=$(OBJS_DIR)/%) +KRTLD_O = $(OBJS_DIR)/krtld.o + ROOTMODULE = $(ROOT_OPL_KERN_DIR)/$(UNIX) UNIX_BIN = $(OBJS_DIR)/$(UNIX) -KRTLD_32 = misc/krtld -KRTLD_64 = misc/$(SUBDIR64)/krtld -KRTLD = $(KRTLD_$(CLASS)) - LIBS = $(GENLIB) $(PLATLIB) $(CPULIB) GENUNIX = genunix @@ -99,8 +100,9 @@ UNIX_DIR = . # # Overrides # -CLEANFILES += $(UNIX_O) $(MODSTUBS_O) $(OBJS_DIR)/vers.c \ - $(OBJS_DIR)/vers.o $(CPU_OBJ) $(CPULIB) \ +CLEANFILES += $(UNIX_O) $(MODSTUBS_O) $(KRTLD_O) $(KRTLD_OBJECTS) \ + $(OBJS_DIR)/vers.c $(OBJS_DIR)/vers.o \ + $(CPU_OBJ) $(CPULIB) \ $(DTRACESTUBS_O) $(DTRACESTUBS) CLOBBERFILES = $(CLEANFILES) $(UNIX_BIN) @@ -133,19 +135,23 @@ install: $(INSTALL_DEPS) symcheck: $(SYM_DEPS) -$(UNIX_BIN): $(UNIX_O) $(MODSTUBS_O) $(MAPFILE) $(LIBS) $(DTRACESTUBS) - $(LD) -dy -b -o $@ -e _start -I $(KRTLD) -M $(MAPFILE) \ - $(UNIX_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) +$(UNIX_BIN): $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(MAPFILE) $(LIBS) \ + $(DTRACESTUBS) + $(LD) -dy -b -o $@ -e _start -M $(MAPFILE) \ + $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) $(CTFMERGE_UNIQUIFY_AGAINST_GENUNIX) $(POST_PROCESS) -symcheck.targ: $(UNIX_O) $(MODSTUBS_O) $(LIBS) $(DTRACESTUBS) +symcheck.targ: $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBS) $(DTRACESTUBS) $(LD) -dy -b -o $(SYM_MOD) -M $(MAPFILE) \ - $(UNIX_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) + $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) $(UNIX_O): $(OBJECTS) $(OBJS_DIR)/vers.o $(LD) -r -o $@ $(OBJECTS) $(OBJS_DIR)/vers.o +$(KRTLD_O): $(KRTLD_OBJECTS) + $(LD) -r -o $@ -M$(KRTLD_MAPFILE) $(KRTLD_OBJECTS) + # # Special rules for generating assym.h for inclusion in assembly files. # diff --git a/usr/src/uts/sun4u/schumacher/os/schumacher.c b/usr/src/uts/sun4u/schumacher/os/schumacher.c index c8463c4226..abc5dec3c7 100644 --- a/usr/src/uts/sun4u/schumacher/os/schumacher.c +++ b/usr/src/uts/sun4u/schumacher/os/schumacher.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -350,21 +349,3 @@ plat_fill_mc(pnode_t nodeid) if (portid < max_mem_nodes) plat_assign_lgrphand_to_mem_node(portid, portid); } - -/* ARGSUSED */ -void -plat_build_mem_nodes(u_longlong_t *list, size_t nelems) -{ - size_t elem; - pfn_t basepfn; - pgcnt_t npgs; - - /* - * Boot install lists are arranged <addr, len>, <addr, len>, ... - */ - for (elem = 0; elem < nelems; elem += 2) { - basepfn = btop(list[elem]); - npgs = btop(list[elem+1]); - mem_node_add_slice(basepfn, basepfn + npgs - 1); - } -} diff --git a/usr/src/uts/sun4u/seattle/os/seattle.c b/usr/src/uts/sun4u/seattle/os/seattle.c index ee74bbe5df..c165e2eeac 100644 --- a/usr/src/uts/sun4u/seattle/os/seattle.c +++ b/usr/src/uts/sun4u/seattle/os/seattle.c @@ -194,7 +194,7 @@ load_platform_drivers(void) * updates to ALOM. */ rmc_req_now = (int (*)(rmc_comm_msg_t *, uint8_t)) - modgetsymvalue("rmc_comm_request_nowait", 0); + modgetsymvalue("rmc_comm_request_nowait", 0); } /* @@ -315,7 +315,7 @@ plat_nodename_set(void) * find the symbol for the mailbox routine */ rmc_req_res = (int (*)(rmc_comm_msg_t *, rmc_comm_msg_t *, time_t)) - modgetsymvalue("rmc_comm_request_response", 0); + modgetsymvalue("rmc_comm_request_response", 0); if (rmc_req_res == NULL) { return; @@ -387,7 +387,7 @@ cpu_sgn_update(ushort_t sig, uchar_t state, uchar_t sub_state, int cpuid) * find the symbol for the mailbox routine */ rmc_req_now = (int (*)(rmc_comm_msg_t *, uint8_t)) - modgetsymvalue("rmc_comm_request_nowait", 0); + modgetsymvalue("rmc_comm_request_nowait", 0); if (rmc_req_now == NULL) { return; } @@ -565,24 +565,6 @@ plat_fill_mc(pnode_t nodeid) plat_assign_lgrphand_to_mem_node((lgrp_handle_t)portid, portid); } -/* ARGSUSED */ -void -plat_build_mem_nodes(u_longlong_t *list, size_t nelems) -{ - size_t elem; - pfn_t basepfn; - pgcnt_t npgs; - - /* - * Boot install lists are arranged <addr, len>, <addr, len>, ... - */ - for (elem = 0; elem < nelems; elem += 2) { - basepfn = btop(list[elem]); - npgs = btop(list[elem+1]); - mem_node_add_slice(basepfn, basepfn + npgs - 1); - } -} - /* * Common locking enter code */ diff --git a/usr/src/uts/sun4u/serengeti/os/serengeti.c b/usr/src/uts/sun4u/serengeti/os/serengeti.c index ce9e95e669..847384abee 100644 --- a/usr/src/uts/sun4u/serengeti/os/serengeti.c +++ b/usr/src/uts/sun4u/serengeti/os/serengeti.c @@ -405,7 +405,7 @@ plat_fill_mc(pnode_t nodeid) */ /* ARGSUSED */ void -plat_build_mem_nodes(u_longlong_t *list, size_t nelems) +plat_build_mem_nodes(prom_memlist_t *list, size_t nelems) { int slice; pfn_t basepfn; @@ -813,7 +813,7 @@ plat_nodename_set(void) * find the symbol for the mailbox routine */ sg_mbox = (int (*)(sbbc_msg_t *, sbbc_msg_t *, time_t)) - modgetsymvalue("sbbc_mbox_request_response", 0); + modgetsymvalue("sbbc_mbox_request_response", 0); if (sg_mbox == NULL) { cmn_err(CE_NOTE, "!plat_nodename_set: sg_mbox not found\n"); @@ -856,7 +856,7 @@ plat_nodename_set(void) cmn_err(CE_NOTE, "!plat_nodename_set: sg_mbox retval %d\n", rv); } else if (resp.msg_status != 0) { cmn_err(CE_NOTE, "!plat_nodename_set: msg_status %d\n", - resp.msg_status); + resp.msg_status); } else { DCMNERR(CE_NOTE, "!plat_nodename_set was successful\n"); @@ -1116,10 +1116,10 @@ plat_send_ecc_mailbox_msg(plat_ecc_message_type_t msg_type, void *datap) } msgp = (sbbc_ecc_mbox_t *)kmem_zalloc(sizeof (sbbc_ecc_mbox_t), - sleep_flag); + sleep_flag); if (msgp == NULL) { cmn_err(CE_NOTE, "!plat_send_ecc_mailbox_msg: " - "unable to allocate sbbc_ecc_mbox"); + "unable to allocate sbbc_ecc_mbox"); return (ENOMEM); } @@ -1136,7 +1136,7 @@ plat_send_ecc_mailbox_msg(plat_ecc_message_type_t msg_type, void *datap) if (msgp->ecc_req.msg_buf == NULL) { cmn_err(CE_NOTE, "!plat_send_ecc_mailbox_msg: " - "unable to allocate request msg_buf"); + "unable to allocate request msg_buf"); kmem_free((void *)msgp, sizeof (sbbc_ecc_mbox_t)); return (ENOMEM); } @@ -1258,11 +1258,11 @@ cpu_sgn_update(ushort_t sig, uchar_t state, uchar_t sub_state, int cpuid) " could not check current domain signature\n"); } else { (void) (*iosram_read_ptr)(SBBC_SIGBLCK_KEY, - SG_SGNBLK_DOMAINSIG_OFFSET, - (char *)¤t_sgn, sizeof (current_sgn)); + SG_SGNBLK_DOMAINSIG_OFFSET, + (char *)¤t_sgn, sizeof (current_sgn)); if (current_sgn.state_t.state == SIGST_EXIT) signature = CPU_SIG_BLD(sig, state, - SIGSUBST_PANIC_REBOOT); + SIGSUBST_PANIC_REBOOT); } } @@ -1271,17 +1271,17 @@ cpu_sgn_update(ushort_t sig, uchar_t state, uchar_t sub_state, int cpuid) */ if (cpuid >= 0) { (void) (*iosram_write_ptr)(SBBC_SIGBLCK_KEY, - SG_SGNBLK_CPUSIG_OFFSET(cpuid), (char *)&signature, - sizeof (signature)); + SG_SGNBLK_CPUSIG_OFFSET(cpuid), (char *)&signature, + sizeof (signature)); } else { for (i = 0; i < NCPU; i++) { if (cpu[i] == NULL || !(cpu[i]->cpu_flags & - (CPU_EXISTS|CPU_QUIESCED))) { + (CPU_EXISTS|CPU_QUIESCED))) { continue; } (void) (*iosram_write_ptr)(SBBC_SIGBLCK_KEY, - SG_SGNBLK_CPUSIG_OFFSET(i), (char *)&signature, - sizeof (signature)); + SG_SGNBLK_CPUSIG_OFFSET(i), (char *)&signature, + sizeof (signature)); } } @@ -1290,8 +1290,8 @@ cpu_sgn_update(ushort_t sig, uchar_t state, uchar_t sub_state, int cpuid) } (void) (*iosram_write_ptr)(SBBC_SIGBLCK_KEY, - SG_SGNBLK_DOMAINSIG_OFFSET, (char *)&signature, - sizeof (signature)); + SG_SGNBLK_DOMAINSIG_OFFSET, (char *)&signature, + sizeof (signature)); } void diff --git a/usr/src/uts/sun4u/serengeti/unix/Makefile b/usr/src/uts/sun4u/serengeti/unix/Makefile index e909cd31e1..5e01356937 100644 --- a/usr/src/uts/sun4u/serengeti/unix/Makefile +++ b/usr/src/uts/sun4u/serengeti/unix/Makefile @@ -49,13 +49,14 @@ LINTS = $(SPECIAL_OBJS:%.o=$(LINTS_DIR)/%.ln) \ $(MACH_NOT_YET_KMODS:%.o=$(LINTS_DIR)/%.ln) \ $(LINTS_DIR)/vers.ln \ $(LINTS_DIR)/modstubs.ln + +KRTLD_MAPFILE = $(UTSBASE)/sparc/krtld/mapfile +KRTLD_OBJECTS = $(KRTLD_OBJS:%=$(OBJS_DIR)/%) +KRTLD_O = $(OBJS_DIR)/krtld.o + ROOTMODULE = $(ROOT_SERENGETI_KERN_DIR)/$(UNIX) UNIX_BIN = $(OBJS_DIR)/$(UNIX) -KRTLD_32 = misc/krtld -KRTLD_64 = misc/$(SUBDIR64)/krtld -KRTLD = $(KRTLD_$(CLASS)) - LIBS = $(GENLIB) $(PLATLIB) $(CPULIB) GENUNIX = genunix @@ -100,8 +101,9 @@ UNIX_DIR = . # # Overrides # -CLEANFILES += $(UNIX_O) $(MODSTUBS_O) $(OBJS_DIR)/vers.c \ - $(OBJS_DIR)/vers.o $(CPU_OBJ) $(CPULIB) \ +CLEANFILES += $(UNIX_O) $(MODSTUBS_O) $(KRTLD_O) $(KRTLD_OBJECTS) \ + $(OBJS_DIR)/vers.c $(OBJS_DIR)/vers.o \ + $(CPU_OBJ) $(CPULIB) \ $(DTRACESTUBS_O) $(DTRACESTUBS) CLOBBERFILES = $(CLEANFILES) $(UNIX_BIN) @@ -134,19 +136,23 @@ install: $(INSTALL_DEPS) symcheck: $(SYM_DEPS) -$(UNIX_BIN): $(UNIX_O) $(MODSTUBS_O) $(MAPFILE) $(LIBS) $(DTRACESTUBS) - $(LD) -dy -b -o $@ -e _start -I $(KRTLD) -M $(MAPFILE) \ - $(UNIX_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) +$(UNIX_BIN): $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(MAPFILE) $(LIBS) \ + $(DTRACESTUBS) + $(LD) -dy -b -o $@ -e _start -M $(MAPFILE) \ + $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) $(CTFMERGE_UNIQUIFY_AGAINST_GENUNIX) $(POST_PROCESS) -symcheck.targ: $(UNIX_O) $(MODSTUBS_O) $(LIBS) $(DTRACESTUBS) +symcheck.targ: $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBS) $(LD) -dy -b -o $(SYM_MOD) -M $(MAPFILE) \ - $(UNIX_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) + $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) $(UNIX_O): $(OBJECTS) $(OBJS_DIR)/vers.o $(LD) -r -o $@ $(OBJECTS) $(OBJS_DIR)/vers.o +$(KRTLD_O): $(KRTLD_OBJECTS) + $(LD) -r -o $@ -M $(KRTLD_MAPFILE) $(KRTLD_OBJECTS) + # # Special rules for generating assym.h for inclusion in assembly files. # diff --git a/usr/src/uts/sun4u/starcat/os/starcat.c b/usr/src/uts/sun4u/starcat/os/starcat.c index 4cde2078c8..c00976dfc9 100644 --- a/usr/src/uts/sun4u/starcat/os/starcat.c +++ b/usr/src/uts/sun4u/starcat/os/starcat.c @@ -313,7 +313,7 @@ plat_pfn_to_mem_node(pfn_t pfn) /* ARGSUSED */ void -plat_build_mem_nodes(u_longlong_t *list, size_t nelems) +plat_build_mem_nodes(prom_memlist_t *list, size_t nelems) { size_t elem; pfn_t basepfn; @@ -330,9 +330,9 @@ plat_build_mem_nodes(u_longlong_t *list, size_t nelems) /* * Boot install lists are arranged <addr, len>, <addr, len>, ... */ - for (elem = 0; elem < nelems; elem += 2) { - basepfn = btop(list[elem]); - npgs = btop(list[elem+1]); + for (elem = 0; elem < nelems; list++, elem++) { + basepfn = btop(list->addr); + npgs = btop(list->size); mem_node_add_slice(basepfn, basepfn + npgs - 1); } } diff --git a/usr/src/uts/sun4u/starcat/unix/Makefile b/usr/src/uts/sun4u/starcat/unix/Makefile index 9d1c3b50f5..0920829465 100644 --- a/usr/src/uts/sun4u/starcat/unix/Makefile +++ b/usr/src/uts/sun4u/starcat/unix/Makefile @@ -49,13 +49,14 @@ LINTS = $(SPECIAL_OBJS:%.o=$(LINTS_DIR)/%.ln) \ $(MACH_NOT_YET_KMODS:%.o=$(LINTS_DIR)/%.ln) \ $(LINTS_DIR)/vers.ln \ $(LINTS_DIR)/modstubs.ln + +KRTLD_MAPFILE = $(UTSBASE)/sparc/krtld/mapfile +KRTLD_OBJECTS = $(KRTLD_OBJS:%=$(OBJS_DIR)/%) +KRTLD_O = $(OBJS_DIR)/krtld.o + ROOTMODULE = $(ROOT_STARCAT_KERN_DIR)/$(UNIX) UNIX_BIN = $(OBJS_DIR)/$(UNIX) -KRTLD_32 = misc/krtld -KRTLD_64 = misc/$(SUBDIR64)/krtld -KRTLD = $(KRTLD_$(CLASS)) - LIBS = $(GENLIB) $(PLATLIB) $(CPULIB) GENUNIX = genunix @@ -100,8 +101,9 @@ UNIX_DIR = . # # Overrides # -CLEANFILES += $(UNIX_O) $(MODSTUBS_O) $(OBJS_DIR)/vers.c \ - $(OBJS_DIR)/vers.o $(CPU_OBJ) $(CPULIB) \ +CLEANFILES += $(UNIX_O) $(MODSTUBS_O) $(KRTLD_O) $(KRTLD_OBJECTS) \ + $(OBJS_DIR)/vers.c $(OBJS_DIR)/vers.o \ + $(CPU_OBJ) $(CPULIB) \ $(DTRACESTUBS_O) $(DTRACESTUBS) CLOBBERFILES = $(CLEANFILES) $(UNIX_BIN) @@ -134,19 +136,23 @@ install: $(INSTALL_DEPS) symcheck: $(SYM_DEPS) -$(UNIX_BIN): $(UNIX_O) $(MODSTUBS_O) $(MAPFILE) $(LIBS) $(DTRACESTUBS) - $(LD) -dy -b -o $@ -e _start -I $(KRTLD) -M $(MAPFILE) \ - $(UNIX_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) +$(UNIX_BIN): $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(MAPFILE) $(LIBS) \ + $(DTRACESTUBS) + $(LD) -dy -b -o $@ -e _start -M $(MAPFILE) \ + $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) $(CTFMERGE_UNIQUIFY_AGAINST_GENUNIX) $(POST_PROCESS) -symcheck.targ: $(UNIX_O) $(MODSTUBS_O) $(LIBS) $(DTRACESTUBS) +symcheck.targ: $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBS) $(DTRACESTUBS) $(LD) -dy -b -o $(SYM_MOD) -M $(MAPFILE) \ - $(UNIX_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) + $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) $(UNIX_O): $(OBJECTS) $(OBJS_DIR)/vers.o $(LD) -r -o $@ $(OBJECTS) $(OBJS_DIR)/vers.o +$(KRTLD_O): $(KRTLD_OBJECTS) + $(LD) -r -o $@ -M$(KRTLD_MAPFILE) $(KRTLD_OBJECTS) + # # Special rules for generating assym.h for inclusion in assembly files. # diff --git a/usr/src/uts/sun4u/starfire/unix/Makefile b/usr/src/uts/sun4u/starfire/unix/Makefile index 889cfa5b4d..e856bc1f2f 100644 --- a/usr/src/uts/sun4u/starfire/unix/Makefile +++ b/usr/src/uts/sun4u/starfire/unix/Makefile @@ -49,14 +49,15 @@ LINTS = $(SPECIAL_OBJS:%.o=$(LINTS_DIR)/%.ln) \ $(MACH_NOT_YET_KMODS:%.o=$(LINTS_DIR)/%.ln) \ $(LINTS_DIR)/vers.ln \ $(LINTS_DIR)/modstubs.ln + +KRTLD_MAPFILE = $(UTSBASE)/sparc/krtld/mapfile +KRTLD_OBJECTS = $(KRTLD_OBJS:%=$(OBJS_DIR)/%) +KRTLD_O = $(OBJS_DIR)/krtld.o + ROOTMODULE = $(ROOT_STARFIRE_KERN_DIR)/$(UNIX) UNIX32_LINK = $(ROOT_STARFIRE_KERN_DIR_32)/$(UNIX) UNIX_BIN = $(OBJS_DIR)/$(UNIX) -KRTLD_32 = misc/krtld -KRTLD_64 = misc/$(SUBDIR64)/krtld -KRTLD = $(KRTLD_$(CLASS)) - LIBS = $(GENLIB) $(PLATLIB) $(CPULIB) GENUNIX = genunix @@ -93,8 +94,9 @@ UNIX_DIR = . # # Overrides # -CLEANFILES += $(UNIX_O) $(MODSTUBS_O) $(OBJS_DIR)/vers.c \ - $(OBJS_DIR)/vers.o $(CPU_OBJ) $(CPULIB) \ +CLEANFILES += $(UNIX_O) $(MODSTUBS_O) $(KRTLD_O) $(KRTLD_OBJECTS) \ + $(OBJS_DIR)/vers.c $(OBJS_DIR)/vers.o \ + $(CPU_OBJ) $(CPULIB) \ $(DTRACESTUBS_O) $(DTRACESTUBS) CLOBBERFILES = $(CLEANFILES) $(UNIX_BIN) @@ -125,22 +127,26 @@ clean.lint: $(CLEAN_LINT_DEPS) install: $(INSTALL_DEPS) -$(UNIX_BIN): $(UNIX_O) $(MODSTUBS_O) $(MAPFILE) $(LIBS) $(DTRACESTUBS) - $(LD) -dy -b -o $@ -e _start -I $(KRTLD) -M $(MAPFILE) \ - $(UNIX_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) +$(UNIX_BIN): $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(MAPFILE) $(LIBS) \ + $(DTRACESTUBS) + $(LD) -dy -b -o $@ -e _start -M $(MAPFILE) \ + $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) $(CTFMERGE_UNIQUIFY_AGAINST_GENUNIX) $(POST_PROCESS) $(UNIX32_LINK): $(ROOT_PSM_KERN_DIR_32) $(UNIX_BIN) -$(RM) $@; ln -s $(SUBDIR64)/$(UNIX) $@ -symcheck: $(UNIX_O) $(MODSTUBS_O) $(LIBS) +symcheck: $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBS) $(LD) -dy -b -o $(SYM_MOD) -M $(MAPFILE) \ - $(UNIX_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) + $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) $(UNIX_O): $(OBJECTS) $(OBJS_DIR)/vers.o $(LD) -r -o $@ $(OBJECTS) $(OBJS_DIR)/vers.o +$(KRTLD_O): $(KRTLD_OBJECTS) + $(LD) -r -o $@ -M$(KRTLD_MAPFILE) $(KRTLD_OBJECTS) + # # Special rules for generating assym.h for inclusion in assembly files. # diff --git a/usr/src/uts/sun4u/sys/machparam.h b/usr/src/uts/sun4u/sys/machparam.h index 394079a247..c53632a5eb 100644 --- a/usr/src/uts/sun4u/sys/machparam.h +++ b/usr/src/uts/sun4u/sys/machparam.h @@ -201,6 +201,14 @@ extern "C" { #define SYSLIMIT32 ADDRESS_C(0x80000000) /* + * BOOTTMPBASE is the base of a space that can be reclaimed + * after the kernel takes over the machine. It contains the + * boot archive and memory allocated by krtld before kmem_alloc + * is brought online. + */ +#define BOOTTMPBASE ADDRESS_C(0x4C000000) + +/* * MEMSCRUBBASE is the base virtual address for the memory scrubber * to read large pages. It MUST be 4MB page aligned. */ @@ -242,15 +250,7 @@ extern "C" { /* * Allocate space for kernel modules on nucleus pages */ -#define MODDATA 1024 * 256 - -/* - * On systems with <MODTEXT_SM_SIZE MB available physical memory, - * cap the in-nucleus module text to MODTEXT_SM_CAP bytes. The - * cap must be a multiple of the base page size. Also see startup.c. - */ -#define MODTEXT_SM_CAP (0x200000) /* bytes */ -#define MODTEXT_SM_SIZE (256) /* MB */ +#define MODDATA 1024 * 512 /* * The heap has a region allocated from it specifically for module text that @@ -292,7 +292,7 @@ extern "C" { * reflect the fact that it's actually the limit for 32-bit kernel virtual * addresses. */ -#define KERNEL_LIMIT32 (SYSBASE32) +#define KERNEL_LIMIT32 BOOTTMPBASE #define PFN_TO_BUSTYPE(pfn) (((pfn) >> 19) & 0x1FF) #define IO_BUSTYPE(pfn) ((PFN_TO_BUSTYPE(pfn) & 0x100) >> 8) diff --git a/usr/src/uts/sun4u/sys/machsystm.h b/usr/src/uts/sun4u/sys/machsystm.h index 28d3f1a137..76e96a56d6 100644 --- a/usr/src/uts/sun4u/sys/machsystm.h +++ b/usr/src/uts/sun4u/sys/machsystm.h @@ -276,9 +276,19 @@ extern uint_t vac_colors_mask; extern int ndata_alloc_page_freelists(struct memlist *, int); extern int ndata_alloc_dmv(struct memlist *); extern int ndata_alloc_tsbs(struct memlist *, pgcnt_t); -extern int ndata_alloc_hat(struct memlist *, pgcnt_t, pgcnt_t); -extern caddr_t alloc_page_freelists(int, caddr_t, int); -extern caddr_t alloc_hme_buckets(caddr_t, int); +extern int ndata_alloc_hat(struct memlist *, pgcnt_t); +extern int ndata_alloc_kpm(struct memlist *, pgcnt_t); +extern int ndata_alloc_page_mutexs(struct memlist *ndata); + +extern size_t calc_pp_sz(pgcnt_t); +extern size_t calc_kpmpp_sz(pgcnt_t); +extern size_t calc_hmehash_sz(pgcnt_t); +extern size_t calc_pagehash_sz(pgcnt_t); +extern size_t calc_free_pagelist_sz(void); + +extern caddr_t alloc_hmehash(caddr_t); +extern caddr_t alloc_page_freelists(caddr_t); + extern size_t page_ctrs_sz(void); extern caddr_t page_ctrs_alloc(caddr_t); extern void page_freelist_coalesce_all(int); diff --git a/usr/src/uts/sun4u/sys/prom_plat.h b/usr/src/uts/sun4u/sys/prom_plat.h index 646da1c7cc..66ea55b2c1 100644 --- a/usr/src/uts/sun4u/sys/prom_plat.h +++ b/usr/src/uts/sun4u/sys/prom_plat.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -150,6 +150,14 @@ extern int prom_map_phys(int mode, size_t size, caddr_t virt, extern void prom_unmap_phys(size_t size, caddr_t virt); extern void prom_unmap_virt(size_t size, caddr_t virt); +extern int prom_phys_installed_len(void); +extern int prom_phys_avail_len(void); +extern int prom_virt_avail_len(void); + +extern int prom_phys_installed(caddr_t); +extern int prom_phys_avail(caddr_t); +extern int prom_virt_avail(caddr_t); + /* * prom_retain allocates or returns retained physical memory * identified by the arguments of name string "id", "size" and "align". diff --git a/usr/src/uts/sun4u/sys/traptrace.h b/usr/src/uts/sun4u/sys/traptrace.h index b0c36d6ac6..24a6104b9e 100644 --- a/usr/src/uts/sun4u/sys/traptrace.h +++ b/usr/src/uts/sun4u/sys/traptrace.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -53,7 +53,7 @@ extern "C" { * the TRAP_ENT_TT field */ -#define TRAP_TPGS (2 * PAGESIZE) /* default size is two pages */ +#define TRAP_TSIZE (2 * PAGESIZE) /* default size is two pages */ #ifndef _ASM @@ -71,13 +71,6 @@ struct trap_trace_record { uintptr_t tt_f4; }; -#define TRAP_TSIZE ((TRAP_TPGS / sizeof (struct trap_trace_record)) * \ - sizeof (struct trap_trace_record)) - -#else - -#define TRAP_TSIZE ((TRAP_TPGS / TRAP_ENT_SIZE) * TRAP_ENT_SIZE) - #endif #define HTRAP_TSIZE 0 @@ -111,9 +104,9 @@ extern TRAP_TRACE_CTL trap_trace_ctl[]; /* allocated in locore.s */ extern int trap_trace_bufsize; /* default buffer size */ extern char trap_tr0[]; /* prealloc buf for boot cpu */ extern int trap_freeze; /* freeze the trap trace */ -extern caddr_t ttrace_buf; /* buffer bop alloced */ +extern caddr_t ttrace_buf; /* kmem64 buffer */ extern int ttrace_index; /* index used */ -extern caddr_t trap_trace_alloc(caddr_t); +extern size_t calc_traptrace_sz(void); extern void mach_htraptrace_setup(int); extern void mach_htraptrace_configure(int); extern void mach_htraptrace_cleanup(int); diff --git a/usr/src/uts/sun4u/unix/Makefile b/usr/src/uts/sun4u/unix/Makefile index 90535da2de..d41a0a9f07 100644 --- a/usr/src/uts/sun4u/unix/Makefile +++ b/usr/src/uts/sun4u/unix/Makefile @@ -27,7 +27,7 @@ # # -# This makefile drives the production of /unix (and unix.o). +# This makefile drives the production of unix (and unix.o). # # sun4u implementation architecture dependent # @@ -46,16 +46,19 @@ OBJECTS = $(SPECIAL_OBJS:%=$(OBJS_DIR)/%) \ $(MACH_NOT_YET_KMODS:%=$(OBJS_DIR)/%) LINTS = $(SPECIAL_OBJS:%.o=$(LINTS_DIR)/%.ln) \ $(CORE_OBJS:%.o=$(LINTS_DIR)/%.ln) \ + $(KRTLD_OBJS:%.o=$(LINTS_DIR)/%.ln) \ $(MACH_NOT_YET_KMODS:%.o=$(LINTS_DIR)/%.ln) \ $(LINTS_DIR)/vers.ln \ $(LINTS_DIR)/modstubs.ln + +KRTLD_MAPFILE = $(UTSBASE)/sparc/krtld/mapfile +KRTLD_OBJECTS = $(KRTLD_OBJS:%=$(OBJS_DIR)/%) +KRTLD_O = $(OBJS_DIR)/krtld.o + ROOTMODULE = $(ROOT_PSM_KERN_DIR)/$(UNIX) UNIX32_LINK = $(ROOT_PSM_KERN_DIR_32)/$(UNIX) UNIX_BIN = $(OBJS_DIR)/$(UNIX) - -KRTLD_32 = misc/krtld -KRTLD_64 = misc/$(SUBDIR64)/krtld -KRTLD = $(KRTLD_$(CLASS)) +#UNIX_GLOM = $(OBJS_DIR)/unix.glom LIBS = $(GENLIB) $(PLATLIB) $(CPULIB) @@ -93,8 +96,9 @@ UNIX_DIR = . # # Overrides # -CLEANFILES += $(UNIX_O) $(MODSTUBS_O) $(OBJS_DIR)/vers.c \ - $(OBJS_DIR)/vers.o $(CPU_OBJ) $(CPULIB) \ +CLEANFILES += $(UNIX_O) $(MODSTUBS_O) $(KRTLD_O) $(KRTLD_OBJECTS) \ + $(OBJS_DIR)/vers.c $(OBJS_DIR)/vers.o \ + $(CPU_OBJ) $(CPULIB) \ $(DTRACESTUBS_O) $(DTRACESTUBS) CLOBBERFILES = $(CLEANFILES) $(UNIX_BIN) @@ -138,22 +142,26 @@ clean.lint: $(CLEAN_LINT_DEPS) install: $(INSTALL_DEPS) -$(UNIX_BIN): $(UNIX_O) $(MODSTUBS_O) $(MAPFILE) $(LIBS) $(DTRACESTUBS) - $(LD) -dy -b -o $@ -e _start -I $(KRTLD) -M $(MAPFILE) \ - $(UNIX_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) +$(UNIX_BIN): $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(MAPFILE) $(LIBS) \ + $(DTRACESTUBS) + $(LD) -dy -b -o $@ -e _start -M $(MAPFILE) \ + $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) $(CTFMERGE_UNIQUIFY_AGAINST_GENUNIX) $(POST_PROCESS) $(UNIX32_LINK): $(ROOT_PSM_KERN_DIR_32) $(UNIX_BIN) -$(RM) $@; ln -s $(SUBDIR64)/$(UNIX) $@ -symcheck: $(UNIX_O) $(MODSTUBS_O) $(LIBS) +symcheck: $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBS) $(LD) -dy -b -o $(SYM_MOD) -M $(MAPFILE) \ - $(UNIX_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) + $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) $(UNIX_O): $(OBJECTS) $(OBJS_DIR)/vers.o $(LD) -r -o $@ $(OBJECTS) $(OBJS_DIR)/vers.o +$(KRTLD_O): $(KRTLD_OBJECTS) + $(LD) -r -o $@ -M$(KRTLD_MAPFILE) $(KRTLD_OBJECTS) + # # Special rules for generating assym.h for inclusion in assembly files. # diff --git a/usr/src/uts/sun4v/Makefile.files b/usr/src/uts/sun4v/Makefile.files index aac90ceb1b..9cc13305af 100644 --- a/usr/src/uts/sun4v/Makefile.files +++ b/usr/src/uts/sun4v/Makefile.files @@ -34,7 +34,6 @@ # object lists # CORE_OBJS += bootops.o -CORE_OBJS += prom_alloc.o CORE_OBJS += cmp.o CORE_OBJS += cpc_hwreg.o CORE_OBJS += cpc_subr.o diff --git a/usr/src/uts/sun4v/ml/mach_locore.s b/usr/src/uts/sun4v/ml/mach_locore.s index fdd6b28992..8e391ed480 100644 --- a/usr/src/uts/sun4v/ml/mach_locore.s +++ b/usr/src/uts/sun4v/ml/mach_locore.s @@ -242,16 +242,19 @@ afsrbuf: ! Stash away our arguments in memory. ! sethi %hi(_local_p1275cis), %g1 - stn %o0, [%g1 + %lo(_local_p1275cis)] - sethi %hi(bootops), %g1 - stn %o1, [%g1 + %lo(bootops)] + stn %o4, [%g1 + %lo(_local_p1275cis)] ! ! Initialize CPU state registers ! wrpr %g0, PSTATE_KERN, %pstate wr %g0, %g0, %fprs - CLEARTICKNPT ! allow user rdtick + + ! + ! call krtld to link the world together + ! + call kobj_start + mov %o4, %o0 ! Write 0x1f (MAX_REG_WINDOWS) to %cwp and read back to get ! the actual implemented nwin - 1 value @@ -308,8 +311,8 @@ afsrbuf: set t0stacktop, %g1 ! setup kernel stack pointer sub %g1, SA(KFPUSIZE+GSR_SIZE), %g2 and %g2, 0x3f, %g3 - sub %g2, %g3, %o2 - sub %o2, SA(MPCBSIZE) + STACK_BIAS, %sp + sub %g2, %g3, %o1 + sub %o1, SA(MPCBSIZE) + STACK_BIAS, %sp ! ! Initialize global thread register. @@ -337,10 +340,7 @@ afsrbuf: ! ! Call mlsetup with address of prototype user registers. - ! and p1275cis pointers. - - sethi %hi(_local_p1275cis), %o1 - ldn [%o1 + %lo(_local_p1275cis)], %o1 + ! call mlsetup add %sp, REGOFF + STACK_BIAS, %o0 diff --git a/usr/src/uts/sun4v/os/mpo.c b/usr/src/uts/sun4v/os/mpo.c index d1bae0a815..cf4a4836b1 100644 --- a/usr/src/uts/sun4v/os/mpo.c +++ b/usr/src/uts/sun4v/os/mpo.c @@ -874,7 +874,7 @@ mpo_plat_assign_lgrphand_to_mem_node(lgrp_handle_t plathand, int mnode) */ void -plat_build_mem_nodes(u_longlong_t *list, size_t nelems) +plat_build_mem_nodes(prom_memlist_t *list, size_t nelems) { lgrp_handle_t lgrphand, lgrp_start; int i, mnode, elem; @@ -888,9 +888,9 @@ plat_build_mem_nodes(u_longlong_t *list, size_t nelems) /* Check for non-MPO sun4v platforms */ if (n_locality_groups <= 1) { mpo_plat_assign_lgrphand_to_mem_node(LGRP_DEFAULT_HANDLE, 0); - for (elem = 0; elem < nelems; elem += 2) { - base = list[elem]; - len = list[elem+1]; + for (elem = 0; elem < nelems; list++, elem++) { + base = list->addr; + len = list->size; mpo_mem_node_add_slice(btop(base), btop(base + len - 1)); diff --git a/usr/src/uts/sun4v/sys/machparam.h b/usr/src/uts/sun4v/sys/machparam.h index ffa3fec5da..b6ca2491a3 100644 --- a/usr/src/uts/sun4v/sys/machparam.h +++ b/usr/src/uts/sun4v/sys/machparam.h @@ -184,6 +184,14 @@ extern "C" { #define SYSLIMIT32 ADDRESS_C(0x80000000) /* + * BOOTTMPBASE is the base of a space that can be reclaimed + * after the kernel takes over the machine. It contains the + * boot archive and memory allocated by krtld before kmem_alloc + * is brought online. + */ +#define BOOTTMPBASE ADDRESS_C(0x4C000000) + +/* * MEMSCRUBBASE is the base virtual address for the memory scrubber * to read large pages. It MUST be 4MB page aligned. */ @@ -225,15 +233,7 @@ extern "C" { /* * Allocate space for kernel modules on nucleus pages */ -#define MODDATA 1024 * 256 - -/* - * On systems with <MODTEXT_SM_SIZE MB available physical memory, - * cap the in-nucleus module text to MODTEXT_SM_CAP bytes. The - * cap must be a multiple of the base page size. Also see startup.c. - */ -#define MODTEXT_SM_CAP (0x200000) /* bytes */ -#define MODTEXT_SM_SIZE (256) /* MB */ +#define MODDATA 1024 * 512 /* * The heap has a region allocated from it specifically for module text that @@ -283,7 +283,7 @@ extern "C" { * reflect the fact that it's actually the limit for 32-bit kernel virtual * addresses. */ -#define KERNEL_LIMIT32 (SYSBASE32) +#define KERNEL_LIMIT32 BOOTTMPBASE /* * Defines used for the ptl1_panic parameter, which is passed to the diff --git a/usr/src/uts/sun4v/sys/machsystm.h b/usr/src/uts/sun4v/sys/machsystm.h index 84ef8b740f..b9df6e3f45 100644 --- a/usr/src/uts/sun4v/sys/machsystm.h +++ b/usr/src/uts/sun4v/sys/machsystm.h @@ -277,9 +277,19 @@ extern int ndata_alloc_mmfsa(struct memlist *); extern int ndata_alloc_page_freelists(struct memlist *, int); extern int ndata_alloc_dmv(struct memlist *); extern int ndata_alloc_tsbs(struct memlist *, pgcnt_t); -extern int ndata_alloc_hat(struct memlist *, pgcnt_t, pgcnt_t); -extern caddr_t alloc_page_freelists(int, caddr_t, int); -extern caddr_t alloc_hme_buckets(caddr_t, int); +extern int ndata_alloc_hat(struct memlist *, pgcnt_t); +extern int ndata_alloc_kpm(struct memlist *, pgcnt_t); +extern int ndata_alloc_page_mutexs(struct memlist *ndata); + +extern size_t calc_pp_sz(pgcnt_t); +extern size_t calc_kpmpp_sz(pgcnt_t); +extern size_t calc_hmehash_sz(pgcnt_t); +extern size_t calc_pagehash_sz(pgcnt_t); +extern size_t calc_free_pagelist_sz(void); + +extern caddr_t alloc_hmehash(caddr_t); +extern caddr_t alloc_page_freelists(caddr_t); + extern size_t page_ctrs_sz(void); extern caddr_t page_ctrs_alloc(caddr_t); extern void page_freelist_coalesce_all(int); diff --git a/usr/src/uts/sun4v/sys/prom_plat.h b/usr/src/uts/sun4v/sys/prom_plat.h index 6e7ffb247b..7316a5c211 100644 --- a/usr/src/uts/sun4v/sys/prom_plat.h +++ b/usr/src/uts/sun4v/sys/prom_plat.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -150,6 +150,14 @@ extern int prom_map_phys(int mode, size_t size, caddr_t virt, extern void prom_unmap_phys(size_t size, caddr_t virt); extern void prom_unmap_virt(size_t size, caddr_t virt); +extern int prom_phys_installed_len(void); +extern int prom_phys_avail_len(void); +extern int prom_virt_avail_len(void); + +extern int prom_phys_installed(caddr_t); +extern int prom_phys_avail(caddr_t); +extern int prom_virt_avail(caddr_t); + /* * prom_retain allocates or returns retained physical memory * identified by the arguments of name string "id", "size" and "align". diff --git a/usr/src/uts/sun4v/sys/traptrace.h b/usr/src/uts/sun4v/sys/traptrace.h index 90343b8767..08f5dea459 100644 --- a/usr/src/uts/sun4v/sys/traptrace.h +++ b/usr/src/uts/sun4v/sys/traptrace.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -58,7 +58,7 @@ extern "C" { * the TRAP_ENT_TT field */ -#define TRAP_TBUF (2 * PAGESIZE) /* default size is two pages */ +#define TRAP_TSIZE (2 * PAGESIZE) /* default size is two pages */ #ifndef _ASM @@ -113,19 +113,10 @@ struct trap_trace_record { uintptr_t tt_f4; }; -#define TRAP_TSIZE ((TRAP_TBUF / sizeof (struct trap_trace_record)) * \ - sizeof (struct trap_trace_record)) - -/* Rounding not needed, done for consistency */ -#define HTRAP_TSIZE ((TRAP_TBUF / sizeof (struct htrap_trace_record)) * \ - sizeof (struct htrap_trace_record)) - -#else +#endif -#define TRAP_TSIZE ((TRAP_TBUF / TRAP_ENT_SIZE) * TRAP_ENT_SIZE) -#define HTRAP_TSIZE ((TRAP_TBUF / HTRAP_ENT_SIZE) * HTRAP_ENT_SIZE) +#define HTRAP_TSIZE TRAP_TSIZE -#endif /* * Trap tracing buffer header. @@ -159,9 +150,9 @@ extern TRAP_TRACE_CTL trap_trace_ctl[]; /* allocated in locore.s */ extern int trap_trace_bufsize; /* default buffer size */ extern char trap_tr0[]; /* prealloc buf for boot cpu */ extern int trap_freeze; /* freeze the trap trace */ -extern caddr_t ttrace_buf; /* buffer bop alloced */ +extern caddr_t ttrace_buf; /* kmem64 buffer */ extern int ttrace_index; /* index used */ -extern caddr_t trap_trace_alloc(caddr_t); +extern size_t calc_traptrace_sz(void); extern int htrap_trace_bufsize; /* default hv buffer size */ extern int mach_htraptrace_enable; diff --git a/usr/src/uts/sun4v/unix/Makefile b/usr/src/uts/sun4v/unix/Makefile index cc2f63dd7e..411bd5ef04 100644 --- a/usr/src/uts/sun4v/unix/Makefile +++ b/usr/src/uts/sun4v/unix/Makefile @@ -46,17 +46,19 @@ OBJECTS = $(SPECIAL_OBJS:%=$(OBJS_DIR)/%) \ $(MACH_NOT_YET_KMODS:%=$(OBJS_DIR)/%) LINTS = $(SPECIAL_OBJS:%.o=$(LINTS_DIR)/%.ln) \ $(CORE_OBJS:%.o=$(LINTS_DIR)/%.ln) \ + $(KRTLD_OBJS:%.o=$(LINTS_DIR)/%.ln) \ $(MACH_NOT_YET_KMODS:%.o=$(LINTS_DIR)/%.ln) \ $(LINTS_DIR)/vers.ln \ $(LINTS_DIR)/modstubs.ln + +KRTLD_MAPFILE = $(UTSBASE)/sparc/krtld/mapfile +KRTLD_OBJECTS = $(KRTLD_OBJS:%=$(OBJS_DIR)/%) +KRTLD_O = $(OBJS_DIR)/krtld.o + ROOTMODULE = $(ROOT_PSM_KERN_DIR)/$(UNIX) UNIX32_LINK = $(ROOT_PSM_KERN_DIR_32)/$(UNIX) UNIX_BIN = $(OBJS_DIR)/$(UNIX) -KRTLD_32 = misc/krtld -KRTLD_64 = misc/$(SUBDIR64)/krtld -KRTLD = $(KRTLD_$(CLASS)) - LIBS = $(GENLIB) $(PLATLIB) $(CPULIB) GENUNIX = genunix @@ -93,8 +95,9 @@ UNIX_DIR = . # # Overrides # -CLEANFILES += $(UNIX_O) $(MODSTUBS_O) $(OBJS_DIR)/vers.c \ - $(OBJS_DIR)/vers.o $(CPU_OBJ) $(CPULIB) \ +CLEANFILES += $(UNIX_O) $(MODSTUBS_O) $(KRTLD_O) $(KRTLD_OBJECTS) \ + $(OBJS_DIR)/vers.c $(OBJS_DIR)/vers.o \ + $(CPU_OBJ) $(CPULIB) \ $(DTRACESTUBS_O) $(DTRACESTUBS) CLOBBERFILES = $(CLEANFILES) $(UNIX_BIN) @@ -138,22 +141,26 @@ clean.lint: $(CLEAN_LINT_DEPS) install: $(INSTALL_DEPS) -$(UNIX_BIN): $(UNIX_O) $(MODSTUBS_O) $(MAPFILE) $(LIBS) $(DTRACESTUBS) - $(LD) -dy -b -o $@ -e _start -I $(KRTLD) -M $(MAPFILE) \ - $(UNIX_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) +$(UNIX_BIN): $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(MAPFILE) $(LIBS) \ + $(DTRACESTUBS) + $(LD) -dy -b -o $@ -e _start -M $(MAPFILE) \ + $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) $(CTFMERGE_UNIQUIFY_AGAINST_GENUNIX) $(POST_PROCESS) $(UNIX32_LINK): $(ROOT_PSM_KERN_DIR_32) $(UNIX_BIN) -$(RM) $@; ln -s $(SUBDIR64)/$(UNIX) $@ -symcheck: $(UNIX_O) $(MODSTUBS_O) $(LIBS) +symcheck: $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBS) $(LD) -dy -b -o $(SYM_MOD) -M $(MAPFILE) \ - $(UNIX_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) + $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) $(UNIX_O): $(OBJECTS) $(OBJS_DIR)/vers.o $(LD) -r -o $@ $(OBJECTS) $(OBJS_DIR)/vers.o +$(KRTLD_O): $(KRTLD_OBJECTS) + $(LD) -r -o $@ -M$(KRTLD_MAPFILE) $(KRTLD_OBJECTS) + # # Special rules for generating assym.h for inclusion in assembly files. # diff --git a/usr/src/uts/sun4v/vm/mach_vm_dep.c b/usr/src/uts/sun4v/vm/mach_vm_dep.c index b46a1f3f09..09aea923e0 100644 --- a/usr/src/uts/sun4v/vm/mach_vm_dep.c +++ b/usr/src/uts/sun4v/vm/mach_vm_dep.c @@ -53,6 +53,7 @@ #include <vm/seg_kmem.h> #include <sys/stack.h> #include <sys/atomic.h> +#include <sys/promif.h> uint_t page_colors = 0; uint_t page_colors_mask = 0; @@ -730,6 +731,10 @@ contig_mem_prealloc(caddr_t alloc_base, pgcnt_t npages) MMU_PAGESIZE4M); alloc_base = (caddr_t)roundup((uintptr_t)alloc_base, MMU_PAGESIZE4M); + if (prom_alloc(alloc_base, contig_mem_prealloc_size, + MMU_PAGESIZE4M) != alloc_base) + prom_panic("can't allocate contig mem"); + contig_mem_prealloc_buf = alloc_base; alloc_base += contig_mem_prealloc_size; |