summaryrefslogtreecommitdiff
path: root/usr/src/psm/stand
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/psm/stand')
-rw-r--r--usr/src/psm/stand/Makefile57
-rw-r--r--usr/src/psm/stand/README61
-rw-r--r--usr/src/psm/stand/boot/Makefile99
-rw-r--r--usr/src/psm/stand/boot/Makefile.boot93
-rw-r--r--usr/src/psm/stand/boot/Makefile.rules124
-rw-r--r--usr/src/psm/stand/boot/Makefile.targ38
-rw-r--r--usr/src/psm/stand/boot/amd64/alloc.c58
-rw-r--r--usr/src/psm/stand/boot/amd64/amd64/alloc.h45
-rw-r--r--usr/src/psm/stand/boot/amd64/amd64/amd64.h74
-rw-r--r--usr/src/psm/stand/boot/amd64/amd64/amd64_page.h161
-rw-r--r--usr/src/psm/stand/boot/amd64/amd64/auxv64.h52
-rw-r--r--usr/src/psm/stand/boot/amd64/amd64/boothooks.h57
-rw-r--r--usr/src/psm/stand/boot/amd64/amd64/bootops64.h69
-rw-r--r--usr/src/psm/stand/boot/amd64/amd64/bootsvcs64.h66
-rw-r--r--usr/src/psm/stand/boot/amd64/amd64/cpu.h66
-rw-r--r--usr/src/psm/stand/boot/amd64/amd64/debug.h57
-rw-r--r--usr/src/psm/stand/boot/amd64/amd64/machregs.h198
-rw-r--r--usr/src/psm/stand/boot/amd64/amd64/memlist64.h49
-rw-r--r--usr/src/psm/stand/boot/amd64/amd64/msr.h46
-rw-r--r--usr/src/psm/stand/boot/amd64/amd64/print.h61
-rw-r--r--usr/src/psm/stand/boot/amd64/amd64/segments.h386
-rw-r--r--usr/src/psm/stand/boot/amd64/amd64/tss.h120
-rw-r--r--usr/src/psm/stand/boot/amd64/amd64/types.h49
-rw-r--r--usr/src/psm/stand/boot/amd64/context.c322
-rw-r--r--usr/src/psm/stand/boot/amd64/cpu.c307
-rw-r--r--usr/src/psm/stand/boot/amd64/exception.s268
-rw-r--r--usr/src/psm/stand/boot/amd64/genassym.c47
-rw-r--r--usr/src/psm/stand/boot/amd64/handoff.c91
-rw-r--r--usr/src/psm/stand/boot/amd64/i386_subr.s224
-rw-r--r--usr/src/psm/stand/boot/amd64/locore.s577
-rw-r--r--usr/src/psm/stand/boot/amd64/memlist.c70
-rw-r--r--usr/src/psm/stand/boot/amd64/offsets.in111
-rw-r--r--usr/src/psm/stand/boot/amd64/print.c278
-rw-r--r--usr/src/psm/stand/boot/amd64/ptops.c372
-rw-r--r--usr/src/psm/stand/boot/amd64/ptxlate.c359
-rw-r--r--usr/src/psm/stand/boot/amd64/segments.c217
-rw-r--r--usr/src/psm/stand/boot/amd64/vtrap.c1148
-rw-r--r--usr/src/psm/stand/boot/common/heap_kmem.c882
-rw-r--r--usr/src/psm/stand/boot/common/readfile.c1571
-rw-r--r--usr/src/psm/stand/boot/common/stripalign.c162
-rw-r--r--usr/src/psm/stand/boot/i386/Makefile56
-rw-r--r--usr/src/psm/stand/boot/i386/Makefile.com207
-rw-r--r--usr/src/psm/stand/boot/i386/common/bios.c90
-rw-r--r--usr/src/psm/stand/boot/i386/common/biosint.h46
-rw-r--r--usr/src/psm/stand/boot/i386/common/biosint.map28
-rw-r--r--usr/src/psm/stand/boot/i386/common/biosutil.c335
-rw-r--r--usr/src/psm/stand/boot/i386/common/boot_plat.c267
-rw-r--r--usr/src/psm/stand/boot/i386/common/boot_ramdisk.c119
-rw-r--r--usr/src/psm/stand/boot/i386/common/bootenv.c205
-rw-r--r--usr/src/psm/stand/boot/i386/common/bootflags.c279
-rw-r--r--usr/src/psm/stand/boot/i386/common/bootops.c193
-rw-r--r--usr/src/psm/stand/boot/i386/common/bootprop.c331
-rw-r--r--usr/src/psm/stand/boot/i386/common/bootprop.h70
-rw-r--r--usr/src/psm/stand/boot/i386/common/chario.h145
-rw-r--r--usr/src/psm/stand/boot/i386/common/check_iopath.c96
-rw-r--r--usr/src/psm/stand/boot/i386/common/console.c592
-rw-r--r--usr/src/psm/stand/boot/i386/common/console.h63
-rw-r--r--usr/src/psm/stand/boot/i386/common/cpu_id.h66
-rw-r--r--usr/src/psm/stand/boot/i386/common/debug.h52
-rw-r--r--usr/src/psm/stand/boot/i386/common/graphics.c743
-rw-r--r--usr/src/psm/stand/boot/i386/common/graphics.h79
-rw-r--r--usr/src/psm/stand/boot/i386/common/i86.il122
-rw-r--r--usr/src/psm/stand/boot/i386/common/keyboard.c554
-rw-r--r--usr/src/psm/stand/boot/i386/common/keyboard_table.c181
-rw-r--r--usr/src/psm/stand/boot/i386/common/keyboard_table.h75
-rw-r--r--usr/src/psm/stand/boot/i386/common/machine.h128
-rw-r--r--usr/src/psm/stand/boot/i386/common/mapfile28
-rw-r--r--usr/src/psm/stand/boot/i386/common/memory.c216
-rw-r--r--usr/src/psm/stand/boot/i386/common/mkbin.c134
-rw-r--r--usr/src/psm/stand/boot/i386/common/multiboot.c285
-rw-r--r--usr/src/psm/stand/boot/i386/common/multiboot.h170
-rw-r--r--usr/src/psm/stand/boot/i386/common/serial.h83
-rw-r--r--usr/src/psm/stand/boot/i386/common/standalloc.c481
-rw-r--r--usr/src/psm/stand/boot/i386/common/standalloc.h67
-rw-r--r--usr/src/psm/stand/boot/i386/common/util.h61
-rw-r--r--usr/src/psm/stand/boot/i386/common/vga.c117
-rw-r--r--usr/src/psm/stand/boot/i386/common/vga.h57
-rw-r--r--usr/src/psm/stand/boot/i386/common/vgaprobe.c204
-rw-r--r--usr/src/psm/stand/boot/i386/i86pc/Makefile52
-rw-r--r--usr/src/psm/stand/boot/i386/i86pc/asm.s329
-rw-r--r--usr/src/psm/stand/boot/i386/i86pc/biosint.s325
-rw-r--r--usr/src/psm/stand/boot/i386/i86pc/cpu_id.s246
-rw-r--r--usr/src/psm/stand/boot/i386/i86pc/idttab.s700
-rw-r--r--usr/src/psm/stand/boot/i386/i86pc/samuldiv64.s1077
-rw-r--r--usr/src/psm/stand/boot/inc.flg48
-rw-r--r--usr/src/psm/stand/boot/sparc/common/boot.c108
-rw-r--r--usr/src/psm/stand/boot/sparc/common/boot_plat.c682
-rw-r--r--usr/src/psm/stand/boot/sparc/common/boot_plat.h131
-rw-r--r--usr/src/psm/stand/boot/sparc/common/boot_services.c713
-rw-r--r--usr/src/psm/stand/boot/sparc/common/bootflags.c274
-rw-r--r--usr/src/psm/stand/boot/sparc/common/bootops.c213
-rw-r--r--usr/src/psm/stand/boot/sparc/common/bootprop.c263
-rw-r--r--usr/src/psm/stand/boot/sparc/common/get.c84
-rw-r--r--usr/src/psm/stand/boot/sparc/common/hsfsconf.c50
-rw-r--r--usr/src/psm/stand/boot/sparc/common/mapfile36
-rw-r--r--usr/src/psm/stand/boot/sparc/common/nfsconf.c57
-rw-r--r--usr/src/psm/stand/boot/sparc/common/ramdisk.c567
-rw-r--r--usr/src/psm/stand/boot/sparc/common/ramdisk.h50
-rw-r--r--usr/src/psm/stand/boot/sparc/common/sparc.il33
-rw-r--r--usr/src/psm/stand/boot/sparc/common/sparcv9_subr.s293
-rw-r--r--usr/src/psm/stand/boot/sparc/common/sun4dep.c135
-rw-r--r--usr/src/psm/stand/boot/sparc/common/sun4u_memlist.c219
-rw-r--r--usr/src/psm/stand/boot/sparc/common/sun4u_srt0.s214
-rw-r--r--usr/src/psm/stand/boot/sparc/common/sun4x_standalloc.c339
-rw-r--r--usr/src/psm/stand/boot/sparc/common/ufsconf.c57
-rw-r--r--usr/src/psm/stand/boot/sparc/common/wanboot.c1762
-rw-r--r--usr/src/psm/stand/boot/sparc/common/wbcli.c1425
-rw-r--r--usr/src/psm/stand/boot/sparc/common/wbcli.h51
-rw-r--r--usr/src/psm/stand/boot/sparc/common/wbfsconf.c62
-rw-r--r--usr/src/psm/stand/boot/sparcv9/Makefile62
-rw-r--r--usr/src/psm/stand/boot/sparcv9/Makefile.com360
-rw-r--r--usr/src/psm/stand/boot/sparcv9/sun4u/Makefile144
-rw-r--r--usr/src/psm/stand/boot/sparcv9/sun4u/machdep.c173
-rw-r--r--usr/src/psm/stand/boot/sparcv9/sun4v/Makefile121
-rw-r--r--usr/src/psm/stand/boot/sparcv9/sun4v/machdep.c80
-rw-r--r--usr/src/psm/stand/bootblks/Makefile45
-rw-r--r--usr/src/psm/stand/bootblks/Makefile.127555
-rw-r--r--usr/src/psm/stand/bootblks/Makefile.com94
-rw-r--r--usr/src/psm/stand/bootblks/Makefile.obp55
-rw-r--r--usr/src/psm/stand/bootblks/Makefile.targ39
-rw-r--r--usr/src/psm/stand/bootblks/hsfs/Makefile51
-rw-r--r--usr/src/psm/stand/bootblks/hsfs/Makefile.hsfs35
-rw-r--r--usr/src/psm/stand/bootblks/hsfs/common/Makefile.com56
-rw-r--r--usr/src/psm/stand/bootblks/hsfs/common/boot_obp.fth598
-rw-r--r--usr/src/psm/stand/bootblks/hsfs/common/hsfs.c683
-rw-r--r--usr/src/psm/stand/bootblks/hsfs/common/hsfs_sig.h66
-rw-r--r--usr/src/psm/stand/bootblks/hsfs/common/hsfs_small.c674
-rw-r--r--usr/src/psm/stand/bootblks/hsfs/common/iob.h51
-rw-r--r--usr/src/psm/stand/bootblks/hsfs/i386/Makefile44
-rw-r--r--usr/src/psm/stand/bootblks/hsfs/sparc/Makefile49
-rw-r--r--usr/src/psm/stand/bootblks/hsfs/sparc/unix/Makefile71
-rw-r--r--usr/src/psm/stand/bootblks/obp-c/Makefile.rules105
-rw-r--r--usr/src/psm/stand/bootblks/obp-c/Makefile.targ61
-rw-r--r--usr/src/psm/stand/bootblks/obp-c/common/cbootblk.h74
-rw-r--r--usr/src/psm/stand/bootblks/obp-c/common/makevers.sh48
-rw-r--r--usr/src/psm/stand/bootblks/obp-c/common/mkboot.c172
-rw-r--r--usr/src/psm/stand/bootblks/obp-c/common/romp.h226
-rw-r--r--usr/src/psm/stand/bootblks/obp-c/common/stub.c101
-rw-r--r--usr/src/psm/stand/bootblks/obp-c/common/unix_devio.c124
-rw-r--r--usr/src/psm/stand/bootblks/obp-c/sparc/common/mapfile35
-rw-r--r--usr/src/psm/stand/bootblks/obp-c/sparc/common/obp_srt0.s74
-rw-r--r--usr/src/psm/stand/bootblks/ufs/Makefile55
-rw-r--r--usr/src/psm/stand/bootblks/ufs/Makefile.ufs58
-rw-r--r--usr/src/psm/stand/bootblks/ufs/common/Makefile.com55
-rw-r--r--usr/src/psm/stand/bootblks/ufs/common/boot_1275.fth898
-rw-r--r--usr/src/psm/stand/bootblks/ufs/common/boot_obp.fth463
-rw-r--r--usr/src/psm/stand/bootblks/ufs/common/iob.h74
-rw-r--r--usr/src/psm/stand/bootblks/ufs/common/ufs.c375
-rw-r--r--usr/src/psm/stand/bootblks/ufs/i386/Makefile84
-rw-r--r--usr/src/psm/stand/bootblks/ufs/i386/installboot.sh55
-rw-r--r--usr/src/psm/stand/bootblks/ufs/i386/mboot.S394
-rw-r--r--usr/src/psm/stand/bootblks/ufs/sparc/Makefile65
-rw-r--r--usr/src/psm/stand/bootblks/ufs/sparc/installboot.sh48
-rw-r--r--usr/src/psm/stand/bootblks/ufs/sparc/sun4c/Makefile59
-rw-r--r--usr/src/psm/stand/bootblks/ufs/sparc/sun4d/Makefile62
-rw-r--r--usr/src/psm/stand/bootblks/ufs/sparc/sun4m/Makefile55
-rw-r--r--usr/src/psm/stand/bootblks/ufs/sparc/sun4u/Makefile76
-rw-r--r--usr/src/psm/stand/bootblks/ufs/sparc/sun4v/Makefile55
-rw-r--r--usr/src/psm/stand/bootblks/ufs/sparc/unix/Makefile72
-rw-r--r--usr/src/psm/stand/cpr/Makefile62
-rw-r--r--usr/src/psm/stand/cpr/common/Makefile.com147
-rw-r--r--usr/src/psm/stand/cpr/common/support.c243
-rw-r--r--usr/src/psm/stand/cpr/sparcv9/Makefile47
-rw-r--r--usr/src/psm/stand/cpr/sparcv9/sun4u/Makefile69
-rw-r--r--usr/src/psm/stand/cpr/sparcv9/sun4u/bitmap.c599
-rw-r--r--usr/src/psm/stand/cpr/sparcv9/sun4u/cb_srt0.s405
-rw-r--r--usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.c577
-rw-r--r--usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.h259
-rw-r--r--usr/src/psm/stand/cpr/sparcv9/sun4u/machdep.c315
-rw-r--r--usr/src/psm/stand/cpr/sparcv9/sun4u/mapfile35
-rw-r--r--usr/src/psm/stand/cpr/sparcv9/sun4u/pages.c364
-rw-r--r--usr/src/psm/stand/cpr/sparcv9/sun4u/util.c495
-rw-r--r--usr/src/psm/stand/lib/Makefile45
-rw-r--r--usr/src/psm/stand/lib/Makefile.lib88
-rw-r--r--usr/src/psm/stand/lib/Makefile.rules50
-rw-r--r--usr/src/psm/stand/lib/boot/Makefile49
-rw-r--r--usr/src/psm/stand/lib/boot/inc.flg30
-rw-r--r--usr/src/psm/stand/lib/boot/sparc/Makefile45
-rw-r--r--usr/src/psm/stand/lib/boot/sparc/Makefile.com112
-rw-r--r--usr/src/psm/stand/lib/boot/sparc/sun4u/Makefile38
-rw-r--r--usr/src/psm/stand/lib/boot/sparcv9/Makefile45
-rw-r--r--usr/src/psm/stand/lib/boot/sparcv9/Makefile.com112
-rw-r--r--usr/src/psm/stand/lib/boot/sparcv9/sun4u/Makefile42
-rw-r--r--usr/src/psm/stand/lib/names/Makefile48
-rw-r--r--usr/src/psm/stand/lib/names/sparc/common/mfgname.c59
-rw-r--r--usr/src/psm/stand/lib/names/sparc/common/uname-i.c213
-rw-r--r--usr/src/psm/stand/lib/names/sparc/common/uname-m.c101
-rw-r--r--usr/src/psm/stand/lib/names/sparcv9/Makefile45
-rw-r--r--usr/src/psm/stand/lib/names/sparcv9/Makefile.com116
-rw-r--r--usr/src/psm/stand/lib/names/sparcv9/sun4u/Makefile41
-rw-r--r--usr/src/psm/stand/lib/names/sparcv9/sun4u/modpath.c34
-rw-r--r--usr/src/psm/stand/lib/names/sparcv9/sun4v/Makefile41
-rw-r--r--usr/src/psm/stand/lib/names/sparcv9/sun4v/modpath.c34
-rw-r--r--usr/src/psm/stand/lib/promif/Makefile48
-rw-r--r--usr/src/psm/stand/lib/promif/sparcv9/Makefile47
-rw-r--r--usr/src/psm/stand/lib/promif/sparcv9/ieee1275/Makefile46
-rw-r--r--usr/src/psm/stand/lib/promif/sparcv9/ieee1275/common/Makefile146
-rw-r--r--usr/src/psm/stand/lib/promif/sparcv9/ieee1275/sun4u/Makefile144
-rw-r--r--usr/src/psm/stand/lib/promif/sparcv9/ieee1275/sun4v/Makefile143
-rw-r--r--usr/src/psm/stand/old/bootblks/common/goforth.s60
-rw-r--r--usr/src/psm/stand/old/bootblks/common/process.c43
-rw-r--r--usr/src/psm/stand/sys/boot.h82
-rw-r--r--usr/src/psm/stand/sys/boot_policy.h47
-rw-r--r--usr/src/psm/stand/sys/boot_redirect.h45
-rw-r--r--usr/src/psm/stand/sys/platnames.h49
205 files changed, 40246 insertions, 0 deletions
diff --git a/usr/src/psm/stand/Makefile b/usr/src/psm/stand/Makefile
new file mode 100644
index 0000000000..cbc6f7bc13
--- /dev/null
+++ b/usr/src/psm/stand/Makefile
@@ -0,0 +1,57 @@
+#
+# 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.
+#
+# 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 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../../Makefile.master
+
+# note: the x86 needs the "bootblks" target for installboot
+SUBDIRS= lib bootblks boot cpr
+
+all := TARGET= all
+install := TARGET= install
+clean := TARGET= clean
+clobber := TARGET= clobber
+lint := TARGET= lint
+clean.lint := TARGET= clean.lint
+
+.KEEP_STATE:
+
+all install clean lint clean.lint clobber: $(SUBDIRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+#
+# Cross-reference customization: include all of the PROM and standalone
+# goo in the cross-reference, except for the crufty "old" directory.
+#
+STANDDIR= ../../stand
+PROMDIRS= ../promif ../../uts/intel/ia32/promif ../../uts/intel/promif
+XRDIRS += $(STANDDIR)/lib $(STANDDIR)/sys $(PROMDIRS)
+XRPRUNE = old
diff --git a/usr/src/psm/stand/README b/usr/src/psm/stand/README
new file mode 100644
index 0000000000..56c880ac4d
--- /dev/null
+++ b/usr/src/psm/stand/README
@@ -0,0 +1,61 @@
+#
+# 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.
+#
+# 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 1996 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+README file for the usr/src/stand directory: (tpl 8/1/94)
+ please update this as required
+
+This tree has source code for both sparc and x86 platforms.
+1). The lint target is implemented, but the source tree is not lint-free yet.
+2). It is too much of a change to "clean-up" this directory at the time
+ of stand and stand.i386 merge. So, let's use the following rule for
+ the benefit of all.
+ Each time you check in a new version of a file, please try to
+ a). lint that file individually
+ b). cstyle that file
+3). Please avoid using the following fragments in the common/ directory
+ #ifdef i386
+ #ifdef sparc
+4). The following fragment is non-ideal for the merge (promif) source base
+ #ifdef I386BOOT
+ It should be removed, re-org'ed after a good understanding of the
+ pieces involved and with suitable testing.
+5). If you change "common" source files including Makefiles, you have
+ to build [ and test ] for all platforms.
+6). The following list should be addressed and eliminated as we continue
+ to separate the PSM code out of shared common (PIM) code
+ a). nfs_readsize for sun4 and i386.
+ b). lib/fs/nfs_inet/netaddr.h: MAX_PKT_SIZE different between i386 and sparc
+ c). lib/fs/nfs_inet/nfsops.c: boot_nfs_read() uses local buffer for i386 case
+ d). all #ifdef sparc caused by prom_getversion() calls
+
+Commonly asked questions and brief answers:
+
+Q: Why is inetboot packaged differently?
+A: inetboot is loaded by PROM code, especially old PROMs. They load
+ to certain specific address and can only recognize a.out header.
+ Thus, inetboot has to be packaged accordingly. Note that the bootblk
+ for sparc has the same constraints. These historical reasons do
+ not apply for i386 architecture.
diff --git a/usr/src/psm/stand/boot/Makefile b/usr/src/psm/stand/boot/Makefile
new file mode 100644
index 0000000000..cf248df166
--- /dev/null
+++ b/usr/src/psm/stand/boot/Makefile
@@ -0,0 +1,99 @@
+#
+# 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.
+#
+# 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 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../../../Makefile.master
+
+sparcv9_ARCHITECTURES = sparcv9
+sparc_ARCHITECTURES = $(sparcv9_ARCHITECTURES)
+i386_ARCHITECTURES = i386
+
+SUBDIRS = $($(MACH)_ARCHITECTURES)
+
+all := TARGET= all
+install := TARGET= install
+clean := TARGET= clean
+clobber := TARGET= clobber
+lint := TARGET= lint
+
+.KEEP_STATE:
+
+all install lint clean: $(SUBDIRS)
+
+clobber: $(SUBDIRS)
+ $(RM) make.out lint.out
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+#
+# Cross-reference customization: include all boot-related source files.
+#
+UTSDIR = ../../../uts
+STANDLIBDIR = ../../../stand/lib
+STANDSYSDIRS = ../../../stand/sys ../../../stand/i386/sys
+PROMDIRS = ../../promif $(UTSDIR)/intel/promif
+NAMESDIRS = ../lib/names
+XRDIRS += $(STANDLIBDIR) $(STANDSYSDIRS) $(PROMDIRS) $(NAMESDIRS)
+XRINCDIRS = $(UTSDIR)/sun4u $(UTSDIR)/sfmmu $(UTSDIR)/sparc/v7 \
+ $(UTSDIR)/sparc/v9 $(UTSDIR)/sparc $(UTSDIR)/sun \
+ $(UTSDIR)/common $(UTSDIR)/intel $(UTSDIR)/i86pc
+
+cscope.out tags: FRC
+ $(XREF) -x $@
+
+FRC:
+
+# EXPORT DELETE START
+EXPORT_SRC:
+ $(RM) sparc/common/wanboot.c+
+ sed -e "/EXPORT DELETE START/,/EXPORT DELETE END/d" \
+ < sparc/common/wanboot.c > sparc/common/wanboot.c+
+ $(MV) sparc/common/wanboot.c+ sparc/common/wanboot.c
+ $(CHMOD) 444 sparc/common/wanboot.c
+ $(RM) sparc/common/wbcli.c+
+ sed -e "/EXPORT DELETE START/,/EXPORT DELETE END/d" \
+ < sparc/common/wbcli.c > sparc/common/wbcli.c+
+ $(MV) sparc/common/wbcli.c+ sparc/common/wbcli.c
+ $(CHMOD) 444 sparc/common/wbcli.c
+ $(RM) sparc/common/ramdisk.c+
+ sed -e "/EXPORT DELETE START/,/EXPORT DELETE END/d" \
+ < sparc/common/ramdisk.c > sparc/common/ramdisk.c+
+ $(MV) sparc/common/ramdisk.c+ sparc/common/ramdisk.c
+ $(CHMOD) 444 sparc/common/ramdisk.c
+ $(RM) sparcv9/Makefile.com+
+ sed -e "/^# EXPORT DELETE START/,/^# EXPORT DELETE END/d" \
+ < sparcv9/Makefile.com > sparcv9/Makefile.com+
+ $(MV) sparcv9/Makefile.com+ sparcv9/Makefile.com
+ $(CHMOD) 444 sparcv9/Makefile.com
+ $(RM) Makefile+
+ sed -e "/^# EXPORT DELETE START/,/^# EXPORT DELETE END/d" \
+ < Makefile > Makefile+
+ $(RM) Makefile
+ $(MV) Makefile+ Makefile
+ $(CHMOD) 444 Makefile
+# EXPORT DELETE END
diff --git a/usr/src/psm/stand/boot/Makefile.boot b/usr/src/psm/stand/boot/Makefile.boot
new file mode 100644
index 0000000000..b5d0f7c8ca
--- /dev/null
+++ b/usr/src/psm/stand/boot/Makefile.boot
@@ -0,0 +1,93 @@
+#
+# 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.
+#
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# psm/stand/boot/Makefile.boot
+
+#
+# Hack until stand makefiles are fixed
+#
+CLASS = 32
+
+include $(TOPDIR)/Makefile.master
+include $(TOPDIR)/Makefile.psm
+
+STANDDIR = $(TOPDIR)/stand
+PSMSTANDDIR = $(TOPDIR)/psm/stand
+
+SYSHDRDIR = $(STANDDIR)
+SYSLIBDIR = $(ROOT)/stand/lib
+
+PSMSYSHDRDIR = $(PSMSTANDDIR)
+PSMNAMELIBDIR = $(PSMSTANDDIR)/lib/names/$(MACH)
+PSMNAMELIBDIR64 = $(PSMSTANDDIR)/lib/names/$(MACH64)
+PSMPROMLIBDIR = $(PSMSTANDDIR)/lib/promif/$(MACH)
+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
+#
+FILEMODE = 644
+DIRMODE = 755
+OWNER = root
+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
+# suspect pointer casts. Since these may be serious problems (especially
+# on SPARC), this really needs to be investigated thoroughly one day.
+# However, we shouldn't feel too bad: the whole kernel is linted with this
+# turned off as well (along with a dozen other disabled warnings).
+#
+# The other two -erroff's are needed only because lint's -u flag is lame
+# and also turns off "name used but not defined" checks (so we instead
+# just enumerate the errors that -u turns off that we want turned off).
+#
+LINTFLAGS = -nmsF -erroff=E_BAD_PTR_CAST_ALIGN \
+ -erroff=E_NAME_DECL_NOT_USED_DEF2 -erroff=E_NAME_DEF_NOT_USED2
diff --git a/usr/src/psm/stand/boot/Makefile.rules b/usr/src/psm/stand/boot/Makefile.rules
new file mode 100644
index 0000000000..5999c83c6a
--- /dev/null
+++ b/usr/src/psm/stand/boot/Makefile.rules
@@ -0,0 +1,124 @@
+#
+# 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.
+#
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+# psm/stand/boot/Makefile.rules
+
+#CPPFLAGS += -DDEBUG=1
+
+#
+# Pattern matching rules to compile the source in the current directory
+#
+%.o: $(TOP_CMN_DIR)/util/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+%.o: $(TOP_CMN_DIR)/fs/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+%.o: $(PROM_DIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+%.o: $(CMN_DIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+%.o: $(PIM_DIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+%.o: $(PAMD64_DIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+%.o: $(PAMD64_DIR)/%.s
+ $(COMPILE.s) -o $@ $<
+ $(POST_PROCESS_O)
+
+%.o: $(MACH_DIR)/%.s
+ $(COMPILE.s) -o $@ $<
+ $(POST_PROCESS_O)
+
+%.o: $(MACH_DIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+%.o: %.s
+ $(COMPILE.s) -o $@ $<
+ $(POST_PROCESS_O)
+
+%.o: $(PLAT_DIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+#
+# Pattern matching rules to lint the source in the current directory
+#
+%.ln: $(TOP_CMN_DIR)/util/%.c
+ @($(LHEAD) $(LINT.c) -c $< $(LTAIL))
+
+%.ln: $(TOP_CMN_DIR)/fs/%.c
+ @($(LHEAD) $(LINT.c) -c $< $(LTAIL))
+
+%.ln: $(PROM_DIR)/%.c
+ @($(LHEAD) $(LINT.c) -c $< $(LTAIL))
+
+%.ln: $(CMN_DIR)/%.c
+ @($(LHEAD) $(LINT.c) -c $< $(LTAIL))
+
+%.ln: $(PIM_DIR)/%.c
+ @($(LHEAD) $(LINT.c) -c $< $(LTAIL))
+
+%.ln: $(PAMD64_DIR)/%.s
+ @($(LHEAD) $(LINT.c) -c $< $(LTAIL))
+
+%.ln: $(PAMD64_DIR)/%.c
+ @($(LHEAD) $(LINT.c) -c $< $(LTAIL))
+
+%.ln: $(MACH_DIR)/%.s
+ @($(LHEAD) $(LINT.c) -c $< $(LTAIL))
+
+%.ln: $(MACH_DIR)/%.c
+ @($(LHEAD) $(LINT.c) -c $< $(LTAIL))
+
+%.ln: %.s
+ @($(LHEAD) $(LINT.c) -c $< $(LTAIL))
+
+%.ln: $(PLAT_DIR)/%.c
+ @($(LHEAD) $(LINT.c) -c $< $(LTAIL))
+
+#
+# Rules to compile libraries needed to build and lint the boot loaders.
+#
+$(LIBPROM_DIR)/libprom.a $(LIBPLAT_DEP) $(LIBNAME_DIR)/libnames.a: FRC
+ @cd $(@D); pwd; $(MAKE) $(@F)
+
+$(LIBPROM_DIR)/llib-lprom.ln $(LIBPLAT_DEP_L) $(LIBNAME_DIR)/llib-lnames.ln: FRC
+ @cd $(@D); pwd; $(MAKE) $(@F)
+
+FRC:
diff --git a/usr/src/psm/stand/boot/Makefile.targ b/usr/src/psm/stand/boot/Makefile.targ
new file mode 100644
index 0000000000..4d58601c91
--- /dev/null
+++ b/usr/src/psm/stand/boot/Makefile.targ
@@ -0,0 +1,38 @@
+#
+# 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.
+#
+# 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 (c) 1994 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# psm/stand/boot/Makefile.files
+
+#
+# Targets common to all versions
+#
+install: all $(ROOT_PSM_UFSBOOT) $(USR_PSM_NFSBOOT)
+
+#
+# Install rules
+#
+include $(TOPDIR)/Makefile.psm.targ
diff --git a/usr/src/psm/stand/boot/amd64/alloc.c b/usr/src/psm/stand/boot/amd64/alloc.c
new file mode 100644
index 0000000000..0b1181477d
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/alloc.c
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <amd64/boothooks.h>
+#include <amd64/alloc.h>
+#include <amd64/amd64_page.h>
+#include <amd64/cpu.h>
+#include <amd64/print.h>
+
+void *
+amd64_alloc_identity(size_t size)
+{
+ void *addr;
+
+ if (addr = (void *)idmap_mem((uint32_t)0, size, AMD64_PAGESIZE))
+ return (addr);
+
+ amd64_panic("amd64_alloc_identity: boot failed to identity map 0x%lx "
+ "bytes\n", size);
+
+ /*NOTREACHED*/
+}
+
+void *
+amd64_zalloc_identity(size_t size)
+{
+ void *p;
+
+ if (p = amd64_alloc_identity(size))
+ bzero(p, size);
+
+ return (p);
+}
diff --git a/usr/src/psm/stand/boot/amd64/amd64/alloc.h b/usr/src/psm/stand/boot/amd64/amd64/alloc.h
new file mode 100644
index 0000000000..ba6a8c8da5
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/amd64/alloc.h
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _AMD64_ALLOC_H
+#define _AMD64_ALLOC_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+
+extern void *amd64_alloc_identity(size_t);
+extern void *amd64_zalloc_identity(size_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AMD64_ALLOC_H */
diff --git a/usr/src/psm/stand/boot/amd64/amd64/amd64.h b/usr/src/psm/stand/boot/amd64/amd64/amd64.h
new file mode 100644
index 0000000000..f67a17d485
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/amd64/amd64.h
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _AMD64_AMD64_H
+#define _AMD64_AMD64_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/link.h>
+
+#include <amd64/types.h>
+#include <amd64/boothooks.h>
+
+struct amd64_machregs;
+
+extern void amd64_system_reset(void);
+
+extern const char *amd64_getmmulist(void);
+extern int amd64_config_cpu(void);
+
+extern struct bootops64 *init_bootops64(struct bootops *);
+extern struct boot_syscalls64 *init_boot_syscalls64(struct boot_syscalls *);
+
+/*
+ * These routines probably belong in machregs.h
+ * Or we need to type the arguments as void * ..
+ */
+struct amd64_machregs;
+
+extern void amd64_vtrap(struct amd64_machregs *);
+extern void amd64_dump_amd64_machregs(struct amd64_machregs *);
+extern void amd64_dump_memlist(const char *);
+
+struct i386_machregs;
+extern void amd64_dump_i386_machregs(struct i386_machregs *);
+
+extern struct amd64_machregs *amd64_makectx64(uint64_t);
+
+extern void amd64_exitto(struct amd64_machregs *);
+extern void amd64_i386_clrtss(struct i386_machregs *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AMD64_AMD64_H */
diff --git a/usr/src/psm/stand/boot/amd64/amd64/amd64_page.h b/usr/src/psm/stand/boot/amd64/amd64/amd64_page.h
new file mode 100644
index 0000000000..c2e7115205
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/amd64/amd64_page.h
@@ -0,0 +1,161 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _AMD64_AMD64_PAGE_H
+#define _AMD64_AMD64_PAGE_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define AMD64_PAGESIZE 4096
+#define AMD64_PAGESIZE2M (2*1024*1024)
+#define AMD64_PAGESIZE4M (4*1024*1024)
+
+#define AMD64_PAGEOFFSET(pagesize) ((uint64_t)((pagesize) - 1))
+#define AMD64_PAGEMASK(pagesize) (~(AMD64_PAGEOFFSET(pagesize)))
+
+#define AMD64_PAGEALIGNED(va, pagesize) \
+ (!((uint64_t)(va) & AMD64_PAGEOFFSET(pagesize)))
+
+#define AMD64_PAGESIZE_OFFSET_NBITS 11
+
+#define BIT_GLOBAL 8
+#define BIT_PS 7 /* PDE only */
+#define BIT_US 2
+#define BIT_RW 1
+#define BIT_VALID 0
+
+#define TBL_GLOBAL (1 << BIT_GLOBAL)
+#define TBL_US (1 << BIT_US)
+#define TBL_RW (1 << BIT_RW)
+#define TBL_VALID (1 << BIT_VALID)
+
+#define PDE_PS (1 << BIT_PS)
+
+#define IS_PDE(level, amd64_mmu_mode) \
+ ((level) == (mmus[(amd64_mmu_mode)].map_level - 1))
+
+#define IS_PTE(level, amd64_mmu_mode) \
+ ((level) == mmus[(amd64_mmu_mode)].map_level)
+
+#define IS_LARGEMAP(entry) ((entry) & PDE_PS)
+#define ENTRY_VALID(entry) ((entry) & TBL_VALID)
+
+#define PA_MODBITS_MASK 0x1eULL
+#define PA_MODBITS(entry) (((uint64_t)(entry)) & PA_MODBITS_MASK)
+
+#define AMD64_MODE_LEGACY 0
+#define AMD64_MODE_LONG64 1
+
+typedef struct amd64_mmumode {
+ uint8_t shift_base; /* shift to start of page tables */
+ uint8_t level_shift; /* shift between page table levels */
+ uint8_t map_level; /* mapping level for AMD64_PAGESIZE pages */
+ uint16_t tbl_entries; /* number of entries per table level */
+} amd64_mmumode_t;
+
+/*
+ * This macro is needed because of a difference of opinion between compilers
+ * that can result in inadvertent sign extension when converting from 32-bit
+ * to 64-bit values.
+ *
+ * For example, given the code:
+ *
+ * long *i = (long *)0xf0000000;
+ * unsigned long long l;
+ *
+ * l = (unsigned long long)i;
+ *
+ * GCC will currently sign extend "i" before converting it to unsigned long
+ * long, resulting in the value 0xfffffffff0000000 being stored in l.
+ *
+ * On the other hand, Forte compilers will not do the extension, resulting in
+ * l receiving the value 0xf0000000.
+ *
+ * The only way to assure sane results regardless of compiler is to use this
+ * macro whenever converting any value to an unsigned 64-bit value.
+ */
+#define UINT64_FROMPTR32(val32) ((uint64_t)(uintptr_t)(val32))
+
+#define TBL_ENTRY_DEFAULT(pa) (UINT64_FROMPTR32(pa) | TBL_RW | TBL_VALID)
+#define TBL_PTR(table) ((uint64_t *)(&table))
+
+#define TBL_INDEX(va, shift, mask) (((va) >> (shift)) & mask)
+
+#define TBL_ENTRY32(amd64_mmu_mode, tbl_base, va, shift, mask) \
+ (((amd64_mmu_mode) == AMD64_MODE_LEGACY) ? \
+ (*(((uint32_t *)(tbl_base)) + \
+ TBL_INDEX((va), (shift), (mask)))) : \
+ ((uint32_t)*(((uint64_t *)(tbl_base)) + \
+ TBL_INDEX((va), (shift), (mask)))))
+
+#define TBL_ENTRY64(amd64_mmu_mode, tbl_base, va, shift, mask) \
+ (((amd64_mmu_mode) == AMD64_MODE_LEGACY) ? \
+ ((uint64_t)(*(((uint32_t *)(tbl_base)) + \
+ TBL_INDEX((va), (shift), (mask))))) : \
+ (*(((uint64_t *)(tbl_base)) + TBL_INDEX((va), (shift), (mask)))))
+
+#define SET_TABLEVAL(amd64_mmu_mode, tbl_base, va, shift, mask, val) \
+ (((amd64_mmu_mode) == AMD64_MODE_LEGACY) ? \
+ (*(((uint32_t *)(tbl_base)) + \
+ TBL_INDEX((va), (shift), (mask))) = (uint32_t)val) : \
+ (*(((uint64_t *)(tbl_base)) + TBL_INDEX((va), (shift), \
+ (mask))) = val))
+
+#define VA64_OFFSET (0xffffffff00000000ULL)
+
+#define ADDR_TRUNC(a) ((void *)((uintptr_t)(a)))
+#define ADDR_XTND(a) (((uintptr_t)(a)) == 0 ? 0ULL : \
+ ((UINT64_FROMPTR32(a)) | VA64_OFFSET))
+
+extern void amd64_map_mem(uint64_t, uint64_t, uint32_t, uint8_t, uint32_t,
+ uint16_t);
+
+extern uint16_t amd64_modbits(uint64_t);
+
+extern uint64_t amd64_legacy_physaddr(uint32_t);
+extern uint64_t amd64_long_physaddr(uint64_t);
+extern uint64_t amd64_physaddr(uint64_t, uint8_t);
+
+extern uint64_t amd64_long_lookup(uint64_t, uint32_t *, uint32_t);
+extern uint32_t amd64_legacy_lookup(uint64_t, uint32_t *, uint32_t);
+extern uint64_t amd64_legacy_lookup_physaddr(uint64_t, uint32_t);
+
+extern uint64_t amd64_init_longpt(uint32_t);
+
+extern void amd64_xlate_legacy_va(uint32_t, uint32_t, uint32_t, uint32_t);
+extern void amd64_xlate_long_va(uint64_t, uint32_t, uint32_t, uint32_t);
+
+extern void amd64_xlate_boot_tables(uint32_t, uint32_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AMD64_AMD64_PAGE_H */
diff --git a/usr/src/psm/stand/boot/amd64/amd64/auxv64.h b/usr/src/psm/stand/boot/amd64/amd64/auxv64.h
new file mode 100644
index 0000000000..42e897e7ce
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/amd64/auxv64.h
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _AMD64_AUXV64_H
+#define _AMD64_AUXV64_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/auxv.h>
+
+typedef struct {
+ int a_type;
+ int a_pad; /* XX64 */
+ union {
+ int64_t a_val;
+ uint64_t a_ptr;
+ } a_un;
+} auxv64_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AMD64_AUXV64_H */
diff --git a/usr/src/psm/stand/boot/amd64/amd64/boothooks.h b/usr/src/psm/stand/boot/amd64/amd64/boothooks.h
new file mode 100644
index 0000000000..becc1ef9b9
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/amd64/boothooks.h
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _AMD64_BOOTHOOKS_H
+#define _AMD64_BOOTHOOKS_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/bootconf.h>
+#include <sys/bootsvcs.h>
+
+/*
+ * Grrr... conflicting #defines in sys/bootsvcs.h and sys/saio.h...
+ */
+#undef printf
+#undef getchar
+#undef putchar
+#undef ischar
+
+#include <sys/saio.h>
+#include <strings.h>
+
+extern caddr_t idmap_mem(uint32_t, size_t, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AMD64_BOOTHOOKS_H */
diff --git a/usr/src/psm/stand/boot/amd64/amd64/bootops64.h b/usr/src/psm/stand/boot/amd64/amd64/bootops64.h
new file mode 100644
index 0000000000..1281ccef3f
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/amd64/bootops64.h
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _AMD64_BOOTOPS64_H
+#define _AMD64_BOOTOPS64_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/inttypes.h>
+
+#include <amd64/types.h>
+
+struct bsys_mem64 {
+ caddr64_t physinstalled; /* struct memlist64 pointer */
+ caddr64_t physavail; /* struct memlist64 pointer */
+ caddr64_t pcimem; /* struct memlist64 pointer */
+};
+
+/*
+ * We need bootops-extensions >= 1 to make S10 work.
+ * bsys_version is BO_VERSION == 5.
+ */
+struct bootops64 {
+ uint32_t bsys_version;
+ uint32_t __bsys_pad0;
+ caddr64_t boot_mem; /* struct bsys_mem64 pointer */
+ fnaddr64_t bsys_alloc;
+ fnaddr64_t bsys_free;
+ fnaddr64_t bsys_getproplen;
+ fnaddr64_t bsys_getprop;
+ fnaddr64_t bsys_nextprop;
+ fnaddr64_t bsys_printf;
+ fnaddr64_t bsys_doint;
+ fnaddr64_t bsys_ealloc;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AMD64_BOOTOPS64_H */
diff --git a/usr/src/psm/stand/boot/amd64/amd64/bootsvcs64.h b/usr/src/psm/stand/boot/amd64/amd64/bootsvcs64.h
new file mode 100644
index 0000000000..4fd533e2df
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/amd64/bootsvcs64.h
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _AMD64_BOOTSVCS64_H
+#define _AMD64_BOOTSVCS64_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * We have to do this uglyness because of <bootsvcs.h>, sigh...
+ */
+
+#ifndef _KERNEL
+#define _KERNEL 1
+#define __XX64_KERNEL 1
+#endif /* _KERNEL */
+
+#undef getchar
+#undef putchar
+#undef ischar
+
+#include <amd64/types.h>
+
+struct boot_syscalls64 {
+ fnaddr64_t getchar; /* 7 - getchar */
+ fnaddr64_t putchar; /* 8 - putchar */
+ fnaddr64_t ischar; /* 9 - ischar */
+};
+
+#ifdef __XX64_KERNEL
+#undef _KERNEL
+#undef __XX64_KERNEL
+#endif /* __XX64_KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AMD64_BOOTSVCS64_H */
diff --git a/usr/src/psm/stand/boot/amd64/amd64/cpu.h b/usr/src/psm/stand/boot/amd64/amd64/cpu.h
new file mode 100644
index 0000000000..d92faaeff0
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/amd64/cpu.h
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _AMD64_CPU
+#define _AMD64_CPU
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+
+extern void amd64_flush_tlb(void);
+extern void amd64_flush_tlbentry(caddr_t);
+
+extern ulong_t amd64_get_cr2(void);
+extern ulong_t amd64_get_cr0(void);
+extern ulong_t amd64_get_cr3(void);
+extern ulong_t amd64_get_cr4(void);
+
+extern ulong_t amd64_get_eflags(void);
+
+struct amd64_cpuid_regs {
+ uint32_t r_eax;
+ uint32_t r_ebx;
+ uint32_t r_ecx;
+ uint32_t r_edx;
+};
+
+#define AMD64_Auth 0x68747541
+#define AMD64_enti 0x69746e65
+#define AMD64_cAMD 0x444d4163
+
+extern uint32_t amd64_cpuid_supported(void);
+extern void amd64_cpuid_insn(uint32_t, struct amd64_cpuid_regs *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AMD64_CPU */
diff --git a/usr/src/psm/stand/boot/amd64/amd64/debug.h b/usr/src/psm/stand/boot/amd64/amd64/debug.h
new file mode 100644
index 0000000000..d62d24c927
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/amd64/debug.h
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _AMD64_DEBUG_H
+#define _AMD64_DEBUG_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/varargs.h>
+#include <sys/promif.h>
+#include <sys/debug.h>
+
+extern int amd64_debug;
+extern int amd64_pt_debug;
+extern uint_t bop_trace;
+
+#define dprintf if (amd64_debug) printf
+
+#define AMD64_TRACE_BOP_IO 1
+#define AMD64_TRACE_BOP_VM 2
+#define AMD64_TRACE_BOP_PROP 4
+#define AMD64_TRACE_BOP_1275 8
+#define AMD64_TRACE_BOP_BIOS 16
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AMD64_DEBUG_H */
diff --git a/usr/src/psm/stand/boot/amd64/amd64/machregs.h b/usr/src/psm/stand/boot/amd64/amd64/machregs.h
new file mode 100644
index 0000000000..6784059966
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/amd64/machregs.h
@@ -0,0 +1,198 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _AMD64_MACHREGS_H
+#define _AMD64_MACHREGS_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(_ASM)
+
+/*
+ * AMD64 is somewhat unique in that it involves switching the state
+ * of the machine back and forth between being a complete implementation
+ * of an i386 processor, and a complete implementation of an amd64
+ * processor. As a result, it has to "know" about the state of both
+ * physical machines.
+ */
+
+#include <sys/types.h>
+#include <amd64/tss.h>
+#include <amd64/segments.h>
+
+struct i386_machregs {
+
+ /*
+ * This is the privileged machine (register) state
+ */
+
+ uint32_t r_cr0;
+ uint32_t r_cr2;
+ uint32_t r_cr3;
+ uint32_t r_cr4;
+
+ union {
+ desctbr_t un_gdt;
+ uint64_t __pad0;
+ } r_gdt_un;
+#define r_gdt r_gdt_un.un_gdt
+
+ union {
+ desctbr_t un_idt;
+ uint64_t __pad0;
+ } r_idt_un;
+#define r_idt r_idt_un.un_idt
+
+ uint32_t r_ldt;
+ uint32_t r_tr;
+
+ /*
+ * The rest of this structure is an i386 'struct regs'
+ */
+
+ int32_t r_gs;
+ int32_t r_fs;
+ int32_t r_es;
+ int32_t r_ds;
+ int32_t r_edi;
+ int32_t r_esi;
+ int32_t r_ebp;
+ int32_t r_esp;
+ int32_t r_ebx;
+ int32_t r_edx;
+ int32_t r_ecx;
+ int32_t r_eax;
+ int32_t r_trapno;
+ int32_t r_err;
+ int32_t r_eip;
+ int32_t r_cs;
+ int32_t r_efl;
+ int32_t r_uesp;
+ int32_t r_ss;
+};
+
+/*
+ * XX64 need assertions to validate structure offsets are really
+ * what they need to be!
+ */
+
+struct amd64_machregs {
+ /*
+ * This is the privileged machine (register) state
+ * (Does NOT include amd64-specific MSRs, because boot doesn't
+ * touch them)
+ *
+ * XX64 An open question, however, is if the switch between amd64
+ * and i386 modes damages any of them -- we may need to save more
+ * than present below.
+ */
+
+ uint64_t r_kgsbase;
+ uint64_t r_gsbase;
+ uint64_t r_fsbase;
+
+ uint64_t r_cr0;
+ uint64_t r_cr2;
+ uint64_t r_cr3;
+ uint64_t r_cr4;
+ uint64_t r_cr8;
+
+ union {
+ desctbr64_t un_gdt;
+ upad128_t __pad0;
+ } r_gdt_un;
+
+ union {
+ desctbr64_t un_idt;
+ upad128_t __pad0;
+ } r_idt_un;
+
+ uint64_t r_ldt;
+ uint64_t r_tr;
+
+ /*
+ * The rest of this structure is an amd64 'struct regs'
+ *
+ * It is intended to match the 'struct regs' definition
+ * in amd64/sys/privregs.h
+ *
+ * XX64 Need to ensure that it does!
+ */
+
+ int64_t r_rdi;
+ int64_t r_rsi;
+ int64_t r_rdx;
+ int64_t r_rcx;
+ int64_t r_r8;
+ int64_t r_r9;
+ int64_t r_rax;
+ int64_t r_rbx;
+ int64_t r_rbp;
+ int64_t r_r10;
+ int64_t r_r11;
+ int64_t r_r12;
+ int64_t r_r13;
+ int64_t r_r14;
+ int64_t r_r15;
+ int64_t r_gs;
+ int64_t r_fs;
+ int64_t r_ds;
+ int64_t r_es;
+ int64_t r_trapno;
+ int64_t r_err;
+ int64_t r_rip;
+ int64_t r_cs;
+ int64_t r_rfl;
+ int64_t r_rsp;
+ int64_t r_ss;
+};
+
+/*
+ * C-calling convention argument order:
+ *
+ * %rdi, %rsi, %rdx, %rcx, %r8, %r9
+ *
+ * and how to get them out of an amd64_machregs structure:
+ */
+
+#define _ARG1(rp) ((rp)->r_rdi)
+#define _ARG2(rp) ((rp)->r_rsi)
+#define _ARG3(rp) ((rp)->r_rdx)
+#define _ARG4(rp) ((rp)->r_rcx)
+#define _ARG5(rp) ((rp)->r_r8)
+#define _ARG6(rp) ((rp)->r_r9)
+
+#endif /* !_ASM */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AMD64_MACHREGS_H */
diff --git a/usr/src/psm/stand/boot/amd64/amd64/memlist64.h b/usr/src/psm/stand/boot/amd64/amd64/memlist64.h
new file mode 100644
index 0000000000..ce3978e1e8
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/amd64/memlist64.h
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _AMD64_MEMLIST64_H
+#define _AMD64_MEMLIST64_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <amd64/types.h>
+
+struct memlist64 {
+ uint64_t address; /* starting address of memory segment */
+ uint64_t size; /* size of same */
+ caddr64_t next; /* struct memlist64 pointer */
+ caddr64_t prev; /* struct memlist64 pointer */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AMD64_MEMLIST64_H */
diff --git a/usr/src/psm/stand/boot/amd64/amd64/msr.h b/usr/src/psm/stand/boot/amd64/amd64/msr.h
new file mode 100644
index 0000000000..4bbba75b9b
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/amd64/msr.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _AMD64_MSR_H
+#define _AMD64_MSR_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/controlregs.h>
+
+extern void amd64_rdmsr(uint32_t, uint64_t *);
+extern void amd64_wrmsr(uint32_t, const uint64_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AMD64_MSR_H */
diff --git a/usr/src/psm/stand/boot/amd64/amd64/print.h b/usr/src/psm/stand/boot/amd64/amd64/print.h
new file mode 100644
index 0000000000..80b3edff33
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/amd64/print.h
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _AMD64_PRINT_H
+#define _AMD64_PRINT_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/varargs.h>
+
+#undef printf /* unbelievably broken bootsvcs.h */
+
+extern int amd64_vsnprintf(char *, size_t, const char *, va_list)
+ __VPRINTFLIKE(3);
+extern int amd64_vsnprintf64(char *, size_t, const char *, va_list)
+ __VPRINTFLIKE(3);
+extern int amd64_snprintf(char *, size_t, const char *, ...)
+ __PRINTFLIKE(3);
+extern int amd64_snprintf64(char *, size_t, const char *, ...)
+ __PRINTFLIKE(3);
+extern void amd64_vpanic(const char *, va_list)
+ __VPRINTFLIKE(1);
+extern void amd64_panic(const char *, ...)
+ __PRINTFLIKE(1);
+extern void amd64_warning(const char *, ...)
+ __PRINTFLIKE(1);
+extern int amd64_assfail(const char *, const char *, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AMD64_PRINT_H */
diff --git a/usr/src/psm/stand/boot/amd64/amd64/segments.h b/usr/src/psm/stand/boot/amd64/amd64/segments.h
new file mode 100644
index 0000000000..478fc99790
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/amd64/segments.h
@@ -0,0 +1,386 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _AMD64_SEGMENTS_H
+#define _AMD64_SEGMENTS_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Copyright (c) 1989, 1990 William F. Jolitz
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)segments.h 7.1 (Berkeley) 5/9/91
+ * $FreeBSD: src/sys/i386/include/segments.h,v 1.34 2003/09/10 01:07:04
+ * jhb Exp $
+ *
+ * 386 Segmentation Data Structures and definitions
+ * William F. Jolitz (william@ernie.berkeley.edu) 6/20/1989
+ */
+
+/*
+ * Selector register format
+ * CS, DS, ES, FS, GS, SS
+ *
+ * 15 3 2 1 0
+ * +---------------------+---+----+
+ * | SI |TI |RPL |
+ * +---------------------+---+----+
+ *
+ * SI = selector index
+ * TI = table indicator (0 = GDT, 1 = LDT)
+ * RPL = requestor privilege level
+ */
+#define SELTOIDX(s) ((s) >> 3) /* selector to index */
+#define IDXTOSEL(s) ((s) << 3) /* index to selector */
+#define SEL_KPL 0 /* kernel priority level */
+#define SEL_UPL 3 /* user priority level */
+#define SEL_TI_LDT 4 /* local descriptor table */
+#define SEL_LDT(s) (IDXTOSEL(s) | SEL_TI_LDT | SEL_UPL) /* local sel */
+#define SEL_GDT(s, r) (IDXTOSEL(s) | r) /* global sel */
+#define SELISLDT(s) (((s) & SEL_TI_LDT) == SEL_TI_LDT)
+#define CPL_MASK 3 /* RPL mask for selector */
+
+#ifndef _ASM
+
+typedef uint16_t selector_t; /* selector reigster */
+
+/*
+ * Hardware descriptor table register format for GDT and IDT.
+ */
+#pragma pack(2)
+typedef struct descriptor_table_register64 {
+ uint16_t dtr_limit; /* table limit */
+ uint64_t dtr_base; /* table base address */
+} desctbr64_t;
+#pragma pack()
+
+#pragma pack(2)
+typedef struct descriptor_table_register {
+ uint16_t dtr_limit; /* table limit */
+ uint32_t dtr_base; /* table base address */
+} desctbr_t;
+#pragma pack()
+
+
+/*
+ * Functions for loading and storing descriptor table
+ * registers.
+ */
+extern void rd_idtr(desctbr_t *);
+extern void wr_idtr(desctbr_t *);
+extern void rd_gdtr(desctbr_t *);
+extern void wr_gdtr(desctbr_t *);
+extern void wr_ldtr(selector_t);
+extern void wr_tsr(selector_t);
+
+/*
+ * User segment descirptors (code and data).
+ * Legacy mode 64-bits wide.
+ */
+typedef struct user_segment_descriptor {
+ uint32_t usd_lolimit:16; /* segment limit 15:0 */
+ uint32_t usd_lobase:16; /* segment base 15:0 */
+ uint32_t usd_midbase:8; /* segment base 23:16 */
+ uint32_t usd_type:5; /* segment type, includes S bit */
+ uint32_t usd_dpl:2; /* segment descriptor priority level */
+ uint32_t usd_p:1; /* segment descriptor present */
+ uint32_t usd_hilimit:4; /* segment limit 19:16 */
+ uint32_t usd_avl:1; /* available to sw, but not used */
+ uint32_t usd_reserved:1; /* unsued, ignored */
+ uint32_t usd_def32:1; /* default 32 vs 16 bit operand */
+ uint32_t usd_gran:1; /* limit unit (bytes vs pages) */
+ uint32_t usd_hibase:8; /* segment base 31:24 */
+} user_desc_t;
+
+/*
+ * User segment descriptors.
+ * Long mode 64-bits wide.
+ *
+ * In 32-bit compatibility mode (%cs:usd_long=0) all fields are interpreted
+ * as in legacy mode for both code and data.
+ *
+ * In 64-bit mode (%cs:usd_long=1) code segments only have the conforming
+ * bit in usd_type, usd_dpl, usd_p, usd_long and usd_def32=0. usd_def32
+ * must be zero in 64-bit mode. Setting it to 1 is reserved for future use.
+ * All other fields are loaded but ignored by hardware.
+ *
+ * 64-bit data segments only have usd_p. All other fields are loaded but
+ * ignored by hardware when in 64-bit mode.
+ */
+typedef struct user_segment_descriptor64 {
+ uint32_t usd_lolimit:16; /* segment limit 15:0 */
+ uint32_t usd_lobase:16; /* segment base 15:0 */
+ uint32_t usd_midbase:8; /* segment base 23:16 */
+ uint32_t usd_type:5; /* segment type, includes S bit */
+ uint32_t usd_dpl:2; /* segment descriptor priority level */
+ uint32_t usd_p:1; /* segment descriptor present */
+ uint32_t usd_hilimit:4; /* segment limit 19:16 */
+ uint32_t usd_avl:1; /* available to sw, but not used */
+ uint32_t usd_long:1; /* long mode (%cs only) */
+ uint32_t usd_def32:1; /* default 32 vs 16 bit operand */
+ uint32_t usd_gran:1; /* limit gran (byte/page units) */
+ uint32_t usd_hibase:8; /* segment base 31:24 */
+} user_desc64_t;
+
+/*
+ * System segment descriptors for LDT and TSS segments.
+ * Legacy mode 64-bits wide.
+ */
+typedef struct system_segment_descriptor {
+ uint32_t ssd_lolimit:16; /* segment limit 15:0 */
+ uint32_t ssd_lobase:16; /* segment base 15:0 */
+ uint32_t ssd_midbase:8; /* segment base 23:16 */
+ uint32_t ssd_type:4; /* segment type */
+ uint32_t ssd_zero:1; /* must be zero */
+ uint32_t ssd_dpl:2; /* segment descriptor priority level */
+ uint32_t ssd_p:1; /* segment descriptor present */
+ uint32_t ssd_hilimit:4; /* segment limit 19:16 */
+ uint32_t ssd_avl:1; /* available to sw, but not used */
+ uint32_t ssd_reserved:2; /* unused, ignored */
+ uint32_t ssd_gran:1; /* limit unit (bytes vs pages) */
+ uint32_t ssd_hibase:8; /* segment base 31:24 */
+} system_desc_t;
+
+/*
+ * System segment descriptors for LDT and TSS segments.
+ * Long mode 128-bits wide.
+ *
+ * 32-bit LDT and TSS descriptor types are redefined to 64-bit equivalents.
+ * All other legacy types are reserved and illegal.
+ */
+typedef struct system_segment_descriptor64 {
+ uint32_t ssd_lolimit:16; /* segment limit 15:0 */
+ uint32_t ssd_lobase:16; /* segment base 15:0 */
+ uint32_t ssd_midbase:8; /* segment base 23:16 */
+ uint32_t ssd_type:4; /* segment type */
+ uint32_t ssd_zero1:1; /* must be zero */
+ uint32_t ssd_dpl:2; /* segment descriptor priority level */
+ uint32_t ssd_p:1; /* segment descriptor present */
+ uint32_t ssd_hilimit:4; /* segment limit 19:16 */
+ uint32_t ssd_avl:1; /* available to sw, but not used */
+ uint32_t ssd_resv1:2; /* unused, ignored */
+ uint32_t ssd_gran:1; /* limit unit (bytes vs pages) */
+ uint32_t ssd_hibase:8; /* segment base 31:24 */
+ uint32_t ssd_hi64base:32; /* segment base 63:32 */
+ uint32_t ssd_resv2:8; /* unused, ignored */
+ uint32_t ssd_zero2:5; /* must be zero */
+ uint32_t ssd_resv3:19; /* unused, ignored */
+} system_desc64_t;
+
+/*
+ * System gate segment descriptors for interrupt, trap, call and task gates.
+ * Legacy mode 64-bits wide.
+ */
+typedef struct gate_segment_descriptor {
+ uint32_t sgd_looffset:16; /* segment code offset 15:0 */
+ uint32_t sgd_selector:16; /* target code or task selector */
+ uint32_t sgd_stkcpy:5; /* number of stack wds to cpy */
+ uint32_t sgd_resv:3; /* unused, ignored */
+ uint32_t sgd_type:5; /* segment type, includes S bit */
+ uint32_t sgd_dpl:2; /* segment descriptor priority level */
+ uint32_t sgd_p:1; /* segment descriptor present */
+ uint32_t sgd_hioffset:16; /* code seg off 31:16 */
+} gate_desc_t;
+
+/*
+ * System segment descriptors for interrupt, trap and call gates.
+ * Long mode 128-bits wide.
+ *
+ * 32-bit interrupt, trap and call gate types are redefined to 64-bit
+ * equivalents. Task gates along with all other legacy types are reserved
+ * and illegal.
+ */
+typedef struct gate_segment_descriptor64 {
+ uint32_t sgd_looffset:16; /* segment code offset 15:0 */
+ uint32_t sgd_selector:16; /* target code or task selector */
+ uint32_t sgd_ist:3; /* IST table index */
+ uint32_t sgd_resv1:5; /* unused, ignored */
+ uint32_t sgd_type:5; /* segment type, includes S bit */
+ uint32_t sgd_dpl:2; /* segment descriptor priority level */
+ uint32_t sgd_p:1; /* segment descriptor present */
+ uint32_t sgd_hioffset:16; /* segment code offset 31:16 */
+ uint32_t sgd_hi64offset:32; /* segment code offset 63:32 */
+ uint32_t sgd_resv2:8; /* unused, ignored */
+ uint32_t sgd_zero:5; /* call gate only: must be zero */
+ uint32_t sgd_resv3:19; /* unused, ignored */
+} gate_desc64_t;
+
+#undef BYTES
+#define BYTES 0
+
+#undef PAGES
+#define PAGES 1
+
+#undef OP32
+#define OP32 1
+
+#undef LONG
+#define LONG 1
+
+#undef SHORT
+#define SHORT 0
+
+/*
+ * functions for initializing and updating segment descriptors.
+ */
+extern void set_usegd64(user_desc64_t *, uint_t, void *, size_t, uint_t, uint_t,
+ uint_t, uint_t);
+extern void set_gatesegd64(gate_desc64_t *, void (*)(void), selector_t, uint_t,
+ uint_t, uint_t);
+void set_syssegd64(system_desc64_t *, void *, size_t, uint_t, uint_t);
+
+extern void set_usegd(user_desc_t *, void *, size_t, uint_t, uint_t,
+ uint_t, uint_t);
+extern void set_gatesegd(gate_desc_t *, void (*)(void), selector_t,
+ uint_t, uint_t, uint_t);
+void set_syssegd(system_desc_t *, void *, size_t, uint_t, uint_t);
+
+#endif /* _ASM */
+
+/*
+ * System segments and gate types.
+ *
+ * In long mode i386 32-bit ldt, tss, call, interrupt and trap gate
+ * types are redefined into 64-bit equivalents.
+ */
+#define SDT_SYSNULL 0 /* system null */
+#define SDT_SYS286TSS 1 /* system 286 TSS available */
+#define SDT_SYSLDT 2 /* system local descriptor table */
+#define SDT_SYS286BSY 3 /* system 286 TSS busy */
+#define SDT_SYS286CGT 4 /* system 286 call gate */
+#define SDT_SYSTASKGT 5 /* system task gate */
+#define SDT_SYS286IGT 6 /* system 286 interrupt gate */
+#define SDT_SYS286TGT 7 /* system 286 trap gate */
+#define SDT_SYSNULL2 8 /* system null again */
+#define SDT_SYSTSS 9 /* system TSS available */
+#define SDT_SYSNULL3 10 /* system null again */
+#define SDT_SYSTSSBSY 11 /* system TSS busy */
+#define SDT_SYSCGT 12 /* system call gate */
+#define SDT_SYSNULL4 13 /* system null again */
+#define SDT_SYSIGT 14 /* system interrupt gate */
+#define SDT_SYSTGT 15 /* system trap gate */
+
+/*
+ * Memory segment types.
+ *
+ * While in long mode expand-down, writable and accessed type field
+ * attributes are ignored. Only the conforming bit is loaded by hardware
+ * for long mode code segment descriptors.
+ */
+#define SDT_MEMRO 16 /* read only */
+#define SDT_MEMROA 17 /* read only accessed */
+#define SDT_MEMRW 18 /* read write */
+#define SDT_MEMRWA 19 /* read write accessed */
+#define SDT_MEMROD 20 /* read only expand dwn limit */
+#define SDT_MEMRODA 21 /* read only expand dwn limit accessed */
+#define SDT_MEMRWD 22 /* read write expand dwn limit */
+#define SDT_MEMRWDA 23 /* read write expand dwn limit accessed */
+#define SDT_MEME 24 /* execute only */
+#define SDT_MEMEA 25 /* execute only accessed */
+#define SDT_MEMER 26 /* execute read */
+#define SDT_MEMERA 27 /* execute read accessed */
+#define SDT_MEMEC 28 /* execute only conforming */
+#define SDT_MEMEAC 29 /* execute only accessed conforming */
+#define SDT_MEMERC 30 /* execute read conforming */
+#define SDT_MEMERAC 31 /* execute read accessed conforming */
+
+
+/*
+ * Entries in the Interrupt Descriptor Table (IDT)
+ */
+#define IDT_DE 0 /* #DE: Divide Error */
+#define IDT_DB 1 /* #DB: Debug */
+#define IDT_NMI 2 /* Nonmaskable External Interrupt */
+#define IDT_BP 3 /* #BP: Breakpoint */
+#define IDT_OF 4 /* #OF: Overflow */
+#define IDT_BR 5 /* #BR: Bound Range Exceeded */
+#define IDT_UD 6 /* #UD: Undefined/Invalid Opcode */
+#define IDT_NM 7 /* #NM: No Math Coprocessor */
+#define IDT_DF 8 /* #DF: Double Fault */
+#define IDT_FPUGP 9 /* Coprocessor Segment Overrun */
+#define IDT_TS 10 /* #TS: Invalid TSS */
+#define IDT_NP 11 /* #NP: Segment Not Present */
+#define IDT_SS 12 /* #SS: Stack Segment Fault */
+#define IDT_GP 13 /* #GP: General Protection Fault */
+#define IDT_PF 14 /* #PF: Page Fault */
+#define IDT_MF 16 /* #MF: FPU Floating-Point Error */
+#define IDT_AC 17 /* #AC: Alignment Check */
+#define IDT_MC 18 /* #MC: Machine Check */
+#define IDT_XF 19 /* #XF: SIMD Floating-Point Exception */
+#define IDT_SYSCALL 0x80 /* System Call Interrupt Vector */
+#define NIDT 256 /* size in entries of IDT */
+
+/*
+ * Entries in the Global Descriptor Table (GDT) for VMX (stretch)
+ *
+ * We make sure to space the system descriptors (LDT's, TSS')
+ * such that they are double gdt slot aligned. This is because
+ * in long mode system segment decriptors expand to 128 bits.
+ */
+#define GDT_NULL 0 /* null */
+#define GDT_DATA32 1 /* 32-bit data */
+#define GDT_CODE32 2 /* 32-bit code */
+#define GDT_DATA64 3 /* 64-bit data */
+#define GDT_CODE64 4 /* 64-bit code */
+#define GDT_NULL1 5 /* null */
+#define GDT_TSS64 6 /* 64-bit tss */
+#define GDT_NULL2 7 /* null */
+
+#define NGDT 8
+
+#ifndef _ASM
+
+extern void amd64_div0trap(), amd64_dbgtrap(), amd64_nmiint(), amd64_brktrap();
+extern void amd64_ovflotrap(), amd64_boundstrap(), amd64_invoptrap();
+extern void amd64_ndptrap(), amd64_doublefault();
+extern void amd64_invaltrap(), amd64_invtsstrap(), amd64_segnptrap();
+extern void amd64_stktrap(), amd64_gptrap(), amd64_pftrap(), amd64_ndperr();
+extern void amd64_overrun(), amd64_resvtrap(), amd64_achktrap();
+extern void amd64_mcetrap(), amd64_xmtrap();
+
+#endif /* _ASM */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AMD64_SEGMENTS_H */
diff --git a/usr/src/psm/stand/boot/amd64/amd64/tss.h b/usr/src/psm/stand/boot/amd64/amd64/tss.h
new file mode 100644
index 0000000000..1aff429e8d
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/amd64/tss.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
+/* All Rights Reserved */
+
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)tss.h 5.4 (Berkeley) 1/18/91
+ * $FreeBSD: src/sys/i386/include/tss.h,v 1.13 2002/09/23 05:04:05 peter Exp $
+ */
+
+#ifndef _AMD64_TSS_H
+#define _AMD64_TSS_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _ASM
+/*
+ * amd64 long mode TSS definition
+ */
+#pragma pack(2)
+typedef struct amd64tss {
+ uint32_t tss_rsvd0; /* reserved, ignored */
+ uint64_t tss_rsp0; /* stack pointer CPL = 0 */
+ uint64_t tss_rsp1; /* stack pointer CPL = 1 */
+ uint64_t tss_rsp2; /* stack pointer CPL = 2 */
+ uint64_t tss_rsvd1; /* reserved, ignored */
+ uint64_t tss_ist1; /* Interrupt stack table 1 */
+ uint64_t tss_ist2; /* Interrupt stack table 2 */
+ uint64_t tss_ist3; /* Interrupt stack table 3 */
+ uint64_t tss_ist4; /* Interrupt stack table 4 */
+ uint64_t tss_ist5; /* Interrupt stack table 5 */
+ uint64_t tss_ist6; /* Interrupt stack table 6 */
+ uint64_t tss_ist7; /* Interrupt stack table 7 */
+ uint64_t tss_rsvd2; /* reserved, ignored */
+ uint16_t tss_rsvd3; /* reserved, ignored */
+ uint16_t tss_iobase; /* io bitmap offset */
+} amd64tss_t;
+#pragma pack()
+
+/*
+ * Legacy 386 TSS definition
+ */
+typedef struct i386tss {
+ uint32_t tss_link; /* 16-bit prior TSS selector */
+ uint32_t tss_esp0;
+ uint32_t tss_ss0;
+ uint32_t tss_esp1;
+ uint32_t tss_ss1;
+ uint32_t tss_esp2;
+ uint32_t tss_ss2;
+ uint32_t tss_cr3;
+ uint32_t tss_eip;
+ uint32_t tss_eflags;
+ uint32_t tss_eax;
+ uint32_t tss_ecx;
+ uint32_t tss_edx;
+ uint32_t tss_ebx;
+ uint32_t tss_esp;
+ uint32_t tss_ebp;
+ uint32_t tss_esi;
+ uint32_t tss_edi;
+ uint32_t tss_es;
+ uint32_t tss_cs;
+ uint32_t tss_ss;
+ uint32_t tss_ds;
+ uint32_t tss_fs;
+ uint32_t tss_gs;
+ uint32_t tss_ldt;
+ uint32_t tss_bitmapbase;
+} i386tss_t;
+
+#endif /* !_ASM */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AMD64_TSS_H */
diff --git a/usr/src/psm/stand/boot/amd64/amd64/types.h b/usr/src/psm/stand/boot/amd64/amd64/types.h
new file mode 100644
index 0000000000..127effff25
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/amd64/types.h
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _AMD64_TYPES_H
+#define _AMD64_TYPES_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/inttypes.h>
+
+typedef uint64_t caddr64_t;
+typedef uint64_t fnaddr64_t;
+typedef uint64_t size64_t;
+
+#define BITX(u, h, l) (((u) >> (l)) & ((1lu << ((h) - (l) + 1lu)) - 1lu))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AMD64_TYPES_H */
diff --git a/usr/src/psm/stand/boot/amd64/context.c b/usr/src/psm/stand/boot/amd64/context.c
new file mode 100644
index 0000000000..7fb2d61c7f
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/context.c
@@ -0,0 +1,322 @@
+/*
+ * 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.
+ *
+ * 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 2004 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/trap.h>
+#include <sys/controlregs.h>
+#include <sys/sysmacros.h>
+#include <sys/link.h>
+
+#include <amd64/types.h>
+#include <amd64/amd64.h>
+#include <amd64/cpu.h>
+#include <amd64/machregs.h>
+#include <amd64/tss.h>
+#include <amd64/segments.h>
+#include <amd64/debug.h>
+#include <amd64/bootops64.h>
+#include <amd64/bootsvcs64.h>
+#include <amd64/amd64_page.h>
+
+/*
+ * This save area is initialized by amd64_exitto(), and used to
+ * restore the state of the machine before invoking various
+ * bootops.
+ *
+ * However, it needs to be mapped 1:1 so that we can reference it
+ * while paging is disabled. This is achieved via mapfile trickery;
+ * we glom the entire program into one contiguous segment.
+ */
+struct i386_machregs exitto_i386_machregs;
+
+/*CSTYLED*/
+#pragma align 16 (amd64_stack)
+static uint8_t amd64_stack[1024*16];
+
+/*CSTYLED*/
+#pragma align 16 (amd64_dblfault_stack)
+static uint8_t amd64_dblfault_stack[1024*16];
+
+/*CSTYLED*/
+#pragma align 16 (amd64_exception_stack)
+static uint8_t amd64_exception_stack[1024*16];
+
+static const selector_t cs64sel = SEL_GDT(GDT_CODE64, SEL_KPL);
+static const selector_t ds64sel = SEL_GDT(GDT_DATA64, SEL_KPL);
+
+static user_desc64_t gdt64[NGDT]; /* long mode gdt */
+static amd64tss_t tss64; /* long mode tss */
+
+static void
+make_gdt(desctbr64_t *rgdt)
+{
+ /*
+ * TSS
+ */
+ bzero(&tss64, sizeof (tss64));
+
+ /*
+ * All exceptions but #DF will run on the exception stack.
+ */
+ tss64.tss_ist1 = (uint64_t)(uintptr_t)
+ &amd64_exception_stack[sizeof (amd64_exception_stack)];
+
+ /*
+ * #DF (double fault) gets its own private stack.
+ */
+ tss64.tss_ist2 = (uint64_t)(uintptr_t)
+ &amd64_dblfault_stack[sizeof (amd64_dblfault_stack)];
+
+ /*
+ * GDT
+ */
+ bzero(gdt64, sizeof (gdt64));
+
+ /*
+ * 32-bit legacy or compatibility mode for data.
+ * Maps entire 4G address space.
+ */
+ set_usegd64(&gdt64[GDT_DATA32], SHORT, NULL, 0xfffff, SDT_MEMRW,
+ SEL_KPL, PAGES, OP32);
+
+ /*
+ * 32-bit legacy or compatibility mode for code.
+ * Maps entire 4G address space.
+ */
+ set_usegd64(&gdt64[GDT_CODE32], SHORT, NULL, 0xfffff, SDT_MEMERC,
+ SEL_KPL, PAGES, OP32);
+
+ /*
+ * 64-bit long mode for data. XXX don't really need this.
+ * Maps entire 64-bit address space by definition.
+ */
+ set_usegd64(&gdt64[GDT_DATA64], LONG, NULL, 0, SDT_MEMRW,
+ SEL_KPL, PAGES, OP32);
+
+ /*
+ * 64-bit long mode for code.
+ * Maps entire 64-bit address space by definition.
+ */
+ set_usegd64(&gdt64[GDT_CODE64], LONG, NULL, 0, SDT_MEMERC,
+ SEL_KPL, PAGES, OP32);
+
+ /*
+ * 64-bit long mode TSS.
+ */
+ set_syssegd64((system_desc64_t *)&gdt64[GDT_TSS64], &tss64,
+ sizeof (tss64), SDT_SYSTSS, SEL_KPL);
+
+ rgdt->dtr_limit = sizeof (gdt64) - 1;
+ rgdt->dtr_base = (uint64_t)(uintptr_t)gdt64;
+}
+
+static gate_desc64_t idt64[NIDT]; /* long mode idt */
+
+static void
+make_idt(desctbr64_t *ridt)
+{
+ int i;
+
+ /*
+ * IDT
+ *
+ * First initialize all entries to reserve trap then overwrite
+ * the important ones with specific handlers.
+ *
+ * XXX how big does this idt really need to be ? I suspect
+ * only large enough to hold kmdb's soft int?
+ *
+ * XX64 fbsd only uses interrupt gates for all. Perhaps
+ * This is good for amd64 since we want to block maskable
+ * interrupts once we take an exception?
+ */
+ bzero(idt64, sizeof (idt64)); /* FIXME */
+
+ for (i = 0; i < NIDT; i++)
+ set_gatesegd64(&idt64[i], &amd64_resvtrap, cs64sel, 1,
+ SDT_SYSIGT, SEL_KPL);
+
+ set_gatesegd64(&idt64[T_ZERODIV], &amd64_div0trap, cs64sel, 1,
+ SDT_SYSIGT, SEL_KPL);
+ set_gatesegd64(&idt64[T_SGLSTP], &amd64_dbgtrap, cs64sel, 1,
+ SDT_SYSIGT, SEL_KPL);
+ set_gatesegd64(&idt64[T_NMIFLT], &amd64_nmiint, cs64sel, 1,
+ SDT_SYSIGT, SEL_KPL);
+ set_gatesegd64(&idt64[T_BPTFLT], &amd64_brktrap, cs64sel, 1,
+ SDT_SYSIGT, SEL_UPL);
+ set_gatesegd64(&idt64[T_OVFLW], &amd64_ovflotrap, cs64sel, 1,
+ SDT_SYSIGT, SEL_UPL);
+ set_gatesegd64(&idt64[T_BOUNDFLT], &amd64_boundstrap, cs64sel, 1,
+ SDT_SYSIGT, SEL_KPL);
+ set_gatesegd64(&idt64[T_ILLINST], &amd64_invoptrap, cs64sel, 1,
+ SDT_SYSIGT, SEL_KPL);
+ set_gatesegd64(&idt64[T_NOEXTFLT], &amd64_ndptrap, cs64sel, 1,
+ SDT_SYSIGT, SEL_KPL);
+
+ /*
+ * double fault handler gets its own private stack (tss.ist2).
+ */
+ set_gatesegd64(&idt64[T_DBLFLT], &amd64_doublefault, cs64sel, 2,
+ SDT_SYSIGT, SEL_KPL);
+
+ /*
+ * T_EXTOVRFLT coprocessor-segment-overrun not supported.
+ */
+
+ set_gatesegd64(&idt64[T_TSSFLT], &amd64_invtsstrap, cs64sel, 1,
+ SDT_SYSIGT, SEL_KPL);
+ set_gatesegd64(&idt64[T_SEGFLT], &amd64_segnptrap, cs64sel, 1,
+ SDT_SYSIGT, SEL_KPL);
+ set_gatesegd64(&idt64[T_STKFLT], &amd64_stktrap, cs64sel, 1,
+ SDT_SYSIGT, SEL_KPL);
+ set_gatesegd64(&idt64[T_GPFLT], &amd64_gptrap, cs64sel, 1,
+ SDT_SYSIGT, SEL_KPL);
+ set_gatesegd64(&idt64[T_PGFLT], &amd64_pftrap, cs64sel, 1,
+ SDT_SYSIGT, SEL_KPL);
+
+ /*
+ * 15 reserved.
+ */
+ set_gatesegd64(&idt64[15], &amd64_resvtrap, cs64sel, 1,
+ SDT_SYSIGT, SEL_KPL);
+
+ set_gatesegd64(&idt64[T_EXTERRFLT], &amd64_ndperr, cs64sel, 1,
+ SDT_SYSIGT, SEL_KPL);
+ set_gatesegd64(&idt64[T_ALIGNMENT], &amd64_achktrap, cs64sel, 1,
+ SDT_SYSIGT, SEL_KPL);
+ set_gatesegd64(&idt64[T_MCE], &amd64_mcetrap, cs64sel, 1,
+ SDT_SYSIGT, SEL_KPL);
+ set_gatesegd64(&idt64[T_SIMDFPE], &amd64_xmtrap, cs64sel, 1,
+ SDT_SYSIGT, SEL_KPL);
+
+ /*
+ * 20-31 reserved
+ */
+ for (i = 20; i < 32; i++)
+ set_gatesegd64(&idt64[i], &amd64_invaltrap, cs64sel, 1,
+ SDT_SYSIGT, SEL_KPL);
+
+ /*
+ * XX64 -- why not resvtrap in initial programming??
+ * either way, move this to the top so that the defaults
+ * are set together.
+ */
+ ridt->dtr_limit = sizeof (idt64) - 1;
+ ridt->dtr_base = (uint64_t)(uintptr_t)idt64;
+}
+
+/*
+ * Note that when rsp is being pushed, like the processor, we must
+ * ensure that the value of the stack pointer at the beginning of the
+ * instruction is the one that is pushed, NOT the value after.
+ */
+#define PUSHQ(rsp, value) \
+ rsp[-1] = ((uint64_t)(value)); rsp--
+
+#define SUBQ(rsp, value) \
+ rsp -= ((value) / sizeof (*rsp))
+
+struct amd64_machregs *
+amd64_makectx64(uint64_t entry)
+{
+ extern struct bootops *bop;
+ extern struct boot_syscalls *sysp;
+ extern Elf64_Boot *elfbootvecELF64;
+
+ struct boot_syscalls64 *sysp64;
+ struct bootops64 *bop64;
+ uint64_t *rsp;
+
+ bzero(amd64_stack, sizeof (amd64_stack));
+
+ rsp = (void *)&amd64_stack[sizeof (amd64_stack)];
+
+ PUSHQ(rsp, entry);
+
+ /*
+ * terminate stack walks with a null RBP value.
+ */
+ PUSHQ(rsp, 0);
+
+ /*
+ * push in amd64_machregs order.
+ */
+ PUSHQ(rsp, ds64sel); /* ss */
+ PUSHQ(rsp, (uintptr_t)rsp); /* rsp */
+ PUSHQ(rsp, amd64_get_eflags()); /* rfl */
+ PUSHQ(rsp, cs64sel); /* cs */
+ PUSHQ(rsp, 0); /* %rip - because we didn't go thru a stub */
+ PUSHQ(rsp, 0); /* err */
+ PUSHQ(rsp, 0); /* trapno */
+ PUSHQ(rsp, ds64sel); /* es */
+ PUSHQ(rsp, ds64sel); /* ds */
+ PUSHQ(rsp, 0); /* fs */
+ PUSHQ(rsp, 0); /* gs */
+
+ SUBQ(rsp, 11 * 8); /* r8 thru r15 are zero */
+
+ bop64 = init_bootops64(bop);
+ sysp64 = init_boot_syscalls64(sysp);
+
+ PUSHQ(rsp, (uintptr_t)elfbootvecELF64); /* rcx */
+ PUSHQ(rsp, (uintptr_t)bop64); /* rdx */
+ PUSHQ(rsp, 0); /* rsi - null dvec */
+ PUSHQ(rsp, (uintptr_t)sysp64); /* rdi */
+
+ PUSHQ(rsp, SEL_GDT(GDT_TSS64, SEL_KPL)); /* tr */
+
+ SUBQ(rsp, 1 * 8); /* null ldt */
+
+ PUSHQ(rsp, 0); /* idt */
+ PUSHQ(rsp, 0);
+ make_idt((desctbr64_t *)rsp);
+
+ PUSHQ(rsp, 0); /* gdt */
+ PUSHQ(rsp, 0);
+ make_gdt((desctbr64_t *)rsp);
+
+ PUSHQ(rsp, 0); /* cr8 */
+
+ /*
+ * XX64: Note that boot enables CR4_PGE (global pages)
+ * and Joe has discovered errata that warns against
+ * mixing this. Need to investigate.
+ */
+ PUSHQ(rsp, CR4_PGE | CR4_PAE | amd64_get_cr4()); /* cr4 */
+ PUSHQ(rsp, amd64_init_longpt(amd64_get_cr3())); /* cr3 */
+ PUSHQ(rsp, amd64_get_cr2()); /* cr2 */
+
+ /*
+ * XX64 - CR0_PG already set?
+ */
+ PUSHQ(rsp, CR0_PG | amd64_get_cr0()); /* cr0 */
+
+ SUBQ(rsp, 3 * 8); /* kgsbase, gsbase, fsbase */
+
+ return ((struct amd64_machregs *)rsp);
+}
diff --git a/usr/src/psm/stand/boot/amd64/cpu.c b/usr/src/psm/stand/boot/amd64/cpu.c
new file mode 100644
index 0000000000..61cbc19942
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/cpu.c
@@ -0,0 +1,307 @@
+/*
+ * 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.
+ *
+ * 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 2005 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/psw.h>
+
+#include <amd64/print.h>
+#include <amd64/debug.h>
+#include <amd64/cpu.h>
+#include <amd64/amd64.h>
+#include <amd64/msr.h>
+#include "../i386/common/biosint.h"
+
+#ifdef DEBUG
+static void
+amd64_dump_cpuid(uint32_t eaxmin, uint32_t eaxmax)
+{
+ uint32_t eax;
+ struct amd64_cpuid_regs __vcr, *vcr = &__vcr;
+
+ printf("\t%8s | %8s %8s %8s %8s\n",
+ "eax in", "eax", "ebx", "ecx", "edx");
+ for (eax = eaxmin; eax <= eaxmax; eax++) {
+ amd64_cpuid_insn(eax, vcr);
+ printf("\t%8x | %8x %8x %8x %8x\n", eax,
+ vcr->r_eax, vcr->r_ebx, vcr->r_ecx, vcr->r_edx);
+ }
+}
+
+#define cmprintf printf
+
+#else /* !DEBUG */
+
+#ifdef lint
+#define cmprintf printf
+#else
+#define cmprintf
+#endif /* lint */
+
+#endif /* DEBUG */
+
+static int detect_target_operating_mode();
+
+int is_amd64;
+
+/*ARGSUSED*/
+int
+amd64_config_cpu(void)
+{
+ struct amd64_cpuid_regs __vcr, *vcr = &__vcr;
+ uint32_t maxeax;
+ uint32_t max_maxeax = 0x100;
+ char vendor[13];
+ int isamd64 = 0;
+ uint32_t stdfeatures = 0, xtdfeatures = 0;
+ uint64_t efer;
+
+ /*
+ * This check may seem silly, but if the C preprocesor symbol __amd64
+ * is #defined during compilation, something that may outwardly seem
+ * like a good idea, uts/common/sys/isa_defs.h will #define _LP64,
+ * which will cause uts/common/sys/int_types.h to typedef uint64_t as
+ * an unsigned long - which is only 4 bytes in size when using a 32-bit
+ * compiler.
+ *
+ * If that happens, all the page table translation routines will fail
+ * horribly, so check the size of uint64_t just to insure some degree
+ * of sanity in future operations.
+ */
+ /*LINTED [sizeof result is invarient]*/
+ if (sizeof (uint64_t) != 8)
+ prom_panic("multiboot compiled improperly, unable to boot "
+ "64-bit AMD64 executables");
+
+ /*
+ * If the CPU doesn't support the CPUID instruction, it's definitely
+ * not an AMD64.
+ */
+ if (amd64_cpuid_supported() == 0)
+ return (0);
+
+ amd64_cpuid_insn(0, vcr);
+
+ maxeax = vcr->r_eax;
+ {
+ /*LINTED [vendor string from cpuid data]*/
+ uint32_t *iptr = (uint32_t *)vendor;
+
+ *iptr++ = vcr->r_ebx;
+ *iptr++ = vcr->r_edx;
+ *iptr++ = vcr->r_ecx;
+
+ vendor[12] = '\0';
+ }
+
+ if (maxeax > max_maxeax) {
+ cmprintf("cpu: warning, maxeax was 0x%x -> 0x%x\n",
+ maxeax, max_maxeax);
+ maxeax = max_maxeax;
+ }
+
+ if (maxeax < 1)
+ return (0); /* no additional functions, not an AMD64 */
+ else {
+ uint_t family, model, step;
+
+ amd64_cpuid_insn(1, vcr);
+
+ /*
+ * All AMD64/IA32e processors technically SHOULD report
+ * themselves as being in family 0xf, but for some reason
+ * Simics doesn't, and this may change in the future, so
+ * don't error out if it's not true.
+ */
+ if ((family = BITX(vcr->r_eax, 11, 8)) == 0xf)
+ family += BITX(vcr->r_eax, 27, 20);
+
+ if ((model = BITX(vcr->r_eax, 7, 4)) == 0xf)
+ model += BITX(vcr->r_eax, 19, 16) << 4;
+ step = BITX(vcr->r_eax, 3, 0);
+
+ cmprintf("cpu: '%s' family %d model %d step %d\n",
+ vendor, family, model, step);
+ stdfeatures = vcr->r_edx;
+ }
+
+#ifdef DEBUG
+ if (amd64_debug) {
+ cmprintf("cpu: standard cpuid data:\n");
+ amd64_dump_cpuid(0, maxeax);
+ }
+#endif /* DEBUG */
+
+ amd64_cpuid_insn(0x80000000, vcr);
+
+ if (vcr->r_eax & 0x80000000) {
+ uint32_t xmaxeax = vcr->r_eax;
+ const uint32_t max_xmaxeax = 0x80000100;
+
+ if (xmaxeax > max_xmaxeax) {
+ cmprintf("amd64: warning, xmaxeax was 0x%x -> 0x%x\n",
+ xmaxeax, max_xmaxeax);
+ xmaxeax = max_xmaxeax;
+ }
+
+#ifdef DEBUG
+ if (amd64_debug) {
+ cmprintf("amd64: extended cpuid data:\n");
+ amd64_dump_cpuid(0x80000000, xmaxeax);
+ }
+#endif /* DEBUG */
+
+ if (xmaxeax >= 0x80000001) {
+ amd64_cpuid_insn(0x80000001, vcr);
+ xtdfeatures = vcr->r_edx;
+ }
+ }
+
+ if (BITX(xtdfeatures, 29, 29)) /* long mode */
+ isamd64++;
+ else
+ cmprintf("amd64: CPU does NOT support long mode\n");
+
+ if (!BITX(stdfeatures, 0, 0)) {
+ cmprintf("amd64: CPU does NOT support FPU\n");
+ isamd64--;
+ }
+
+ if (!BITX(stdfeatures, 3, 3)) {
+ cmprintf("amd64: CPU does NOT support PSE\n");
+ isamd64--;
+ }
+
+ if (!BITX(stdfeatures, 4, 4)) {
+ cmprintf("amd64: CPU does NOT support TSC\n");
+ isamd64--;
+ }
+
+ if (!BITX(stdfeatures, 5, 5)) {
+ cmprintf("amd64: CPU does NOT support MSRs\n");
+ isamd64--;
+ }
+
+ if (!BITX(stdfeatures, 6, 6)) {
+ cmprintf("amd64: CPU does NOT support PAE\n");
+ isamd64--;
+ }
+
+ if (!BITX(stdfeatures, 8, 8)) {
+ cmprintf("amd64: CPU does NOT support CX8\n");
+ isamd64--;
+ }
+
+ if (!BITX(stdfeatures, 13, 13)) {
+ cmprintf("amd64: CPU does NOT support PGE\n");
+ isamd64--;
+ }
+
+ if (!BITX(stdfeatures, 17, 17)) {
+ cmprintf("amd64: CPU does NOT support PSE\n");
+ isamd64--;
+ }
+
+ if (!BITX(stdfeatures, 19, 19)) {
+ cmprintf("amd64: CPU does NOT support CLFSH\n");
+ isamd64--;
+ }
+
+ if (!BITX(stdfeatures, 23, 23)) {
+ cmprintf("amd64: CPU does NOT support MMX\n");
+ isamd64--;
+ }
+
+ if (!BITX(stdfeatures, 24, 24)) {
+ cmprintf("amd64: CPU does NOT support FXSR\n");
+ isamd64--;
+ }
+
+ if (!BITX(stdfeatures, 25, 25)) {
+ cmprintf("amd64: CPU does NOT support SSE\n");
+ isamd64--;
+ }
+
+ if (!BITX(stdfeatures, 26, 26)) {
+ cmprintf("amd64: CPU does NOT support SSE2\n");
+ isamd64--;
+ }
+
+ if (isamd64 < 1) {
+ cmprintf("amd64: CPU does not support amd64 executables.\n");
+ return (0);
+ }
+
+ amd64_rdmsr(MSR_AMD_EFER, &efer);
+ if (efer & AMD_EFER_SCE)
+ cmprintf("amd64: EFER_SCE (syscall/sysret) already enabled\n");
+ if (efer & AMD_EFER_NXE)
+ cmprintf("amd64: EFER_NXE (no-exec prot) already enabled\n");
+ if (efer & AMD_EFER_LME)
+ cmprintf("amd64: EFER_LME (long mode) already enabled\n");
+
+ return (detect_target_operating_mode());
+}
+
+/*
+ * Issue 'Detect Target Operating Mode' callback to the BIOS
+ */
+static int
+detect_target_operating_mode()
+{
+ struct int_pb ic = {0};
+ int ret, ah;
+
+ ic.ax = 0xec00; /* Detect Target Operating Mode */
+ ic.bx = 0x03; /* mixed mode target */
+
+ ret = bios_doint(0x15, &ic);
+
+ ah = ic.ax >> 8;
+ if (ah == 0x86 && (ret & PS_C) != 0) {
+ dprintf("[BIOS 'Detect Target Operating Mode' "
+ "callback unsupported on this platform]\n");
+ return (1); /* unsupported, ignore */
+ }
+
+ if (ah == 0x0 && (ret & PS_C) == 0) {
+ dprintf("[BIOS accepted mixed-mode target setting!]\n");
+ return (1); /* told the bios what we're up to */
+ }
+
+ if (ah == 0 && ret & PS_C) {
+ printf("fatal: BIOS reports this machine CANNOT run in mixed "
+ "32/64-bit mode!\n");
+ return (0);
+ }
+
+ dprintf("warning: BIOS Detect Target Operating Mode callback "
+ "confused.\n %%ax = 0x%x, carry = %d\n", ic.ax,
+ ret & PS_C ? 1 : 0);
+
+ return (1);
+}
diff --git a/usr/src/psm/stand/boot/amd64/exception.s b/usr/src/psm/stand/boot/amd64/exception.s
new file mode 100644
index 0000000000..0d696a6120
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/exception.s
@@ -0,0 +1,268 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1990, 1991 UNIX System Laboratories, Inc.
+ * Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T
+ * All Rights Reserved
+ */
+#if defined(__lint)
+
+#include <sys/link.h>
+
+#include <amd64/amd64.h>
+
+#endif /* __lint */
+
+#include <sys/asm_linkage.h>
+#include <sys/controlregs.h>
+#include <sys/trap.h>
+
+#include <amd64/machregs.h>
+
+#include <assym.h>
+
+#ifdef lint
+void
+amd64_div0trap(void)
+{}
+
+void
+amd64_dbgtrap(void)
+{}
+
+void
+amd64_nmiint(void)
+{}
+
+void
+amd64_brktrap(void)
+{}
+
+void
+amd64_ovflotrap(void)
+{}
+
+void
+amd64_boundstrap(void)
+{}
+
+void
+amd64_invoptrap(void)
+{}
+
+void
+amd64_ndptrap(void)
+{}
+
+void
+amd64_doublefault(void)
+{}
+
+void
+amd64_overrun(void)
+{}
+
+void
+amd64_invtsstrap(void)
+{}
+
+void
+amd64_segnptrap(void)
+{}
+
+void
+amd64_stktrap(void)
+{}
+
+void
+amd64_gptrap(void)
+{}
+
+void
+amd64_pftrap(void)
+{}
+
+void
+amd64_resvtrap(void)
+{}
+
+void
+amd64_ndperr(void)
+{}
+
+void
+amd64_achktrap(void)
+{}
+
+void
+amd64_mcetrap(void)
+{}
+
+void
+amd64_xmtrap(void)
+{}
+
+void
+amd64_invaltrap(void)
+{}
+
+#else
+
+/*
+ * never returns.
+ */
+#define TRAP(trapno) \
+ push $trapno; \
+ jmp __amd64_exception;
+
+ .text
+ .code64
+
+ ENTRY_NP(amd64_div0trap)
+ push $0
+ TRAP(T_ZERODIV) / $0
+ hlt
+ SET_SIZE(amd64_div0trap)
+
+ ENTRY_NP(amd64_dbgtrap)
+ push $0
+ TRAP(T_SGLSTP) / $1
+ hlt
+ SET_SIZE(amd64_dbgtrap)
+
+ ENTRY_NP(amd64_nmiint)
+ push $0
+ TRAP(T_NMIFLT) / $2
+ hlt
+ SET_SIZE(amd64_nmiint)
+
+ ENTRY_NP(amd64_brktrap)
+ push $0
+ TRAP(T_BPTFLT) / $3
+ hlt
+ SET_SIZE(amd64_brktrap)
+
+ ENTRY_NP(amd64_ovflotrap)
+ push $0
+ TRAP(T_OVFLW) / $4
+ hlt
+ SET_SIZE(amd64_ovflotrap)
+
+ ENTRY_NP(amd64_boundstrap)
+ push $0
+ TRAP(T_BOUNDFLT) / $5
+ hlt
+ SET_SIZE(amd64_boundstrap)
+
+ ENTRY_NP(amd64_invoptrap)
+ push $0
+ TRAP(T_ILLINST) / $6
+ hlt
+ SET_SIZE(amd64_invoptrap)
+
+ ENTRY_NP(amd64_ndptrap)
+ push $0
+ TRAP(T_NOEXTFLT) / $7
+ hlt
+ SET_SIZE(amd64_ndptrap)
+
+ ENTRY_NP(amd64_doublefault)
+ push $0
+ TRAP(T_DBLFLT) / $8
+ hlt
+ SET_SIZE(amd64_doublefault)
+
+ ENTRY_NP(amd64_overrun)
+ push $0
+ TRAP(T_EXTOVRFLT) / $9 i386 only - not generated
+ hlt
+ SET_SIZE(amd64_overrun)
+
+ ENTRY_NP(amd64_invtsstrap)
+ TRAP(T_TSSFLT) / $10 already have error code on stack
+ hlt
+ SET_SIZE(amd64_invtsstrap)
+
+ ENTRY_NP(amd64_segnptrap)
+ TRAP(T_SEGFLT) / $11 already have error code on stack
+ hlt
+ SET_SIZE(amd64_segnptrap)
+
+ ENTRY_NP(amd64_stktrap)
+ TRAP(T_STKFLT) / $12 already have error code on stack
+ hlt
+ SET_SIZE(amd64_stktrap)
+
+ ENTRY_NP(amd64_gptrap)
+ TRAP(T_GPFLT) / $13 already have error code on stack
+ hlt
+ SET_SIZE(amd64_gptrap)
+
+ ENTRY_NP(amd64_pftrap)
+ TRAP(T_PGFLT) / $14 already have error code on stack
+ hlt
+ SET_SIZE(amd64_pftrap)
+
+ ENTRY_NP(amd64_resvtrap)
+ TRAP(15) / (reserved)
+ hlt
+ SET_SIZE(amd64_resvtrap)
+
+ ENTRY_NP(amd64_ndperr)
+ push $0
+ TRAP(T_EXTERRFLT) / $16
+ hlt
+ SET_SIZE(amd64_ndperr)
+
+ ENTRY_NP(amd64_achktrap)
+ TRAP(T_ALIGNMENT) / $17 zero already on stack
+ hlt
+ SET_SIZE(amd64_achktrap)
+
+ ENTRY_NP(amd64_mcetrap)
+ push $0
+ TRAP(T_MCE) / $18
+ hlt
+ SET_SIZE(amd64_mcetrap)
+
+ ENTRY_NP(amd64_xmtrap)
+ push $0
+ TRAP(T_SIMDFPE) / $19
+ hlt
+ SET_SIZE(amd64_xmtrap)
+
+ /*
+ * XX64 if amd64 had sprintf we could do better.
+ */
+ ENTRY_NP(amd64_invaltrap)
+ push $0
+ TRAP(-1) / invalid trap
+ hlt
+ SET_SIZE(amd64_invaltrap)
+#endif /* !__lint */
diff --git a/usr/src/psm/stand/boot/amd64/genassym.c b/usr/src/psm/stand/boot/amd64/genassym.c
new file mode 100644
index 0000000000..cba7592a16
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/genassym.c
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <stdio.h>
+#include "amd64/segments.h"
+
+int
+main(void)
+{
+ (void) printf("#define\tKCS64SEL\t0x%x\n",
+ SEL_GDT(GDT_CODE64, SEL_KPL));
+ (void) printf("#define\tKDS64SEL\t0x%x\n",
+ SEL_GDT(GDT_DATA64, SEL_KPL));
+ (void) printf("#define\tKCS32SEL\t0x%x\n",
+ SEL_GDT(GDT_CODE32, SEL_KPL));
+ (void) printf("#define\tKDS32SEL\t0x%x\n",
+ SEL_GDT(GDT_DATA32, SEL_KPL));
+ (void) printf("#define\tTSS64SEL\t0x%x\n",
+ SEL_GDT(GDT_TSS64, SEL_KPL));
+ return (0);
+}
diff --git a/usr/src/psm/stand/boot/amd64/handoff.c b/usr/src/psm/stand/boot/amd64/handoff.c
new file mode 100644
index 0000000000..dafc7ad751
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/handoff.c
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <amd64/amd64.h>
+#include <amd64/print.h>
+#include <amd64/amd64_page.h>
+#include <amd64/cpu.h>
+#include <amd64/debug.h>
+#include <amd64/alloc.h>
+#include <amd64/msr.h>
+#include <amd64/auxv64.h>
+
+#ifdef DEBUG
+int amd64_debug = 1;
+#else
+int amd64_debug = 0;
+#endif
+
+/*ARGSUSED*/
+void
+amd64_handoff(uint64_t entry)
+{
+ uint64_t va, pa;
+ void *rp;
+
+ va = UINT64_FROMPTR32(amd64_handoff);
+ pa = amd64_legacy_lookup_physaddr(va, amd64_get_cr3());
+
+ if (va != pa)
+ amd64_panic("amd64 booter text not identity mapped (va 0x%llx "
+ "!= pa 0x%llx)\nCannot continue boot.\n", va, pa);
+
+ rp = amd64_makectx64(entry);
+#if defined(DEBUG)
+ amd64_dump_amd64_machregs(rp);
+#endif
+
+ /*
+ * XX64: Any other post-ELF load, pre-exitto() initialization required
+ * for AMD64 goes here.
+ */
+
+ amd64_exitto(rp);
+ /*NOTREACHED*/
+}
+
+/*
+ * The kernel is linked against a module whose
+ * name includes $MMU, thus krtld requires that
+ * boot supplies an mmu module list.
+ *
+ * For now, there's only one kind of mmu module for
+ * 64-bit systems
+ *
+ * XX64 So do we need this -- could we just link
+ * the kernel explicitly with mmu64? Are there
+ * any interesting MMU reworks in the future that
+ * might make this modularity more useful?
+ */
+
+/*ARGSUSED*/
+const char *
+amd64_getmmulist(void)
+{
+ return ("mmu64");
+}
diff --git a/usr/src/psm/stand/boot/amd64/i386_subr.s b/usr/src/psm/stand/boot/amd64/i386_subr.s
new file mode 100644
index 0000000000..b5f7c4fd79
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/i386_subr.s
@@ -0,0 +1,224 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/asm_linkage.h>
+
+#if defined(__lint)
+#include <amd64/amd64.h>
+#include <amd64/cpu.h>
+#else
+#include <assym.h>
+#endif
+
+#if defined(__lint)
+
+void
+amd64_system_reset(void)
+{}
+
+void
+amd64_flush_tlb(void)
+{}
+
+/*ARGSUSED*/
+void
+amd64_flush_tlbentry(char *addr)
+{}
+
+#else
+
+ ENTRY_NP(amd64_system_reset)
+ movw $0x64, %dx
+ movb $0xfe, %al
+ outb (%dx)
+ hlt
+ SET_SIZE(amd64_system_reset);
+
+ /*
+ * Note: does NOT flush global entries if PGE enabled...
+ */
+ ENTRY_NP(amd64_flush_tlb)
+ movl %cr3, %eax
+ movl %eax, %cr3
+ ret
+ SET_SIZE(amd64_flush_tlb)
+
+ ENTRY_NP(amd64_flush_tlbentry)
+ movl 4(%esp), %eax
+ invlpg (%eax)
+ ret
+ SET_SIZE(amd64_flush_tlbentry)
+#endif
+
+#if defined(__lint)
+
+ulong_t
+amd64_get_cr0(void)
+{ return (0ul); }
+
+ulong_t
+amd64_get_cr2(void)
+{ return (0ul); }
+
+ulong_t
+amd64_get_cr3(void)
+{ return (0ul); }
+
+ulong_t
+amd64_get_cr4(void)
+{ return (0ul); }
+
+#else
+
+ ENTRY(amd64_get_cr0)
+ movl %cr0, %eax
+ ret
+ SET_SIZE(amd64_get_cr0)
+
+ ENTRY(amd64_get_cr2)
+ movl %cr2, %eax
+ ret
+ SET_SIZE(amd64_get_cr2)
+
+ ENTRY(amd64_get_cr3)
+ movl %cr3, %eax
+ ret
+ SET_SIZE(amd64_get_cr3)
+
+ ENTRY(amd64_get_cr4)
+ movl %cr4, %eax
+ ret
+ SET_SIZE(amd64_get_cr4)
+
+#endif
+
+#if defined(__lint)
+
+/*ARGSUSED*/
+void
+amd64_rdmsr(uint32_t msr, uint64_t *data)
+{}
+
+/*ARGSUSED*/
+void
+amd64_wrmsr(uint32_t msr, const uint64_t *data)
+{}
+
+#else
+
+ ENTRY(amd64_rdmsr)
+ movl 4(%esp), %ecx
+ rdmsr
+ movl 8(%esp), %ecx
+ movl %eax, (%ecx)
+ movl %edx, 4(%ecx)
+ ret
+ SET_SIZE(amd64_rdmsr)
+
+ ENTRY(amd64_wrmsr)
+ movl 8(%esp), %ecx
+ movl (%ecx), %eax
+ movl 4(%ecx), %edx
+ movl 4(%esp), %ecx
+ wrmsr
+ ret
+ SET_SIZE(amd64_wrmsr)
+
+#endif /* __lint */
+
+#if defined(__lint)
+
+ulong_t
+amd64_get_eflags(void)
+{ return (0); }
+
+#else /* __lint */
+
+ ENTRY(amd64_get_eflags)
+ pushfl
+ pop %eax
+ ret
+ SET_SIZE(amd64_get_eflags)
+
+#endif /* __lint */
+
+#if defined(__lint)
+
+/*ARGSUSED*/
+void
+amd64_cpuid_insn(uint32_t eax, struct amd64_cpuid_regs *vcr)
+{}
+
+#else /* __lint */
+
+ ENTRY(amd64_cpuid_insn)
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %ebx
+ pushl %esi
+ movl 0x8(%ebp), %eax
+ movl 0xc(%ebp), %esi
+ cpuid
+ movl %eax, AMD64_CPUID_REG_EAX(%esi)
+ movl %ebx, AMD64_CPUID_REG_EBX(%esi)
+ movl %ecx, AMD64_CPUID_REG_ECX(%esi)
+ movl %edx, AMD64_CPUID_REG_EDX(%esi)
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+ SET_SIZE(amd64_cpuid_insn)
+
+#endif /* __lint */
+
+#if defined(__lint)
+
+unsigned
+amd64_cpuid_supported(void) { return (1); }
+
+#else
+ /*
+ * Based on code from AMD64 Volume 3
+ */
+ ENTRY(amd64_cpuid_supported)
+ pushf
+ popl %eax
+ mov %eax, %edx /* save %eax for later */
+ xorl %eax, 0x200000 /* toggle bit 21 */
+ pushl %eax
+ popf /* save new %eax to EFLAGS */
+ pushf /* save new EFLAGS */
+ popl %ecx /* copy EFLAGS to %eax */
+ xorl %eax, %eax
+ cmpl %ecx, %edx /* see if bit 21 has changes */
+ jne 1f
+ incl %eax
+1:
+ ret
+ SET_SIZE(amd64_cpuid_supported)
+#endif /* __lint */
diff --git a/usr/src/psm/stand/boot/amd64/locore.s b/usr/src/psm/stand/boot/amd64/locore.s
new file mode 100644
index 0000000000..a127e02f05
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/locore.s
@@ -0,0 +1,577 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined(__lint)
+
+#include <sys/link.h>
+
+#include <amd64/amd64.h>
+
+#endif /* __lint */
+
+#include <sys/asm_linkage.h>
+#include <sys/controlregs.h>
+
+#include <amd64/machregs.h>
+
+#include <assym.h>
+
+#if defined(__lint)
+
+/*ARGSUSED*/
+void
+amd64_exitto(struct amd64_machregs *rp)
+{}
+
+#else /* __lint */
+
+ .data
+ .globl need_init_cr8
+need_init_cr8:
+ .long 1
+
+ ENTRY_NP(amd64_exitto)
+ pushl %ebp
+ movl %esp, %ebp
+ /*
+ * stash current i386 state in i386_machregs
+ */
+ lea exitto_i386_machregs, %eax
+ movw %ss, %dx
+ movzx %dx, %edx
+ mov %edx, i386_REG_SS(%eax)
+ pushfl
+ pop %edx
+ mov %edx, i386_REG_EFL(%eax)
+ movw %cs, %dx
+ movzx %dx, %edx
+ mov %edx, i386_REG_CS(%eax)
+ mov %ebx, i386_REG_EBX(%eax)
+ mov %esp, i386_REG_ESP(%eax)
+ mov %ebp, i386_REG_EBP(%eax)
+ mov %esi, i386_REG_ESI(%eax)
+ mov %edi, i386_REG_EDI(%eax)
+ movw %ds, %dx
+ movzx %dx, %edx
+ mov %edx, i386_REG_DS(%eax)
+ movw %es, %dx
+ movzx %dx, %edx
+ mov %edx, i386_REG_ES(%eax)
+ movw %fs, %dx
+ movzx %dx, %edx
+ mov %edx, i386_REG_FS(%eax)
+ movw %gs, %dx
+ movzx %dx, %edx
+ mov %edx, i386_REG_GS(%eax)
+ str i386_REG_TR(%eax)
+ sldt i386_REG_LDT(%eax)
+ sidt i386_REG_IDT(%eax)
+ sgdt i386_REG_GDT(%eax)
+ mov %cr4, %edx
+ mov %edx, i386_REG_CR4(%eax)
+ mov %cr3, %edx
+ mov %edx, i386_REG_CR3(%eax)
+ mov %cr2, %edx
+ mov %edx, i386_REG_CR2(%eax)
+ mov %cr0, %edx
+ mov %edx, i386_REG_CR0(%eax)
+ movl $1, need_init_cr8 /* set flag to cause %cr8 init */
+#ifdef DEBUG
+ push %eax
+ call amd64_dump_i386_machregs
+ addl $4, %esp
+#endif /* DEBUG */
+ /*
+ * Fetch the argument, and switch to it as a stack;
+ * the new stack contains an amd64_machregs on it,
+ * just sitting there waiting for us to restore it.
+ */
+ mov 8(%ebp), %esp
+ jmp __return_to_long_mode
+ /*NOTREACHED*/
+ SET_SIZE(amd64_exitto)
+
+#endif /* __lint */
+
+#if defined(__lint)
+
+#define VTRAP_STUB_BEGIN(opname) \
+ uintptr_t opname;
+
+#define VTRAP_STUB_END(opname) \
+ uintptr_t opname;
+
+#define VTRAP_STUB(symname) \
+ uintptr_t symname;
+
+#else
+
+#define VTRAP_STUB_BEGIN(symname) \
+ .global symname; \
+symname: \
+ .code64
+
+#define VTRAP_STUB_END(symname) \
+ .code32; \
+ .global symname; \
+symname:
+
+/*
+ * callbacks from the amd64 kernel to the i386 world are handled
+ * as calls into a virtual amd64 boot program as if they were
+ * virtual traps i.e. we save the machine state, switch to i386 mode,
+ * then decode and interpret the request in C code (amd64_vtrap)
+ */
+
+#define VTRAP_STUB(opname) \
+ ENTRY_NP(opname); \
+ pushq %rbp; \
+ movq %rsp, %rbp; \
+ call 1f; \
+1: pop %r11; \
+ sub $_CONST(1b - opname), %r11; \
+ jmp __vtrap_common; \
+ SET_SIZE(opname)
+
+ ENTRY_NP(__vtrap_common)
+ .code64
+ /*
+ * put the state of the amd64 machine onto the stack
+ */
+ movq %rsp, %r10
+ addq $0x10, %r10 /* (%rsp immediately before the call) */
+ push $0 /* %ss */
+ push %r10 /* %rsp */
+ pushf /* rflags */
+ push $0 /* %cs */
+ push %r11 /* %rip (the pc we came in on) */
+ push $0 /* err */
+ push $-1 /* trapno (virt trap# larger than idt itself) */
+ cli
+
+ ALTENTRY(__amd64_exception) /* vectored from amd64_idt */
+ push $0 /* %es */
+ push $0 /* %ds */
+ push %fs
+ push %gs
+ push %r15
+ push %r14
+ push %r13
+ push %r12
+ push %r11
+ push %r10
+ push %rbp
+ push %rbx
+ push %rax
+ push %r9
+ push %r8
+ push %rcx
+ push %rdx
+ push %rsi
+ push %rdi
+
+ /*
+ * (that was the 'struct regs' part, now for the somewhat trickier
+ * parts of the machine (with all the implicit state that goes
+ * along with those registers (?)))
+ */
+
+ str %rax
+ push %rax
+ sldt %rax
+ push %rax
+
+ /* XX64 need to do some compile-time assert here to check this! */
+
+ push $0
+ push $0
+ sidt (%rsp)
+
+ push $0
+ push $0
+ sgdt (%rsp)
+
+#define PUSH_CREG(creg) \
+ mov creg, %rax; \
+ push %rax
+
+ PUSH_CREG(%cr8)
+ PUSH_CREG(%cr4)
+ PUSH_CREG(%cr3)
+ PUSH_CREG(%cr2)
+ PUSH_CREG(%cr0)
+
+#define PUSH_SEG_BASE(msr) \
+ mov $msr, %ecx; \
+ rdmsr; \
+ salq $32, %rdx; \
+ mov %eax, %eax; \
+ or %rdx, %rax; \
+ push %rax
+
+ PUSH_SEG_BASE(MSR_AMD_FSBASE)
+ PUSH_SEG_BASE(MSR_AMD_GSBASE)
+ PUSH_SEG_BASE(MSR_AMD_KGSBASE)
+
+ /*
+ * save the sodding segment registers (because push doesn't work!)
+ */
+ mov %cs, %ax
+ movzx %ax, %rax
+ mov %rax, amd64_REG_CS(%rsp)
+
+ mov %ds, %ax
+ movzx %ax, %rax
+ mov %rax, amd64_REG_DS(%rsp)
+
+ mov %es, %ax
+ movzx %ax, %rax
+ mov %rax, amd64_REG_ES(%rsp)
+
+ mov %ss, %ax
+ movzx %ax, %rax
+ mov %rax, amd64_REG_SS(%rsp)
+
+ /*
+ * Back to i386 mode
+ */
+
+ /*
+ * reload %ds here so we can refer to i386_machregs below
+ */
+ mov $KDS32SEL, %rax
+ movw %ax, %ds
+
+ /*
+ * 1. Switch to compatibility mode at CPL=0
+ *
+ * We seem forced to do this -- which is a complicated
+ * way to do:
+ *
+ * ljmp $KCS32SEL, $__amd64_compat_mode
+ * __amd64_compat_mode:
+ *
+ * which unfortunately isn't legal in long mode.
+ *
+ * You'd think this would work, but it doesn't.
+ *
+ * push $KCS32SEL
+ * push %rax
+ * lret
+ *
+ * Perhaps there's a better way?
+ */
+ call 9f
+9: pop %rax
+ add $_CONST(__amd64_compat_mode - 9b), %rax
+ mov %rsp, %rdx
+ push $KDS32SEL
+ push %rdx
+ pushf
+ push $KCS32SEL
+ push %rax
+ iretq
+
+__amd64_compat_mode:
+ .code32
+ /*
+ * 2. Deactivate long mode by clearing CR0.PG
+ */
+ mov %cr0, %eax
+ and $_BITNOT(CR0_PG), %eax
+ mov %eax, %cr0
+ /*
+ * 2a. Disable PAE
+ */
+ mov %cr4, %eax
+ and $_BITNOT(CR4_PAE), %eax
+ mov %eax, %cr4
+ /*
+ * 3. Load CR3 with physical base address of page tables
+ *
+ * (Note we loaded %ds above)
+ */
+ lea exitto_i386_machregs, %eax
+ mov i386_REG_CR3(%eax), %edx
+ mov %edx, %cr3
+ /*
+ * 4. Disable long mode by clearing EFER.LME to 0
+ */
+ mov $MSR_AMD_EFER, %ecx
+ rdmsr
+ and $_BITNOT(AMD_EFER_LME), %eax
+ wrmsr
+ /*
+ * 5. Enable legacy page-translation
+ */
+ mov %cr0, %eax
+ or $CR0_PG, %eax
+ mov %eax, %cr0
+ jmp __i386_mode
+__i386_mode:
+ /*
+ * Reconstruct our life as an i386 processor from the
+ * exitto save area.
+ */
+ lea exitto_i386_machregs, %eax
+ mov i386_REG_CR0(%eax), %edx
+ mov %edx, %cr0
+ /*
+ * %cr2 is the page fault address; we have no need to restore it
+ */
+ mov i386_REG_CR3(%eax), %edx
+ mov %edx, %cr3
+ mov i386_REG_CR4(%eax), %edx
+ mov %edx, %cr4
+ lgdt i386_REG_GDT(%eax)
+ lidt i386_REG_IDT(%eax)
+
+ /*
+ * Need to clear busy bit in our tss descriptor
+ */
+/ clrtss:
+/ push %eax
+/ call amd64_i386_clrtss
+/ pop %eax
+/
+/ ltr i386_REG_TR(%eax)
+
+ mov i386_REG_GS(%eax), %edx
+ movw %dx, %gs
+ mov i386_REG_FS(%eax), %edx
+ movw %dx, %fs
+ mov i386_REG_ES(%eax), %edx
+ movw %dx, %es
+ mov i386_REG_DS(%eax), %edx
+ movw %dx, %ds
+ mov i386_REG_SS(%eax), %edx
+ movw %dx, %ss
+
+ pushl i386_REG_EFL(%eax)
+ popf
+
+ /*
+ * As long as the transition from long mode to i386 mode
+ * simply truncated %rsp -> %esp, we now have a struct amd64_machregs
+ * sitting on the top of the stack.
+ */
+ pushl %esp
+ call amd64_vtrap
+ addl $4, %esp
+
+ /*
+ * let's go long ..
+ */
+__return_to_long_mode:
+ mov amd64_REG_CR3(%esp), %edx
+
+ /*
+ * Disable paging
+ */
+ mov %cr0, %eax
+ and $_BITNOT(CR0_PG), %eax
+ mov %eax, %cr0
+ /*
+ * 2a. enable PAE
+ */
+ mov %cr4, %eax
+ or $CR4_PAE, %eax
+ mov %eax, %cr4
+ /*
+ * 2b. load CR3 with PML4 base address
+ */
+ mov %edx, %cr3
+ /*
+ * 2c. enable long mode
+ */
+ mov $MSR_AMD_EFER, %ecx
+ rdmsr
+ or $AMD_EFER_LME, %eax
+ wrmsr
+ /*
+ * 2d. enable paging
+ */
+ mov %cr0, %eax
+ or $CR0_PG, %eax
+ mov %eax, %cr0
+ jmp __enable_long_mode
+__enable_long_mode:
+
+ /*
+ * we are now in compatibility mode
+ * move to the 64 bit descriptor tables so that
+ * we find ourselves in a sane place when we lret
+ * and switch to 64 bit mode ..
+ */
+ lgdt amd64_REG_GDT(%esp)
+
+ /*
+ * switch to 64-bit mode
+ */
+ call 1f
+1: pop %eax
+ add $_CONST(__amd64_64bit_mode - 1b), %eax
+ mov amd64_REG_CS(%esp), %edx
+ push %edx
+ push %eax
+ lret
+__amd64_64bit_mode:
+ .code64
+
+ /*
+ * the following descriptor table loads fetch the full
+ * 64-bit values expected by the client.
+ */
+ lgdt amd64_REG_GDT(%rsp)
+ lidt amd64_REG_IDT(%rsp)
+ lldt amd64_REG_LDT(%rsp)
+ ltr amd64_REG_TR(%rsp)
+
+ /*
+ * fix up the selectors for long mode
+ */
+ mov amd64_REG_DS(%rsp), %rax
+ movw %ax, %ds
+ mov amd64_REG_ES(%rsp), %rax
+ movw %ax, %es
+ mov amd64_REG_FS(%rsp), %rax
+ movw %ax, %fs
+ mov amd64_REG_GS(%rsp), %rax
+ movw %ax, %gs
+ mov amd64_REG_SS(%rsp), %rax
+ movw %ax, %ss
+
+#define RESTORE_SEG_BASE(seg) \
+ movq amd64_REG_/**/seg(%rsp), %rax; \
+ movq %rax, %rdx; \
+ movl %eax, %eax; \
+ shrq $32, %rdx; \
+ movl $MSR_AMD_/**/seg, %ecx; \
+ wrmsr
+
+ RESTORE_SEG_BASE(KGSBASE)
+ RESTORE_SEG_BASE(GSBASE)
+ RESTORE_SEG_BASE(FSBASE)
+
+#define RESTORE_CR(num) \
+ movq amd64_REG_CR/**/num(%rsp), %rax; \
+ movq %rax, %cr/**/num
+
+ RESTORE_CR(0)
+
+ /* don't restore %cr2 */
+
+ RESTORE_CR(3)
+ RESTORE_CR(4)
+
+ /*
+ * Only restore %cr8 if it's nonzero or if we have not yet initialized
+ * it (if it's zero, that means it's not safe to restore it -- we're
+ * either using the local APIC TPR or no TPR at all). We only test the
+ * non-reserved bits. The %cr8 initialization is done only on the first
+ * transfer from the booter to the loaded image.
+ */
+ cmpl $0, need_init_cr8(%rip) /* Did we initialize cr8 yet? */
+ jnz 1f /* No? Then go and zero it. */
+
+ testq $0xF, amd64_REG_CR8(%rsp) /* Is the saved cr8 zero? */
+ jz 2f /* Yes, -- skip the restore */
+1:
+ movl $0, need_init_cr8(%rip) /* Mark cr8 as initialized */
+ RESTORE_CR(8)
+2:
+ /*
+ * gdt/idt/ldt/tr have already been restored, as have %gs, %fs, %ds
+ * and %es.
+ *
+ * Meanwhile %rbp, %r11, err and trapno don't get restored at all.
+ */
+ movq amd64_REG_RDI(%rsp), %rdi
+ movq amd64_REG_RSI(%rsp), %rsi
+ movq amd64_REG_RAX(%rsp), %rax
+ movq amd64_REG_RCX(%rsp), %rcx
+ movq amd64_REG_RDX(%rsp), %rdx
+ movq amd64_REG_R8(%rsp), %r8
+ movq amd64_REG_R9(%rsp), %r9
+ movq amd64_REG_RBX(%rsp), %rbx
+ movq amd64_REG_R10(%rsp), %r10
+ movq amd64_REG_R12(%rsp), %r12
+ movq amd64_REG_R13(%rsp), %r13
+ movq amd64_REG_R14(%rsp), %r14
+ movq amd64_REG_R15(%rsp), %r15
+
+ /*
+ * The bottom five arguments in the struct amd64_machregs on the
+ * stack (starting with r_rip) are positioned such that they can be
+ * used as-is by iretq to return to the caller, switch interrupts
+ * back on if needed, and restore the proper %rsp.
+ *
+ * HOWEVER, we need the %rbp and %rip sitting in the return frame
+ * on the stack, so grab them from beyond the end of the amd64_machregs
+ * structure on the stack so that everything will be restored properly
+ * by the iretq.
+ *
+ * The stack after the addq below will be:
+ *
+ * 0 amd64_machregs %rip
+ * +8 amd64_machregs %cs
+ * +0x10 amd64_machflags rflags
+ * +0x18 amd64_machflags %rsp
+ * +0x20 amd64_machflags %ss
+ * +0x28 return %rbp from bootops 'call' insn
+ * +0x30 return %rip from bootops 'call' insn
+ */
+ addq $amd64_REG_RIP, %rsp
+ movq 0x28(%rsp), %rbp /* load the return %rbp to %rbp */
+ movq 0x30(%rsp), %r11 /* copy the return %rip to %r11 */
+ movq %r11, (%rsp) /* save it as amd64_machregs' r_rip */
+ iretq
+ SET_SIZE(__vtrap_common)
+
+#endif /* __lint */
+
+ VTRAP_STUB_BEGIN(bop64_first)
+
+ VTRAP_STUB(bop64_alloc)
+ VTRAP_STUB(bop64_free)
+ VTRAP_STUB(bop64_getproplen)
+ VTRAP_STUB(bop64_getprop)
+ VTRAP_STUB(bop64_nextprop)
+ VTRAP_STUB(bop64_printf)
+ VTRAP_STUB(bop64_doint)
+ VTRAP_STUB(bop64_ealloc)
+
+ VTRAP_STUB_END(bop64_last)
+
+ VTRAP_STUB_BEGIN(bsys64_first)
+
+ VTRAP_STUB(bsys64_getchar)
+ VTRAP_STUB(bsys64_putchar)
+ VTRAP_STUB(bsys64_ischar)
+
+ VTRAP_STUB_END(bsys64_last)
diff --git a/usr/src/psm/stand/boot/amd64/memlist.c b/usr/src/psm/stand/boot/amd64/memlist.c
new file mode 100644
index 0000000000..023fd240ef
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/memlist.c
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <amd64/boothooks.h>
+#include <amd64/print.h>
+#include <amd64/types.h>
+#include <amd64/bootops64.h>
+#include <amd64/memlist64.h>
+#include <amd64/amd64_page.h>
+
+struct memlist64 *
+amd64_convert_memlist(struct memlist *ml, struct memlist64 *ml64)
+{
+ extern struct memlist64 *amd64_memlistpage;
+
+ ml64->prev = (caddr64_t)0;
+
+ while (ml) {
+ ml64->address = ml->address;
+ ml64->size = ml->size;
+ ml = ml->next;
+
+ if (ml) {
+ struct memlist64 *next_ml = ml64 + 1;
+
+ ml64->next = (caddr64_t)(uintptr_t)next_ml;
+ next_ml->prev = (caddr64_t)(uintptr_t)ml64;
+ ml64++;
+
+ /*
+ * This may end up being shortsighted, but currently
+ * boot will panic if the memlists don't all fit on
+ * one page so we may as well make the same assumption.
+ */
+ if ((uint64_t)ml64 > ((uint64_t)amd64_memlistpage +
+ AMD64_PAGESIZE))
+ amd64_panic("Memory space for 64-bit memlists "
+ "exhausted when converting memlist @ 0x%x.",
+ (uint32_t)ml->prev);
+ }
+ }
+
+ ml64->next = (caddr64_t)0;
+ return (ml64 + 1);
+}
diff --git a/usr/src/psm/stand/boot/amd64/offsets.in b/usr/src/psm/stand/boot/amd64/offsets.in
new file mode 100644
index 0000000000..b07ea48e76
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/offsets.in
@@ -0,0 +1,111 @@
+\
+\ Copyright 2005 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.
+\
+\ 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
+\
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+\
+\ offsets.in: input file to produce assym.h using the ctfstabs program
+\
+
+#include <sys/types.h>
+#include <amd64/cpu.h>
+#include <amd64/machregs.h>
+#include <amd64/tss.h>
+#include <amd64/segments.h>
+
+amd64_cpuid_regs
+ r_eax AMD64_CPUID_REG_EAX
+ r_ebx AMD64_CPUID_REG_EBX
+ r_ecx AMD64_CPUID_REG_ECX
+ r_edx AMD64_CPUID_REG_EDX
+
+amd64_machregs SIZEOF_amd64_machregs
+ r_kgsbase amd64_REG_KGSBASE
+ r_gsbase amd64_REG_GSBASE
+ r_fsbase amd64_REG_FSBASE
+ r_cr0 amd64_REG_CR0
+ r_cr2 amd64_REG_CR2
+ r_cr3 amd64_REG_CR3
+ r_cr4 amd64_REG_CR4
+ r_cr8 amd64_REG_CR8
+ r_gdt_un.un_gdt amd64_REG_GDT
+ r_idt_un.un_idt amd64_REG_IDT
+ r_ldt amd64_REG_LDT
+ r_tr amd64_REG_TR
+ r_rdi amd64_REG_RDI
+ r_rsi amd64_REG_RSI
+ r_rdx amd64_REG_RDX
+ r_rcx amd64_REG_RCX
+ r_r8 amd64_REG_R8
+ r_r9 amd64_REG_R9
+ r_rax amd64_REG_RAX
+ r_rbx amd64_REG_RBX
+ r_rbp amd64_REG_RBP
+ r_r10 amd64_REG_R10
+ r_r11 amd64_REG_R11
+ r_r12 amd64_REG_R12
+ r_r13 amd64_REG_R13
+ r_r14 amd64_REG_R14
+ r_r15 amd64_REG_R15
+ r_gs amd64_REG_GS
+ r_fs amd64_REG_FS
+ r_ds amd64_REG_DS
+ r_es amd64_REG_ES
+ r_trapno amd64_REG_TRAPNO
+ r_err amd64_REG_ERR
+ r_rip amd64_REG_RIP
+ r_cs amd64_REG_CS
+ r_rfl amd64_REG_FLAGS
+ r_rsp amd64_REG_RSP
+ r_ss amd64_REG_SS
+
+i386_machregs SIZEOF_i386_machregs
+ r_ss i386_REG_SS
+ r_uesp i386_REG_UESP
+ r_efl i386_REG_EFL
+ r_cs i386_REG_CS
+ r_eip i386_REG_EIP
+ r_err i386_REG_ERR
+ r_trapno i386_REG_TRAPNO
+ r_eax i386_REG_EAX
+ r_ecx i386_REG_ECX
+ r_edx i386_REG_EDX
+ r_ebx i386_REG_EBX
+ r_esp i386_REG_ESP
+ r_ebp i386_REG_EBP
+ r_esi i386_REG_ESI
+ r_edi i386_REG_EDI
+ r_ds i386_REG_DS
+ r_es i386_REG_ES
+ r_fs i386_REG_FS
+ r_gs i386_REG_GS
+ r_tr i386_REG_TR
+ r_ldt i386_REG_LDT
+ r_idt_un.un_idt i386_REG_IDT
+ r_gdt_un.un_gdt i386_REG_GDT
+ r_cr4 i386_REG_CR4
+ r_cr3 i386_REG_CR3
+ r_cr2 i386_REG_CR2
+ r_cr0 i386_REG_CR0
diff --git a/usr/src/psm/stand/boot/amd64/print.c b/usr/src/psm/stand/boot/amd64/print.c
new file mode 100644
index 0000000000..7f2f7f3aef
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/print.c
@@ -0,0 +1,278 @@
+/*
+ * 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.
+ *
+ * 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 2005 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/inttypes.h>
+#include <sys/varargs.h>
+#include <sys/promif.h>
+
+#include <amd64/print.h>
+#include <amd64/amd64.h>
+
+/*
+ * Printn prints a number n in base b.
+ * We don't use recursion to avoid deep stacks.
+ */
+static void
+__amd64_printn(uint64_t n, int b, int width, int pad,
+ void (*put)(void *, int), void *arg)
+{
+ char prbuf[65];
+ char *cp;
+
+ cp = prbuf;
+ do {
+ *cp++ = "0123456789abcdef"[n%b];
+ n /= b;
+ width--;
+ } while (n);
+ while (width-- > 0)
+ *cp++ = (char)pad;
+ do {
+ (*put)(arg, *--cp);
+ } while (cp > prbuf);
+}
+
+/*
+ * This routine is highly specific to amd64, and is essentially a
+ * complete kludge which allows amd64 to print using the 64-bit regs
+ * from an LP64 kernel.
+ *
+ * The worst part about it is the assumptions around decoding string
+ * pointers -- we assume that the top bits of the string pointer can
+ * be discarded yet still remain as a valid address.
+ *
+ * cell size == sizeof (long long)
+ */
+static void
+__amd64_doprnt64(
+ const char *fmt,
+ va_list adx,
+ void (*put)(void *, int),
+ void *arg)
+{
+ int b, c, i, pad, width, ells;
+ char *s;
+ int64_t l;
+ uint64_t ul;
+
+loop:
+ while ((c = *fmt++) != '%') {
+ if (c == '\0')
+ goto out;
+ (*put)(arg, c);
+ }
+
+ c = *fmt++;
+ for (pad = ' '; c == '0'; c = *fmt++)
+ pad = '0';
+
+ for (width = 0; c >= '0' && c <= '9'; c = *fmt++)
+ width = width * 10 + c - '0';
+
+ for (ells = 0; c == 'l'; c = *fmt++)
+ ells++;
+
+ switch (c) {
+ case 'd':
+ case 'D':
+ b = 10;
+ if (ells == 0)
+ l = (int64_t)(int)va_arg(adx, int64_t);
+ else if (ells == 1)
+ l = (int64_t)va_arg(adx, int64_t);
+ else
+ l = (int64_t)va_arg(adx, int64_t);
+ if (l < 0) {
+ (*put)(arg, '-');
+ width--;
+ ul = -l;
+ } else
+ ul = l;
+ goto number;
+
+ case 'p':
+ ells = 1;
+ /*FALLTHROUGH*/
+ case 'x':
+ case 'X':
+ b = 16;
+ goto u_number;
+
+ case 'u':
+ b = 10;
+ goto u_number;
+
+ case 'o':
+ case 'O':
+ b = 8;
+u_number:
+ if (ells == 0)
+ ul = (uint64_t)(uint_t)va_arg(adx, uint64_t);
+ else if (ells == 1)
+ ul = (uint64_t)va_arg(adx, uint64_t);
+ else
+ ul = (uint64_t)va_arg(adx, uint64_t);
+number:
+ __amd64_printn(ul, b, width, pad, put, arg);
+ break;
+
+ case 'c':
+ b = (int)va_arg(adx, uint64_t);
+ for (i = 24; i >= 0; i -= 8)
+ if ((c = ((b >> i) & 0x7f)) != 0)
+ (*put)(arg, (char)c);
+ break;
+
+ /*
+ * Yuck. We're encoding the assumption that a valid 32-bit pointer
+ * can be obtained by simply truncating the 64-bit pointer.
+ */
+ case 's':
+ s = (char *)(uintptr_t)va_arg(adx, uint64_t);
+ for (width -= strlen(s); width > 0; width--)
+ (*put)(arg, pad);
+ while ((c = *s++) != 0)
+ (*put)(arg, c);
+ break;
+
+ case '%':
+ (*put)(arg, (char)c);
+ break;
+
+ default:
+ break;
+ }
+ goto loop;
+out:
+ ;
+}
+
+struct strbuf {
+ char *sb_base;
+ char *sb_ptr;
+ size_t sb_maxsize;
+};
+
+static void
+sput(void *arg, int c)
+{
+ struct strbuf *sb = arg;
+
+ if (c == '\n')
+ sput(arg, '\r');
+
+ if ((sb->sb_ptr - sb->sb_base) >= sb->sb_maxsize)
+ sb->sb_ptr++;
+ else
+ *sb->sb_ptr++ = (char)c;
+}
+
+static int
+amd64_vsnprintf_helper(char *s, size_t n, const char *fmt, va_list ap,
+ void (*doprnt)(const char *, va_list, void (*)(void *, int), void *))
+{
+ struct strbuf sbuf, *sb = &sbuf;
+ int count;
+
+ sb->sb_base = sb->sb_ptr = s;
+ sb->sb_maxsize = n;
+
+ (*doprnt)(fmt, ap, sput, sb);
+
+ /*
+ * Ensure there's a trailing NULL to terminate the string
+ */
+ if (sb->sb_maxsize == 0)
+ return ((int)(sb->sb_ptr - sb->sb_base));
+ if ((count = sb->sb_ptr - sb->sb_base) >= sb->sb_maxsize)
+ sb->sb_ptr = sb->sb_base + sb->sb_maxsize - 1;
+ if (sb->sb_ptr)
+ *sb->sb_ptr = '\0';
+ return (count);
+}
+
+/*
+ * Specialized vsnprintf() that is used to print arguments from
+ * an environment where the native argument size is 64-bit
+ */
+int
+amd64_vsnprintf64(char *s, size_t n, const char *fmt, va_list ap)
+{
+ return (amd64_vsnprintf_helper(s, n, fmt, ap, __amd64_doprnt64));
+}
+
+int
+amd64_snprintf64(char *s, size_t n, const char *fmt, ...)
+{
+ int r;
+ va_list ap;
+
+ va_start(ap, fmt);
+ r = amd64_vsnprintf64(s, n, fmt, ap);
+ va_end(ap);
+ return (r);
+}
+
+struct amd64buf {
+ char *vb_base;
+ char *vb_ptr;
+ size_t vb_maxsize;
+ struct bootops *vb_bop;
+};
+
+void
+amd64_vpanic(const char *fmt, va_list ap)
+{
+ printf("amd64_panic: ");
+ prom_vprintf(fmt, ap);
+ printf("\n");
+ amd64_system_reset();
+}
+
+void
+amd64_panic(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ amd64_vpanic(fmt, ap);
+ va_end(ap);
+}
+
+void
+amd64_warning(const char *fmt, ...)
+{
+ va_list ap;
+
+ printf("amd64 warning: ");
+ va_start(ap, fmt);
+ prom_vprintf(fmt, ap);
+ va_end(ap);
+ printf("\n");
+}
diff --git a/usr/src/psm/stand/boot/amd64/ptops.c b/usr/src/psm/stand/boot/amd64/ptops.c
new file mode 100644
index 0000000000..3b6244efe9
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/ptops.c
@@ -0,0 +1,372 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+
+#include <amd64/amd64.h>
+#include <amd64/print.h>
+#include <amd64/debug.h>
+#include <amd64/alloc.h>
+#include <amd64/cpu.h>
+#include <amd64/amd64_page.h>
+
+static amd64_mmumode_t mmus[] = {
+ { 22, 10, 2, 1024 }, /* legacy 32-bit mode */
+ { 39, 9, 4, 512 } /* long 64-bit mode */
+};
+
+uint16_t
+amd64_modbits(uint64_t entry)
+{
+ return ((uint16_t)PA_MODBITS(entry));
+}
+
+uint64_t
+amd64_legacy_physaddr(uint32_t entry)
+{
+ return (IS_LARGEMAP(entry) ?
+ ((uint64_t)(entry) & ~0x3fffffULL |
+ (((uint64_t)(entry) >> 13) & 0xffULL) << 32)
+ : ((uint64_t)(entry) & ~0xfffULL));
+}
+
+uint64_t
+amd64_long_physaddr(uint64_t entry)
+{
+ return (IS_LARGEMAP(entry) ? (entry & ~0x1fffffULL) :
+ (entry & ~0xfffULL));
+}
+
+uint64_t
+amd64_physaddr(uint64_t entry, uint8_t amd64_mmu_mode)
+{
+ return (amd64_mmu_mode == AMD64_MODE_LONG64) ?
+ amd64_long_physaddr(entry) : amd64_legacy_physaddr((uint32_t)entry);
+}
+
+static uint64_t
+amd64_tbl_lookup(uint8_t amd64_mmu_mode, uint64_t va, uint32_t tbl_base,
+ uint32_t *addr_inc)
+{
+ uint8_t level;
+ uint8_t level_shift = mmus[amd64_mmu_mode].level_shift;
+ uint8_t pde_level = mmus[amd64_mmu_mode].map_level - 1;
+ uint8_t shift = mmus[amd64_mmu_mode].shift_base;
+ uint64_t mask = (1ULL << level_shift) - 1;
+ uint64_t entry;
+
+ ASSERT(tbl_base);
+
+ for (level = 1; shift > AMD64_PAGESIZE_OFFSET_NBITS;
+ shift -= level_shift, level++) {
+ entry = TBL_ENTRY64(amd64_mmu_mode, tbl_base, va, shift,
+ mask);
+
+ if (!(ENTRY_VALID(entry))) {
+ /*
+ * If a page level is empty, set addr_inc to the shift
+ * value because in a sequential search we know the next
+ * (1 << level_shift) bytes are unmapped.
+ */
+ while (shift >= 32)
+ shift -= level_shift; /* XXX */
+
+ if (addr_inc)
+ *addr_inc = (1 << shift);
+
+ return (0);
+ }
+
+ if (((level == pde_level) && (IS_LARGEMAP(entry))) ||
+ IS_PTE(level, amd64_mmu_mode)) {
+ /* Set addr_inc to pagesize found and return entry. */
+
+ while (shift >= 32)
+ shift -= level_shift; /* XXX */
+
+ if (addr_inc)
+ *addr_inc = (1 << shift);
+
+ return (entry);
+ }
+
+ tbl_base = (uint32_t)amd64_physaddr(entry, amd64_mmu_mode);
+ }
+
+ if (addr_inc)
+ *addr_inc = (uint32_t)AMD64_PAGESIZE;
+
+ return (0);
+}
+
+uint64_t
+amd64_long_lookup(uint64_t va, uint32_t *addr_inc, uint32_t tbl_base)
+{
+ return (amd64_tbl_lookup(AMD64_MODE_LONG64, va, tbl_base, addr_inc));
+}
+
+uint32_t
+amd64_legacy_lookup(uint64_t va, uint32_t *addr_inc, uint32_t tbl_base)
+{
+ return ((uint32_t)amd64_tbl_lookup(AMD64_MODE_LEGACY, va, tbl_base,
+ addr_inc));
+}
+
+uint64_t
+amd64_legacy_lookup_physaddr(uint64_t va, uint32_t tbl_base)
+{
+ uint32_t entry, pagesize;
+ uint64_t offset;
+
+ if (!(entry = amd64_legacy_lookup(va, &pagesize, tbl_base)))
+ amd64_panic("legacy lookup failed for va 0x%llx\n!", va);
+
+ offset = va & AMD64_PAGEOFFSET(pagesize);
+ return (amd64_legacy_physaddr(entry) + offset);
+}
+
+uint64_t
+amd64_long_lookup_physaddr(uint64_t va, uint32_t tbl_base)
+{
+ uint32_t pagesize;
+ uint64_t entry, offset;
+
+ if (!(entry = amd64_long_lookup(va, &pagesize, tbl_base)))
+ amd64_panic("long lookup failed for va 0x%llx\n!", va);
+
+ offset = va & AMD64_PAGEOFFSET(pagesize);
+ return (amd64_long_physaddr(entry) + offset);
+}
+
+void
+amd64_map_mem(uint64_t va, uint64_t pa, uint32_t len, uint8_t amd64_mmu_mode,
+ uint32_t tbl_base, uint16_t page_modbits)
+{
+ uint64_t parentlvl_entry;
+ uint64_t entry;
+ uint64_t local_pagebits;
+
+ uint32_t pagesize;
+ uint32_t parent_base;
+ uint32_t tbl_root = tbl_base;
+
+ uint8_t level_shift = mmus[amd64_mmu_mode].level_shift;
+ uint64_t idx_mask = (1ULL << level_shift) - 1;
+
+ uint8_t level, map_level;
+ uint8_t shift;
+
+ ASSERT(tbl_base);
+ ASSERT(AMD64_PAGEALIGNED(va, AMD64_PAGESIZE));
+ ASSERT(AMD64_PAGEALIGNED(pa, AMD64_PAGESIZE));
+ ASSERT(AMD64_PAGEALIGNED(len, AMD64_PAGESIZE));
+
+ if ((amd64_mmu_mode == AMD64_MODE_LONG64) && ((va >> 47) & 1) &&
+ ((va >> 48) != 0xffffULL))
+ amd64_panic("amd64_map_mem: map attempted into 64-bit VA "
+ "hole (va 0x%llx)\n", va);
+
+ while (len != 0) {
+ map_level = mmus[amd64_mmu_mode].map_level;
+
+ /*
+ * Check to see if we're mapping a range that could be
+ * mapped by a large page one page table level up. If so,
+ * use the larger page for efficiency:
+ *
+ * Long 64-bit mode: 2M PAGE = (AMD64_PAGESIZE << LEVEL_SHIFT)
+ * Legacy 32-bit mode: 4M PAGE = (AMD64_PAGESIZE << LEVEL_SHIFT)
+ */
+ pagesize = AMD64_PAGESIZE << level_shift;
+
+ if (AMD64_PAGEALIGNED(va, pagesize) && AMD64_PAGEALIGNED(pa,
+ pagesize) && (len >= pagesize)) {
+ map_level--;
+ local_pagebits = PDE_PS;
+ } else {
+ pagesize = AMD64_PAGESIZE;
+ local_pagebits = 0;
+ }
+
+ level = 1;
+ shift = mmus[amd64_mmu_mode].shift_base;
+
+ while ((level <= map_level) && (len >= pagesize)) {
+ entry = TBL_ENTRY64(amd64_mmu_mode, tbl_base, va, shift,
+ idx_mask);
+
+ if (level < map_level) {
+ if (!(ENTRY_VALID(entry))) {
+ uint32_t page;
+
+ /*
+ * Grab an identity-mapped page at this
+ * level for an array of entries.
+ */
+ page = (uint32_t)amd64_zalloc_identity(
+ AMD64_PAGESIZE);
+
+ /*
+ * Setup entry pointing to the new array
+ */
+ entry = TBL_ENTRY_DEFAULT(page);
+
+ /*
+ * Insert new entry into table
+ */
+ SET_TABLEVAL(amd64_mmu_mode, tbl_base,
+ va, shift, idx_mask, entry);
+
+ /*
+ * If we're mapping in 64-bit long mode,
+ * make sure to identity map the
+ * allocation above into the 64-bit
+ * page tables to make sure the kernel
+ * can walk the 64-bit page tables.
+ */
+ if (amd64_mmu_mode ==
+ AMD64_MODE_LONG64)
+ amd64_map_mem(
+ (uint64_t)page,
+ (uint64_t)page,
+ AMD64_PAGESIZE,
+ amd64_mmu_mode, tbl_root,
+ page_modbits);
+ }
+
+ /*
+ * Continue down another level.
+ */
+ if ((level + 1) == map_level) {
+ parent_base = tbl_base;
+ parentlvl_entry = entry;
+ }
+
+ tbl_base = (uint32_t)amd64_physaddr(entry,
+ amd64_mmu_mode);
+ shift -= level_shift;
+ level++;
+ continue;
+ }
+
+ do {
+ /*
+ * Create mapping entry at this level.
+ */
+ entry = TBL_ENTRY_DEFAULT(pa) | page_modbits |
+ local_pagebits;
+
+ /*
+ * Install mapping entry
+ */
+ SET_TABLEVAL(amd64_mmu_mode, tbl_base, va,
+ shift, idx_mask, entry);
+
+ va += pagesize;
+ pa += pagesize;
+ len -= pagesize;
+ } while ((TBL_ENTRY64(amd64_mmu_mode, parent_base, va,
+ shift + level_shift,
+ idx_mask) == parentlvl_entry) && (len >= pagesize));
+
+ if (len != 0) {
+ /*
+ * We went over a parent's table entry mapping
+ * border, so we need to recalculate where we
+ * should be adding page tables.
+ *
+ * For example, if we are mapping 4K page
+ * tables in long mode, this means we crossed a
+ * 2M boundary. (It would be a 4M boundary for
+ * 32-bit legacy mode.)
+ */
+ level = 1;
+ tbl_base = tbl_root;
+ shift = mmus[amd64_mmu_mode].shift_base;
+ }
+ }
+ }
+}
+
+/*
+ * Save top of boot's 64-bit page tables for future use.
+ */
+uint64_t amd64_boot_pml4;
+
+/*
+ * Initialize long page tables
+ */
+uint64_t
+amd64_init_longpt(uint32_t cr3)
+{
+ extern int magic_phys;
+ int i;
+ uint64_t *pml4, *pdpt, *pdpt_hi, *pdt, *pte_zero;
+
+ pml4 = amd64_zalloc_identity(AMD64_PAGESIZE);
+ pdpt = amd64_zalloc_identity(AMD64_PAGESIZE);
+ pdpt_hi = amd64_zalloc_identity(AMD64_PAGESIZE);
+ pdt = amd64_zalloc_identity(AMD64_PAGESIZE * 4);
+ pte_zero = amd64_zalloc_identity(AMD64_PAGESIZE);
+
+ /*
+ * Initialize long mode page tables.
+ *
+ * The only initial mappings are those for the identity mapped boot 4M
+ * (0x01000:0x400000) and those boot has already allocated.
+ */
+ *pml4 = TBL_ENTRY_DEFAULT(pdpt);
+
+ /*
+ * Preallocate enough level two and three entries to map the lower 4G
+ * of VA space, which will be reflected to the top 4G of VM space
+ * directly at the level two page tables.
+ */
+ *(pml4 + 511) = TBL_ENTRY_DEFAULT(pdpt_hi);
+
+ *pdpt = *(pdpt_hi + 508) = TBL_ENTRY_DEFAULT(pdt);
+ *(pdpt + 1) = *(pdpt_hi + 509) = TBL_ENTRY_DEFAULT(pdt + 512);
+ *(pdpt + 2) = *(pdpt_hi + 510) = TBL_ENTRY_DEFAULT(pdt + 1024);
+ *(pdpt + 3) = *(pdpt_hi + 511) = TBL_ENTRY_DEFAULT(pdt + 1536);
+
+ *pdt = TBL_ENTRY_DEFAULT(pte_zero); /* leave page zero unmapped */
+
+ /* Identity map VA 0x200000:magic_phys at the PDE level via 2M pages */
+ for (i = 1; (i + 1) * 0x200000 < magic_phys; i++)
+ *(pdt + i) = TBL_ENTRY_DEFAULT(i * 0x200000) | PDE_PS;
+
+ /*
+ * Copy the balance of boot's initial mappings - this will fill in
+ * mapped entries in the page tables other than the 2M identity mapped
+ * page mentioned above.
+ */
+ amd64_xlate_boot_tables(cr3, (uint32_t)pml4);
+ amd64_boot_pml4 = UINT64_FROMPTR32(pml4);
+
+ return (amd64_boot_pml4);
+}
diff --git a/usr/src/psm/stand/boot/amd64/ptxlate.c b/usr/src/psm/stand/boot/amd64/ptxlate.c
new file mode 100644
index 0000000000..80e20f783a
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/ptxlate.c
@@ -0,0 +1,359 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+
+#include <amd64/amd64.h>
+#include <amd64/print.h>
+#include <amd64/debug.h>
+#include <amd64/amd64_page.h>
+
+/*
+ * NOTE: ALL these routines assume that page tables are identity mapped (1:1,
+ * VA == PA). If they cannot access a given physical address by
+ * dereferencing the equivalent virtual address, they will fail due to
+ * the inability of the x86 to easily access any given physical address
+ * without explicitly mapping a special page specifically to do so.
+ *
+ * Since boot already maps the 32-bit page tables this way and we control
+ * creation of the 64-bit page tables, we can assure that this remains
+ * the case unless a callback is made from 64-bit mode that references a
+ * kernel-mapped page; doing THAT will likely cause a crash as the
+ * routines try to dereference an unmapped or wrong address.
+ */
+
+/*
+ * Routines to manage legacy 32-bit and long mode 64-bit page mappings
+ */
+
+void
+amd64_xlate_legacy_va(uint32_t va, uint32_t len, uint32_t legacy_ptbase,
+ uint32_t long_ptbase)
+{
+ uint64_t map_pa, map_va, entry, offset;
+ uint32_t pagesize, map_pagesize;
+
+ uint64_t maplen = 0;
+
+ /*
+ * If passed VA is not page aligned, make it so
+ * and add the offset to the length we need to map,
+ * so a map of va 0x3100, len 0x1000 becomes a map
+ * of va 0x3000, len 0x1100.
+ */
+ if (!(AMD64_PAGEALIGNED(va, AMD64_PAGESIZE))) {
+ len += va & AMD64_PAGEOFFSET(AMD64_PAGESIZE);
+ va &= AMD64_PAGEMASK(AMD64_PAGESIZE);
+ }
+
+ while (len) {
+ uint64_t check_pa, entry_64;
+
+ entry = amd64_legacy_lookup((uint64_t)(va), &map_pagesize,
+ legacy_ptbase);
+
+ if (entry_64 = amd64_long_lookup((uint64_t)(va), &pagesize,
+ long_ptbase)) {
+ /*
+ * We can skip the next map_pagesize bytes since
+ * they've already been mapped.
+ */
+
+#ifdef DEBUG
+ if ((amd64_physaddr(entry_64, AMD64_MODE_LONG64)) !=
+ (amd64_physaddr((uint64_t)entry,
+ AMD64_MODE_LEGACY))) {
+ printf("WARNING: 64-bit va 0x%llx already "
+ "mapped, pa 0x%llx, len 0x%x!\n",
+ (uint64_t)va, amd64_physaddr(entry_64,
+ AMD64_MODE_LONG64),
+ pagesize);
+ printf(" Will not remap address to pa "
+ "0x%llx as requested.\n",
+ amd64_physaddr((uint64_t)entry,
+ AMD64_MODE_LEGACY));
+ }
+#endif /* DEBUG */
+#ifdef lint
+ entry_64 = entry_64;
+#endif /* lint */
+ map_pagesize = pagesize;
+ entry = 0;
+ }
+
+ pagesize = (map_pagesize > len) ? AMD64_PAGESIZE : map_pagesize;
+
+ if (entry) {
+ /*
+ * Valid page mapping for va found, so either add
+ * it to the current page range or map what we have
+ * and start a new range.
+ */
+ check_pa = amd64_legacy_physaddr(entry);
+
+ if ((map_pagesize == AMD64_PAGESIZE4M) &&
+ (!(AMD64_PAGEALIGNED(va, map_pagesize)))) {
+ offset = va & AMD64_PAGEMASK(map_pagesize);
+ check_pa += offset;
+ pagesize = AMD64_PAGESIZE;
+ }
+
+ if (!maplen) {
+ map_va = (uint64_t)(va);
+
+ map_pa = check_pa;
+ maplen = pagesize;
+
+ if (!(AMD64_PAGEALIGNED(va, pagesize))) {
+ offset = va &
+ AMD64_PAGEOFFSET(pagesize);
+ map_pa += offset;
+ maplen -= offset;
+ }
+ } else {
+ if (check_pa != (map_pa + maplen)) {
+ /*
+ * Range of mapped entries ends,
+ * so map what we've got and start
+ * a new range.
+ */
+ amd64_map_mem(map_va, map_pa,
+ maplen, AMD64_MODE_LONG64,
+ long_ptbase,
+ amd64_modbits((uint64_t)entry));
+
+ /*
+ * Use current mapping as start of
+ * new range.
+ */
+ map_va = (uint64_t)(va);
+ map_pa = check_pa;
+ maplen = pagesize;
+
+ if (!(AMD64_PAGEALIGNED(va,
+ pagesize))) {
+ offset = va &
+ AMD64_PAGEOFFSET(pagesize);
+ map_pa += offset;
+ maplen -= offset;
+ }
+ } else {
+ /*
+ * Just increment mapping range
+ * by mapped pagesize.
+ */
+ maplen += pagesize;
+ }
+ }
+ } else if (maplen) {
+ /*
+ * Found a bad map entry, so end the mapping range and
+ * translate the address range we have.
+ */
+ amd64_map_mem(map_va, map_pa, maplen, AMD64_MODE_LONG64,
+ long_ptbase, amd64_modbits((uint64_t)entry));
+
+ maplen = 0;
+ }
+
+ va += pagesize;
+ len -= (pagesize > len) ? len : pagesize;
+ }
+
+ /*
+ * If we ended with an outstanding range left to map, be sure to map it
+ * now.
+ */
+ if (maplen)
+ amd64_map_mem(map_va, map_pa, maplen, AMD64_MODE_LONG64,
+ long_ptbase, amd64_modbits((uint64_t)entry));
+}
+
+void
+amd64_xlate_long_va(uint64_t va, uint32_t len, uint32_t long_ptbase,
+ uint32_t legacy_ptbase)
+{
+ uint32_t map_pagesize, pagesize;
+ uint64_t map_pa, map_va, entry, offset;
+ uint64_t maplen = 0;
+
+ /*
+ * If passed VA is not page aligned, make it so
+ * and add the offset to the length we need to map,
+ * so a map of va 0x3100, len 0x1000 becomes a map
+ * of va 0x3000, len 0x1100.
+ */
+ if (!(AMD64_PAGEALIGNED(va, AMD64_PAGESIZE))) {
+ len += va & AMD64_PAGEOFFSET(AMD64_PAGESIZE);
+ va &= AMD64_PAGEMASK(AMD64_PAGESIZE);
+ }
+
+ while (len) {
+ uint64_t check_pa;
+ uint32_t entry_32;
+
+ entry = amd64_long_lookup(va, &map_pagesize, long_ptbase);
+
+ if (entry_32 = amd64_legacy_lookup((uint32_t)ADDR_TRUNC(va),
+ &pagesize, legacy_ptbase)) {
+ /*
+ * We can skip the next map_pagesize bytes since
+ * they've already been mapped.
+ */
+#ifdef DEBUG
+ if ((amd64_physaddr((uint64_t)entry_32,
+ AMD64_MODE_LEGACY)) != (amd64_physaddr(entry,
+ AMD64_MODE_LONG64))) {
+ printf("WARNING: 32-bit va 0x%llx already "
+ "mapped, pa 0x%llx, len 0x%x!\n",
+ (uint64_t)va, amd64_physaddr(entry_32,
+ AMD64_MODE_LEGACY), pagesize);
+ printf(" Will not remap address to "
+ "pa 0x%llx as requested.\n",
+ amd64_physaddr(entry, AMD64_MODE_LONG64));
+ }
+
+#endif /* DEBUG */
+#ifdef lint
+ entry_32 = entry_32;
+#endif /* lint */
+ map_pagesize = pagesize;
+ entry = 0;
+ }
+
+ pagesize = (map_pagesize > len) ? AMD64_PAGESIZE
+ : map_pagesize;
+
+ if (entry) {
+ /*
+ * Valid page mapping for va found, so either add
+ * it to the current page range or map what we have
+ * and start a new range.
+ */
+ check_pa = amd64_long_physaddr(entry);
+
+ if ((map_pagesize == AMD64_PAGESIZE2M) &&
+ (!(AMD64_PAGEALIGNED(va, map_pagesize)))) {
+ offset = va & AMD64_PAGEMASK(map_pagesize);
+ check_pa += offset;
+ pagesize = AMD64_PAGESIZE;
+ }
+
+ if (!maplen) {
+ map_va = va;
+ map_pa = check_pa;
+ maplen = pagesize;
+
+ if (!(AMD64_PAGEALIGNED(va, pagesize))) {
+ offset = va &
+ AMD64_PAGEOFFSET(pagesize);
+
+ map_pa += offset;
+ maplen -= offset;
+ }
+ } else {
+ if (check_pa != (map_pa + maplen)) {
+ /*
+ * Range of mapped entries ends,
+ * so map what we've got and start
+ * a new range.
+ */
+ amd64_map_mem(map_va, map_pa, maplen,
+ AMD64_MODE_LEGACY, legacy_ptbase,
+ amd64_modbits(entry));
+
+ /*
+ * Use current mapping as start of
+ * new range.
+ */
+ map_va = va;
+ map_pa = check_pa;
+ maplen = pagesize;
+
+ if (!(AMD64_PAGEALIGNED(va,
+ pagesize))) {
+ offset = va &
+ AMD64_PAGEOFFSET(pagesize);
+ map_pa += offset;
+ maplen -= offset;
+ }
+ } else {
+ /*
+ * Just increment mapping range
+ * by mapped pagesize.
+ */
+ maplen += pagesize;
+ }
+ }
+ } else if (maplen) {
+ /*
+ * Found a bad map entry, so end the mapping range and
+ * translate the address range we have.
+ */
+ amd64_map_mem(map_va, map_pa, maplen, AMD64_MODE_LEGACY,
+ legacy_ptbase, amd64_modbits(entry));
+ maplen = 0;
+ }
+
+ va += pagesize;
+ len -= (pagesize > len) ? len : pagesize;
+ }
+
+ /*
+ * If we ended with an outstanding range left to map, be sure to map it
+ * now.
+ */
+ if (maplen)
+ amd64_map_mem(map_va, map_pa, maplen, AMD64_MODE_LEGACY,
+ legacy_ptbase, amd64_modbits(entry));
+}
+
+void
+amd64_xlate_boot_tables(uint32_t boot_ptbase, uint32_t long_ptbase)
+{
+ extern uint_t magic_phys;
+
+ /*
+ * The initial 64-bit page tables are setup with 0x200000:0x600000
+ * already identity mapped, so we can skip that range.
+ */
+
+ /*
+ * Copy first 2M of boot's pages but SKIP PAGE ZERO.
+ */
+ amd64_xlate_legacy_va(0x1000ULL, 0x1ff000, boot_ptbase, long_ptbase);
+
+ /*
+ * Now copy balance of boot's pages.
+ *
+ * The initial 64-bit page tables are setup with 0x200000:0x400000
+ * already identity mapped, so we can skip that range...
+ */
+ amd64_xlate_legacy_va((magic_phys / 0x200000) * 0x200000,
+ 0xffc00000, boot_ptbase, long_ptbase);
+}
diff --git a/usr/src/psm/stand/boot/amd64/segments.c b/usr/src/psm/stand/boot/amd64/segments.c
new file mode 100644
index 0000000000..f384110045
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/segments.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1992 Terrence R. Lambert.
+ * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
+ */
+
+#include <sys/types.h>
+
+#include <amd64/boothooks.h>
+#include <amd64/types.h>
+#include <amd64/debug.h>
+#include <amd64/tss.h>
+#include <amd64/segments.h>
+
+/*
+ * Routines for loading segment descriptors in a format the hardware
+ * understands.
+ */
+
+/*
+ * Install user segment descriptor for code and data.
+ */
+void
+set_usegd(user_desc_t *dp, void *base, size_t size, uint_t type,
+ uint_t dpl, uint_t gran, uint_t defopsz)
+{
+ bzero(dp, sizeof (*dp));
+
+ dp->usd_lolimit = size;
+ dp->usd_hilimit = (uintptr_t)size >> 16;
+
+ dp->usd_lobase = (uintptr_t)base;
+ dp->usd_midbase = (uintptr_t)base >> 16;
+ dp->usd_hibase = (uintptr_t)base >> (16 + 8);
+
+ dp->usd_type = type;
+ dp->usd_dpl = dpl;
+ dp->usd_p = 1;
+ dp->usd_def32 = defopsz; /* 0 = 16, 1 = 32 bit operands */
+ dp->usd_gran = gran; /* 0 = bytes, 1 = pages */
+}
+
+/*
+ * In long mode we have the new L or long mode attribute bit
+ * for code segments. Only the conforming bit in type is used along
+ * with descriptor priority and present bits. Default operand size must
+ * be zero when in long mode. In 32-bit compatibility mode all fields
+ * are treated as in legacy mode. For data segments while in long mode
+ * only the present bit is loaded.
+ */
+void
+set_usegd64(user_desc64_t *dp, uint_t lmode, void *base, size_t size,
+ uint_t type, uint_t dpl, uint_t gran, uint_t defopsz)
+{
+ bzero(dp, sizeof (*dp));
+
+ ASSERT(lmode == 0 || lmode == 1);
+
+ /*
+ * 64-bit long mode.
+ */
+ if (lmode == LONG) {
+ dp->usd_type = type;
+ dp->usd_dpl = dpl;
+ dp->usd_p = 1;
+ dp->usd_long = 1; /* 64-bit mode */
+ dp->usd_def32 = 0; /* must be zero for 32-bit operands */
+ dp->usd_gran = gran; /* 0 = bytes, 1 = pages */
+ } else {
+
+ /*
+ * 32-bit compatibility mode.
+ */
+ dp->usd_lolimit = size;
+ dp->usd_hilimit = (uintptr_t)size >> 16;
+
+ dp->usd_lobase = (uintptr_t)base;
+ dp->usd_midbase = (uintptr_t)base >> 16;
+ dp->usd_hibase = (uintptr_t)base >> (16 + 8);
+
+ dp->usd_type = type;
+ dp->usd_dpl = dpl;
+ dp->usd_p = 1;
+ dp->usd_long = 0; /* 32-bit mode */
+ dp->usd_def32 = defopsz; /* 0 = 16, 1 = 32-bit ops */
+ dp->usd_gran = gran; /* 0 = bytes, 1 = pages */
+ }
+}
+
+/*
+ * Install system segment descriptor for LDT and TSS segments.
+ */
+void
+set_syssegd(system_desc_t *dp, void *base, size_t size, uint_t type,
+ uint_t dpl)
+{
+ bzero(dp, sizeof (*dp));
+
+ dp->ssd_lolimit = size;
+ dp->ssd_hilimit = (uintptr_t)size >> 16;
+
+ dp->ssd_lobase = (uintptr_t)base;
+ dp->ssd_midbase = (uintptr_t)base >> 16;
+ dp->ssd_hibase = (uintptr_t)base >> (16 + 8);
+
+ dp->ssd_type = type;
+ dp->ssd_zero = 0; /* must be zero */
+ dp->ssd_dpl = dpl;
+ dp->ssd_p = 1;
+
+ /*
+ * XXX why would anyone care to use page units for
+ * ldt or tss sizes? Force it to be bytes.
+ */
+ dp->ssd_gran = 0;
+}
+
+void
+set_syssegd64(system_desc64_t *dp, void *base, size_t size, uint_t type,
+ uint_t dpl)
+{
+ bzero(dp, sizeof (*dp));
+
+ dp->ssd_lolimit = size;
+ dp->ssd_hilimit = (uintptr_t)size >> 16;
+
+ dp->ssd_lobase = (uint32_t)base;
+ dp->ssd_midbase = (uint64_t)(uint32_t)base >> 16;
+ dp->ssd_hibase = (uint64_t)(uint32_t)base >> (16 + 8);
+ dp->ssd_hi64base = (uint64_t)(uint32_t)base >> (16 + 8 + 8);
+
+ dp->ssd_type = type;
+ dp->ssd_zero1 = 0; /* must be zero */
+ dp->ssd_zero2 = 0;
+ dp->ssd_dpl = dpl;
+ dp->ssd_p = 1;
+ dp->ssd_gran = 0; /* force byte units */
+}
+
+/*
+ * Install gate segment descriptor for interrupt, trap, call and task gates.
+ */
+void
+set_gatesegd(gate_desc_t *dp, void (*func)(void), selector_t sel,
+ uint_t wcount, uint_t type, uint_t dpl)
+{
+ bzero(dp, sizeof (*dp));
+
+ dp->sgd_looffset = (uintptr_t)func;
+ dp->sgd_hioffset = (uintptr_t)func >> 16;
+
+ dp->sgd_selector = (uint16_t)sel;
+ dp->sgd_stkcpy = wcount;
+ dp->sgd_type = type;
+ dp->sgd_dpl = dpl;
+ dp->sgd_p = 1;
+}
+
+/*
+ * Note stkcpy is replaced with ist. Read the PRM for details on this.
+ */
+void
+set_gatesegd64(gate_desc64_t *dp, void (*func)(void), selector_t sel,
+ uint_t ist, uint_t type, uint_t dpl)
+{
+ bzero(dp, sizeof (*dp));
+
+ dp->sgd_looffset = (uint64_t)(uint32_t)func;
+ dp->sgd_hioffset = (uint64_t)(uint32_t)func >> 16;
+ dp->sgd_hi64offset = (uint64_t)(uint32_t)func >> (16 + 16);
+
+ dp->sgd_selector = (uint16_t)sel;
+ dp->sgd_ist = ist;
+ dp->sgd_type = type;
+ dp->sgd_dpl = dpl;
+ dp->sgd_p = 1;
+}
diff --git a/usr/src/psm/stand/boot/amd64/vtrap.c b/usr/src/psm/stand/boot/amd64/vtrap.c
new file mode 100644
index 0000000000..cfd0df618d
--- /dev/null
+++ b/usr/src/psm/stand/boot/amd64/vtrap.c
@@ -0,0 +1,1148 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Contains the set of routines that implement the bootops and bsyscall
+ * vectors for a 64-bit client program.
+ */
+
+#include <sys/types.h>
+#include <sys/controlregs.h>
+#include <sys/trap.h>
+#include <sys/bootsvcs.h>
+
+#include <amd64/print.h>
+#include <amd64/bootops64.h>
+#include <amd64/bootsvcs64.h>
+#include <amd64/machregs.h>
+#include <amd64/alloc.h>
+#include <amd64/amd64_page.h>
+#include <amd64/cpu.h>
+#include <amd64/debug.h>
+#include <amd64/amd64.h>
+
+uint_t bop64_trace =
+#if defined(DEBUG)
+ /* AMD64_TRACE_BOP_VM | XX64 - also too chatty */
+ /* AMD64_TRACE_BOP_PROP | XX64 - also too chatty */
+ /* AMD64_TRACE_BOP_BIOS | XX64 - final vestiges of chattyness */
+#endif
+ 0;
+
+static struct bsys_mem64 *amd64_update_ml64(struct bootops *);
+
+/*
+ * Memory page set aside for translation of boot's memory lists into
+ * "struct memlist64" format
+ */
+struct memlist64 *amd64_memlistpage;
+
+static void
+return_int(struct amd64_machregs *rp, int rval)
+{
+ rp->r_rax = (int64_t)rval;
+}
+
+static void
+return_paddr(struct amd64_machregs *rp, void *rval)
+{
+ rp->r_rax = (caddr64_t)(uint32_t)rval;
+}
+
+static void
+return_addr(struct amd64_machregs *rp, void *rval)
+{
+ rp->r_rax = (caddr64_t)ADDR_XTND(rval);
+}
+
+static const char *
+trap_type_name(uint_t type)
+{
+ switch (type) {
+ case T_ZERODIV: return ("Divide error (#de)");
+ case T_SGLSTP: return ("Debug (#db)");
+ case T_NMIFLT: return ("NMI interrupt");
+ case T_BPTFLT: return ("Breakpoint (#bp)");
+ case T_OVFLW: return ("Overflow (#of)");
+ case T_BOUNDFLT: return ("BOUND range exceeded (#br)");
+ case T_ILLINST: return ("Invalid opcode (#ud)");
+ case T_NOEXTFLT: return ("Device not available (#nm)");
+ case T_DBLFLT: return ("Double fault (#df)");
+ case T_EXTOVRFLT: return ("(i386 only reserved trap (9))");
+ case T_TSSFLT: return ("Invalid TSS (#ts)");
+ case T_SEGFLT: return ("Segment not present (#np)");
+ case T_STKFLT: return ("Stack segment fault (#ss)");
+ case T_GPFLT: return ("General protection (#gp)");
+ case T_PGFLT: return ("Page fault (#pf)");
+ case 15: return ("Intel reserved trap (15)");
+ case T_EXTERRFLT: return ("x87 floating point error (#mf)");
+ case T_ALIGNMENT: return ("Alignment check (#ac)");
+ case T_MCE: return ("Machine check (#mc)");
+ case T_SIMDFPE: return ("SIMD floating point exception (#xf)");
+ default:
+ /*
+ * see r_trapno for type. Sorry but amd64
+ * does not support sprtintf().
+ */
+ return ("reserved, external or soft int");
+ }
+}
+
+/*
+ * (When we need to get more ambitious with this, we
+ * can climb the long-mode stack to see how we got here..)
+ */
+/*PRINTFLIKE2*/
+static void
+traceback64(struct amd64_machregs *rp, const char *fmt, ...)
+{
+ va_list ap;
+
+ printf("%%rip: entry 0x%16" PRIx64 " return 0x%16" PRIx64 "\n",
+ rp->r_trapno, rp->r_rip);
+ printf("%%rsp: 0x%16" PRIx64 "\n", rp->r_rsp);
+
+ va_start(ap, fmt);
+ amd64_vpanic(fmt, ap);
+ va_end(ap);
+}
+
+/*
+ * We took a real exception thru amd64's IDT.
+ * Dump state and reset machine.
+ */
+static void
+idt_exception(struct amd64_machregs *rp)
+{
+ printf("AMD64_BAD_TRAP: %s error=0x%llx\n\n",
+ trap_type_name(rp->r_trapno), rp->r_err);
+
+ amd64_dump_amd64_machregs(rp);
+ printf("resetting ...");
+ amd64_system_reset();
+ /*NOTREACHED*/
+}
+
+extern uintptr_t bsys64_first, bsys64_last, bop64_first, bop64_last;
+extern struct boot_syscalls *entry_boot_syscalls;
+
+#ifdef DEBUG
+static void
+amd64_assert_addr(caddr_t addr, int64_t arg_64, char *caller_name, char *type)
+{
+ if ((int64_t)ADDR_XTND(addr) != arg_64)
+ amd64_panic("%s(): unexpected address for %s\n"
+ " (expected 0x%llx, passed 0x%llx)\n", caller_name,
+ type, (int64_t)ADDR_XTND(addr), arg_64);
+}
+
+static int
+amd64_check_mapped_32(uint64_t addr, char *caller_name, char *type)
+{
+ if (!(amd64_legacy_lookup((uint64_t)(uintptr_t)addr, (uint32_t *)0,
+ amd64_get_cr3()))) {
+ printf("ERROR: %s(): called with unmapped 32-bit %s @ "
+ "0x%llx\n failing operation...\n", caller_name, type,
+ addr);
+ return (0);
+ }
+
+ return (1);
+}
+
+static int
+amd64_check_arg(caddr_t addr, int64_t arg_64, char *caller_name, char *type)
+{
+ amd64_assert_addr(addr, arg_64, caller_name, type);
+ return (amd64_check_mapped_32((uint64_t)(uintptr_t)addr, caller_name,
+ type));
+}
+#endif /* DEBUG */
+
+static void
+amd64_invoke_bootop(
+ struct amd64_machregs *rp,
+ struct bootops64 *bop64,
+ struct bootops *bop)
+{
+ extern uint64_t amd64_boot_pml4;
+ static int amd64_io_quiesced = 0;
+
+ fnaddr64_t this = (fnaddr64_t)rp->r_rip;
+ enum tracetype {
+ TRACE_NONE_RETURN,
+ TRACE_INT_RETURN,
+ TRACE_ADDR_RETURN,
+ TRACE_VOID_RETURN
+ } trace = TRACE_NONE_RETURN;
+
+ if (this == bop64->bsys_alloc) {
+
+ caddr_t vahint = ADDR_TRUNC(_ARG2(rp));
+ size_t size = (size_t)_ARG3(rp);
+ int align = (int)_ARG4(rp);
+ void *retval;
+
+ if (rp->r_cr3 != amd64_boot_pml4)
+ amd64_panic("bop64_alloc() called with wrong 64-bit "
+ "page table start address\n (caller's cr3: "
+ "0x%llx, should be: 0x%llx)\n", rp->r_cr3,
+ amd64_boot_pml4);
+
+ if (bop64_trace & AMD64_TRACE_BOP_VM) {
+ printf("+alloc(vahint 0x%p/0x%" PRIx64
+ " size %lu/%" PRIu64 " align %d) ",
+ (void *)vahint, _ARG2(rp),
+ size, _ARG3(rp), align);
+ trace = TRACE_ADDR_RETURN;
+ }
+
+#ifdef DEBUG
+ amd64_assert_addr(vahint, _ARG2(rp), "BOP_ALLOC", "vahint");
+#endif /* DEBUG */
+
+ retval = BOP_ALLOC(bop, vahint, size, align);
+
+ if (retval != 0)
+ amd64_xlate_legacy_va((uint32_t)retval, size,
+ amd64_get_cr3(), amd64_boot_pml4);
+
+ return_addr(rp, retval);
+
+ } else if (this == bop64->bsys_free) {
+
+ caddr_t va = ADDR_TRUNC(_ARG2(rp));
+ size_t size = (size_t)_ARG3(rp);
+
+ if (rp->r_cr3 != amd64_boot_pml4)
+ amd64_panic("bop64_free() called with wrong 64-bit "
+ "page table start address\n (caller's cr3: "
+ "0x%llx, should be: 0x%llx)\n", rp->r_cr3,
+ amd64_boot_pml4);
+
+ if (bop64_trace & AMD64_TRACE_BOP_VM) {
+ printf("+free(va 0x%p/0x%" PRIx64
+ " size %lu/%" PRIu64 ") ",
+ (void *)va, _ARG2(rp), size, _ARG3(rp));
+ trace = TRACE_VOID_RETURN;
+ }
+
+#ifdef DEBUG
+ amd64_assert_addr(va, _ARG2(rp), "BOP_FREE", "va");
+#endif /* DEBUG */
+
+ BOP_FREE(bop, va, size);
+
+ } else if (this == bop64->bsys_getproplen) {
+
+ /*
+ * The property routines are mostly pass-through, but
+ * we take steps to hide our existence, so that the
+ * 64-bit kernel really does think it's talking to
+ * a native booter
+ *
+ * XX64 The "real" version of 'whoami' handling should be
+ * done in boot -- if that booter is asked to boot an
+ * EM_AMD64 file, it should know to put stretch into
+ * memory, then tell stretch and the kernel to boot
+ * that program, then we wouldn't need to fib here,
+ * because boot would be fibbing for us.
+ */
+
+ char *name = ADDR_TRUNC(_ARG2(rp));
+
+ if (bop64_trace & AMD64_TRACE_BOP_PROP) {
+ printf("+getproplen(name 0x%p/0x%" PRIx64
+ " '%s') ", (void *)name, _ARG2(rp), name);
+ trace = TRACE_INT_RETURN;
+ }
+
+#ifdef DEBUG
+ if (!amd64_check_arg((caddr_t)name, _ARG2(rp), "BOP_GETPROPLEN",
+ "property name")) {
+ return_int(rp, 0);
+ return;
+ }
+#endif /* DEBUG */
+
+ if (strcmp(name, "mmu-modlist") == 0) {
+ return_int(rp, strlen(amd64_getmmulist()) + 1);
+ } else
+ return_int(rp, BOP_GETPROPLEN(bop, name));
+
+ } else if (this == bop64->bsys_getprop) {
+
+ char *name = ADDR_TRUNC(_ARG2(rp));
+ caddr_t value = ADDR_TRUNC(_ARG3(rp));
+
+ if (bop64_trace & AMD64_TRACE_BOP_PROP) {
+ printf("+getprop(name 0x%p/0x%" PRIx64
+ " '%s' value 0x%p/0x%" PRIx64 " ",
+ (void *)name, _ARG2(rp), name, (void *)value,
+ _ARG3(rp));
+ }
+
+#ifdef DEBUG
+ if (!amd64_check_arg((caddr_t)name, _ARG2(rp), "BOP_GETPROP",
+ "property name")) {
+ return_int(rp, -1);
+ return;
+ }
+
+ /*
+ * amd64_check_arg() can't be used here because krtld
+ * does a bop_getprop("whoami") with a buffer that is in stack
+ * space allocated just above AMD64 in memory, typically on the
+ * page mapped at 0x100f000), so just check to make sure the
+ * destination buffer is mapped in a way we can access.
+ */
+ if (!amd64_check_mapped_32((uint64_t)(uintptr_t)value,
+ "BOP_GETPROP", "property value buffer")) {
+ return_int(rp, -1);
+ return;
+ }
+#endif /* DEBUG */
+
+ if (strcmp(name, "memory-update") == 0) {
+ int retval;
+
+ retval = BOP_GETPROP(bop, name, value);
+ (void) amd64_update_ml64(bop);
+ return_int(rp, retval);
+ } else if (strcmp(name, "mmu-modlist") == 0) {
+ (void) strcpy(value, amd64_getmmulist());
+ return_int(rp, 0);
+ } else
+ return_int(rp, BOP_GETPROP(bop, name, value));
+
+ if (bop64_trace & AMD64_TRACE_BOP_PROP) {
+ static const char *string_props[] = {
+ "backfs-fstype",
+ "backfs-path",
+ "bootargs",
+ "bootpath",
+ "boot-path",
+ "boot-message",
+ "default-name",
+ "extent",
+ "frontfs-fstype",
+ "frontfs-path",
+ "fstype",
+ "impl-arch-name",
+ "mfg-name",
+ "whoami",
+ 0
+ };
+ const char * const *sp;
+
+ printf(" = %" PRId64, rp->r_rax);
+
+ /*
+ * (Sigh. This is a rather tawdry hack so that
+ * we can print out various "well-known" string
+ * properties as strings.)
+ */
+ for (sp = string_props; *sp; sp++)
+ if (strcmp(*sp, name) == 0) {
+ printf(" [= '%s']", value);
+ break;
+ }
+
+ printf("\n");
+ }
+
+ } else if (this == bop64->bsys_nextprop) {
+
+ char *prevprop = ADDR_TRUNC(_ARG2(rp));
+
+ if (bop64_trace & AMD64_TRACE_BOP_PROP) {
+ printf("+nextprop(prevprop 0x%p/0x%" PRIx64
+ "/'%s') ", (void *)prevprop, _ARG2(rp), prevprop);
+ trace = TRACE_ADDR_RETURN;
+ }
+
+#ifdef DEBUG
+ if (!amd64_check_arg((caddr_t)prevprop, _ARG2(rp),
+ "BOP_NEXTPROP", "previous property")) {
+ return_addr(rp, 0);
+ return;
+ }
+#endif /* DEBUG */
+
+ return_addr(rp, BOP_NEXTPROP(bop, prevprop));
+
+ } else if (this == bop64->bsys_printf) {
+
+ char lnbuf[128];
+ char *fmt = ADDR_TRUNC(_ARG2(rp));
+ int lnlen;
+
+#if 0 /* correct code */
+ ASSERT((uint16_t)rp->r_rax <= 8); /* no SSE regs! */
+#else /* XX64 */
+ /*
+ * Technically an ABI violation, gcc 3.2.3 currently
+ * only does a "mov $0, al" before calling printf, with
+ * the result that we tripped over this assert due to garbage
+ * in the upper 8 bytes of what would be ax.
+ */
+ ASSERT((uint8_t)rp->r_rax <= 8); /* no SSE regs! */
+#endif
+
+#ifdef DEBUG
+ if (!amd64_check_mapped_32((uint64_t)(uintptr_t)fmt,
+ "BOP_PRINTF", "fmt string"))
+ return;
+#endif /* DEBUG */
+
+ lnlen = amd64_snprintf64(lnbuf, sizeof (lnbuf), fmt,
+ _ARG3(rp), _ARG4(rp), _ARG5(rp), _ARG6(rp));
+
+ printf("%s%s", lnbuf,
+ (lnlen > sizeof (lnbuf)) ? " [truncated]\n" : "");
+
+ } else if (this == bop64->bsys_doint) {
+
+ int intnum = (int)_ARG2(rp);
+ struct bop_regs *regs = ADDR_TRUNC(_ARG3(rp));
+
+ /*
+ * (Looks like the -kernel- only does this for pci_check()
+ */
+
+ if (bop64_trace & AMD64_TRACE_BOP_BIOS) {
+ printf("+doint(intnum %d "
+ "regs 0x%p/0x%" PRIx64 ") ",
+ intnum, (void *)regs, _ARG3(rp));
+ trace = TRACE_VOID_RETURN;
+ }
+
+#ifdef DEBUG
+ if (!amd64_check_arg((caddr_t)regs, _ARG3(rp), "BOP_DOINT",
+ "regs"))
+ return;
+#endif /* DEBUG */
+
+ BOP_DOINT(bop, intnum, regs);
+
+ } else if (this == bop64->bsys_ealloc) {
+
+ caddr_t vahint = ADDR_TRUNC(_ARG2(rp));
+ size_t size = (size_t)_ARG3(rp);
+ int align = (int)_ARG4(rp);
+ int flags = (int)_ARG5(rp);
+ void *retval;
+
+ if (rp->r_cr3 != amd64_boot_pml4)
+ amd64_panic("bop64_ealloc() called with wrong 64-bit "
+ "page table start address\n (caller's cr3: "
+ "0x%llx, should be: 0x%llx)\n", rp->r_cr3,
+ amd64_boot_pml4);
+
+ if (bop64_trace & AMD64_TRACE_BOP_VM) {
+ printf("+ealloc(vahint 0x%p/0x%" PRIx64
+ " size %lu/%" PRIu64 " align %d flags 0x%x) ",
+ (void *)vahint, _ARG2(rp), size, _ARG3(rp), align,
+ flags);
+ trace = TRACE_ADDR_RETURN;
+ }
+
+#ifdef DEBUG
+ if (vahint)
+ amd64_assert_addr(vahint, _ARG2(rp), "BOP_EALLOC",
+ "vahint");
+#endif /* DEBUG */
+
+ retval = BOP_EALLOC(bop, vahint, size, align, flags);
+
+ /*
+ * Don't attempt to create 64-bit mappings for purely physical
+ * memory reservations or for failed allocations,
+ */
+ if (flags & BOPF_X86_ALLOC_PHYS)
+ return_paddr(rp, retval);
+ else {
+ if (retval != 0)
+ amd64_xlate_legacy_va((uint32_t)retval, size,
+ amd64_get_cr3(), amd64_boot_pml4);
+
+ return_addr(rp, retval);
+ }
+ } else
+ traceback64(rp, "BOP_xxx (@ 0x%" PRIx64 ") unimp", this);
+
+ switch (trace) {
+ case TRACE_NONE_RETURN:
+ break;
+ case TRACE_INT_RETURN:
+ printf(" = %" PRId64 "\n", rp->r_rax);
+ break;
+ case TRACE_ADDR_RETURN:
+ printf(" = 0x%p/0x%" PRIx64 "\n",
+ ADDR_TRUNC(rp->r_rax), rp->r_rax);
+ break;
+ case TRACE_VOID_RETURN:
+ printf(" = (void)\n");
+ break;
+ }
+}
+
+static struct bsys_mem64 *
+amd64_update_ml64(struct bootops *bop)
+{
+ extern struct memlist64 *amd64_convert_memlist(struct memlist *,
+ struct memlist64 *);
+
+ static struct bsys_mem64 __memlist64, *bop_ml64 = &__memlist64;
+
+ struct memlist64 *ml64 = amd64_memlistpage;
+
+ /*
+ * amd64_convert_memlist() returns a pointer to the entry one past the
+ * previous translated list, suitable for the start of the next new
+ * memlist64, so the assignments below may seem a bit non-intuitive
+ * at first...
+ */
+ bop_ml64->physinstalled = UINT64_FROMPTR32(ml64);
+ ml64 = amd64_convert_memlist(bop->boot_mem->physinstalled, ml64);
+
+ bop_ml64->physavail = UINT64_FROMPTR32(ml64);
+ ml64 = amd64_convert_memlist(bop->boot_mem->physavail, ml64);
+
+ bop_ml64->pcimem = UINT64_FROMPTR32(ml64);
+ ml64 = amd64_convert_memlist(bop->boot_mem->pcimem, ml64);
+ return (bop_ml64);
+}
+
+static struct bootops *saved_bootops;
+
+/*
+ * This is the 64-bit bootops vector that we hand to the 64-bit standalone
+ */
+struct bootops64 *
+init_bootops64(struct bootops *bop)
+{
+ static struct bootops64 __bootops64, *bop64 = &__bootops64;
+
+#define SET_BOP64(bop, opname) \
+ { \
+ extern uintptr_t bop64_##opname; \
+ (bop)->bsys_##opname = \
+ (fnaddr64_t)(uintptr_t)&bop64_##opname; \
+ }
+
+ /* move to main.c or to startup */
+
+ ASSERT(bop->bsys_version >= BO_VERSION);
+
+ amd64_memlistpage = (struct memlist64 *)
+ amd64_zalloc_identity(2 * AMD64_PAGESIZE);
+
+ saved_bootops = bop;
+ bop64->bsys_version = BO_VERSION;
+ bop64->boot_mem = (caddr64_t)(uintptr_t)amd64_update_ml64(bop);
+
+ SET_BOP64(bop64, alloc)
+ SET_BOP64(bop64, free)
+ SET_BOP64(bop64, getproplen)
+ SET_BOP64(bop64, getprop)
+ SET_BOP64(bop64, nextprop)
+ SET_BOP64(bop64, printf)
+ SET_BOP64(bop64, doint)
+ SET_BOP64(bop64, ealloc)
+
+#undef SET_BOP64
+
+ return (bop64);
+}
+
+static void
+amd64_invoke_boot_syscall(
+ struct amd64_machregs *rp,
+ struct boot_syscalls *bsys,
+ struct boot_syscalls64 *bsys64)
+{
+ fnaddr64_t this = (fnaddr64_t)rp->r_rip;
+
+ if (this == bsys64->getchar) {
+ rp->r_rax = BSVC_GETCHAR(bsys);
+ } else if (this == bsys64->putchar) {
+ BSVC_PUTCHAR(bsys, (uchar_t)rp->r_rdi);
+ } else if (this == bsys64->ischar) {
+ rp->r_rax = BSVC_ISCHAR(bsys);
+ } else
+ traceback64(rp, "bsys_xxx (type 0x%" PRIx64 ") unimp", this);
+}
+
+static struct boot_syscalls64 __boot_syscalls64; /* XXX - global scope */
+static struct boot_syscalls *saved_boot_syscallp;
+
+/*
+ * Return the 64-bit bsyscall vector that we hand to the 64-bit standalone
+ */
+struct boot_syscalls64 *
+init_boot_syscalls64(struct boot_syscalls *bsys)
+{
+ struct boot_syscalls64 *bsys64 = &__boot_syscalls64;
+
+ /*
+ * This variable is awful; the 'bsys' pointer should be
+ * the first argument to every bsys handler .. but in the
+ * meantime, this'll do.
+ */
+ saved_boot_syscallp = bsys;
+
+ bzero(bsys64, sizeof (*bsys64));
+
+#define SET_BSYS64(bsys, opname) \
+ { \
+ extern uintptr_t bsys64_##opname; \
+ (bsys)->opname = \
+ (fnaddr64_t)(uintptr_t)&bsys64_##opname; \
+ }
+
+ SET_BSYS64(bsys64, getchar)
+ SET_BSYS64(bsys64, putchar)
+ SET_BSYS64(bsys64, ischar)
+
+#undef SET_BSYS64
+
+ return (bsys64);
+}
+
+static void dump_desctbr(const char *, desctbr_t *);
+static void dump_desctbr64(const char *, desctbr64_t *);
+
+/*
+ * After stashing machine state we must convert the tss gdt entry from
+ * busy to available type.
+ */
+void
+amd64_i386_clrtss(struct i386_machregs *rp)
+{
+#if 0
+ system_desc_t *ssd;
+
+ if (rp->r_tr != 0) {
+ ASSERT(SELTOIDX(rp->r_tr) < SELTOIDX(rp->r_gdt.dtr_limit));
+ ASSERT((rp->r_tr & CPL_MASK) == 0);
+ ssd = (system_desc_t *)(rp->r_gdt.dtr_base + rp->r_tr);
+
+ ASSERT(ssd->ssd_type == SDT_SYSTSSBSY);
+ ssd->ssd_type = SDT_SYSTSS;
+ ASSERT(rp->r_gdt.dtr_limit != 0);
+ }
+#endif
+}
+
+static void
+amd64_clrtss(struct amd64_machregs *rp)
+{
+ system_desc64_t *ssd;
+
+ if (rp->r_tr != 0) {
+
+ ASSERT(SELTOIDX(rp->r_tr) < SELTOIDX(rp->r_gdt.dtr_limit));
+ ASSERT((rp->r_tr & CPL_MASK) == 0);
+ ssd = (system_desc64_t *)(uintptr_t)
+ (rp->r_gdt.dtr_base + rp->r_tr);
+
+ ssd->ssd_type = SDT_SYSTSS;
+ ASSERT(rp->r_gdt.dtr_limit != 0);
+ }
+}
+
+void
+amd64_vtrap(struct amd64_machregs *rp)
+{
+ uintptr_t addr = (uintptr_t)rp->r_rip;
+
+ /*
+ * __vtrap_common always sets r_trapno to -1
+ */
+ if (rp->r_trapno == -1) {
+ if ((addr - (uintptr_t)&bsys64_first) <=
+ ((uintptr_t)&bsys64_last - (uintptr_t)&bsys64_first)) {
+ amd64_invoke_boot_syscall(rp,
+ saved_boot_syscallp, &__boot_syscalls64);
+ } else if ((addr - (uintptr_t)&bop64_first) <=
+ ((uintptr_t)&bop64_last - (uintptr_t)&bop64_first)) {
+ struct bootops64 *bop64 = ADDR_TRUNC(_ARG1(rp));
+ amd64_invoke_bootop(rp, bop64, saved_bootops);
+ }
+ } else {
+ /*
+ * we took a real exception.
+ */
+ idt_exception(rp);
+ }
+
+ amd64_clrtss(rp);
+}
+
+static const char *
+desc_type_name(uint_t type)
+{
+ switch (type) {
+ case SDT_SYSNULL:
+ case SDT_SYSNULL2:
+ case SDT_SYSNULL3:
+ case SDT_SYSNULL4: return ("illegal");
+ case SDT_SYS286TSS: return ("16-bit tss");
+ case SDT_SYSLDT: return ("ldt");
+ case SDT_SYS286BSY: return ("16-bit tss busy");
+ case SDT_SYS286CGT: return ("16-bit call gate");
+ case SDT_SYSTASKGT: return ("task gate");
+ case SDT_SYS286IGT: return ("16-bit intr gate");
+ case SDT_SYS286TGT: return ("16-bit trap gate");
+ case SDT_SYSTSS: return ("32-bit tss");
+ case SDT_SYSTSSBSY: return ("32-bit tss busy");
+ case SDT_SYSCGT: return ("32-bit call gate");
+ case SDT_SYSIGT: return ("32-bit intr gate");
+ case SDT_SYSTGT: return ("32-bit trap gate");
+
+ case SDT_MEMRO: return ("r-- --");
+ case SDT_MEMROA: return ("r-- -a");
+ case SDT_MEMRW: return ("rw- --");
+ case SDT_MEMRWA: return ("rw- -a");
+ case SDT_MEMROD: return ("r-- d-");
+ case SDT_MEMRODA: return ("r-- da");
+ case SDT_MEMRWD: return ("rw- d-");
+ case SDT_MEMRWDA: return ("rw- da");
+ case SDT_MEME: return ("--x --");
+ case SDT_MEMEA: return ("--x -a");
+ case SDT_MEMER: return ("r-x --");
+ case SDT_MEMERA: return ("r-x -a");
+ case SDT_MEMEC: return ("--x c-");
+ case SDT_MEMEAC: return ("--x ca");
+ case SDT_MEMERC: return ("r-x c-");
+ case SDT_MEMERAC: return ("r-x ca");
+ default: return ("(unknown)");
+ }
+}
+
+static size_t
+dump_ssd(void *desc)
+{
+ uint_t type = ((struct user_segment_descriptor *)desc)->usd_type;
+
+ printf("type %2d (%s) ", type, desc_type_name(type));
+
+ switch (type) {
+
+ case SDT_SYSTASKGT: {
+ struct gate_segment_descriptor *sgd = desc;
+
+ printf("tss sel 0x%x dpl %d %spresent\n",
+ sgd->sgd_selector, sgd->sgd_dpl,
+ sgd->sgd_p ? "" : "NOT ");
+ return (sizeof (*sgd));
+ }
+
+ case SDT_SYSLDT:
+ case SDT_SYSTSS:
+ case SDT_SYSTSSBSY: {
+ struct system_segment_descriptor *ssd = desc;
+ uint32_t base = ssd->ssd_lobase |
+ (ssd->ssd_midbase << 16) | (ssd->ssd_hibase << 24);
+ uint32_t lim = ssd->ssd_lolimit |
+ (ssd->ssd_hilimit << 16);
+
+ printf("base 0x%x lim 0x%x dpl %d %spresent\n",
+ base, ssd->ssd_gran ? lim * 4096 : lim,
+ ssd->ssd_dpl, ssd->ssd_p ? "" : "NOT ");
+ return (sizeof (*ssd));
+ }
+
+ case SDT_SYSCGT:
+ case SDT_SYSIGT:
+ case SDT_SYSTGT: {
+ struct gate_segment_descriptor *sgd = desc;
+
+ printf("target 0x%x:0x%x dpl %d %spresent",
+ sgd->sgd_selector, sgd->sgd_looffset |
+ (sgd->sgd_hioffset << 16),
+ sgd->sgd_dpl, sgd->sgd_p ? "" : "NOT ");
+ if (type == SDT_SYSCGT)
+ printf(" %d parms", sgd->sgd_stkcpy);
+ printf("\n");
+ return (sizeof (*sgd));
+ }
+
+ case SDT_MEMRO:
+ case SDT_MEMROA:
+ case SDT_MEMRW:
+ case SDT_MEMRWA:
+ case SDT_MEMROD:
+ case SDT_MEMRODA:
+ case SDT_MEMRWD:
+ case SDT_MEMRWDA:
+ case SDT_MEME:
+ case SDT_MEMEA:
+ case SDT_MEMER:
+ case SDT_MEMERA:
+ case SDT_MEMEC:
+ case SDT_MEMEAC:
+ case SDT_MEMERC:
+ case SDT_MEMERAC: {
+ struct user_segment_descriptor *usd = desc;
+ uint32_t base = usd->usd_lobase |
+ (usd->usd_midbase << 16) | (usd->usd_hibase << 24);
+ uint32_t lim = usd->usd_lolimit |
+ (usd->usd_hilimit << 16);
+
+ printf("base 0x%x lim 0x%x dpl %d %spresent\n",
+ base, usd->usd_gran ? lim * 4096 : lim,
+ usd->usd_dpl, usd->usd_p ? "" : "NOT ");
+ return (sizeof (*usd));
+ }
+
+ default: {
+ uint16_t *u16 = desc;
+ struct system_segment_descriptor *ssd = desc;
+
+ printf("0x%x.%x.%x.%x dpl %d %spresent\n",
+ u16[0], u16[1], u16[2], u16[3],
+ ssd->ssd_dpl, ssd->ssd_p ? "" : "NOT ");
+ return (sizeof (*ssd));
+ }
+
+ }
+}
+
+static void
+dump_desctbr(const char *name, desctbr_t *dtr)
+{
+ uintptr_t entry, theend;
+
+ printf(" %s [limit %x base %x]\n",
+ name, dtr->dtr_limit, dtr->dtr_base);
+
+ theend = (uintptr_t)(dtr->dtr_base + dtr->dtr_limit);
+
+ for (entry = dtr->dtr_base; entry < theend; ) {
+ printf(" %6lu: ", entry - (uintptr_t)dtr->dtr_base);
+ entry += dump_ssd((void *)entry);
+ /*
+ * Hack to print only the hardware entries in the idt
+ */
+ if (entry - (uintptr_t)dtr->dtr_base > 19 &&
+ strcmp(name, "idt") == 0)
+ return;
+ }
+}
+
+static void
+dump_user_descriptor(desctbr_t *gdt, const char *name, uint16_t sel)
+{
+ uint_t index;
+ static const char fmt1[] = " %8s %16x\n ";
+
+ printf(fmt1, name, sel);
+
+ if ((index = SELTOIDX(sel)) == 0)
+ printf("<null selector>\n");
+ else if (index > gdt->dtr_limit)
+ printf("<selector out of range?>\n");
+ else {
+ uintptr_t entry =
+ (uintptr_t)gdt->dtr_base + IDXTOSEL(index);
+
+ (void) dump_ssd((void *)entry);
+ }
+}
+
+void
+amd64_dump_i386_machregs(struct i386_machregs *rp)
+{
+ static const char fmt1[] = " %8s %16x\n";
+ static const char fmt2[] = " %8s %16x %8s %16x\n";
+ static const char fmtb[] = " %8s %16b\n";
+
+ printf("struct i386_machregs @0x%p = {\n", (void *)rp);
+
+#if defined(__GNUC__)
+ printf(fmt1, "cr0", rp->r_cr0);
+ printf(fmt1, "cr2", rp->r_cr2);
+ printf(fmt1, "cr3", rp->r_cr3);
+ printf(fmt1, "cr4", rp->r_cr4);
+#else
+ printf(fmtb, "cr0", rp->r_cr0, FMT_CR0);
+ printf(fmt1, "cr2", rp->r_cr2);
+ printf(fmtb, "cr3", rp->r_cr3, FMT_CR3);
+ printf(fmtb, "cr4", rp->r_cr4, FMT_CR4);
+#endif
+ dump_desctbr("gdt", &rp->r_gdt);
+ dump_desctbr("idt", &rp->r_idt);
+
+ dump_user_descriptor(&rp->r_gdt, "ldt", rp->r_ldt);
+ dump_user_descriptor(&rp->r_gdt, "tr", rp->r_tr);
+
+ printf(fmt2, "edi", rp->r_edi, "esi", rp->r_esi);
+ printf(fmt2, "ebp", rp->r_ebp, "esp", rp->r_esp);
+ printf(fmt2, "ebx", rp->r_ebx, "ecx", rp->r_ecx);
+
+ printf(fmt2, "eip", rp->r_eip, "efl", rp->r_efl);
+ printf(fmt1, "uesp", rp->r_uesp);
+
+ dump_user_descriptor(&rp->r_gdt, "cs", (uint16_t)rp->r_cs);
+ dump_user_descriptor(&rp->r_gdt, "ds", (uint16_t)rp->r_ds);
+ dump_user_descriptor(&rp->r_gdt, "es", (uint16_t)rp->r_es);
+ dump_user_descriptor(&rp->r_gdt, "fs", (uint16_t)rp->r_fs);
+ dump_user_descriptor(&rp->r_gdt, "gs", (uint16_t)rp->r_gs);
+ dump_user_descriptor(&rp->r_gdt, "ss", (uint16_t)rp->r_ss);
+
+ printf(fmt2, "trapno", rp->r_trapno, "err", rp->r_err);
+
+ printf("}\n");
+}
+
+static const char *
+desc64_type_name(uint_t type)
+{
+ switch (type) {
+ case SDT_SYSNULL:
+ case SDT_SYS286TSS:
+ case SDT_SYS286BSY:
+ case SDT_SYS286CGT:
+ case SDT_SYSTASKGT:
+ case SDT_SYS286IGT:
+ case SDT_SYS286TGT:
+ case SDT_SYSNULL2:
+ case SDT_SYSNULL3:
+ case SDT_SYSNULL4: return ("illegal");
+
+ case SDT_SYSLDT: return ("64-bit ldt");
+ case SDT_SYSTSS: return ("64-bit tss");
+ case SDT_SYSTSSBSY: return ("64-bit tss busy");
+ case SDT_SYSCGT: return ("64-bit call gate");
+ case SDT_SYSIGT: return ("64-bit intr gate");
+ case SDT_SYSTGT: return ("64-bit trap gate");
+
+ case SDT_MEMRO: return ("r-- --");
+ case SDT_MEMROA: return ("r-- -a");
+ case SDT_MEMRW: return ("rw- --");
+ case SDT_MEMRWA: return ("rw- -a");
+ case SDT_MEMROD: return ("r-- d-");
+ case SDT_MEMRODA: return ("r-- da");
+ case SDT_MEMRWD: return ("rw- d-");
+ case SDT_MEMRWDA: return ("rw- da");
+ case SDT_MEME: return ("--x --");
+ case SDT_MEMEA: return ("--x -a");
+ case SDT_MEMER: return ("r-x --");
+ case SDT_MEMERA: return ("r-x -a");
+ case SDT_MEMEC: return ("--x c-");
+ case SDT_MEMEAC: return ("--x ca");
+ case SDT_MEMERC: return ("r-x c-");
+ case SDT_MEMERAC: return ("r-x ca");
+ default: return ("(unknown)");
+ }
+}
+
+static size_t
+dump_ssd64(void *desc)
+{
+ uint_t type = ((struct user_segment_descriptor64 *)desc)->usd_type;
+
+ printf("type %d (%s) ", type, desc64_type_name(type));
+
+ switch (type) {
+ case SDT_SYSLDT:
+ case SDT_SYSTSS:
+ case SDT_SYSTSSBSY: {
+ struct system_segment_descriptor64 *ssd = desc;
+ uint64_t base = (uint64_t)ssd->ssd_lobase |
+ ((uint64_t)ssd->ssd_midbase << 16) |
+ ((uint64_t)ssd->ssd_hibase << 24) |
+ ((uint64_t)ssd->ssd_hi64base << 32);
+ uint32_t lim = ssd->ssd_lolimit |
+ (ssd->ssd_hilimit << 16);
+
+ printf("base 0x%" PRIx64
+ " lim 0x%x dpl %d %spresent\n",
+ base, ssd->ssd_gran ? lim * 4096 : lim,
+ ssd->ssd_dpl, ssd->ssd_p ? "" : "NOT ");
+
+ if (ssd->ssd_zero1 != 0 || ssd->ssd_zero2)
+ amd64_warning("zero1 field 0x%x zero2 field "
+ "0x%x", ssd->ssd_zero1, ssd->ssd_zero2);
+ return (sizeof (*ssd));
+ }
+
+ case SDT_SYSCGT:
+ case SDT_SYSIGT:
+ case SDT_SYSTGT: {
+ struct gate_segment_descriptor64 *sgd = desc;
+
+ printf("target 0x%x:0x%" PRIx64 " dpl %d "
+ "%spresent\n", sgd->sgd_selector,
+ (uint64_t)sgd->sgd_looffset |
+ ((uint64_t)sgd->sgd_hioffset) << 16 |
+ ((uint64_t)sgd->sgd_hi64offset),
+ sgd->sgd_dpl, sgd->sgd_p ? "" : "NOT ");
+
+ if (type == SDT_SYSCGT && sgd->sgd_zero != 0)
+ amd64_warning("zero field 0x%x\n",
+ sgd->sgd_zero);
+ return (sizeof (*sgd));
+ }
+
+ case SDT_MEMRO:
+ case SDT_MEMROA:
+ case SDT_MEMRW:
+ case SDT_MEMRWA:
+ case SDT_MEMROD:
+ case SDT_MEMRODA:
+ case SDT_MEMRWD:
+ case SDT_MEMRWDA: {
+ struct user_segment_descriptor64 *usd = desc;
+
+ printf("%spresent\n", usd->usd_p ? "" : "NOT ");
+ return (sizeof (*usd));
+ }
+
+ case SDT_MEME:
+ case SDT_MEMEA:
+ case SDT_MEMER:
+ case SDT_MEMERA:
+ case SDT_MEMEC:
+ case SDT_MEMEAC:
+ case SDT_MEMERC:
+ case SDT_MEMERAC: {
+ struct user_segment_descriptor64 *usd = desc;
+
+ printf("%sconforming, dpl %d, %spresent, "
+ "long %d, defopsz %d\n",
+ BITX(usd->usd_type, 2, 2) ? "" : "non-",
+ usd->usd_dpl,
+ usd->usd_p ? "" : "NOT ",
+ usd->usd_long, usd->usd_def32);
+ if (usd->usd_long && usd->usd_def32)
+ amd64_warning("both the L and D bit are "
+ "set!\n");
+ return (sizeof (*usd));
+ }
+
+ default:
+ printf("\n");
+ return (sizeof (struct user_segment_descriptor64));
+ }
+}
+
+static void
+dump_desctbr64(const char *name, desctbr64_t *dtr)
+{
+ uintptr_t entry, theend;
+
+ printf(" %s [limit 0x%x base 0x%" PRIx64 "]\n",
+ name, dtr->dtr_limit, dtr->dtr_base);
+
+ theend = (uintptr_t)(dtr->dtr_base + dtr->dtr_limit);
+
+ for (entry = (uintptr_t)dtr->dtr_base; entry < theend; ) {
+ printf(" %6lu: ", entry - (uintptr_t)dtr->dtr_base);
+ entry += dump_ssd64((void *)entry);
+
+ /*
+ * Hack to print only the hardware entries in the idt
+ */
+ if (entry - (uintptr_t)dtr->dtr_base > 19 &&
+ strcmp(name, "idt") == 0)
+ return;
+ }
+}
+
+static void
+dump_user_descriptor64(desctbr64_t *gdt, const char *name, uint16_t sel)
+{
+ uint_t index;
+ static const char fmt1[] = " %8s %16x\n ";
+
+ printf(fmt1, name, sel);
+
+ if ((index = SELTOIDX(sel)) == 0)
+ printf("<null selector>\n");
+ else if (index > gdt->dtr_limit)
+ printf("<selector out of range?>\n");
+ else {
+ uintptr_t entry =
+ (uintptr_t)gdt->dtr_base + IDXTOSEL(index);
+
+ (void) dump_ssd((void *)entry);
+ }
+}
+
+void
+amd64_dump_amd64_machregs(struct amd64_machregs *rp)
+{
+ static const char fmt1[] = " %8s %16" PRIx64 "\n";
+ static const char fmt2[] = " %8s %16" PRIx64 " %8s %16" PRIx64 "\n";
+ static const char fmtb[] = " %8s %16b\n";
+
+ printf("struct amd64_machregs @0x%p = {\n", (void *)rp);
+
+ printf(fmt1, "kgsbase", rp->r_kgsbase);
+ printf(fmt2, "gsbase", rp->r_gsbase, "fsbase", rp->r_fsbase);
+
+ printf(fmt2, "cr0", rp->r_cr0, "cr2", rp->r_cr2);
+ printf(fmt2, "cr3", rp->r_cr3, "cr4", rp->r_cr4);
+ printf(fmt1, "cr8", rp->r_cr8);
+
+#if !defined(__GNUC__)
+ printf(fmtb, "cr0", (uint_t)rp->r_cr0, FMT_CR0);
+ printf(fmtb, "cr3", (uint_t)rp->r_cr3, FMT_CR3);
+ printf(fmtb, "cr4", (uint_t)rp->r_cr4, FMT_CR4);
+#endif
+
+ dump_desctbr64("gdt", &rp->r_gdt);
+ dump_desctbr64("idt", &rp->r_idt);
+
+ dump_user_descriptor64(&rp->r_gdt, "ldt", (uint16_t)rp->r_ldt);
+ dump_user_descriptor64(&rp->r_gdt, "tr", (uint16_t)rp->r_tr);
+
+ printf(fmt2, "rdi", rp->r_rdi, "rsi", rp->r_rsi);
+ printf(fmt2, "rdx", rp->r_rdx, "rcx", rp->r_rcx);
+ printf(fmt2, "r8", rp->r_r8, "r9", rp->r_r9);
+ printf(fmt2, "rax", rp->r_rax, "rbx", rp->r_rbx);
+ printf(fmt2, "rbp", rp->r_rbp, "r10", rp->r_r10);
+ printf(fmt2, "r11", rp->r_r11, "r12", rp->r_r12);
+ printf(fmt2, "r13", rp->r_r13, "r14", rp->r_r14);
+ printf(fmt2, "r15", rp->r_r15, "rsp", rp->r_rsp);
+ printf(fmt2, "rip", rp->r_rip, "rfl", rp->r_rfl);
+
+ dump_user_descriptor64(&rp->r_gdt, "cs", (uint16_t)rp->r_cs);
+ dump_user_descriptor64(&rp->r_gdt, "ds", (uint16_t)rp->r_ds);
+ dump_user_descriptor64(&rp->r_gdt, "es", (uint16_t)rp->r_es);
+ dump_user_descriptor64(&rp->r_gdt, "fs", (uint16_t)rp->r_fs);
+ dump_user_descriptor64(&rp->r_gdt, "gs", (uint16_t)rp->r_gs);
+ dump_user_descriptor64(&rp->r_gdt, "ss", (uint16_t)rp->r_ss);
+
+ printf(fmt2, "trapno", rp->r_trapno, "err", rp->r_err);
+
+ printf("}\n");
+}
diff --git a/usr/src/psm/stand/boot/common/heap_kmem.c b/usr/src/psm/stand/boot/common/heap_kmem.c
new file mode 100644
index 0000000000..344325ca99
--- /dev/null
+++ b/usr/src/psm/stand/boot/common/heap_kmem.c
@@ -0,0 +1,882 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if 1
+#undef DEBUG
+#endif
+
+/* #define DEBUG ON */
+
+/*
+ * Conditions on use:
+ * kmem_alloc and kmem_free must not be called from interrupt level,
+ * except from software interrupt level. This is because they are
+ * not reentrant, and only block out software interrupts. They take
+ * too long to block any real devices. There is a routine
+ * kmem_free_intr that can be used to free blocks at interrupt level,
+ * but only up to splimp, not higher. This is because kmem_free_intr
+ * only spl's to splimp.
+ *
+ * Also, these routines are not that fast, so they should not be used
+ * in very frequent operations (e.g. operations that happen more often
+ * than, say, once every few seconds).
+ */
+
+/*
+ * description:
+ * Yet another memory allocator, this one based on a method
+ * described in C.J. Stephenson, "Fast Fits", IBM Sys. Journal
+ *
+ * The basic data structure is a "Cartesian" binary tree, in which
+ * nodes are ordered by ascending addresses (thus minimizing free
+ * list insertion time) and block sizes decrease with depth in the
+ * tree (thus minimizing search time for a block of a given size).
+ *
+ * In other words, for any node s, letting D(s) denote
+ * the set of descendents of s, we have:
+ *
+ * a. addr(D(left(s))) < addr(s) < addr(D(right(s)))
+ * b. len(D(left(s))) <= len(s) >= len(D(right(s)))
+ */
+
+#include <sys/param.h>
+#include <sys/sysmacros.h>
+#include <sys/salib.h>
+#include <sys/saio.h>
+#include <sys/promif.h>
+
+/*
+ * The node header structure.
+ *
+ * To reduce storage consumption, a header block is associated with
+ * free blocks only, not allocated blocks.
+ * When a free block is allocated, its header block is put on
+ * a free header block list.
+ *
+ * This creates a header space and a free block space.
+ * The left pointer of a header blocks is used to chain free header
+ * blocks together.
+ */
+
+typedef enum {false, true} bool;
+typedef struct freehdr *Freehdr;
+typedef struct dblk *Dblk;
+
+/*
+ * Description of a header for a free block
+ * Only free blocks have such headers.
+ */
+struct freehdr {
+ Freehdr left; /* Left tree pointer */
+ Freehdr right; /* Right tree pointer */
+ Dblk block; /* Ptr to the data block */
+ size_t size; /* Size of the data block */
+};
+
+#define NIL ((Freehdr) 0)
+#define WORDSIZE sizeof (int)
+#define SMALLEST_BLK 1 /* Size of smallest block */
+
+/*
+ * Description of a data block.
+ */
+struct dblk {
+ char data[1]; /* Addr returned to the caller */
+};
+
+/*
+ * weight(x) is the size of a block, in bytes; or 0 if and only if x
+ * is a null pointer. It is the responsibility of kmem_alloc() and
+ * kmem_free() to keep zero-length blocks out of the arena.
+ */
+
+#define weight(x) ((x) == NIL? 0: (x->size))
+#define nextblk(p, size) ((Dblk) ((char *)(p) + (size)))
+#define max(a, b) ((a) < (b)? (b): (a))
+
+void *kmem_alloc(size_t, int);
+void kmem_free(void *ptr, size_t nbytes);
+Freehdr getfreehdr(void);
+static bool morecore(size_t);
+void insert(Dblk p, size_t len, Freehdr *tree);
+void freehdr(Freehdr p);
+void delete(Freehdr *p);
+static void check_need_to_free(void);
+extern caddr_t resalloc(enum RESOURCES, size_t, caddr_t, int);
+#ifdef __sparc
+extern void resalloc_init(void);
+#endif
+extern int splnet(void);
+extern int splimp(void);
+extern void splx(int);
+
+/*
+ * Structure containing various info about allocated memory.
+ */
+#define NEED_TO_FREE_SIZE 5
+struct kmem_info {
+ Freehdr free_root;
+ Freehdr free_hdr_list;
+ struct map *map;
+ struct pte *pte;
+ caddr_t vaddr;
+ struct need_to_free {
+ caddr_t addr;
+ size_t nbytes;
+ } need_to_free_list, need_to_free[NEED_TO_FREE_SIZE];
+} kmem_info;
+
+
+struct map *kernelmap;
+
+#ifdef DEBUG
+static void prtree(Freehdr, char *);
+#endif
+
+/*
+ * Initialize kernel memory allocator
+ */
+
+void
+kmem_init(void)
+{
+ int i;
+ struct need_to_free *ntf;
+
+#ifdef DEBUG
+printf("kmem_init entered\n");
+#endif
+
+#ifdef __sparc
+ resalloc_init();
+#endif
+
+ kmem_info.free_root = NIL;
+ kmem_info.free_hdr_list = NULL;
+ kmem_info.map = kernelmap;
+ kmem_info.need_to_free_list.addr = 0;
+ ntf = kmem_info.need_to_free;
+ for (i = 0; i < NEED_TO_FREE_SIZE; i++) {
+ ntf[i].addr = 0;
+ }
+#ifdef DEBUG
+printf("kmem_init returning\n");
+prtree(kmem_info.free_root, "kmem_init");
+#endif
+}
+
+/*
+ * Insert a new node in a cartesian tree or subtree, placing it
+ * in the correct position with respect to the existing nodes.
+ *
+ * algorithm:
+ * Starting from the root, a binary search is made for the new
+ * node. If this search were allowed to continue, it would
+ * eventually fail (since there cannot already be a node at the
+ * given address); but in fact it stops when it reaches a node in
+ * the tree which has a length less than that of the new node (or
+ * when it reaches a null tree pointer). The new node is then
+ * inserted at the root of the subtree for which the shorter node
+ * forms the old root (or in place of the null pointer).
+ */
+
+
+void
+insert(Dblk p, /* Ptr to the block to insert */
+ size_t len, /* Length of new node */
+ Freehdr *tree) /* Address of ptr to root */
+{
+ Freehdr x;
+ Freehdr *left_hook; /* Temp for insertion */
+ Freehdr *right_hook; /* Temp for insertion */
+ Freehdr newhdr;
+
+ x = *tree;
+ /*
+ * Search for the first node which has a weight less
+ * than that of the new node; this will be the
+ * point at which we insert the new node.
+ */
+
+ while (weight(x) >= len) {
+ if (p < x->block)
+ tree = &x->left;
+ else
+ tree = &x->right;
+ x = *tree;
+ }
+
+ /*
+ * Perform root insertion. The variable x traces a path through
+ * the tree, and with the help of left_hook and right_hook,
+ * rewrites all links that cross the territory occupied
+ * by p. Note that this improves performance under
+ * paging.
+ */
+
+ newhdr = getfreehdr();
+ *tree = newhdr;
+ left_hook = &newhdr->left;
+ right_hook = &newhdr->right;
+
+ newhdr->left = NIL;
+ newhdr->right = NIL;
+ newhdr->block = p;
+ newhdr->size = len;
+
+ while (x != NIL) {
+ /*
+ * Remark:
+ * The name 'left_hook' is somewhat confusing, since
+ * it is always set to the address of a .right link
+ * field. However, its value is always an address
+ * below (i.e., to the left of) p. Similarly
+ * for right_hook. The values of left_hook and
+ * right_hook converge toward the value of p,
+ * as in a classical binary search.
+ */
+ if (x->block < p) {
+ /*
+ * rewrite link crossing from the left
+ */
+ *left_hook = x;
+ left_hook = &x->right;
+ x = x->right;
+ } else {
+ /*
+ * rewrite link crossing from the right
+ */
+ *right_hook = x;
+ right_hook = &x->left;
+ x = x->left;
+ } /* else */
+ } /* while */
+
+ *left_hook = *right_hook = NIL; /* clear remaining hooks */
+
+} /* insert */
+
+
+/*
+ * Delete a node from a cartesian tree. p is the address of
+ * a pointer to the node which is to be deleted.
+ *
+ * algorithm:
+ * The left and right sons of the node to be deleted define two
+ * subtrees which are to be merged and attached in place of the
+ * deleted node. Each node on the inside edges of these two
+ * subtrees is examined and longer nodes are placed above the
+ * shorter ones.
+ *
+ * On entry:
+ * *p is assumed to be non-null.
+ */
+
+void
+delete(Freehdr *p)
+{
+ Freehdr x;
+ Freehdr left_branch; /* left subtree of deleted node */
+ Freehdr right_branch; /* right subtree of deleted node */
+
+ x = *p;
+ left_branch = x->left;
+ right_branch = x->right;
+
+ while (left_branch != right_branch) {
+ /*
+ * iterate until left branch and right branch are
+ * both NIL.
+ */
+ if (weight(left_branch) >= weight(right_branch)) {
+ /*
+ * promote the left branch
+ */
+ *p = left_branch;
+ p = &left_branch->right;
+ left_branch = left_branch->right;
+ } else {
+ /*
+ * promote the right branch
+ */
+ *p = right_branch;
+ p = &right_branch->left;
+ right_branch = right_branch->left;
+ } /* else */
+ } /* while */
+ *p = NIL;
+ freehdr(x);
+} /* delete */
+
+
+/*
+ * Demote a node in a cartesian tree, if necessary, to establish
+ * the required vertical ordering.
+ *
+ * algorithm:
+ * The left and right subtrees of the node to be demoted are to
+ * be partially merged and attached in place of the demoted node.
+ * The nodes on the inside edges of these two subtrees are
+ * examined and the longer nodes are placed above the shorter
+ * ones, until a node is reached which has a length no greater
+ * than that of the node being demoted (or until a null pointer
+ * is reached). The node is then attached at this point, and
+ * the remaining subtrees (if any) become its descendants.
+ *
+ * on entry:
+ * a. All the nodes in the tree, including the one to be demoted,
+ * must be correctly ordered horizontally;
+ * b. All the nodes except the one to be demoted must also be
+ * correctly positioned vertically. The node to be demoted
+ * may be already correctly positioned vertically, or it may
+ * have a length which is less than that of one or both of
+ * its progeny.
+ * c. *p is non-null
+ */
+
+
+static void
+demote(Freehdr *p)
+{
+ Freehdr x; /* addr of node to be demoted */
+ Freehdr left_branch;
+ Freehdr right_branch;
+ size_t wx;
+
+ x = *p;
+ left_branch = x->left;
+ right_branch = x->right;
+ wx = weight(x);
+
+ while (weight(left_branch) > wx || weight(right_branch) > wx) {
+ /*
+ * select a descendant branch for promotion
+ */
+ if (weight(left_branch) >= weight(right_branch)) {
+ /*
+ * promote the left branch
+ */
+ *p = left_branch;
+ p = &left_branch->right;
+ left_branch = *p;
+ } else {
+ /*
+ * promote the right branch
+ */
+ *p = right_branch;
+ p = &right_branch->left;
+ right_branch = *p;
+ } /* else */
+ } /* while */
+
+ *p = x; /* attach demoted node here */
+ x->left = left_branch;
+ x->right = right_branch;
+} /* demote */
+
+/*
+ * Allocate a block of storage
+ *
+ * algorithm:
+ * The freelist is searched by descending the tree from the root
+ * so that at each decision point the "better fitting" child node
+ * is chosen (i.e., the shorter one, if it is long enough, or
+ * the longer one, otherwise). The descent stops when both
+ * child nodes are too short.
+ *
+ * function result:
+ * kmem_alloc returns a pointer to the allocated block; a null
+ * pointer indicates storage could not be allocated.
+ */
+/*
+ * We need to return blocks that are on word boundaries so that callers
+ * that are putting int's into the area will work. Since we allow
+ * arbitrary free'ing, we need a weight function that considers
+ * free blocks starting on an odd boundary special. Allocation is
+ * aligned to 8 byte boundaries (ALIGN).
+ */
+#define ALIGN 8 /* doubleword aligned .. */
+#define ALIGNMASK (ALIGN-1)
+#define ALIGNMORE(addr) (ALIGN - ((uintptr_t)(addr) & ALIGNMASK))
+
+/*
+ * If it is empty then weight == 0
+ * If it is aligned then weight == size
+ * If it is unaligned
+ * if not enough room to align then weight == 0
+ * else weight == aligned size
+ */
+#define mweight(x) ((x) == NIL ? 0 : \
+ ((((uintptr_t)(x)->block) & ALIGNMASK) == 0 ? (x)->size : \
+ (((x)->size <= ALIGNMORE((x)->block)) ? 0 : \
+ (x)->size - ALIGNMORE((x)->block))))
+
+/*ARGSUSED1*/
+void *
+kmem_alloc(size_t nbytes, int kmflag)
+{
+ Freehdr a; /* ptr to node to be allocated */
+ Freehdr *p; /* address of ptr to node */
+ size_t left_weight;
+ size_t right_weight;
+ Freehdr left_son;
+ Freehdr right_son;
+ char *retblock; /* Address returned to the user */
+ int s;
+#ifdef DEBUG
+ printf("kmem_alloc(nbytes 0x%lx)\n", nbytes);
+#endif /* DEBUG */
+
+ if (nbytes == 0) {
+ return (NULL);
+ }
+ s = splnet();
+
+ if (nbytes < SMALLEST_BLK) {
+ printf("illegal kmem_alloc call for %lx bytes\n", nbytes);
+ prom_panic("kmem_alloc");
+ }
+ check_need_to_free();
+
+ /*
+ * ensure that at least one block is big enough to satisfy
+ * the request.
+ */
+
+ if (mweight(kmem_info.free_root) <= nbytes) {
+ /*
+ * the largest block is not enough.
+ */
+ if (!morecore(nbytes)) {
+ printf("kmem_alloc failed, nbytes %lx\n", nbytes);
+ prom_panic("kmem_alloc");
+ }
+ }
+
+ /*
+ * search down through the tree until a suitable block is
+ * found. At each decision point, select the better
+ * fitting node.
+ */
+
+ p = (Freehdr *) &kmem_info.free_root;
+ a = *p;
+ left_son = a->left;
+ right_son = a->right;
+ left_weight = mweight(left_son);
+ right_weight = mweight(right_son);
+
+ while (left_weight >= nbytes || right_weight >= nbytes) {
+ if (left_weight <= right_weight) {
+ if (left_weight >= nbytes) {
+ p = &a->left;
+ a = left_son;
+ } else {
+ p = &a->right;
+ a = right_son;
+ }
+ } else {
+ if (right_weight >= nbytes) {
+ p = &a->right;
+ a = right_son;
+ } else {
+ p = &a->left;
+ a = left_son;
+ }
+ }
+ left_son = a->left;
+ right_son = a->right;
+ left_weight = mweight(left_son);
+ right_weight = mweight(right_son);
+ } /* while */
+
+ /*
+ * allocate storage from the selected node.
+ */
+
+ if (a->size - nbytes < SMALLEST_BLK) {
+ /*
+ * not big enough to split; must leave at least
+ * a dblk's worth of space.
+ */
+ retblock = a->block->data;
+ delete(p);
+ } else {
+
+ /*
+ * split the node, allocating nbytes from the top.
+ * Remember we've already accounted for the
+ * allocated node's header space.
+ */
+ Freehdr x;
+ x = getfreehdr();
+ if ((uintptr_t)a->block->data & ALIGNMASK) {
+ size_t size;
+ if (a->size <= ALIGNMORE(a->block->data))
+ prom_panic("kmem_alloc: short block allocated");
+ size = nbytes + ALIGNMORE(a->block->data);
+ x->block = a->block;
+ x->size = ALIGNMORE(a->block->data);
+ x->left = a->left;
+ x->right = a->right;
+ /*
+ * the node pointed to by *p has become smaller;
+ * move it down to its appropriate place in
+ * the tree.
+ */
+ *p = x;
+ demote(p);
+ retblock = a->block->data + ALIGNMORE(a->block->data);
+ if (a->size > size) {
+ kmem_free((caddr_t)nextblk(a->block, size),
+ (size_t)(a->size - size));
+ }
+ freehdr(a);
+ } else {
+ x->block = nextblk(a->block, nbytes);
+ x->size = a->size - nbytes;
+ x->left = a->left;
+ x->right = a->right;
+ /*
+ * the node pointed to by *p has become smaller;
+ * move it down to its appropriate place in
+ * the tree.
+ */
+ *p = x;
+ demote(p);
+ retblock = a->block->data;
+ freehdr(a);
+ }
+ }
+#ifdef DEBUG
+ prtree(kmem_info.free_root, "kmem_alloc");
+#endif
+
+ splx(s);
+ bzero(retblock, nbytes);
+#ifdef DEBUG
+ printf("kmem_alloc bzero complete - returning %p\n", retblock);
+#endif
+ return (retblock);
+
+} /* kmem_alloc */
+
+/*
+ * Return a block to the free space tree.
+ *
+ * algorithm:
+ * Starting at the root, search for and coalesce free blocks
+ * adjacent to one given. When the appropriate place in the
+ * tree is found, insert the given block.
+ *
+ * Do some sanity checks to avoid total confusion in the tree.
+ * If the block has already been freed, prom_panic.
+ * If the ptr is not from the arena, prom_panic.
+ */
+void
+kmem_free(void *ptr, size_t nbytes)
+{
+ Freehdr *np; /* For deletion from free list */
+ Freehdr neighbor; /* Node to be coalesced */
+ char *neigh_block; /* Ptr to potential neighbor */
+ size_t neigh_size; /* Size of potential neighbor */
+ int s;
+
+#ifdef DEBUG
+printf("kmem_free (ptr %p nbytes %lx)\n", ptr, nbytes);
+prtree(kmem_info.free_root, "kmem_free");
+#endif
+
+#ifdef lint
+ neigh_block = bkmem_zalloc(nbytes);
+ neigh_block = neigh_block;
+#endif
+ if (nbytes == 0) {
+ return;
+ }
+
+ if (ptr == 0) {
+ prom_panic("kmem_free of 0");
+ }
+ s = splnet();
+
+ /*
+ * Search the tree for the correct insertion point for this
+ * node, coalescing adjacent free blocks along the way.
+ */
+ np = &kmem_info.free_root;
+ neighbor = *np;
+ while (neighbor != NIL) {
+ neigh_block = (char *)neighbor->block;
+ neigh_size = neighbor->size;
+ if ((char *)ptr < neigh_block) {
+ if ((char *)ptr + nbytes == neigh_block) {
+ /*
+ * Absorb and delete right neighbor
+ */
+ nbytes += neigh_size;
+ delete(np);
+ } else if ((char *)ptr + nbytes > neigh_block) {
+ /*
+ * The block being freed overlaps
+ * another block in the tree. This
+ * is bad news.
+ */
+ printf("kmem_free: free block overlap %p+%lx"
+ " over %p\n", (void *)ptr, nbytes,
+ (void *)neigh_block);
+ prom_panic("kmem_free: free block overlap");
+ } else {
+ /*
+ * Search to the left
+ */
+ np = &neighbor->left;
+ }
+ } else if ((char *)ptr > neigh_block) {
+ if (neigh_block + neigh_size == ptr) {
+ /*
+ * Absorb and delete left neighbor
+ */
+ ptr = neigh_block;
+ nbytes += neigh_size;
+ delete(np);
+ } else if (neigh_block + neigh_size > (char *)ptr) {
+ /*
+ * This block has already been freed
+ */
+ prom_panic("kmem_free block already free");
+ } else {
+ /*
+ * search to the right
+ */
+ np = &neighbor->right;
+ }
+ } else {
+ /*
+ * This block has already been freed
+ * as "ptr == neigh_block"
+ */
+ prom_panic("kmem_free: block already free as neighbor");
+ return;
+ } /* else */
+ neighbor = *np;
+ } /* while */
+
+ /*
+ * Insert the new node into the free space tree
+ */
+ insert((Dblk) ptr, nbytes, &kmem_info.free_root);
+#ifdef DEBUG
+printf("exiting kmem_free\n");
+prtree(kmem_info.free_root, "kmem_free");
+#endif
+ splx(s);
+} /* kmem_free */
+
+/*
+ * Sigh. We include a header file which the kernel
+ * uses to declare (one of its many) kmem_free prototypes.
+ * In order not to use the kernel's namespace, then, we must
+ * define another name here for use by boot.
+ */
+void *
+bkmem_alloc(size_t size)
+{
+ return (kmem_alloc(size, 0));
+}
+
+/*
+ * Boot's kmem_alloc is really kmem_zalloc().
+ */
+void *
+bkmem_zalloc(size_t size)
+{
+ return (kmem_alloc(size, 0));
+}
+
+void
+bkmem_free(void *p, size_t bytes)
+{
+ kmem_free(p, bytes);
+}
+
+static void
+check_need_to_free(void)
+{
+ int i;
+ struct need_to_free *ntf;
+ caddr_t addr;
+ size_t nbytes;
+ int s;
+
+again:
+ s = splimp();
+ ntf = &kmem_info.need_to_free_list;
+ if (ntf->addr) {
+ addr = ntf->addr;
+ nbytes = ntf->nbytes;
+ *ntf = *(struct need_to_free *)ntf->addr;
+ splx(s);
+ kmem_free(addr, nbytes);
+ goto again;
+ }
+ ntf = kmem_info.need_to_free;
+ for (i = 0; i < NEED_TO_FREE_SIZE; i++) {
+ if (ntf[i].addr) {
+ addr = ntf[i].addr;
+ nbytes = ntf[i].nbytes;
+ ntf[i].addr = 0;
+ splx(s);
+ kmem_free(addr, nbytes);
+ goto again;
+ }
+ }
+ splx(s);
+}
+
+/*
+ * Add a block of at least nbytes to the free space tree.
+ *
+ * return value:
+ * true if at least nbytes can be allocated
+ * false otherwise
+ *
+ * remark:
+ * free space (delimited by the static variable ubound) is
+ * extended by an amount determined by rounding nbytes up to
+ * a multiple of the system page size.
+ */
+
+static bool
+morecore(size_t nbytes)
+{
+#ifdef __sparc
+ enum RESOURCES type = RES_BOOTSCRATCH_NOFAIL;
+#else
+ enum RESOURCES type = RES_BOOTSCRATCH;
+#endif
+ Dblk p;
+#ifdef DEBUG
+ printf("morecore(nbytes 0x%lx)\n", nbytes);
+#endif /* DEBUG */
+
+
+ nbytes = roundup(nbytes, PAGESIZE);
+ p = (Dblk) resalloc(type, nbytes, (caddr_t)0, 0);
+ if (p == 0) {
+ return (false);
+ }
+ kmem_free((caddr_t)p, nbytes);
+#ifdef DEBUG
+ printf("morecore() returing, p = %p\n", p);
+#endif
+ return (true);
+
+} /* morecore */
+
+/*
+ * Get a free block header
+ * There is a list of available free block headers.
+ * When the list is empty, allocate another pagefull.
+ */
+Freehdr
+getfreehdr(void)
+{
+ Freehdr r;
+ int n = 0;
+#ifdef DEBUG
+ printf("getfreehdr()\n");
+#endif /* DEBUG */
+
+ if (kmem_info.free_hdr_list != NIL) {
+ r = kmem_info.free_hdr_list;
+ kmem_info.free_hdr_list = kmem_info.free_hdr_list->left;
+ } else {
+ r = (Freehdr)resalloc(RES_BOOTSCRATCH, PAGESIZE, (caddr_t)0, 0);
+ if (r == 0) {
+ prom_panic("getfreehdr");
+ }
+ for (n = 1; n < PAGESIZE / sizeof (*r); n++) {
+ freehdr(&r[n]);
+ }
+ }
+#ifdef DEBUG
+ printf("getfreehdr: freed %x headers\n", n);
+ printf("getfreehdr: returning %p\n", r);
+#endif /* DEBUG */
+ return (r);
+}
+
+/*
+ * Free a free block header
+ * Add it to the list of available headers.
+ */
+
+void
+freehdr(Freehdr p)
+{
+#ifdef DEBUG
+ printf("freehdr(%p)\n", p);
+#endif /* DEBUG */
+ p->left = kmem_info.free_hdr_list;
+ p->right = NIL;
+ p->block = NULL;
+ kmem_info.free_hdr_list = p;
+}
+
+#ifdef DEBUG
+/*
+ * Diagnostic routines
+ */
+static int depth = 0;
+
+static void
+prtree(Freehdr p, char *cp)
+{
+ int n;
+ if (depth == 0) {
+ printf("prtree(p %p cp %s)\n", p, cp);
+ }
+ if (p != NIL) {
+ depth++;
+ prtree(p->left, (char *)NULL);
+ depth--;
+
+ for (n = 0; n < depth; n++) {
+ printf(" ");
+ }
+ printf(
+ "(%p): (left = %p, right = %p, block = %p, size = %lx)\n",
+ p, p->left, p->right, p->block, p->size);
+
+ depth++;
+ prtree(p->right, (char *)NULL);
+ depth--;
+ }
+}
+#endif /* DEBUG */
diff --git a/usr/src/psm/stand/boot/common/readfile.c b/usr/src/psm/stand/boot/common/readfile.c
new file mode 100644
index 0000000000..3cd0f8279f
--- /dev/null
+++ b/usr/src/psm/stand/boot/common/readfile.c
@@ -0,0 +1,1571 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/sysmacros.h>
+#include <sys/types.h>
+#include <sys/exechdr.h>
+#include <sys/elf.h>
+#include <sys/elf_notes.h>
+#include <sys/bootconf.h>
+#include <sys/reboot.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <sys/modctl.h>
+#include <sys/link.h>
+#include <sys/auxv.h>
+#include <sys/salib.h>
+#include <sys/bootvfs.h>
+#include <sys/platnames.h>
+
+#ifdef BOOTAMD64
+#include <amd64/amd64_page.h>
+#endif /* BOOTAMD64 */
+
+union {
+ struct exec X;
+ Elf32_Ehdr Elfhdr;
+ Elf64_Ehdr Elfhdr64;
+} ex;
+
+#define x ex.X
+#define elfhdr ex.Elfhdr
+#define elfhdr64 ex.Elfhdr64
+
+typedef int (*func_t)();
+
+#define FAIL ((func_t)-1)
+#define ALIGN(x, a) \
+ ((a) == 0 ? (uintptr_t)(x) : (((uintptr_t)(x) + (a) - 1) & ~((a) - 1)))
+
+#define __BOOT_NAUXV_IMPL 22
+
+int use_align = 0;
+int npagesize = 0;
+uint_t icache_flush = 0;
+char *cpulist = NULL;
+char *mmulist = NULL;
+char *module_path; /* path for kernel modules */
+
+/*
+ * This file gets compiled in LP64 (for sun4u) and ILP32 models.
+ * For LP64 compilation, the "client" file we load and run may be LP64 or ILP32,
+ * and during bringup, the LP64 clients may have ELF32 headers.
+ */
+#ifdef _ELF64_SUPPORT
+#ifndef BOOTAMD64
+/*
+ * Bootstrap vector for ELF32 LP64 client - neither supported nor needed for
+ * AMD64
+ */
+Elf32_Boot *elfbootvecELF32_64;
+#endif /* !BOOTAMD64 */
+
+Elf64_Boot *elfbootvecELF64; /* ELF bootstrap vector for Elf64 LP64 */
+
+#define OK ((func_t)0)
+
+#define FAIL_READELF64 ((uint64_t)0)
+#define FAIL_ILOAD64 ((Elf64_Addr)-1)
+#endif /* _ELF64_SUPPORT */
+
+/*
+ * And by an ILP32 client. The non-sun4u/LP64 booters use these.
+ * Also, the sun4u booter must create this for ILP32 clients.
+ */
+Elf32_Boot *elfbootvec; /* ELF bootstrap vector normal ILP32 */
+
+/*
+ * Read in a Unix executable file and return its entry point.
+ * Handle the various a.out formats correctly.
+ * "fd" is the standalone file descriptor to read from.
+ * Print informative little messages if "print" is on.
+ * Returns -1 for errors.
+ */
+
+#ifdef DEBUG
+static int debug = 1;
+#else /* DEBUG */
+static int debug = 0;
+#endif /* DEBUG */
+
+#define dprintf if (debug) printf
+
+#ifdef _ELF64_SUPPORT
+typedef struct {
+ uint_t a_type;
+#ifdef BOOTAMD64
+ uint_t a_pad; /* needed to 8-byte align uint64_ts below for AMD64 */
+#endif /* BOOTAMD64 */
+ union {
+ uint64_t a_val;
+ uint64_t a_ptr;
+#ifndef BOOTAMD64
+ void (*a_fcn)(); /* XXX - UNUSED? */
+#endif /* !BOOTAMD64 */
+ } a_un;
+} auxv64_t;
+
+#if defined(__sparcv9) || defined(__ia64)
+extern int client_isLP64;
+#endif /* __sparcv9 || __ia64 */
+
+static uint64_t read_elf64(int, int, Elf64_Ehdr *);
+static Elf64_Addr iload64(char *, Elf64_Phdr *, Elf64_Phdr *, auxv64_t **);
+#endif /* _ELF64_SUPPORT */
+
+#if defined(i386) && !defined(_SYSCALL32)
+typedef auxv_t auxv32_t;
+#endif
+
+static func_t read_elf32(int, int, Elf32_Ehdr *);
+static func_t iload32(char *, Elf32_Phdr *, Elf32_Phdr *, auxv32_t **);
+static caddr_t segbrk(caddr_t *, size_t, size_t);
+static int openpath(char *, char *, int);
+static char *getmodpath(char *);
+extern void setup_aux(void);
+
+extern void *kmem_alloc(size_t, int);
+extern void kmem_free(void *, size_t);
+extern int cons_gets(char *, int);
+
+#ifdef BOOTAMD64
+extern const char *amd64_getmmulist(void);
+
+extern int amd64_elf64;
+extern int is_amd64;
+#endif /* BOOTAMD64 */
+
+#ifdef lint
+/*
+ * This function is currently inlined
+ */
+/*ARGSUSED*/
+void
+sync_instruction_memory(caddr_t v, size_t len)
+{}
+#else /* lint */
+extern void sync_instruction_memory(caddr_t v, size_t len);
+#endif /* lint */
+
+
+extern int verbosemode;
+extern int boothowto;
+extern int pagesize;
+extern char filename[];
+
+#ifdef MPSAS
+extern void sas_symtab(int start, int end);
+#endif
+
+/*
+ * 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
+xread(int fd, char *p, size_t nbytes)
+{
+ size_t bytesread = 0;
+ int errorcount = 0;
+ ssize_t i;
+
+ while (bytesread < nbytes) {
+ i = read(fd, p, nbytes - bytesread);
+ if (i < 0) {
+ ++errorcount;
+ if (verbosemode)
+ printf("read error (0x%x times)\n", errorcount);
+ continue;
+ }
+ bytesread += i;
+ p += i;
+ }
+ return (bytesread);
+}
+
+func_t
+readfile(int fd, int print)
+{
+#ifdef _ELF64_SUPPORT
+#ifdef BOOTAMD64
+ extern int bsetprop(struct bootops *, char *, caddr_t, int, phandle_t);
+ extern struct bootops *bop;
+ extern uint64_t elf64_go2;
+#else /* !BOOTAMD64 */
+ uint64_t elf64_go2;
+#endif /* BOOTAMD64 */
+#endif /* _ELF64_SUPPORT */
+
+ ssize_t i;
+ int shared = 0;
+
+ if (verbosemode) {
+ dprintf("fd = %x\n", fd);
+ }
+
+ i = xread(fd, (char *)&elfhdr, sizeof (Elf64_Ehdr));
+ if (x.a_magic == ZMAGIC || x.a_magic == NMAGIC)
+ shared = 1;
+ if (i != sizeof (Elf64_Ehdr)) {
+ printf("Error reading ELF header.\n");
+ return (FAIL);
+ }
+ if (!shared && x.a_magic != OMAGIC) {
+ if (*(int *)&elfhdr.e_ident == *(int *)(ELFMAG)) {
+ if (verbosemode) {
+ int is64 = (elfhdr.e_ident[EI_CLASS] ==
+ ELFCLASS64);
+
+ dprintf("calling readelf, elfheader is:\n");
+ dprintf("e_ident\t0x%x, 0x%x, 0x%x, 0x%x\n",
+ *(int *)&elfhdr.e_ident[0],
+ *(int *)&elfhdr.e_ident[4],
+ *(int *)&elfhdr.e_ident[8],
+ *(int *)&elfhdr.e_ident[12]);
+ dprintf("e_machine\t0x%x\n", elfhdr.e_machine);
+
+ dprintf("e_entry\t\t0x%llx\n", (is64 ?
+ elfhdr64.e_entry :
+ (u_longlong_t)elfhdr.e_entry));
+ dprintf("e_shoff\t\t0x%llx\n", (is64 ?
+ elfhdr64.e_shoff :
+ (u_longlong_t)elfhdr.e_shoff));
+ dprintf("e_shnentsize\t%d\n", (is64 ?
+ elfhdr64.e_shentsize : elfhdr.e_shentsize));
+ dprintf("e_shnum\t\t%d\n", (is64 ?
+ elfhdr64.e_shnum : elfhdr.e_shnum));
+ dprintf("e_shstrndx\t%d\n", (is64 ?
+ elfhdr64.e_shstrndx : elfhdr.e_shstrndx));
+ }
+
+
+#ifdef _ELF64_SUPPORT
+ dprintf("ELF file CLASS 0x%x 32 is %x 64 is %x\n",
+ elfhdr.e_ident[EI_CLASS], ELFCLASS32, ELFCLASS64);
+
+ if (elfhdr.e_ident[EI_CLASS] == ELFCLASS64) {
+#ifdef BOOTAMD64
+ if (elfhdr.e_machine != EM_AMD64) {
+ printf("FATAL: 64-bit ELF executable "
+ "not for AMD64\n (e_machine "
+ "= %d).\n", elfhdr.e_machine);
+ return (FAIL);
+ }
+
+ /*
+ * OK, we know the executable is for an AMD64
+ * CPU. Make sure we ARE an AMD64 CPU before
+ * proceeding.
+ */
+ if (is_amd64 == 0) {
+ printf("FATAL: AMD64 executables not "
+ " supported on this CPU.\n");
+ return (FAIL);
+ }
+
+ amd64_elf64 = (elfhdr.e_ident[EI_CLASS] ==
+ ELFCLASS64);
+#endif /* BOOTAMD64 */
+
+ elf64_go2 = read_elf64(fd, print,
+ (Elf64_Ehdr *)&elfhdr);
+
+#ifdef BOOTAMD64
+ if (elf64_go2 != FAIL_READELF64)
+ (void) bsetprop(bop, "mmu-modlist",
+ "mmu64", 0, 0);
+
+ return ((elf64_go2 == FAIL_READELF64) ? FAIL :
+ OK);
+#else /* !BOOTAMD64 */
+ return ((elf64_go2 == FAIL_READELF64) ? FAIL :
+ (func_t)elf64_go2);
+#endif /* BOOTAMD64 */
+
+ } else
+#endif /* _ELF64_SUPPORT */
+ return (read_elf32(fd, print, &elfhdr));
+ } else {
+ printf("File not executable.\n");
+ return (FAIL);
+ }
+ }
+ return (FAIL);
+}
+
+/*
+ * Macros to add attribute/values
+ * to the ELF bootstrap vector
+ * and the aux vector.
+ */
+#define AUX(p, a, v) { (p)->a_type = (a); \
+ ((p)++)->a_un.a_val = (int32_t)(v); }
+
+#define EBV(p, a, v) { (p)->eb_tag = (a); \
+ ((p)++)->eb_un.eb_val = (Elf32_Word)(v); }
+
+static func_t
+read_elf32(int fd, int print, Elf32_Ehdr *elfhdrp)
+{
+ Elf32_Phdr *phdr; /* program header */
+ Elf32_Nhdr *nhdr; /* note header */
+ int nphdrs, phdrsize;
+ caddr_t allphdrs;
+ caddr_t namep, descp;
+ Elf32_Addr loadaddr, base;
+ size_t offset = 0;
+ size_t size;
+ uintptr_t off;
+ int i;
+ int bss_seen = 0;
+ int interp = 0; /* interpreter required */
+ static char dlname[MAXPATHLEN]; /* name of interpeter */
+ uint_t dynamic; /* dynamic tags array */
+ Elf32_Phdr *thdr; /* "text" program header */
+ Elf32_Phdr *dhdr; /* "data" program header */
+ func_t entrypt; /* entry point of standalone */
+
+ /* Initialize pointers so we won't free bogus ones on elferror */
+ allphdrs = NULL;
+ nhdr = NULL;
+
+#ifdef _ELF64_SUPPORT
+ if (verbosemode)
+ printf("Elf32 client\n");
+#endif /* _ELF64_SUPPORT */
+
+ if (elfhdrp->e_phnum == 0 || elfhdrp->e_phoff == 0)
+ goto elferror;
+
+ entrypt = (func_t)elfhdrp->e_entry;
+ if (verbosemode)
+ dprintf("Entry point: %p\n", (void *)entrypt);
+
+ /*
+ * Allocate and read in all the program headers.
+ */
+ nphdrs = elfhdrp->e_phnum;
+ phdrsize = nphdrs * elfhdrp->e_phentsize;
+ allphdrs = (caddr_t)kmem_alloc(phdrsize, 0);
+ if (allphdrs == NULL)
+ goto elferror;
+ if (verbosemode)
+ dprintf("lseek: args = %x %x %x\n", fd, elfhdrp->e_phoff, 0);
+ if (lseek(fd, elfhdrp->e_phoff, 0) == -1)
+ goto elferror;
+ if (xread(fd, allphdrs, phdrsize) != phdrsize)
+ goto elferror;
+
+ /*
+ * First look for PT_NOTE headers that tell us what pagesize to
+ * use in allocating program memory.
+ */
+ npagesize = 0;
+ for (i = 0; i < nphdrs; i++) {
+ void *note_buf;
+
+ phdr = (Elf32_Phdr *)(allphdrs + elfhdrp->e_phentsize * i);
+ if (phdr->p_type != PT_NOTE)
+ continue;
+ if (verbosemode) {
+ dprintf("allocating 0x%x bytes for note hdr\n",
+ phdr->p_filesz);
+ }
+ if ((note_buf = kmem_alloc(phdr->p_filesz, 0)) == NULL)
+ goto elferror;
+ if (verbosemode)
+ dprintf("seeking to 0x%x\n", phdr->p_offset);
+ if (lseek(fd, phdr->p_offset, 0) == -1)
+ goto elferror;
+ if (verbosemode) {
+ dprintf("reading 0x%x bytes into %p\n",
+ 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);
+ }
+
+ /*
+ * Iterate through all ELF PT_NOTE elements looking for
+ * ELF_NOTE_SOLARIS which, if present, will specify the
+ * executable's preferred pagesize.
+ */
+ do {
+ namep = (caddr_t)(nhdr + 1);
+
+ if (nhdr->n_namesz == strlen(ELF_NOTE_SOLARIS) + 1 &&
+ strcmp(namep, ELF_NOTE_SOLARIS) == 0 &&
+ nhdr->n_type == ELF_NOTE_PAGESIZE_HINT) {
+ descp = namep + roundup(nhdr->n_namesz, 4);
+ npagesize = *(int *)descp;
+ if (verbosemode)
+ dprintf("pagesize is %x\n", npagesize);
+ }
+
+ offset += sizeof (Elf32_Nhdr) + roundup(nhdr->n_namesz,
+ 4) + roundup(nhdr->n_descsz, 4);
+
+ nhdr = (Elf32_Nhdr *)((char *)note_buf + offset);
+ } while (offset < phdr->p_filesz);
+
+ kmem_free(note_buf, phdr->p_filesz);
+ nhdr = NULL;
+ }
+
+ /*
+ * Next look for PT_LOAD headers to read in.
+ */
+ if (print)
+ printf("Size: ");
+ for (i = 0; i < nphdrs; i++) {
+ phdr = (Elf32_Phdr *)(allphdrs + elfhdrp->e_phentsize * i);
+ if (verbosemode) {
+ dprintf("Doing header 0x%x\n", i);
+ dprintf("phdr\n");
+ dprintf("\tp_offset = %x, p_vaddr = %x\n",
+ phdr->p_offset, phdr->p_vaddr);
+ dprintf("\tp_memsz = %x, p_filesz = %x\n",
+ phdr->p_memsz, phdr->p_filesz);
+ }
+ if (phdr->p_type == PT_LOAD) {
+ if (verbosemode)
+ dprintf("seeking to 0x%x\n", phdr->p_offset);
+ if (lseek(fd, phdr->p_offset, 0) == -1)
+ goto elferror;
+
+ if (phdr->p_flags == (PF_R | PF_W) &&
+ phdr->p_vaddr == 0) {
+ /*
+ * It's a PT_LOAD segment that is RW but
+ * not executable and has a vaddr
+ * of zero. This is relocation info that
+ * doesn't need to stick around after
+ * krtld is done with it. We allocate boot
+ * memory for this segment, since we don't want
+ * it mapped in permanently as part of
+ * the kernel image.
+ */
+ if ((loadaddr = (uintptr_t)
+ kmem_alloc(phdr->p_memsz, 0)) == NULL)
+ goto elferror;
+ /*
+ * Save this to pass on
+ * to the interpreter.
+ */
+ phdr->p_vaddr = (Elf32_Addr)loadaddr;
+ } else {
+ if (print)
+ printf("0x%x+", phdr->p_filesz);
+ /*
+ * If we found a new pagesize above, use it
+ * to adjust the memory allocation.
+ */
+ loadaddr = phdr->p_vaddr;
+ if (use_align && npagesize != 0) {
+ off = loadaddr & (npagesize - 1);
+ size = roundup(phdr->p_memsz + off,
+ npagesize);
+ base = loadaddr - off;
+ } else {
+ npagesize = 0;
+ size = phdr->p_memsz;
+ base = loadaddr;
+ }
+ /*
+ * Check if it's text or data.
+ */
+ if (phdr->p_flags & PF_W)
+ dhdr = phdr;
+ else
+ thdr = phdr;
+
+ /*
+ * If memory size is zero just ignore this
+ * header.
+ */
+ if (size == 0)
+ continue;
+
+ if (verbosemode)
+ dprintf("allocating memory: %x %lx "
+ "%x\n", base, size, npagesize);
+ /*
+ * We're all set up to read.
+ * Now let's allocate some memory.
+ */
+
+#ifdef i386
+ /*
+ * If vaddr == paddr and npagesize is 0, that
+ * means the executable needs to be identity
+ * mapped in memory (va == pa, mapped 1:1)
+ *
+ * Otherwise load as usual.
+ */
+ if ((phdr->p_vaddr == phdr->p_paddr) &&
+ (npagesize == 0)) {
+ extern caddr_t idmap_mem(uint32_t,
+ size_t, int);
+
+ uint_t n;
+
+ n = (uint_t)base & (pagesize - 1);
+ if (n) {
+ base -= n;
+ size += n;
+ }
+
+ if (!idmap_mem((uint32_t)base,
+ (size_t)size, pagesize))
+ goto elferror;
+ } else
+#endif /* i386 */
+ if (get_progmemory((caddr_t)base, size,
+ npagesize))
+ goto elferror;
+ }
+
+ if (verbosemode) {
+ dprintf("reading 0x%x bytes into 0x%x\n",
+ phdr->p_filesz, loadaddr);
+ }
+ if (xread(fd, (caddr_t)loadaddr, phdr->p_filesz) !=
+ phdr->p_filesz)
+ goto elferror;
+
+ /* zero out BSS */
+ if (phdr->p_memsz > phdr->p_filesz) {
+ loadaddr += phdr->p_filesz;
+ if (verbosemode) {
+ dprintf("bss from 0x%x size 0x%x\n",
+ loadaddr,
+ phdr->p_memsz - phdr->p_filesz);
+ }
+
+ bzero((void *)loadaddr,
+ phdr->p_memsz - phdr->p_filesz);
+ bss_seen++;
+ if (print)
+ printf("0x%x Bytes\n",
+ phdr->p_memsz - phdr->p_filesz);
+ }
+
+ /* force instructions to be visible to icache */
+ if (phdr->p_flags & PF_X)
+ sync_instruction_memory((caddr_t)phdr->p_vaddr,
+ phdr->p_memsz);
+
+#ifdef MPSAS
+ sas_symtab(phdr->p_vaddr,
+ phdr->p_vaddr + phdr->p_memsz);
+#endif
+ } else if (phdr->p_type == PT_INTERP) {
+ /*
+ * Dynamically-linked executable.
+ */
+ interp = 1;
+ if (lseek(fd, phdr->p_offset, 0) == -1) {
+ goto elferror;
+ }
+ /*
+ * Get the name of the interpreter.
+ */
+ if (xread(fd, dlname, phdr->p_filesz) !=
+ phdr->p_filesz ||
+ dlname[phdr->p_filesz - 1] != '\0')
+ goto elferror;
+ } else if (phdr->p_type == PT_DYNAMIC) {
+ dynamic = phdr->p_vaddr;
+ }
+ }
+
+ if (!bss_seen && print)
+ printf("0 Bytes\n");
+
+ /*
+ * Load the interpreter
+ * if there is one.
+ */
+ if (interp) {
+ Elf32_Boot bootv[EB_MAX]; /* Bootstrap vector */
+ auxv32_t auxv[__BOOT_NAUXV_IMPL]; /* Aux vector */
+ Elf32_Boot *bv = bootv;
+ auxv32_t *av = auxv;
+ size_t vsize;
+
+ /*
+ * Load it.
+ */
+ if ((entrypt = iload32(dlname, thdr, dhdr, &av)) == FAIL)
+ goto elferror;
+ /*
+ * Build bootstrap and aux vectors.
+ */
+ setup_aux();
+ EBV(bv, EB_AUXV, 0); /* fill in later */
+ EBV(bv, EB_PAGESIZE, pagesize);
+ EBV(bv, EB_DYNAMIC, dynamic);
+ EBV(bv, EB_NULL, 0);
+
+ AUX(av, AT_BASE, entrypt);
+ AUX(av, AT_ENTRY, elfhdrp->e_entry);
+ AUX(av, AT_PAGESZ, pagesize);
+ AUX(av, AT_PHDR, allphdrs);
+ AUX(av, AT_PHNUM, elfhdrp->e_phnum);
+ AUX(av, AT_PHENT, elfhdrp->e_phentsize);
+ if (use_align)
+ AUX(av, AT_SUN_LPAGESZ, npagesize);
+ AUX(av, AT_SUN_IFLUSH, icache_flush);
+ if (cpulist != NULL)
+ AUX(av, AT_SUN_CPU, cpulist);
+ if (mmulist != NULL)
+ AUX(av, AT_SUN_MMU, mmulist);
+ AUX(av, AT_NULL, 0);
+ /*
+ * Realloc vectors and copy them.
+ */
+ vsize = (caddr_t)bv - (caddr_t)bootv;
+ if ((elfbootvec = (Elf32_Boot *)kmem_alloc(vsize, 0)) == NULL)
+ goto elferror;
+ bcopy((char *)bootv, (char *)elfbootvec, vsize);
+
+ size = (caddr_t)av - (caddr_t)auxv;
+ if (size > sizeof (auxv)) {
+ printf("readelf: overrun of available aux vectors\n");
+ kmem_free(elfbootvec, vsize);
+ goto elferror;
+ }
+ if ((elfbootvec->eb_un.eb_ptr =
+ (Elf32_Addr)kmem_alloc(size, 0)) == NULL) {
+ kmem_free(elfbootvec, vsize);
+ goto elferror;
+ }
+ bcopy(auxv, (void *)(elfbootvec->eb_un.eb_ptr), size);
+
+#if defined(_ELF64_SUPPORT) && !defined(BOOTAMD64)
+ /*
+ * Make an LP64 copy of the vector for use by 64-bit standalones
+ * even if they have ELF32.
+ */
+ if ((elfbootvecELF32_64 = (Elf32_Boot *)kmem_alloc(vsize, 0))
+ == NULL)
+ goto elferror;
+ bcopy(bootv, elfbootvecELF32_64, vsize);
+
+ size = (av - auxv) * sizeof (auxv64_t);
+ if ((elfbootvecELF32_64->eb_un.eb_ptr =
+ (Elf32_Addr)kmem_alloc(size, 0)) == NULL) {
+ kmem_free(elfbootvecELF32_64, vsize);
+ goto elferror;
+ } else {
+ auxv64_t *a64 =
+ (auxv64_t *)elfbootvecELF32_64->eb_un.eb_ptr;
+ auxv32_t *a = auxv;
+
+ for (a = auxv; a < av; a++) {
+ a64->a_type = a->a_type;
+ a64->a_un.a_val = a->a_un.a_val;
+ a64++;
+ }
+ }
+#endif /* _ELF64_SUPPORT && !BOOTAMD64 */
+ } else {
+ kmem_free(allphdrs, phdrsize);
+ }
+ return (entrypt);
+
+elferror:
+ if (allphdrs != NULL)
+ kmem_free(allphdrs, phdrsize);
+ if (nhdr != NULL)
+ kmem_free(nhdr, phdr->p_filesz);
+ printf("Elf32 read error.\n");
+ return (FAIL);
+}
+
+#ifdef _ELF64_SUPPORT
+/*
+ * Macros to add attribute/values to the ELF bootstrap vector
+ * and the aux vector.
+ */
+#define AUX64(p, a, v) { (p)->a_type = (a); \
+ ((p)++)->a_un.a_val = (uint64_t)(v); }
+
+#define EBV64(p, a, v) { (p)->eb_tag = (a); \
+ ((p)++)->eb_un.eb_val = (Elf64_Xword)(v); }
+
+static uint64_t
+read_elf64(int fd, int print, Elf64_Ehdr *elfhdrp)
+{
+ Elf64_Phdr *phdr; /* program header */
+ Elf64_Nhdr *nhdr; /* note header */
+ int nphdrs, phdrsize;
+ caddr_t allphdrs;
+ caddr_t namep, descp;
+ Elf64_Addr loadaddr, base;
+ size_t offset = 0;
+ size_t size;
+ int i;
+ uintptr_t off;
+ int bss_seen = 0;
+ int interp = 0; /* interpreter required */
+ static char dlname[MAXPATHLEN]; /* name of interpeter */
+ uintptr_t dynamic; /* dynamic tags array */
+ Elf64_Phdr *thdr; /* "text" program header */
+ Elf64_Phdr *dhdr; /* "data" program header */
+ Elf64_Addr entrypt; /* entry point of standalone */
+
+ /* Initialize pointers so we won't free bogus ones on elf64error */
+ allphdrs = NULL;
+ nhdr = NULL;
+#if defined(__sparcv9) || defined(__ia64)
+ client_isLP64 = 1;
+#endif /* __sparcv9 || __ia64 */
+
+ if (verbosemode)
+ printf("Elf64 client\n");
+
+ if (elfhdrp->e_phnum == 0 || elfhdrp->e_phoff == 0)
+ goto elf64error;
+
+ entrypt = elfhdrp->e_entry;
+ if (verbosemode)
+ dprintf("Entry point: 0x%llx\n", (u_longlong_t)entrypt);
+
+ /*
+ * Allocate and read in all the program headers.
+ */
+ nphdrs = elfhdrp->e_phnum;
+ phdrsize = nphdrs * elfhdrp->e_phentsize;
+ allphdrs = (caddr_t)kmem_alloc(phdrsize, 0);
+ if (allphdrs == NULL)
+ goto elf64error;
+ if (verbosemode)
+ dprintf("lseek: args = %x %llx %x\n", fd,
+ (u_longlong_t)elfhdrp->e_phoff, 0);
+ if (lseek(fd, elfhdrp->e_phoff, 0) == -1)
+ goto elf64error;
+ if (xread(fd, allphdrs, phdrsize) != phdrsize)
+ goto elf64error;
+
+ /*
+ * First look for PT_NOTE headers that tell us what pagesize to
+ * use in allocating program memory.
+ */
+ npagesize = 0;
+ for (i = 0; i < nphdrs; i++) {
+ void *note_buf;
+
+ phdr = (Elf64_Phdr *)(allphdrs + elfhdrp->e_phentsize * i);
+ if (phdr->p_type != PT_NOTE)
+ continue;
+ if (verbosemode) {
+ dprintf("allocating 0x%llx bytes for note hdr\n",
+ (u_longlong_t)phdr->p_filesz);
+ }
+ if ((note_buf = kmem_alloc(phdr->p_filesz, 0)) == NULL)
+ goto elf64error;
+ if (verbosemode)
+ dprintf("seeking to 0x%llx\n",
+ (u_longlong_t)phdr->p_offset);
+ if (lseek(fd, phdr->p_offset, 0) == -1)
+ goto elf64error;
+ if (verbosemode) {
+ dprintf("reading 0x%llx bytes into 0x%p\n",
+ (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);
+ }
+
+ /*
+ * Iterate through all ELF PT_NOTE elements looking for
+ * ELF_NOTE_SOLARIS which, if present, will specify the
+ * executable's preferred pagesize.
+ */
+ do {
+ namep = (caddr_t)(nhdr + 1);
+
+ if (nhdr->n_namesz == strlen(ELF_NOTE_SOLARIS) + 1 &&
+ strcmp(namep, ELF_NOTE_SOLARIS) == 0 &&
+ nhdr->n_type == ELF_NOTE_PAGESIZE_HINT) {
+ descp = namep + roundup(nhdr->n_namesz, 4);
+ npagesize = *(int *)descp;
+ if (verbosemode)
+ dprintf("pagesize is %x\n", npagesize);
+ }
+
+ offset += sizeof (Elf64_Nhdr) + roundup(nhdr->n_namesz,
+ 4) + roundup(nhdr->n_descsz, 4);
+
+ nhdr = (Elf64_Nhdr *)((char *)note_buf + offset);
+ } while (offset < phdr->p_filesz);
+
+ kmem_free(note_buf, phdr->p_filesz);
+ nhdr = NULL;
+ }
+
+ /*
+ * Next look for PT_LOAD headers to read in.
+ */
+ if (print)
+ printf("Size: ");
+ for (i = 0; i < nphdrs; i++) {
+ phdr = (Elf64_Phdr *)(allphdrs + elfhdrp->e_phentsize * i);
+ if (verbosemode) {
+ 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);
+ dprintf("\tp_memsz = %llx, p_filesz = %llx\n",
+ (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);
+ }
+ if (phdr->p_type == PT_LOAD) {
+ if (verbosemode)
+ dprintf("seeking to 0x%llx\n",
+ (u_longlong_t)phdr->p_offset);
+ if (lseek(fd, phdr->p_offset, 0) == -1)
+ goto elf64error;
+
+ if (phdr->p_flags == (PF_R | PF_W) &&
+ phdr->p_vaddr == 0) {
+ /*
+ * It's a PT_LOAD segment that is RW but
+ * not executable and has a vaddr
+ * of zero. This is relocation info that
+ * doesn't need to stick around after
+ * krtld is done with it. We allocate boot
+ * memory for this segment, since we don't want
+ * it mapped in permanently as part of
+ * the kernel image.
+ */
+#ifdef BOOTAMD64
+ if ((loadaddr = (Elf64_Addr)
+ (ADDR_XTND(kmem_alloc(phdr->p_memsz, 0))))
+ == NULL)
+#else /* !BOOTAMD64 */
+ if ((loadaddr = (Elf64_Addr)(uintptr_t)
+ kmem_alloc(phdr->p_memsz, 0)) == NULL)
+#endif /* BOOTAMD64 */
+ goto elf64error;
+
+ /*
+ * Save this to pass on
+ * to the interpreter.
+ */
+ phdr->p_vaddr = loadaddr;
+ } else {
+ if (print)
+ printf("0x%llx+",
+ (u_longlong_t)phdr->p_filesz);
+ /*
+ * If we found a new pagesize above, use it
+ * to adjust the memory allocation.
+ */
+ loadaddr = phdr->p_vaddr;
+ if (use_align && npagesize != 0) {
+ off = loadaddr & (npagesize - 1);
+ size = roundup(phdr->p_memsz + off,
+ npagesize);
+ base = loadaddr - off;
+ } else {
+ npagesize = 0;
+ size = phdr->p_memsz;
+ base = loadaddr;
+ }
+ /*
+ * Check if it's text or data.
+ */
+ if (phdr->p_flags & PF_W)
+ dhdr = phdr;
+ else
+ thdr = phdr;
+
+ if (verbosemode)
+ dprintf(
+ "allocating memory: %llx %lx %x\n",
+ (u_longlong_t)base,
+ size, npagesize);
+
+ /*
+ * If memory size is zero just ignore this
+ * header.
+ */
+ if (size == 0)
+ continue;
+
+ /*
+ * We're all set up to read.
+ * Now let's allocate some memory.
+ */
+ if (get_progmemory((caddr_t)base, size,
+ npagesize))
+ goto elf64error;
+ }
+
+ if (verbosemode) {
+ dprintf("reading 0x%llx bytes into 0x%llx\n",
+ (u_longlong_t)phdr->p_filesz,
+ (u_longlong_t)loadaddr);
+ }
+ if (xread(fd, (caddr_t)loadaddr, phdr->p_filesz) !=
+ phdr->p_filesz)
+ goto elf64error;
+
+ /* zero out BSS */
+ if (phdr->p_memsz > phdr->p_filesz) {
+ loadaddr += phdr->p_filesz;
+ if (verbosemode) {
+ dprintf("bss from 0x%llx size 0x%llx\n",
+ (u_longlong_t)loadaddr,
+ (u_longlong_t)(phdr->p_memsz -
+ phdr->p_filesz));
+ }
+
+ bzero((caddr_t)loadaddr,
+ phdr->p_memsz - phdr->p_filesz);
+ bss_seen++;
+ if (print)
+ printf("0x%llx Bytes\n",
+ (u_longlong_t)(phdr->p_memsz -
+ phdr->p_filesz));
+ }
+
+ /* force instructions to be visible to icache */
+ if (phdr->p_flags & PF_X)
+ sync_instruction_memory((caddr_t)phdr->p_vaddr,
+ phdr->p_memsz);
+
+#ifdef MPSAS
+ sas_symtab(phdr->p_vaddr,
+ phdr->p_vaddr + phdr->p_memsz);
+#endif
+ } else if (phdr->p_type == PT_INTERP) {
+ /*
+ * Dynamically-linked executable.
+ */
+ interp = 1;
+ if (lseek(fd, phdr->p_offset, 0) == -1) {
+ goto elf64error;
+ }
+ /*
+ * Get the name of the interpreter.
+ */
+ if (xread(fd, dlname, phdr->p_filesz) !=
+ phdr->p_filesz ||
+ dlname[phdr->p_filesz - 1] != '\0')
+ goto elf64error;
+ } else if (phdr->p_type == PT_DYNAMIC) {
+ dynamic = phdr->p_vaddr;
+ }
+ }
+
+ if (!bss_seen && print)
+ printf("0 Bytes\n");
+
+ /*
+ * Load the interpreter
+ * if there is one.
+ */
+ if (interp) {
+ Elf64_Boot bootv[EB_MAX]; /* Bootstrap vector */
+ auxv64_t auxv[__BOOT_NAUXV_IMPL]; /* Aux vector */
+ Elf64_Boot *bv = bootv;
+ auxv64_t *av = auxv;
+ size_t vsize;
+
+ /*
+ * Load it.
+ */
+ if ((entrypt = iload64(dlname, thdr, dhdr, &av)) ==
+ FAIL_ILOAD64)
+ goto elf64error;
+ /*
+ * Build bootstrap and aux vectors.
+ */
+ setup_aux();
+ EBV64(bv, EB_AUXV, 0); /* fill in later */
+ EBV64(bv, EB_PAGESIZE, pagesize);
+ EBV64(bv, EB_DYNAMIC, dynamic);
+ EBV64(bv, EB_NULL, 0);
+
+ AUX64(av, AT_BASE, entrypt);
+ AUX64(av, AT_ENTRY, elfhdrp->e_entry);
+ AUX64(av, AT_PAGESZ, pagesize);
+ AUX64(av, AT_PHDR, allphdrs);
+ AUX64(av, AT_PHNUM, elfhdrp->e_phnum);
+ AUX64(av, AT_PHENT, elfhdrp->e_phentsize);
+ if (npagesize)
+ AUX64(av, AT_SUN_LPAGESZ, npagesize);
+
+#ifdef BOOTAMD64
+ vsize = strlen(amd64_getmmulist()) + 1;
+ if ((mmulist = kmem_alloc(vsize, 0)) == NULL)
+ goto elf64error;
+
+ bcopy(amd64_getmmulist(), mmulist, vsize);
+ AUX64(av, AT_SUN_MMU, (uintptr_t)mmulist);
+#endif /* BOOTAMD64 */
+
+ AUX64(av, AT_SUN_IFLUSH, icache_flush);
+ if (cpulist != NULL)
+ AUX64(av, AT_SUN_CPU, cpulist);
+ AUX64(av, AT_NULL, 0);
+ /*
+ * Realloc vectors and copy them.
+ */
+ vsize = (caddr_t)bv - (caddr_t)bootv;
+ if ((elfbootvecELF64 =
+ (Elf64_Boot *)kmem_alloc(vsize, 0)) == NULL)
+ goto elf64error;
+ bcopy((char *)bootv, (char *)elfbootvecELF64, vsize);
+
+ size = (caddr_t)av - (caddr_t)auxv;
+ if (size > sizeof (auxv)) {
+ printf("readelf: overrun of available aux vectors\n");
+ kmem_free(elfbootvecELF64, vsize);
+ goto elf64error;
+ }
+
+#ifdef BOOTAMD64
+ if ((elfbootvecELF64->eb_un.eb_ptr =
+ ADDR_XTND(kmem_alloc(size, 0))) == NULL) {
+ kmem_free(elfbootvecELF64, vsize);
+ goto elf64error;
+ }
+
+ bcopy((char *)auxv,
+ (char *)ADDR_TRUNC((elfbootvecELF64->eb_un.eb_ptr)), size);
+#else /* !BOOTAMD64 */
+ if ((elfbootvecELF64->eb_un.eb_ptr =
+ (Elf64_Addr)kmem_alloc(size, 0)) == NULL) {
+ kmem_free(elfbootvecELF64, vsize);
+ goto elf64error;
+ }
+
+ bcopy((char *)auxv, (char *)(elfbootvecELF64->eb_un.eb_ptr),
+ size);
+#endif /* BOOTAMD64 */
+ } else {
+ kmem_free(allphdrs, phdrsize);
+ }
+ return ((uint64_t)entrypt);
+
+elf64error:
+ if (allphdrs != NULL)
+ kmem_free(allphdrs, phdrsize);
+ if (nhdr != NULL)
+ kmem_free(nhdr, phdr->p_filesz);
+ printf("Elf64 read error.\n");
+ return (FAIL_READELF64);
+}
+#endif /* _ELF64_SUPPORT */
+
+/*
+ * Load the interpreter. It expects a
+ * relocatable .o capable of bootstrapping
+ * itself.
+ */
+static func_t
+iload32(char *rtld, Elf32_Phdr *thdr, Elf32_Phdr *dhdr, auxv32_t **avp)
+{
+ Elf32_Ehdr *ehdr = NULL;
+ uintptr_t dl_entry = 0;
+ uint_t i;
+ int fd;
+ int size;
+ caddr_t shdrs = NULL;
+ caddr_t etext, edata;
+
+ etext = (caddr_t)thdr->p_vaddr + thdr->p_memsz;
+ edata = (caddr_t)dhdr->p_vaddr + dhdr->p_memsz;
+
+ /*
+ * Get the module path.
+ */
+ module_path = getmodpath(filename);
+
+ if ((fd = openpath(module_path, rtld, O_RDONLY)) < 0) {
+ printf("boot: cannot find %s\n", rtld);
+ goto errorx;
+ }
+ dprintf("Opened %s OK\n", rtld);
+ AUX(*avp, AT_SUN_LDNAME, rtld);
+ /*
+ * Allocate and read the ELF header.
+ */
+ if ((ehdr = (Elf32_Ehdr *)kmem_alloc(sizeof (Elf32_Ehdr), 0)) == NULL) {
+ printf("boot: alloc error reading ELF header (%s).\n", rtld);
+ goto error;
+ }
+
+ if (xread(fd, (char *)ehdr, sizeof (*ehdr)) != sizeof (*ehdr)) {
+ printf("boot: error reading ELF header (%s).\n", rtld);
+ goto error;
+ }
+
+ size = ehdr->e_shentsize * ehdr->e_shnum;
+ if ((shdrs = (caddr_t)kmem_alloc(size, 0)) == NULL) {
+ printf("boot: alloc error reading ELF header (%s).\n", rtld);
+ goto error;
+ }
+ /*
+ * Read the section headers.
+ */
+ if (lseek(fd, ehdr->e_shoff, 0) == -1 ||
+ xread(fd, shdrs, size) != size) {
+ printf("boot: error reading section headers\n");
+ goto error;
+ }
+ AUX(*avp, AT_SUN_LDELF, ehdr);
+ AUX(*avp, AT_SUN_LDSHDR, shdrs);
+ /*
+ * Load sections into the appropriate dynamic segment.
+ */
+ for (i = 1; i < ehdr->e_shnum; i++) {
+ Elf32_Shdr *sp;
+ caddr_t *spp;
+ caddr_t load;
+
+ sp = (Elf32_Shdr *)(shdrs + (i*ehdr->e_shentsize));
+ /*
+ * If it's not allocated and not required
+ * 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)
+#else
+ sp->sh_type != SHT_RELA)
+#endif
+ continue;
+ /*
+ * If the section is read-only,
+ * it goes in as text.
+ */
+ spp = (sp->sh_flags & SHF_WRITE)? &edata: &etext;
+ /*
+ * Make some room for it.
+ */
+ load = segbrk(spp, sp->sh_size, sp->sh_addralign);
+ if (load == NULL) {
+ printf("boot: allocating memory for sections failed\n");
+ goto error;
+ }
+ /*
+ * Compute the entry point of the linker.
+ */
+ if (dl_entry == 0 &&
+ !(sp->sh_flags & SHF_WRITE) &&
+ (sp->sh_flags & SHF_EXECINSTR)) {
+ dl_entry = (uintptr_t)load + ehdr->e_entry;
+ }
+ /*
+ * If it's bss, just zero it out.
+ */
+ if (sp->sh_type == SHT_NOBITS) {
+ bzero(load, sp->sh_size);
+ } else {
+ /*
+ * Read the section contents.
+ */
+ if (lseek(fd, sp->sh_offset, 0) == -1 ||
+ xread(fd, load, sp->sh_size) != sp->sh_size) {
+ printf("boot: error reading sections\n");
+ goto error;
+ }
+ }
+ /*
+ * Assign the section's virtual addr.
+ */
+ sp->sh_addr = (Elf32_Off)load;
+ /* force instructions to be visible to icache */
+ if (sp->sh_flags & SHF_EXECINSTR)
+ sync_instruction_memory((caddr_t)sp->sh_addr,
+ sp->sh_size);
+ }
+ /*
+ * Update sizes of segments.
+ */
+ thdr->p_memsz = (Elf32_Word)((uintptr_t)etext - thdr->p_vaddr);
+ dhdr->p_memsz = (Elf32_Word)((uintptr_t)edata - dhdr->p_vaddr);
+
+ /* load and relocate symbol tables in SAS */
+ (void) close(fd);
+ return ((func_t)dl_entry);
+
+error:
+ (void) close(fd);
+errorx:
+ if (ehdr)
+ kmem_free(ehdr, sizeof (Elf32_Ehdr));
+ if (shdrs)
+ kmem_free(shdrs, size);
+ printf("boot: error loading interpreter (%s)\n", rtld);
+ return (FAIL);
+}
+
+#ifdef _ELF64_SUPPORT
+/*
+ * Load the interpreter. It expects a
+ * relocatable .o capable of bootstrapping
+ * itself.
+ */
+static Elf64_Addr
+iload64(char *rtld, Elf64_Phdr *thdr, Elf64_Phdr *dhdr, auxv64_t **avp)
+{
+ Elf64_Ehdr *ehdr = NULL;
+ Elf64_Addr dl_entry = (Elf64_Addr)0;
+ Elf64_Addr etext, edata;
+ uint_t i;
+ int fd;
+ int size;
+ caddr_t shdrs = NULL;
+
+ etext = thdr->p_vaddr + thdr->p_memsz;
+ edata = dhdr->p_vaddr + dhdr->p_memsz;
+
+ /*
+ * Get the module path.
+ */
+ module_path = getmodpath(filename);
+
+ if ((fd = openpath(module_path, rtld, O_RDONLY)) < 0) {
+ printf("boot: cannot find %s\n", rtld);
+ goto errorx;
+ }
+ dprintf("Opened %s OK\n", rtld);
+ AUX64(*avp, AT_SUN_LDNAME, rtld);
+ /*
+ * Allocate and read the ELF header.
+ */
+#ifdef BOOTAMD64
+ if ((ehdr = (Elf64_Ehdr *)(uintptr_t)kmem_alloc(sizeof (Elf64_Ehdr),
+ 0)) == NULL) {
+#else /* !BOOTAMD64 */
+ if ((ehdr = (Elf64_Ehdr *)kmem_alloc(sizeof (Elf64_Ehdr), 0)) == NULL) {
+#endif /* BOOTAMD64 */
+ printf("boot: alloc error reading ELF header (%s).\n", rtld);
+ goto error;
+ }
+
+ if (xread(fd, (char *)ehdr, sizeof (*ehdr)) != sizeof (*ehdr)) {
+ printf("boot: error reading ELF header (%s).\n", rtld);
+ goto error;
+ }
+
+ size = ehdr->e_shentsize * ehdr->e_shnum;
+ if ((shdrs = (caddr_t)kmem_alloc(size, 0)) == NULL) {
+ printf("boot: alloc error reading ELF header (%s).\n", rtld);
+ goto error;
+ }
+ /*
+ * Read the section headers.
+ */
+ if (lseek(fd, ehdr->e_shoff, 0) == -1 ||
+ xread(fd, shdrs, size) != size) {
+ printf("boot: error reading section headers\n");
+ goto error;
+ }
+
+#ifdef BOOTAMD64
+ AUX64(*avp, AT_SUN_LDELF, (uintptr_t)ehdr);
+ AUX64(*avp, AT_SUN_LDSHDR, (uintptr_t)shdrs);
+#else /* !BOOTAMD64 */
+ AUX64(*avp, AT_SUN_LDELF, ehdr);
+ AUX64(*avp, AT_SUN_LDSHDR, shdrs);
+#endif /* BOOTAMD64 */
+
+ /*
+ * Load sections into the appropriate dynamic segment.
+ */
+ for (i = 1; i < ehdr->e_shnum; i++) {
+ Elf64_Shdr *sp;
+ Elf64_Addr *spp, load;
+
+ sp = (Elf64_Shdr *)(shdrs + (i*ehdr->e_shentsize));
+ /*
+ * If it's not allocated and not required
+ * to do relocation, skip it.
+ */
+ if (!(sp->sh_flags & SHF_ALLOC) &&
+ sp->sh_type != SHT_SYMTAB &&
+ sp->sh_type != SHT_STRTAB &&
+ sp->sh_type != SHT_RELA)
+ continue;
+ /*
+ * If the section is read-only,
+ * it goes in as text.
+ */
+ spp = (sp->sh_flags & SHF_WRITE)? &edata: &etext;
+
+ /*
+ * Make some room for it.
+ */
+#ifdef BOOTAMD64
+ load = ADDR_XTND(segbrk((caddr_t *)spp,
+ sp->sh_size, sp->sh_addralign));
+#else /* !BOOTAMD64 */
+ load = (Elf64_Addr)segbrk((caddr_t *)spp, sp->sh_size,
+ sp->sh_addralign);
+#endif /* BOOTAMD64 */
+
+ if (load == NULL) {
+ printf("boot: allocating memory for section %d "
+ "failed\n", i);
+ goto error;
+ }
+
+ /*
+ * Compute the entry point of the linker.
+ */
+ if (dl_entry == 0 &&
+ !(sp->sh_flags & SHF_WRITE) &&
+ (sp->sh_flags & SHF_EXECINSTR)) {
+ dl_entry = load + ehdr->e_entry;
+ if (verbosemode)
+ dprintf("boot: loading linker @ 0x%llx\n",
+ (u_longlong_t)dl_entry);
+ }
+
+ /*
+ * If it's bss, just zero it out.
+ */
+ if (sp->sh_type == SHT_NOBITS) {
+ bzero((caddr_t)load, sp->sh_size);
+ } else {
+ /*
+ * Read the section contents.
+ */
+ if (lseek(fd, sp->sh_offset, 0) == -1 ||
+ xread(fd, (caddr_t)load, sp->sh_size) !=
+ sp->sh_size) {
+ printf("boot: error reading section %d\n",
+ i);
+ goto error;
+ }
+ }
+ /*
+ * Assign the section's virtual addr.
+ */
+
+ sp->sh_addr = load;
+
+ if (verbosemode)
+ dprintf("boot: section %d, type %d, loaded @ 0x%llx, "
+ "size 0x%llx\n", i, sp->sh_type, (u_longlong_t)load,
+ (u_longlong_t)sp->sh_size);
+
+ /* force instructions to be visible to icache */
+ if (sp->sh_flags & SHF_EXECINSTR)
+ sync_instruction_memory((caddr_t)sp->sh_addr,
+ sp->sh_size);
+ }
+ /*
+ * Update sizes of segments.
+ */
+ thdr->p_memsz = etext - thdr->p_vaddr;
+ dhdr->p_memsz = edata - dhdr->p_vaddr;
+
+ /* load and relocate symbol tables in SAS */
+ (void) close(fd);
+ return (dl_entry);
+
+error:
+ (void) close(fd);
+errorx:
+ if (ehdr)
+ kmem_free((caddr_t)ehdr, sizeof (Elf64_Ehdr));
+ if (shdrs)
+ kmem_free(shdrs, size);
+ printf("boot: error loading interpreter (%s)\n", rtld);
+ return (FAIL_ILOAD64);
+}
+#endif /* _ELF64_SUPPORT */
+
+/*
+ * Extend the segment's "break" value by bytes.
+ */
+static caddr_t
+segbrk(caddr_t *spp, size_t bytes, size_t align)
+{
+ caddr_t va, pva;
+ size_t size = 0;
+ unsigned int alloc_pagesize = pagesize;
+ unsigned int alloc_align = 0;
+
+ if (npagesize) {
+ alloc_align = npagesize;
+ alloc_pagesize = npagesize;
+ }
+
+ va = (caddr_t)ALIGN(*spp, align);
+ pva = (caddr_t)roundup((uintptr_t)*spp, alloc_pagesize);
+ /*
+ * Need more pages?
+ */
+ if (va + bytes > pva) {
+ size = roundup((bytes - (pva - va)), alloc_pagesize);
+
+ if (get_progmemory(pva, size, alloc_align)) {
+ printf("boot: segbrk allocation failed, "
+ "0x%lx bytes @ %p\n", bytes, (void *)pva);
+ return (NULL);
+ }
+ }
+ *spp = va + bytes;
+
+ return (va);
+}
+
+/*
+ * Open the file using a search path and
+ * return the file descriptor (or -1 on failure).
+ */
+static int
+openpath(path, fname, flags)
+char *path;
+char *fname;
+int flags;
+{
+ register char *p, *q;
+ char buf[MAXPATHLEN];
+ int fd;
+
+ /*
+ * If the file name is absolute,
+ * don't use the module search path.
+ */
+ if (fname[0] == '/')
+ return (open(fname, flags));
+
+ q = NULL;
+ for (p = path; /* forever */; p = q) {
+
+ while (*p == ' ' || *p == '\t' || *p == ':')
+ p++;
+ if (*p == '\0')
+ break;
+ q = p;
+ while (*q && *q != ' ' && *q != '\t' && *q != ':')
+ q++;
+ (void) strncpy(buf, p, q - p);
+ if (q[-1] != '/') {
+ buf[q - p] = '/';
+ (void) strcpy(&buf[q - p + 1], fname);
+ } else {
+ /*
+ * This checks for paths that end in '/'
+ */
+ (void) strcpy(&buf[q - p], fname);
+ }
+
+ if ((fd = open(buf, flags)) > 0)
+ return (fd);
+ }
+ return (-1);
+}
+
+/*
+ * Get the module search path.
+ */
+static char *
+getmodpath(fname)
+char *fname;
+{
+ register char *p = strrchr(fname, '/');
+ static char mod_path[MOD_MAXPATH];
+ size_t len;
+ extern char *impl_arch_name;
+#if defined(__sparcv9) || defined(__ia64) || defined(BOOTAMD64)
+#ifdef __sparcv9
+ char *isastr = "/sparcv9";
+#endif /* __sparcv9 */
+#ifdef __ia64
+ char *isastr = "/ia64";
+#endif /* __ia64 */
+#ifdef BOOTAMD64
+ char *isastr = "/amd64";
+#endif /* BOOTAMD64 */
+ size_t isalen = strlen(isastr);
+#endif /* __sparcv9 || __ia64 || BOOTAMD64 */
+
+ if (p == NULL) {
+ /* strchr could not find a "/" */
+ printf("%s is not a legal kernel pathname", fname);
+ return (NULL);
+ }
+ while (p > fname && *(p - 1) == '/')
+ p--; /* remove trailing "/"s */
+ if (p == fname)
+ p++; /* "/" is the modpath in this case */
+
+ len = p - fname;
+ (void) strncpy(mod_path, fname, len);
+ mod_path[len] = 0;
+
+#if defined(__sparcv9) || defined(__ia64) || defined(BOOTAMD64)
+ len = strlen(mod_path);
+ if ((len > isalen) && (strcmp(&mod_path[len - isalen], isastr) == 0)) {
+ mod_path[len - isalen] = '\0';
+#if defined(__sparcv9) || defined(__ia64)
+ if ((client_isLP64 == 0) && verbosemode)
+ printf("Assuming LP64 %s client.\n", isastr);
+ client_isLP64 = 1;
+#endif /* __sparcv9 || __ia64 */
+ }
+#endif /* __sparcv9 || __ia64 || BOOTAMD64 */
+ mod_path_uname_m(mod_path, impl_arch_name);
+ (void) strcat(mod_path, " ");
+ (void) strcat(mod_path, MOD_DEFPATH);
+
+ if (boothowto & RB_ASKNAME) {
+ char buf[MOD_MAXPATH];
+
+ printf("Enter default directory for modules [%s]: ", mod_path);
+ (void) cons_gets(buf, sizeof (buf));
+ if (buf[0] != '\0')
+ (void) strcpy(mod_path, buf);
+ }
+ if (verbosemode)
+ printf("modpath: %s\n", mod_path);
+ return (mod_path);
+}
diff --git a/usr/src/psm/stand/boot/common/stripalign.c b/usr/src/psm/stand/boot/common/stripalign.c
new file mode 100644
index 0000000000..17a2f428c4
--- /dev/null
+++ b/usr/src/psm/stand/boot/common/stripalign.c
@@ -0,0 +1,162 @@
+/*
+ * 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.
+ *
+ * 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 1992-2003 Sun Microsystems, Inc.
+ * All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/exechdr.h>
+#include <sys/elf.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <strings.h>
+
+static Elf32_Ehdr elfhdr;
+static Elf32_Phdr phdr, dphdr;
+static char machine[] = {0, 0, 3, 0, 2};
+static int fd;
+static char buf[4096];
+static long lalignbuf[2];
+
+int
+main(int argc, char **argv)
+{
+ int ifd;
+ struct exec exec;
+ int count;
+ int tot_write = 0;
+ long lalign;
+ int lbytes;
+ int text_written = 0;
+ int data_written = 0;
+ char *prog = *argv;
+
+ if (argc < 3) {
+ (void) printf("usage: stripalign elf_file a.outfile \n");
+ exit(1);
+ }
+ if ((ifd = open(argv[1], O_RDONLY)) == -1) {
+ perror("open input");
+ exit(1);
+ }
+ if (read(ifd, &elfhdr, sizeof (elfhdr)) < sizeof (elfhdr)) {
+ perror("read elfhdr");
+ exit(1);
+ }
+ if ((fd = open(argv[2], O_RDWR | O_TRUNC | O_CREAT, 0777)) == -1) {
+ perror("open aout");
+ exit(1);
+ }
+
+ if (*(int *)(elfhdr.e_ident) != *(int *)(ELFMAG)) {
+ perror("elfmag");
+ exit(1);
+ }
+ if (lseek(ifd, elfhdr.e_phoff, 0) == -1) {
+ perror("lseek");
+ exit(1);
+ }
+ if (read(ifd, &phdr, sizeof (phdr)) < sizeof (phdr)) {
+ perror("read phdr");
+ exit(1);
+ }
+ if (read(ifd, &dphdr, sizeof (dphdr)) < sizeof (dphdr)) {
+ perror("read dphdr");
+ exit(1);
+ }
+
+ bzero(&exec, sizeof (exec));
+ exec.a_dynamic = 0;
+ exec.a_toolversion = 1;
+ exec.a_machtype = machine[elfhdr.e_machine];
+ exec.a_magic = OMAGIC;
+ exec.a_text = dphdr.p_vaddr - phdr.p_vaddr;
+ exec.a_data = dphdr.p_filesz;
+ exec.a_bss = dphdr.p_memsz - dphdr.p_filesz;
+ exec.a_entry = elfhdr.e_entry;
+
+ if (write(fd, &exec, sizeof (exec)) != sizeof (exec)) {
+ perror("write exec");
+ exit(1);
+ }
+ tot_write += sizeof (exec);
+
+ if (lseek(ifd, phdr.p_offset, 0) == -1) {
+ perror("lseek text");
+ exit(1);
+ }
+ /* do text section first */
+ while (text_written < exec.a_text &&
+ (count = read(ifd, buf, sizeof (buf))) > 0) {
+ if (count > exec.a_text - text_written)
+ count = (exec.a_text - text_written);
+ if (write(fd, buf, count) < count) {
+ perror("write text file");
+ exit(1);
+ }
+ text_written += count;
+ }
+ tot_write += text_written;
+ if (lseek(ifd, dphdr.p_offset, 0) == -1) {
+ perror("lseek data");
+ exit(1);
+ }
+ while (data_written < exec.a_data &&
+ (count = read(ifd, buf, sizeof (buf))) > 0) {
+ if (count > exec.a_data - data_written)
+ count = (exec.a_data - data_written);
+ if (write(fd, buf, count) < count) {
+ perror("write data file");
+ exit(1);
+ }
+ data_written += count;
+ }
+ tot_write += data_written;
+
+ /*
+ * Round file size out to long word boundary.
+ * If the longword boundary is a multiple of 512 bytes,
+ * add another longword.
+ */
+ lbytes = 0;
+ if ((lalign = tot_write % sizeof (long)) != 0)
+ lbytes = sizeof (long) - lalign;
+ if (((lbytes + tot_write) % 512) == 0)
+ lbytes += sizeof (long);
+
+ if (lbytes != 0) {
+ (void) printf("%s: (Align) 0x%x + 0x%x = 0x%x bytes\n", prog,
+ tot_write, lbytes, (tot_write + lbytes));
+ if (write(fd, (char *)lalignbuf, lbytes) < lbytes) {
+ perror("write (alignment) data file");
+ exit(1);
+ }
+ }
+ (void) close(fd);
+ (void) close(ifd);
+ return (0);
+}
diff --git a/usr/src/psm/stand/boot/i386/Makefile b/usr/src/psm/stand/boot/i386/Makefile
new file mode 100644
index 0000000000..3c2e60a3cb
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/Makefile
@@ -0,0 +1,56 @@
+#
+# 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.
+#
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../../../../Makefile.master
+
+# firmware libraries, platform-group, and platform-specific
+# subdirectories to visit.
+
+SUBDIRS = i86pc
+
+all := TARGET = all
+install := TARGET = install
+clean := TARGET = clean
+clobber := TARGET = clobber
+lint := TARGET = lint
+
+all install clean clobber lint: $(SUBDIRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(MFLAGS) $(TARGET)
+
+#
+# Cross-reference customization: include all boot-related source files.
+#
+UTSDIR= ../../../../uts
+XRDIRS += ../amd64 ../intel ../common
+
+cscope.out tags: FRC
+ $(XREF) -x $@
+
+FRC:
diff --git a/usr/src/psm/stand/boot/i386/Makefile.com b/usr/src/psm/stand/boot/i386/Makefile.com
new file mode 100644
index 0000000000..7e364c12de
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/Makefile.com
@@ -0,0 +1,207 @@
+#
+# 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.
+#
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# psm/stand/boot/i386/Makefile.com
+
+include $(TOPDIR)/psm/stand/boot/Makefile.boot
+
+BOOTSRCDIR = ../..
+
+TOP_CMN_DIR = $(SRC)/common
+PROM_DIR = $(SRC)/uts/intel/promif
+CMN_DIR = $(BOOTSRCDIR)/common
+MACH_DIR = ../common
+PLAT_DIR = .
+PAMD64_DIR = $(BOOTSRCDIR)/amd64
+
+TOP_CMN_C_SRC = getoptstr.c string.c ufsops.c hsfs.c
+TOP_CMN_C_SRC += memcpy.c memmove.c memset.c bcopy.c bzero.c
+PROM_C_SRC = prom_printf.c prom_putchar.c prom_env.c
+CMN_C_SRC = heap_kmem.c readfile.c
+
+PAMD64_C_SRC = alloc.c context.c cpu.c handoff.c memlist.c print.c
+PAMD64_C_SRC += ptops.c ptxlate.c segments.c vtrap.c
+PAMD64_S_SRC = i386_subr.s
+PAMD64_SL_SRC = locore.s exception.s
+
+ASSYM_H = assym.h
+GENASSYM = genassym
+GENASSYM_FILES = $(ASSYM_H) $(GENASSYM)
+
+$(PAMD64_SL_SRC:%.s=%.o) := AS = $(amd64_AS)
+$(PAMD64_SL_SRC:%.s=%.o) := ASFLAGS = -P $(CPPDEFS) -D_ASM $(CPPINCS)
+
+MACH_C_SRC = bios.c bootflags.c bootops.c bootprop.c
+MACH_C_SRC += boot_plat.c boot_ramdisk.c console.c
+MACH_C_SRC += keyboard.c keyboard_table.c memory.c
+MACH_C_SRC += multiboot.c standalloc.c vga.c graphics.c
+MACH_C_SRC += bootenv.c vgaprobe.c check_iopath.c
+
+BIOS_C_SRC = biosutil.c
+
+C_SRC = $(TOP_CMN_C_SRC) $(CMN_C_SRC) $(MACH_C_SRC) $(ARCH_C_SRC)
+C_SRC += $(PAMD64_C_SRC) $(PROM_C_SRC)
+S_SRC = $(ARCH_S_SRC) $(PAMD64_S_SRC) $(PAMD64_SL_SRC)
+
+START_OBJS = $(START_S_SRC:%.s=%.o)
+OBJS = $(C_SRC:%.c=%.o) $(S_SRC:%.s=%.o)
+L_OBJS = $(OBJS:%.o=%.ln)
+
+# Note: the BIOS_S_SRC (biosint.s) must come first
+BIOS_OBJS = $(BIOS_S_SRC:%.s=%.o) $(BIOS_C_SRC:%.c=%.o)
+
+ELFCONV = mkbin
+BIOSINT = biosint
+UNIBOOT = multiboot
+
+ROOT_PSM_BIOSINT = $(ROOT_PSM_DIR)/$(BIOSINT)
+ROOT_PSM_UNIBOOT = $(ROOT_PSM_DIR)/$(UNIBOOT)
+
+.KEEP_STATE:
+
+.PARALLEL: $(OBJS) $(START_OBJS) $(L_OBJS)
+
+all: $(ELFCONV) $(UNIBOOT) $(BIOSINT)
+
+SYSDIR = $(TOPDIR)/uts
+
+CPPDEFS = $(ARCHOPTS) -D$(PLATFORM) -D_BOOT -D_KERNEL -D_MACHDEP
+CPPINCS += -I$(TOP_CMN_DIR)
+CPPINCS += -I. -I$(PAMD64_DIR)
+CPPINCS += -I$(PSMSYSHDRDIR)
+CPPINCS += -I$(ROOT)/usr/platform/$(PLATFORM)/include
+CPPINCS += -I$(TOPDIR)/uts/intel -I$(TOPDIR)/uts/i86pc
+CPPINCS += -I$(TOPDIR)/uts/common
+CPPINCS += -I$(STANDDIR)/lib/sa
+CPPINCS += -I$(STANDDIR)
+
+CPPFLAGS = $(CPPDEFS) $(CPPINCS)
+CPPFLAGS += $(CCYFLAG)$(SYSDIR)/common
+ASFLAGS = $(CPPDEFS) -P -D__STDC__ -D_BOOT -D_ASM $(CPPINCS)
+
+CFLAGS = ../common/i86.il $(COPTFLAG)
+#
+# Force 16-bit alignment in multiboot
+#
+CFLAGS += -xcache=0/16/0:0/16/0
+#
+# This should be globally enabled!
+#
+CFLAGS += $(CCVERBOSE)
+
+YFLAGS = -d
+
+#
+# Loader flags used to build biosint
+#
+BIOS_LOADMAP = bios_loadmap
+BIOS_MAPFILE = $(MACH_DIR)/biosint.map
+BIOS_LDFLAGS = -dn -m -M $(BIOS_MAPFILE)
+
+$(ELFCONV): $(MACH_DIR)/$$(@).c
+ $(NATIVECC) -O -o $@ $(MACH_DIR)/$@.c
+
+$(BIOSINT): $(ELFCONV) $(BIOS_MAPFILE) $(BIOS_OBJS)
+ $(LD) $(BIOS_OBJS) $(BIOS_LDFLAGS) -o $@.elf > $(BIOS_LOADMAP)
+ cp $@.elf $@.strip
+ $(STRIP) $@.strip
+ $(RM) $@; ./$(ELFCONV) $@.strip $@
+
+#
+# Loader flags used to build unified boot
+#
+UNI_LOADMAP = loadmap
+UNI_MAPFILE = $(MACH_DIR)/mapfile
+UNI_LDFLAGS = -dn -m -M $(UNI_MAPFILE)
+
+#
+# Object files used to build unified boot
+# Note: START_OBJS must come within first 8K to comply with Multiboot Spec
+#
+UNI_OBJS = $(START_OBJS) $(OBJS)
+UNI_L_OBJS = $(UNI_OBJS:%.o=%.ln)
+
+$(UNIBOOT): $(UNI_MAPFILE) $(UNI_OBJS)
+ $(LD) $(UNI_LDFLAGS) -o $@ $(UNI_OBJS) > $(UNI_LOADMAP)
+ $(POST_PROCESS)
+
+$(UNIBOOT)_lint: $(UNI_L_OBJS)
+ $(LINT.c) $(UNI_L_OBJS)
+
+ROOT_BOOT_DIR = $(ROOT)/boot
+ROOT_BOOT_SOL_DIR = $(ROOT_BOOT_DIR)/solaris
+
+$(ROOT_BOOT_DIR): $(ROOT)
+ -$(INS.dir.root.sys)
+
+$(ROOT_BOOT_SOL_DIR): $(ROOT_BOOT_DIR)
+ -$(INS.dir.root.sys)
+
+$(ROOT_BOOT_SOL_DIR)/%: % $(ROOT_BOOT_SOL_DIR)
+ $(INS.file)
+
+#
+# AMD64 genassym fun
+#
+$(PAMD64_S_SRC:%.s=%.o) : $(GENASSYM_FILES)
+$(PAMD64_SL_SRC:%.s=%.o) : $(GENASSYM_FILES)
+
+GENASSYM_SRC = $(PAMD64_DIR)/$(GENASSYM:%=%.c)
+$(GENASSYM) := CFLAGS = -D__sun $(ENVCPPFLAGS1) $(ENVCPPFLAGS2) \
+ $(ENVCPPFLAGS3) $(ENVCPPFLAGS4)
+
+$(GENASSYM): $(GENASSYM_SRC)
+ $(NATIVECC) $(CFLAGS) -o $@ $(GENASSYM_SRC)
+
+OFFSETS = $(PAMD64_DIR)/offsets.in
+$(ASSYM_H) := CC = $(amd64_CC)
+$(ASSYM_H) := CFLAGS = -g -xarch=amd64 -xc99=%none \
+ -D__sun $(CPPFLAGS)
+$(ASSYM_H) := CCYFLAG = -g -YI,
+
+$(ASSYM_H): $(OFFSETS) $(GENASSYM)
+ $(GENOFFSETS) -s $(CTFSTABS) -r $(CTFCONVERT) \
+ $(CC) $(CFLAGS) $(GOFLAGS) <$(OFFSETS) >$@
+ ./$(GENASSYM) >>$@
+
+include $(BOOTSRCDIR)/Makefile.rules
+
+clean:
+ $(RM) $(OBJS) $(BIOS_OBJS)
+ $(RM) $(L_OBJS) $(GENASSYM_FILES)
+ $(RM) $(BIOSINT).elf a.out core
+
+clobber: clean
+ $(RM) $(ELFCONV) $(UNIBOOT) $(UNI_LOADMAP) $(BIOSINT) $(BIOS_LOADMAP)
+ $(RM) $(UFSBOOT) $(NFSBOOT)
+
+include $(TOPDIR)/Makefile.psm.targ
+
+install: $(ROOT_PSM_UNIBOOT) $(ROOT_PSM_BIOSINT)
+
+lint: all $(UNIBOOT)_lint
+
+FRC:
diff --git a/usr/src/psm/stand/boot/i386/common/bios.c b/usr/src/psm/stand/boot/i386/common/bios.c
new file mode 100644
index 0000000000..f6c0ee5013
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/bios.c
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ *
+ * 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 2005 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/controlregs.h>
+#include <sys/bootconf.h>
+#include <sys/bootvfs.h>
+#include <sys/psw.h>
+#include "biosint.h"
+#include "machine.h"
+#include "standalloc.h"
+#include "console.h"
+#include "util.h"
+#include "debug.h"
+
+#define PCI_FUNCTION_ID 0xB1
+#define PCI_BIOS_PRESENT 0x1
+#define dprintf if (debug & D_BIOS) printf
+
+extern int openfile(char *, int);
+int (*bios_doint)(int, struct int_pb *);
+
+static void
+pci_check_bios(void)
+{
+ int ret;
+ struct int_pb ic = {0};
+
+ ic.ax = (PCI_FUNCTION_ID << 8) | PCI_BIOS_PRESENT;
+ ret = bios_doint(0x1a, &ic);
+ if (ret & PS_C)
+ printf("bios_doint failed: %d\r\n", ret);
+ dprintf("bios_doint returned: %d\r\n", ret);
+ dprintf("ic.ax = 0x%x\r\n", (int)ic.ax);
+ dprintf("ic.dx = 0x%x\r\n", (int)ic.dx);
+}
+
+void
+init_biosprog()
+{
+ int fd;
+ char *buf = (char *)0x2000;
+ ssize_t count;
+
+ /* read biosint program to pfn 2 */
+ fd = openfile("biosint", 0);
+ if (fd == -1) {
+ printf("cannot open biosint\n");
+ return;
+ }
+
+ count = read(fd, buf, PAGESIZE);
+ if (count <= 0) {
+ printf("cannot read biosint\n");
+ return;
+ }
+
+ bios_doint = (int (*)(int, struct int_pb *))(buf);
+ dprintf("biosint loaded at 0x%x: %d bytes\r\n", buf, count);
+ if (debug & D_BIOS) /* run a check if debug */
+ pci_check_bios();
+ if (verbosemode)
+ printf("bios service program installed\n");
+}
diff --git a/usr/src/psm/stand/boot/i386/common/biosint.h b/usr/src/psm/stand/boot/i386/common/biosint.h
new file mode 100644
index 0000000000..0372ed078a
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/biosint.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_BIOSINT_H
+#define _SYS_BIOSINT_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct int_pb {
+ unsigned short ax, bx, cx, dx, bp, si, di, ds, es;
+};
+
+extern int (*bios_doint)(int, struct int_pb *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_BIOSINT_H */
diff --git a/usr/src/psm/stand/boot/i386/common/biosint.map b/usr/src/psm/stand/boot/i386/common/biosint.map
new file mode 100644
index 0000000000..8780bf99b3
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/biosint.map
@@ -0,0 +1,28 @@
+#
+# Copyright 2005 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.
+#
+# 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"
+
+text = LOAD V0x2000;
+data = A0x1;
diff --git a/usr/src/psm/stand/boot/i386/common/biosutil.c b/usr/src/psm/stand/boot/i386/common/biosutil.c
new file mode 100644
index 0000000000..8a309f5756
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/biosutil.c
@@ -0,0 +1,335 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * helper functions for switching to realmode and make a bios call.
+ * The only interesting functions are copyin_args and copyout_args.
+ * The rest are for debugging via a serial line.
+ */
+
+#include <sys/types.h>
+#include <sys/varargs.h>
+#include "../common/biosint.h"
+#include "../common/chario.h"
+#include "../common/serial.h"
+
+extern uchar_t inb(int);
+extern void outb(int, uchar_t);
+
+/* Forward declarations. */
+static void putchar(int c);
+static void itoa(char *buf, int base, int d);
+
+void
+copyin_args(int intnum, struct int_pb *ic)
+{
+ extern int ic_int;
+ extern uint16_t ic_ax, ic_bx, ic_cx, ic_dx;
+ extern uint16_t ic_bp, ic_si, ic_di, ic_ds, ic_es;
+
+ ic_int = intnum;
+ ic_ax = ic->ax;
+ ic_bx = ic->bx;
+ ic_cx = ic->cx;
+ ic_dx = ic->dx;
+ ic_bp = ic->bp;
+ ic_si = ic->si;
+ ic_di = ic->di;
+ ic_ds = ic->ds;
+ ic_es = ic->es;
+}
+
+void
+copyout_args(struct int_pb *ic)
+{
+ extern uint16_t ic_ax, ic_bx, ic_cx, ic_dx;
+ extern uint16_t ic_bp, ic_si, ic_di, ic_ds, ic_es;
+
+ ic->ax = ic_ax;
+ ic->bx = ic_bx;
+ ic->cx = ic_cx;
+ ic->dx = ic_dx;
+ ic->bp = ic_bp;
+ ic->si = ic_si;
+ ic->di = ic_di;
+ ic->ds = ic_ds;
+ ic->es = ic_es;
+}
+
+/*
+ * Convert the integer D to a string and save the string in BUF. If
+ * BASE is equal to 'd', interpret that D is decimal, and if BASE is
+ * equal to 'x', interpret that D is hexadecimal.
+ */
+static void
+itoa(char *buf, int base, int d)
+{
+ char *p = buf;
+ char *p1, *p2;
+ unsigned long ud = d;
+ int divisor = 10;
+
+ /* If %d is specified and D is minus, put `-' in the head. */
+ if (base == 'd' && d < 0) {
+ *p++ = '-';
+ buf++;
+ ud = -d;
+ } else if (base == 'x') {
+ divisor = 16;
+ }
+
+ /* Divide UD by DIVISOR until UD == 0. */
+ do {
+ int remainder = ud % divisor;
+
+ *p++ = (remainder < 10) ?
+ remainder + '0' : remainder + 'a' - 10;
+ }
+
+ while (ud /= divisor)
+ ;
+
+ /* Terminate BUF. */
+ *p = 0;
+
+ /* Reverse BUF. */
+ p1 = buf;
+ p2 = p - 1;
+ while (p1 < p2) {
+ char tmp = *p1;
+ *p1 = *p2;
+ *p2 = tmp;
+ p1++;
+ p2--;
+ }
+}
+
+/*
+ * Printn prints a number n in base b.
+ * We don't use recursion to avoid deep kernel stacks.
+ */
+/* XXX need to support 64-bit numbers */
+static void
+_printn(uint_t n, int b, int width, int pad)
+{
+ char prbuf[40];
+ char *cp;
+
+ cp = prbuf;
+ do {
+ *cp++ = "0123456789abcdef"[n%b];
+ n /= b;
+ width--;
+ } while (n);
+ while (width-- > 0)
+ *cp++ = (char)pad;
+ do {
+ putchar(*--cp);
+ } while (cp > prbuf);
+}
+
+/*
+ * Format a string and print it on the screen, just like the libc
+ * function printf.
+ */
+void
+vprintf(const char *fmt, va_list adx)
+{
+ int b, c, i, pad, width, ells;
+ char *s;
+ int64_t l;
+ uint64_t ul;
+
+loop:
+ width = 0;
+ while ((c = *fmt++) != '%') {
+ if (c == '\0')
+ return;
+ putchar(c);
+ }
+
+ c = *fmt++;
+
+ for (pad = ' '; c == '0'; c = *fmt++)
+ pad = '0';
+
+ for (width = 0; c >= '0' && c <= '9'; c = *fmt++)
+ width = (width * 10) + (c - '0');
+
+ for (ells = 0; c == 'l'; c = *fmt++)
+ ells++;
+
+ switch (c) {
+
+ case 'd':
+ case 'D':
+ b = 10;
+ if (ells == 0)
+ l = (int64_t)va_arg(adx, int);
+ else if (ells == 1)
+ l = (int64_t)va_arg(adx, long);
+ else
+ l = (int64_t)va_arg(adx, int64_t);
+ if (l < 0) {
+ putchar('-');
+ width--;
+ putchar('-');
+ width--;
+ ul = -l;
+ } else
+ ul = l;
+ goto number;
+
+ case 'p':
+ ells = 1;
+ /* FALLTHROUGH */
+ case 'x':
+ case 'X':
+ b = 16;
+ goto u_number;
+
+ case 'u':
+ b = 10;
+ goto u_number;
+
+ case 'o':
+ case 'O':
+ b = 8;
+u_number:
+ if (ells == 0)
+ ul = (uint64_t)va_arg(adx, uint_t);
+ else if (ells == 1)
+ ul = (uint64_t)va_arg(adx, ulong_t);
+ else
+ ul = (uint64_t)va_arg(adx, uint64_t);
+number:
+ _printn((uint_t)ul, b, width, pad);
+ break;
+
+ case 'c':
+ b = va_arg(adx, int);
+ for (i = 24; i >= 0; i -= 8)
+ if ((c = ((b >> i) & 0x7f)) != 0) {
+ putchar(c);
+ }
+ break;
+ case 's':
+ s = va_arg(adx, char *);
+ while ((c = *s++) != 0) {
+ putchar(c);
+ }
+ break;
+
+ case '%':
+ putchar('%');
+ break;
+ }
+ goto loop;
+
+}
+
+/*
+ * Format a string and print it on the screen, just like the libc
+ * function printf.
+ */
+void
+printf(const char *fmt, ...)
+{
+ va_list adx;
+
+ va_start(adx, fmt);
+ vprintf(fmt, adx);
+ va_end(adx);
+}
+
+/* serial port stuff */
+static int port = 0x3f8;
+
+static void
+serial_putchar(int c)
+{
+ int checks = 10000;
+
+ while (((inb(port + LSR) & XHRE) == 0) && checks--)
+ ;
+ outb(port + DAT, (char)c);
+}
+
+static void
+_doputchar(int c)
+{
+ serial_putchar(c);
+}
+
+void
+putchar(int c)
+{
+ static int bhcharpos = 0;
+
+ if (c == '\t') {
+ do {
+ _doputchar(' ');
+ } while (++bhcharpos % 8);
+ return;
+ } else if (c == '\n') {
+ bhcharpos = 0;
+ _doputchar('\r');
+ _doputchar(c);
+ return;
+ } else if (c == '\b') {
+ if (bhcharpos)
+ bhcharpos--;
+ _doputchar(c);
+ return;
+ }
+
+ bhcharpos++;
+ _doputchar(c);
+}
+
+void
+print_long(int reg)
+{
+ printf("long = 0x%x\n", reg);
+}
+
+void
+print_word(ushort_t reg)
+{
+ printf("word = 0x%x\n", reg);
+}
+
+void
+print_regs()
+{
+ extern int call_esp, ic_int;
+ extern uint16_t call_cs, call_ss;
+
+ printf("call_cs = %x, call_ss = %x\r\n", call_cs, call_ss);
+ printf("intnum = %x, esp = %x\r\n", ic_int, call_esp);
+}
diff --git a/usr/src/psm/stand/boot/i386/common/boot_plat.c b/usr/src/psm/stand/boot/i386/common/boot_plat.c
new file mode 100644
index 0000000000..14dea10f6f
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/boot_plat.c
@@ -0,0 +1,267 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/param.h>
+#include <sys/bootvfs.h>
+#include <sys/varargs.h>
+#include "console.h"
+#include "util.h"
+#include "bootprop.h"
+#include "biosint.h"
+#include "debug.h"
+
+char filename[MAXPATHLEN];
+char *impl_arch_name = "i86pc";
+int pagesize = 0x1000;
+
+extern void *memset(void *, int, size_t);
+
+
+/*
+ * Open the given filename, expanding to its
+ * platform-dependent location if necessary.
+ */
+int
+openfile(char *fname, char *kern)
+{
+ int fd;
+
+ /*
+ * If the caller -specifies- an absolute pathname, then we just try to
+ * open it.
+ */
+ if (*fname == '/') {
+ (void) strcpy(filename, fname);
+ return (open(fname, 0));
+ }
+
+ (void) strcpy(filename, "/platform/i86pc/");
+ if (kern)
+ (void) strcat(filename, kern);
+ (void) strcat(filename, fname);
+ if ((fd = open(filename, 0)) != -1)
+ return (fd);
+
+ /* try / */
+ (void) strcpy(filename, "/");
+ if (kern)
+ (void) strcat(filename, kern);
+ (void) strcat(filename, fname);
+ return (open(filename, 0));
+}
+
+/*
+ * Is path "/platform/"dir"/" ?
+ */
+static int
+platcmp(char *path, char *dir)
+{
+ static char prefix[] = "/platform/";
+ static char suffix[] = "/kernel";
+ int len;
+
+ if (strncmp(path, prefix, sizeof (prefix) - 1) != 0)
+ return (0);
+ len = strlen(dir);
+ path += sizeof (prefix) - 1;
+ if (strncmp(path, dir, len) != 0)
+ return (0);
+ path += len;
+ if (strcmp(path, suffix) != 0)
+ return (0);
+ return (1);
+}
+
+void
+mod_path_uname_m(char *mod_path, char *ia_name)
+{
+ /*
+ * If we found the kernel in the default "i86pc" dir, prepend the
+ * ia_name directory (e.g. /platform/SUNW,foo/kernel) to the mod_path
+ * unless ia_name is the same as the default dir.
+ *
+ * If we found the kernel in the ia_name dir, append the default
+ * directory to the modpath.
+ *
+ * If neither of the above are true, we were given a specific kernel
+ * to boot, so we leave things well enough alone.
+ */
+ if (platcmp(mod_path, "i86pc")) {
+ if (strcmp(ia_name, "i86pc") != 0) {
+ char tmp[MAXPATHLEN];
+
+ (void) strcpy(tmp, mod_path);
+ (void) strcpy(tmp, mod_path);
+ (void) strcpy(mod_path, "/platform/");
+ (void) strcat(mod_path, ia_name);
+ (void) strcat(mod_path, "/kernel ");
+ (void) strcat(mod_path, tmp);
+ }
+ } else if (platcmp(mod_path, ia_name))
+ (void) strcat(mod_path, " /platform/i86pc/kernel");
+}
+
+void
+setup_aux(void)
+{
+ extern char *mmulist;
+ static char mmubuf[16];
+ int plen;
+
+ if (((plen = bgetproplen(NULL, "mmu-modlist")) > 0) && (plen < 20))
+ (void) bgetprop(NULL, "mmu-modlist", mmubuf);
+ else
+ (void) strcpy(mmubuf, "mmu32"); /* default to mmu32 */
+ mmulist = mmubuf;
+}
+
+/* Print panic string, then blow up! */
+/*PRINTFLIKE1*/
+void
+panic(const char *fmt, ...)
+{
+ va_list adx;
+
+ /* turn on output */
+ verbosemode = 1;
+ printf("panic: ");
+ va_start(adx, fmt);
+ prom_vprintf(fmt, adx);
+ va_end(adx);
+ printf("Press any key to reboot\n");
+ (void) getchar();
+ printf("rebooting...\n");
+ reset();
+}
+
+void
+prom_panic(char *str)
+{
+ panic(str);
+}
+
+/*
+ * stubs for heap_kmem (assuming they're actually even needed there)
+ */
+
+int
+splimp()
+{
+ return (0);
+}
+
+/*ARGSUSED*/
+void
+splx(int rs)
+{
+}
+
+int
+splnet()
+{
+ return (0);
+}
+
+static uint_t
+gettime(void)
+{
+ /*
+ * Read system timer:
+ *
+ * Return milliseconds since last time counter was reset.
+ * The timer ticks 18.2 times per second or approximately
+ * 55 milliseconds per tick.
+ *
+ * The counter will be reset to zero by the bios after 24 hours
+ * or 1,573,040 ticks. The first read after a counter
+ * reset will flag this condition in the %al register.
+ * Unfortunately, it is hard to take advantage of this
+ * fact because some broken bioses will return bogus
+ * counter values if the counter is in the process of
+ * updating. We protect against this race by reading the
+ * counter until we get consecutive identical readings.
+ * By doing so, we lose the counter reset bit. To make this
+ * highly unlikely, we reset the counter to zero on the
+ * first call and assume 24 hours is enough time to get this
+ * machine booted.
+ *
+ * An attempt is made to provide a unique number on each
+ * call by adding 1 millisecond if the 55 millisecond counter
+ * hasn't changed. If this happens more than 54 times, we
+ * return the same value until the next real tick.
+ */
+ static uint_t lasttime = 0;
+ static ushort_t fudge = 0;
+ uint_t ticks, mills, first, tries;
+ struct int_pb ic;
+
+ if (lasttime == 0) {
+ /*
+ * initialize counter to zero so we don't have to
+ * worry about 24 hour wrap.
+ */
+ (void) memset(&ic, 0, sizeof (ic));
+ ic.ax = 0x0100;
+ (void) bios_doint(0x1a, &ic);
+ }
+ tries = 0;
+ do {
+ /*
+ * Loop until we trust the counter value.
+ */
+ (void) memset(&ic, 0, sizeof (ic));
+ (void) bios_doint(0x1a, &ic);
+ first = (ic.cx << 16) + (ic.dx & 0xFFFF);
+ (void) memset(&ic, 0, sizeof (ic));
+ (void) bios_doint(0x1a, &ic);
+ ticks = (ic.cx << 16) + (ic.dx & 0xFFFF);
+ } while (first != ticks && ++tries < 10);
+ if (tries == 10)
+ printf("gettime: BAD BIOS TIMER\n");
+
+ mills = ticks*55;
+ if (mills > lasttime) {
+ fudge = 0;
+ } else {
+ fudge += (fudge < 54) ? 1 : 0;
+ }
+ mills += fudge;
+ lasttime = mills;
+ return (mills);
+}
+
+void
+mdelay(uint_t msec)
+{
+ uint_t time_now = gettime();
+ uint_t time_end = time_now + msec;
+
+ /* spin, we can't do anything else */
+ while (gettime() < time_end)
+ ;
+}
diff --git a/usr/src/psm/stand/boot/i386/common/boot_ramdisk.c b/usr/src/psm/stand/boot/i386/common/boot_ramdisk.c
new file mode 100644
index 0000000000..c9bf684ecd
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/boot_ramdisk.c
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/param.h>
+#include <sys/bootconf.h>
+#include <sys/bootvfs.h>
+#include <sys/filep.h>
+#include "util.h"
+#include "debug.h"
+
+extern struct boot_fs_ops bufs_ops, bhsfs_ops;
+
+extern uint64_t ramdisk_start, ramdisk_end;
+struct boot_fs_ops *bfs_ops;
+struct boot_fs_ops *bfs_tab[] = {&bufs_ops, &bhsfs_ops, NULL};
+
+/*
+ * This one reads the ramdisk. If fi_memp is set, we copy the
+ * ramdisk content to the designated buffer. Otherwise, we
+ * do a "cached" read (set fi_memp to the actual ramdisk buffer).
+ */
+int
+diskread(fileid_t *filep)
+{
+ uint_t blocknum;
+ caddr_t diskloc;
+
+ /* add in offset of root slice */
+ blocknum = filep->fi_blocknum;
+
+ diskloc = (caddr_t)(ramdisk_start + blocknum * DEV_BSIZE);
+ if (diskloc + filep->fi_count > (caddr_t)ramdisk_end) {
+ printf("diskread: reading beyond end of ramdisk\n");
+ printf("\tstart = 0x%p, size = 0x%x\n",
+ diskloc, filep->fi_count);
+ return (-1);
+ }
+
+ if (filep->fi_memp) {
+ bcopy(diskloc, filep->fi_memp, filep->fi_count);
+ } else {
+ /* "cached" read */
+ filep->fi_memp = diskloc;
+ }
+
+ return (0);
+}
+
+int
+mountroot(char *name)
+{
+ int i;
+
+ if (verbosemode)
+ printf("mountroot on ramdisk: 0x%llx-%llx\n",
+ ramdisk_start, ramdisk_end);
+ /* try ops in bfs_tab and return the first successful one */
+ for (i = 0; bfs_tab[i] != NULL; i++) {
+ bfs_ops = bfs_tab[i];
+ if (BRD_MOUNTROOT(bfs_ops, name) == 0)
+ return (0);
+ }
+ return (-1);
+}
+
+int
+unmountroot()
+{
+ return (BRD_UNMOUNTROOT(bfs_ops));
+}
+
+int
+open(const char *filename, int flags)
+{
+ return (BRD_OPEN(bfs_ops, (char *)filename, flags));
+}
+
+int
+close(int fd)
+{
+ return (BRD_CLOSE(bfs_ops, fd));
+}
+
+ssize_t
+read(int fd, void *buf, size_t size)
+{
+ return (BRD_READ(bfs_ops, fd, buf, size));
+}
+
+off_t
+lseek(int fd, off_t addr, int whence)
+{
+ return (BRD_SEEK(bfs_ops, fd, addr, whence));
+}
diff --git a/usr/src/psm/stand/boot/i386/common/bootenv.c b/usr/src/psm/stand/boot/i386/common/bootenv.c
new file mode 100644
index 0000000000..50eb192244
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/bootenv.c
@@ -0,0 +1,205 @@
+/*
+ * 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.
+ *
+ * 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 2005 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/bootconf.h>
+#include <sys/salib.h>
+#include "debug.h"
+#include "multiboot.h"
+#include "bootprop.h"
+
+extern void prom_init(char *, void *);
+extern void prom_panic(char *);
+extern int openfile(char *, char *);
+extern int close(int);
+
+
+#define BOOTENV_BUFSIZE 4096
+#define BOOTENV_LINESIZE 256
+
+/*
+ * Note this path name must be consistent with that used
+ * in the ramdisk construction.
+ */
+static char *f_bootenv = "/boot/solaris/bootenv.rc";
+
+
+static void
+get_bootenv_prop(char *line, int lineno)
+{
+ char *p;
+ int inq;
+ char *name;
+ char *val;
+ char **propp;
+
+ /*
+ * Trim comments, respecting single quotes, then
+ * skip any blank lines and leading white space.
+ */
+ inq = 0;
+ for (p = line; *p; p++) {
+ if (*p == '\'' || *p == '"') {
+ inq ^= 1;
+ } else if ((inq == 0 && *p == '#') ||
+ *p == '\r' || *p == '\n') {
+ *p = 0;
+ break;
+ }
+ }
+
+ while (*line == ' ' || *line == '\t')
+ line++;
+ if (strlen(line) == 0)
+ return;
+
+ /*
+ * Anything remaining must be in a fixed format
+ */
+ if ((name = strchr(line, ' ')) == NULL)
+ goto err;
+ *name++ = 0;
+ if (strcmp(line, "setprop") != 0)
+ goto err;
+ if ((val = strchr(name, ' ')) == NULL)
+ goto err;
+ *val++ = 0;
+
+ p = val + strlen(val) - 1;
+ if (((*val == '\'' && *p == '\'') ||
+ (*val == '"' && *p == '"')) && val != p) {
+ *p = 0;
+ val++;
+ }
+
+ /*
+ * An empty name indicates a syntax error but
+ * an empty value should just be ignored.
+ */
+ if (strlen(name) == 0)
+ goto err;
+ if (strlen(val) == 0)
+ return;
+
+ if (debug & D_BPROP)
+ printf("%s(%d): %s %s\n", f_bootenv, lineno, name, val);
+
+ (void) bsetprop(NULL, name, val, strlen(val) + 1);
+
+ /*
+ * We respect certain eeprom(1M) properties internally
+ * if not overridden on the grub kernel cmdline.
+ * There should never be multiple definitions, but
+ * should that occur, the last one is the one that sticks.
+ */
+ propp = NULL;
+ if (strcmp(name, "boot-file") == 0)
+ propp = &bootfile_prop;
+ else if (strcmp(name, "console") == 0)
+ propp = &console_prop;
+ else if (strcmp(name, "input-device") == 0)
+ propp = &inputdevice_prop;
+ else if (strcmp(name, "output-device") == 0)
+ propp = &outputdevice_prop;
+
+ if (propp) {
+ if (*propp)
+ bkmem_free(*propp, strlen(*propp) + 1);
+ *propp = bkmem_zalloc(strlen(val)+1);
+ strcpy(*propp, val);
+ }
+
+ return;
+
+err:
+ printf("%s: syntax error on line %d\n", f_bootenv, lineno);
+}
+
+int
+get_bootenv_props()
+{
+ int fd;
+ char *line;
+ char *buf;
+ int n, bufcnt;
+ int c, linecnt;
+ char *bp, *lp;
+ int lineno = 1;
+ int err;
+
+ fd = openfile(f_bootenv, 0);
+ if (fd == -1) {
+ printf("error opening %s\n", f_bootenv);
+ return (0);
+ }
+
+ buf = bkmem_zalloc(BOOTENV_BUFSIZE);
+ line = bkmem_zalloc(BOOTENV_LINESIZE);
+
+ lp = line;
+ *lp = 0;
+ bufcnt = 0;
+ linecnt = 0;
+ err = 0;
+
+ for (;;) {
+ if (bufcnt == 0) {
+ n = read(fd, buf, BOOTENV_BUFSIZE);
+ if (n <= 0)
+ goto exit;
+ bufcnt = n;
+ bp = buf;
+ }
+ while (bufcnt > 0) {
+ if ((c = *bp++) == '\n') {
+ get_bootenv_prop(line, lineno++);
+ linecnt = 0;
+ lp = line;
+ err = 0;
+ } else if (linecnt < BOOTENV_LINESIZE-1) {
+ *lp++ = c;
+ linecnt++;
+ } else if (err == 0) {
+ printf("%s: line %d exceeds maximum (%d)\n",
+ f_bootenv, lineno, BOOTENV_LINESIZE);
+ err = 1;
+ }
+ bufcnt--;
+ *lp = 0;
+ }
+ }
+
+exit:
+
+ bkmem_free(buf, BOOTENV_BUFSIZE);
+ bkmem_free(line, BOOTENV_LINESIZE);
+
+ close(fd);
+
+ return (0);
+}
diff --git a/usr/src/psm/stand/boot/i386/common/bootflags.c b/usr/src/psm/stand/boot/i386/common/bootflags.c
new file mode 100644
index 0000000000..95a1c706e5
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/bootflags.c
@@ -0,0 +1,279 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Parse the boot arguments.
+ */
+
+#include <sys/reboot.h>
+#include <sys/promif.h>
+#include <sys/boot.h>
+#include <sys/salib.h>
+#include <sys/param.h>
+#include <util/getoptstr.h>
+#include "bootprop.h"
+#include "debug.h"
+
+int boothowto;
+int verbosemode;
+char *bootprog;
+char *bootfile;
+char bootargs[MAXNAMELEN];
+char bootprop[MAXPATHLEN];
+static char bootfile_buf[MAXNAMELEN];
+static char bootprog_buf[MAXNAMELEN];
+static int grub_line_present;
+
+
+/*
+ * Parse the boot arguments and place results in bootprog, bootfile,
+ * bootargs, and bootprops. Note that anything unknown is treated as
+ * [kern-args] and is passed to kernel as is.
+ *
+ * The format for the GRUB args is:
+ * /boot/multiboot [bootfile [-D path]] [-Vadvk]
+ * [-B prop=value[,prop=value...]] [kern-args]
+ *
+ * The format for the eeprom boot-file is:
+ * [bootfile [-D path]] [-Vadvk] [kern-args]
+ *
+ * The grub line takes precedence
+ */
+static void
+get_bootargs(char *args, int grub)
+{
+ struct gos_params params;
+ const char *cp, *SPC = " \t";
+ char *np;
+ size_t npres;
+ int c;
+
+ /* parse grub bootprog (multiboot) and -B */
+ if (grub) {
+ char *dash_B = strstr(args, " -B");
+ if (dash_B) {
+ /* copy -B arg to bootprop */
+ cp = strtok(dash_B + 3, SPC);
+ (void) strncpy(bootprop, cp, MAXPATHLEN - 1);
+ bootprop[MAXPATHLEN - 1] = 0;
+
+ /* move the end string forward */
+ cp = strtok(NULL, "");
+ if (cp) {
+ *dash_B++ = ' ';
+ while (*dash_B++ = *cp++)
+ ;
+ } else {
+ *dash_B = 0;
+ }
+ }
+
+ /* get the multiboot prog (must be present) */
+ bootprog = strtok(args, SPC);
+ strcpy(bootprog_buf, bootprog);
+ bootprog = bootprog_buf;
+ bootfile = strtok(NULL, SPC);
+ grub_line_present = (bootfile != NULL);
+ } else {
+ /* don't process bootfile_prop if grub line is present */
+ if (grub_line_present) {
+ if (args && verbosemode)
+ printf("grub line specified, ignoring "
+ "boot-file setting %s in bootenv.rc\n",
+ args);
+ return;
+ }
+ bootfile = strtok(args, SPC);
+ }
+
+ /* check for leading kmdb/kadb for compatibility */
+ if (bootfile == NULL)
+ return;
+
+ if (*bootfile == '-') {
+ args = bootfile;
+ /* XXX undo strtok, if have additional tokens */
+ if (strtok(NULL, ""))
+ args[strlen(bootfile)] = ' ';
+ bootfile = NULL;
+ } else {
+ if (strcmp(bootfile, "kmdb") == 0 ||
+ strcmp(bootfile, "kadb") == 0) {
+ bootfile = NULL;
+ boothowto |= RB_KMDB;
+ } else {
+ /* copy to buf to avoid being overwritten */
+ strcpy(bootfile_buf, bootfile);
+ bootfile = bootfile_buf;
+ }
+ /* get the remainder of string */
+ args = strtok(NULL, "");
+ if (args == NULL)
+ args = "";
+ }
+
+ params.gos_opts = "CD:Vadvk";
+ params.gos_strp = args;
+ getoptstr_init(&params);
+ while ((c = getoptstr(&params)) != -1) {
+ extern void check_iopath(void);
+
+ switch (c) {
+ case 'V': /* Undocumented. */
+ verbosemode = 1;
+ break;
+ case 'C': /* Undocumented for checking IO path */
+ check_iopath();
+ /* never returns here */
+ break;
+ case 'D':
+ if (bootfile || (boothowto & RB_KMDB) == 0) {
+ printf("boot: -D invalid without kadb/kmdb. "
+ "Ignoring.\n");
+ break;
+ }
+ if (params.gos_optarglen >= sizeof (bootfile_buf)) {
+ printf("boot: -D argument too long. "
+ "Ignoring.\n");
+ break;
+ }
+ (void) strncpy(bootfile_buf, params.gos_optargp,
+ params.gos_optarglen);
+ bootfile_buf[params.gos_optarglen] = '\0';
+ bootfile = bootfile_buf;
+ break;
+
+ /* Consumed by the kernel */
+ case 'a': /* Undocumented. */
+ boothowto |= RB_ASKNAME;
+ break;
+ case 'd':
+ boothowto |= RB_DEBUGENTER;
+ break;
+ case 'v':
+ boothowto |= RB_VERBOSE;
+ break;
+ case 'k':
+ boothowto |= RB_KMDB;
+ break;
+
+ case '?':
+ /*
+ * Error. Either an unrecognized option, or an option
+ * without an argument. Check for the latter.
+ */
+ switch (params.gos_last_opt) {
+ case 'D':
+ case 'O':
+ printf("boot: -%c flag missing required "
+ "argument. Ignoring.\n",
+ params.gos_last_opt);
+ break;
+ default:
+ /* Unrecognized flag: stop. */
+ goto done;
+ }
+ break;
+
+ default:
+ printf("boot: Ignoring unimplemented option -%c.", c);
+ }
+ }
+done:
+
+ /*
+ * Construct the arguments for the standalone.
+ */
+ *bootargs = '\0';
+ np = bootargs;
+
+ /*
+ * Start with '-' if we encountered an unrecognized option or if we
+ * need to pass flags to the standalone.
+ */
+ if (c == '?' || (boothowto &
+ /* These flags are to be passed to the kernel. */
+ (RB_ASKNAME | RB_DEBUGENTER | RB_VERBOSE |
+ RB_KMDB))) {
+ *np++ = '-';
+ if (boothowto & RB_ASKNAME)
+ *np++ = 'a';
+ if (boothowto & RB_DEBUGENTER)
+ *np++ = 'd';
+ if (boothowto & RB_VERBOSE)
+ *np++ = 'v';
+ if (boothowto & RB_KMDB)
+ *np++ = 'k';
+
+ /*
+ * If we didn't encounter an unrecognized flag and there's
+ * more to copy, add a space to separate these flags.
+ * (Otherwise, unrecognized flags can be appended since we
+ * started this word with a dash.)
+ */
+ if (c == -1 && params.gos_strp[0] != '\0')
+ *np++ = ' ';
+ }
+
+ npres = sizeof (bootargs) - (size_t)(np - bootargs);
+
+ /*
+ * Unrecognized flag. gos_errp contains the remaining bootargs
+ */
+
+ if (c == '?')
+ cp = params.gos_errp;
+ else
+ cp = params.gos_strp;
+
+ while (npres > 0 && (*np++ = *cp++) != '\0')
+ npres--;
+ *np = 0;
+
+ if (verbosemode) {
+ printf("bootprog = %s\n", bootprog);
+ if (bootfile)
+ printf("bootfile = %s\n", bootfile);
+ printf("boot-args = %s\n", bootargs);
+ printf("bootprop = %s\n", bootprop);
+ }
+}
+
+void
+get_grub_bootargs(char *args)
+{
+ /* grub args is always present */
+ get_bootargs(args, 1);
+}
+
+void
+get_eeprom_bootargs(char *args)
+{
+ if (args) /* boot-file prop may not be present */
+ get_bootargs(args, 0);
+}
diff --git a/usr/src/psm/stand/boot/i386/common/bootops.c b/usr/src/psm/stand/boot/i386/common/bootops.c
new file mode 100644
index 0000000000..60b320e0fd
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/bootops.c
@@ -0,0 +1,193 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/param.h>
+#include <sys/promif.h>
+#include <sys/bootconf.h>
+#include <sys/bootvfs.h>
+#include <sys/varargs.h>
+#include "standalloc.h"
+#include "bootprop.h"
+#include "util.h"
+#include "biosint.h"
+#include "debug.h"
+
+#define dprintf if (debug & D_BOP) printf
+
+extern struct memlist *pinstalledp, *pfreelistp, *vfreelistp, *pbooterp;
+extern struct memlist *ppcimemp, *pramdiskp;
+extern struct bootops *bop;
+
+/* Misc memlist stuff */
+extern void update_memlist(char *, char *, struct memlist **);
+
+/*ARGSUSED*/
+static caddr_t
+bkern_alloc(struct bootops *bop, caddr_t virt, size_t size, int align)
+{
+ if (size < PAGESIZE)
+ return (bkmem_alloc(size));
+
+ return (resalloc(((virt == 0) ? RES_BOOTSCRATCH : RES_CHILDVIRT),
+ size, virt, align));
+}
+
+/*ARGSUSED*/
+static caddr_t
+bkern_ealloc(struct bootops *bop, caddr_t virt, size_t size, int align,
+ int flags)
+{
+ uint_t delta;
+
+ /* sanity check */
+ if (size == 0)
+ return ((caddr_t)0);
+
+ if (flags == BOPF_X86_ALLOC_IDMAP ||
+ flags == BOPF_X86_ALLOC_PHYS) {
+
+ /* align to PAGESIZE */
+ delta = (uint_t)virt & (PAGESIZE - 1);
+ size += delta;
+ size = roundup(size, PAGESIZE);
+
+ switch (flags) {
+ case BOPF_X86_ALLOC_IDMAP:
+ return ((caddr_t)idmap_mem(
+ (uint32_t)virt, size, align));
+ /*NOTREACHED*/
+ case BOPF_X86_ALLOC_PHYS:
+ return ((caddr_t)phys_alloc_mem(size, align));
+ /*NOTREACHED*/
+ }
+ }
+
+ return (resalloc(((virt == 0) ? RES_BOOTSCRATCH : RES_CHILDVIRT),
+ size, virt, align));
+}
+
+/*ARGSUSED*/
+static void
+bkern_free(struct bootops *bop, caddr_t virt, size_t size)
+{
+ resfree(virt, size);
+}
+
+void
+install_memlistptrs(void)
+{
+ /* allocate boot_mem structure */
+ bop->boot_mem->physinstalled = pinstalledp;
+ bop->boot_mem->physavail = pfreelistp;
+ bop->boot_mem->pcimem = ppcimemp;
+
+ dprintf("physinstalledp = 0x%p\n",
+ (void *)bop->boot_mem->physinstalled);
+ dprintf("pfreelistp = 0x%p\n",
+ (void *)bop->boot_mem->physavail);
+ dprintf("ppcimemp = 0x%p\n",
+ (void *)bop->boot_mem->pcimem);
+}
+
+/*ARGSUSED*/
+static void
+bkern_printf(struct bootops *bop, char *fmt, ...)
+{
+ va_list adx;
+
+ va_start(adx, fmt);
+ prom_vprintf(fmt, adx);
+ va_end(adx);
+}
+
+/*
+ * Translate register structure fit what /platform/i86pc/biosint expects.
+ */
+static void
+bkern_doint(struct bootops *bop, int intnum, struct bop_regs *rp)
+{
+ struct int_pb ic;
+
+ ic.ax = rp->eax.word.ax;
+ ic.bx = rp->ebx.word.bx;
+ ic.cx = rp->ecx.word.cx;
+ ic.dx = rp->edx.word.dx;
+ ic.bp = rp->ebp.word.bp;
+ ic.si = rp->esi.word.si;
+ ic.di = rp->edi.word.di;
+ ic.ds = rp->ds;
+ ic.es = rp->es;
+
+ if (debug & D_BIOS)
+ printf("bkern_doint: int = 0x%x, ax 0x%x, dx 0x%x\n",
+ intnum, ic.ax, ic.dx);
+ rp->eflags = bios_doint(intnum, &ic);
+ if (debug & D_BIOS)
+ printf("bios_doint ret = %d, ax 0x%x, dx 0x%x\n",
+ rp->eflags, ic.ax, ic.dx);
+
+ rp->eax.word.ax = ic.ax;
+ rp->ebx.word.bx = ic.bx;
+ rp->ecx.word.cx = ic.cx;
+ rp->edx.word.dx = ic.dx;
+ rp->ebp.word.bp = ic.bp;
+ rp->esi.word.si = ic.si;
+ rp->edi.word.di = ic.di;
+ rp->ds = ic.ds;
+ rp->es = ic.es;
+}
+
+bootops_t bootops =
+{
+ /* reduced bootops BO_VERSION == 11 ... */
+
+ BO_VERSION, /* "major" version number */
+ 0, /* memlist pointers */
+ bkern_alloc, /* G.P. memory allocator */
+ bkern_free, /* G.P. memory release */
+ bgetproplen, /* proplen */
+ bgetprop, /* getprop */
+ bnextprop, /* nextprop */
+ bkern_printf, /* limited printf for kobj */
+ bkern_doint, /* biosint */
+ bkern_ealloc
+};
+
+void
+setup_bootops(void)
+{
+ /*
+ * Initialize the bootops struct and establish a pointer to it ("bop")
+ * for use by standalone clients.
+ */
+ bop = &bootops;
+ bop->boot_mem = bkmem_zalloc(sizeof (struct bsys_mem));
+ install_memlistptrs();
+ if (verbosemode)
+ printf("setup bootops\n");
+}
diff --git a/usr/src/psm/stand/boot/i386/common/bootprop.c b/usr/src/psm/stand/boot/i386/common/bootprop.c
new file mode 100644
index 0000000000..5641f6b1f1
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/bootprop.c
@@ -0,0 +1,331 @@
+/*
+ * 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.
+ *
+ * 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 2005 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/bootconf.h>
+#include <sys/bootprops.h>
+#include <sys/salib.h>
+#include "debug.h"
+#include "multiboot.h"
+
+extern void install_memlistptrs();
+#define dprintf if (debug & D_BPROP) printf
+
+struct pseudoprop {
+ char *pp_name;
+ void (*pp_func)();
+} pp_list[] = {
+ { "memory_update", install_memlistptrs },
+ { NULL, NULL}
+};
+
+struct bootprop {
+ struct bootprop *bp_next;
+ char *bp_name;
+ void *bp_val;
+ int bp_len;
+};
+
+static struct bootprop *bp_list;
+
+static int find_pseudo(char *);
+static struct bootprop *find_prop(char *);
+static struct bootprop *alloc_prop(char *);
+static void set_propval(struct bootprop *, void *, int);
+static void setup_rarp_props(struct sol_netinfo *);
+
+/*
+ * Return the length of the "name"d property's value.
+ */
+/*ARGSUSED*/
+int
+bgetproplen(struct bootops *bop, char *name)
+{
+ struct bootprop *bp;
+
+ dprintf("bgetproplen: name = %s\n", name);
+ bp = find_prop(name);
+ return (bp ? bp->bp_len : BOOT_FAILURE);
+}
+
+/*ARGSUSED*/
+int
+bgetprop(struct bootops *bop, char *name, void *value)
+{
+ struct bootprop *bp;
+
+ dprintf("bgetprop: name = %s\n", name);
+ if (find_pseudo(name) == BOOT_SUCCESS)
+ return (BOOT_SUCCESS);
+
+ bp = find_prop(name);
+ if (!bp)
+ return (BOOT_FAILURE);
+
+ /* Found the property in question; return its value */
+ (void) bcopy(bp->bp_val, value, bp->bp_len);
+ return (BOOT_SUCCESS);
+}
+
+/*ARGSUSED*/
+char *
+bnextprop(struct bootops *bop, char *prev)
+{
+ struct bootprop *bp = find_prop(prev);
+
+ if (bp == NULL || bp->bp_next == NULL)
+ return (NULL);
+ return (bp->bp_next->bp_name);
+}
+
+/*ARGSUSED*/
+int
+bsetprop(struct bootops *bop, char *name, char *value, int len)
+{
+ struct bootprop *bp;
+
+ dprintf("bsetprop: name = %s, len = %d", name, len);
+ bp = find_prop(name);
+ if (bp == NULL)
+ bp = alloc_prop(name);
+
+ set_propval(bp, value, len);
+ return (BOOT_SUCCESS);
+}
+
+int
+find_pseudo(char *name)
+{
+ struct pseudoprop *pp = pp_list;
+
+ while (pp->pp_name) {
+ if (strcmp(name, pp->pp_name) == 0) {
+ (*pp->pp_func)();
+ dprintf("find_pseudo: prop = %s\n", name);
+ return (BOOT_SUCCESS);
+ }
+ pp++;
+ }
+ return (BOOT_FAILURE);
+}
+
+struct bootprop *
+find_prop(char *name)
+{
+ struct bootprop *bp = bp_list;
+
+ if (name == NULL || *name == '\0')
+ return (bp);
+
+ while (bp) {
+ if (strcmp(name, bp->bp_name) == 0)
+ break;
+ bp = bp->bp_next;
+ }
+ return (bp);
+}
+
+static struct bootprop *
+alloc_prop(char *name)
+{
+ struct bootprop *bp = bkmem_zalloc(sizeof (*bp));
+
+ dprintf("alloc_prop: name = %s\n", name);
+ bp->bp_name = bkmem_alloc(strlen(name) + 1);
+ (void) strcpy(bp->bp_name, name);
+ bp->bp_next = bp_list;
+ bp_list = bp;
+
+ return (bp);
+}
+
+static void
+set_propval(struct bootprop *bp, void *value, int len)
+{
+ dprintf("set_propval: name = %s\n", bp->bp_name);
+
+ if (bp->bp_val)
+ bkmem_free(bp->bp_val, bp->bp_len);
+ bp->bp_len = len;
+ bp->bp_val = bkmem_alloc(len);
+ bcopy(value, bp->bp_val, len);
+}
+
+void
+setup_bootprop(void)
+{
+ extern char bootprop[], bootargs[];
+ extern char *bootprog;
+ extern uint64_t ramdisk_start, ramdisk_end;
+ extern multiboot_info_t *mbi;
+ char *name, *val, *cp;
+ int netboot = 0;
+ int stdout_val = 0; /* for a dummy property */
+
+ if (verbosemode)
+ printf("setup boot properties.\n");
+
+ dprintf("process command line bootargs: %s\n", bootprop);
+ cp = bootprop;
+ while (cp && *cp) {
+ name = strtok(cp, "=");
+ val = strtok(NULL, "");
+ if (val == NULL) {
+ val = "true";
+ cp = NULL; /* terminate loop */
+ } else if (*val != '\'' && *val != '\"') {
+ cp = strtok(val, ",");
+ cp = strtok(NULL, "");
+ } else {
+ /* look for closing single or double quote */
+ cp = val + 1;
+ while (cp && *cp != *val)
+ ++cp;
+ if (cp == NULL) {
+ printf("missing %c in property %s.\n",
+ *val, name);
+ } else {
+ *cp++ = '\0';
+ if (*cp == ',')
+ cp++;
+ else if (*cp != '\0') {
+ printf("syntax error in GRUB -B option:"
+ " ignore %s\n", cp);
+ cp = NULL; /* terminate */
+ }
+ }
+ val++;
+ }
+
+ (void) bsetprop(NULL, name, val, strlen(val) + 1);
+ }
+
+ (void) bsetprop(NULL, "bootprog", bootprog, strlen(bootprog) + 1);
+ (void) bsetprop(NULL, "boot-args", bootargs, strlen(bootargs) + 1);
+ (void) bsetprop(NULL, "ramdisk_start", (char *)&ramdisk_start,
+ sizeof (ramdisk_start));
+ (void) bsetprop(NULL, "ramdisk_end", (char *)&ramdisk_end,
+ sizeof (ramdisk_end));
+
+ /* a bunch of fixed properties */
+ (void) bsetprop(NULL, "mfg-name", "i86pc", sizeof ("i86pc"));
+ (void) bsetprop(NULL, "impl-arch-name", "i86pc", sizeof ("i86pc"));
+
+ /* figure out the boot device */
+ if (MB_CHECK_FLAG(mbi->flags, 2)) {
+ char str[3];
+ uint_t boot_device = (mbi->boot_device >> 24) & 0xff;
+ if (boot_device == MB_NETWORK_DRIVE)
+ netboot++;
+ (void) snprintf(str, 3, "%x", boot_device);
+ bsetprop(NULL, "bios-boot-device", str, 3);
+ } else { /* assume netboot? */
+ netboot++;
+ }
+
+ /*
+ * In the netboot case, drives_info is overloaded with
+ * the dhcp ack. This is not multiboot compliant and
+ * requires special pxegrub!
+ */
+ if (netboot) {
+ if (verbosemode)
+ printf("booting from network\n");
+
+ if (mbi->drives_length == 0) {
+ if (verbosemode) {
+ printf("no network info, "
+ "need a GRUB with Solaris enhancements\n");
+ }
+ } else {
+ struct sol_netinfo *sip =
+ (struct sol_netinfo *)mbi->drives_addr;
+ switch (sip->sn_infotype) {
+ case SN_TYPE_BOOTP:
+ bsetprop(NULL, BP_BOOTP_RESPONSE,
+ (void *)mbi->drives_addr,
+ mbi->drives_length);
+ break;
+ case SN_TYPE_RARP:
+ setup_rarp_props(sip);
+ break;
+ default:
+ printf("invalid network info: type %d\n",
+ sip->sn_infotype);
+ break;
+ };
+ }
+ }
+
+ /* dummy properties needed by Install miniroot */
+ bsetprop(NULL, "stdout", (char *)&stdout_val, sizeof (stdout_val));
+}
+
+#define BUFLEN 64
+
+static void
+setup_rarp_props(struct sol_netinfo *sip)
+{
+ char *buf = bkmem_alloc(BUFLEN); /* to hold ip/mac addrs */
+ uint8_t *val;
+
+ val = (uint8_t *)&sip->sn_ciaddr;
+ (void) snprintf(buf, BUFLEN, "%d.%d.%d.%d",
+ val[0], val[1], val[2], val[3]);
+ bsetprop(NULL, BP_HOST_IP, buf, strlen(buf) + 1);
+
+ val = (uint8_t *)&sip->sn_siaddr;
+ (void) snprintf(buf, BUFLEN, "%d.%d.%d.%d",
+ val[0], val[1], val[2], val[3]);
+ bsetprop(NULL, BP_SERVER_IP, buf, strlen(buf) + 1);
+
+ if (sip->sn_giaddr != 0) {
+ val = (uint8_t *)&sip->sn_giaddr;
+ (void) snprintf(buf, BUFLEN, "%d.%d.%d.%d",
+ val[0], val[1], val[2], val[3]);
+ bsetprop(NULL, BP_ROUTER_IP, buf, strlen(buf) + 1);
+ }
+
+ if (sip->sn_netmask != 0) {
+ val = (uint8_t *)&sip->sn_netmask;
+ (void) snprintf(buf, BUFLEN, "%d.%d.%d.%d",
+ val[0], val[1], val[2], val[3]);
+ bsetprop(NULL, BP_SUBNET_MASK, buf, strlen(buf) + 1);
+ }
+
+ if (sip->sn_mactype != 4 || sip->sn_maclen != 6) {
+ printf("unsupported mac type %d, mac len %d\n",
+ sip->sn_mactype, sip->sn_maclen);
+ return;
+ }
+
+ val = sip->sn_macaddr;
+ (void) snprintf(buf, BUFLEN, "%x:%x:%x:%x:%x:%x",
+ val[0], val[1], val[2], val[3], val[4], val[5]);
+ bsetprop(NULL, BP_BOOT_MAC, buf, strlen(buf) + 1);
+}
diff --git a/usr/src/psm/stand/boot/i386/common/bootprop.h b/usr/src/psm/stand/boot/i386/common/bootprop.h
new file mode 100644
index 0000000000..004c8049d0
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/bootprop.h
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _BOOTPROP_H
+#define _BOOTPROP_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Global variables which will be exported as boot properties in
+ * i386_bootprop.c.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/bootconf.h>
+#include <sys/obpdefs.h>
+#include <sys/param.h>
+
+extern char *impl_arch_name;
+extern char *module_path;
+
+/*
+ * bootenv.rc properties
+ */
+extern char *bootfile_prop;
+extern char *inputdevice_prop;
+extern char *outputdevice_prop;
+extern char *console_prop;
+
+/* These are actually in intel/bootprop.c. */
+extern int bgetproplen(struct bootops *, char *);
+extern int bgetprop(struct bootops *, char *, void *);
+extern int bsetprop(struct bootops *, char *, void *, int);
+extern char *bnextprop(struct bootops *, char *);
+
+extern void setup_bootprop(void);
+extern void get_grub_bootargs(char *);
+extern void get_eeprom_bootargs(char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _BOOTPROP_H */
diff --git a/usr/src/psm/stand/boot/i386/common/chario.h b/usr/src/psm/stand/boot/i386/common/chario.h
new file mode 100644
index 0000000000..7023c17134
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/chario.h
@@ -0,0 +1,145 @@
+/*
+ * 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.
+ *
+ * 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 (c) 1995-1998, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _CHARIO_H
+#define _CHARIO_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This file contains all character i/o related structures
+ * and defines.
+ *
+ * Project: Devconf
+ * Author : Rick McNeal
+ * Date : 2-Nov-1994
+ */
+struct _char_io_ {
+ struct _char_io_ *next; /* next i/o member */
+ char *name; /* Name for stats */
+ int in, out, errs; /* Simple stats */
+ int flags; /* control bits */
+ int vals; /* state bits */
+ int addr; /* physical address */
+ char *cookie; /* for driver use */
+ char (*getc)(struct _char_io_ *); /* returns character */
+ void (*putc)(struct _char_io_ *, char); /* outputs one character */
+ int (*avail)(struct _char_io_ *); /* returns 1 if char avail */
+ void (*clear)(struct _char_io_ *); /* clear screen */
+ void (*set)(struct _char_io_ *, int, int); /* set cursor pos. */
+};
+typedef struct _char_io_ _char_io_t, *_char_io_p;
+
+int serial_port_enabled(int port);
+
+#define CHARIO_IGNORE_ALL 0x0001 /* don't output to this dev */
+#define CHARIO_DISABLED 0x0002 /* error occured and ports not used */
+#define CHARIO_OUT_ENABLE 0x0004 /* Device does output */
+#define CHARIO_IN_ENABLE 0x0008 /* Device does input */
+#define CHARIO_IGNORE_CD 0x0010 /* Device shouldn't wait for CD */
+#define CHARIO_RTS_DTR_OFF 0x0020 /* Device shouldn't set rts/dtr */
+#define CHARIO_INIT 0x0040 /* Device should be (re)initialized */
+
+/*
+ * Use this macro when debugging the output side of your driver. This
+ * will prevent any printf's from your driver causing an infinite loop
+ */
+#define PRINT(p, x) \
+{ p->flags |= CHARIO_IGNORE_ALL; printf x; p->flags &= ~CHARIO_IGNORE_ALL; }
+
+/*
+ * Defines for the serial port
+ */
+
+#define SERIAL_FIFO_FLUSH 16 /* maximum number of chars to flush */
+
+/* ---- Bit 11 defines direct serial port ---- */
+#define SDIRECT 0x1000
+
+/* ---- Bits 9-10 define flow control ---- */
+#define SSOFT 0x800
+#define SHARD 0x400
+
+/* ---- Bits 5-8 define baud rate ---- */
+#define S110 0x00
+#define S150 0x20
+#define S300 0x40
+#define S600 0x60
+#define S1200 0x80
+#define S2400 0xa0
+#define S4800 0xc0
+#define S9600 0xe0
+#define S19200 0x100
+#define S38400 0x120
+#define S57600 0x140
+#define S76800 0x160
+#define S115200 0x180
+#define S153600 0x1a0
+#define S230400 0x1c0
+#define S307200 0x1e0
+#define S460800 0x200
+
+/* ---- Bits 3 & 4 are parity ---- */
+#define PARITY_NONE 0x10
+#define PARITY_ODD 0x08
+#define PARITY_EVEN 0x18
+
+/* ---- Bit 2 is stop bit ---- */
+#define STOP_1 0x00
+#define STOP_2 0x04
+
+/* ---- Bits 0 & 1 are data bits ---- */
+#define DATA_8 0x03
+#define DATA_7 0x02
+#define DATA_6 0x01
+#define DATA_5 0x00
+
+/* ---- Line Status ---- */
+#define SERIAL_TIMEOUT 0x80
+#define SERIAL_XMITSHFT 0x40
+#define SERIAL_XMITHOLD 0x20
+#define SERIAL_BREAK 0x10
+#define SERIAL_FRAME 0x08
+#define SERIAL_PARITY 0x04
+#define SERIAL_OVERRUN 0x02
+#define SERIAL_DATA 0x01
+
+/*
+ * Bit style flag operations for 32bit ints only
+ */
+#define BCLR(x) x &= ~(1 << y)
+#define BSET(x, y) x |= (1 << y)
+#define BISSET(x, y) x & (1 << y)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CHARIO_H */
diff --git a/usr/src/psm/stand/boot/i386/common/check_iopath.c b/usr/src/psm/stand/boot/i386/common/check_iopath.c
new file mode 100644
index 0000000000..749d89a2cc
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/check_iopath.c
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/promif.h>
+#include "multiboot.h"
+#include "util.h"
+#include "debug.h"
+
+extern multiboot_info_t *mbi;
+
+/* return the number of bits set to 1 */
+static uint_t
+count_bits(int val)
+{
+ int nbits = 0;
+
+ while (val = (val ^ (val - 1)))
+ nbits++;
+
+ return (nbits);
+}
+
+/*
+ * GRUB has loaded two identical modules, we compare the content
+ * to check for potential problems in the BIOS I/O code path.
+ * Andromeda appears to have problems with USB DVD drive, but IDE
+ * drive works fine. This is a simple way to check it.
+ */
+void
+check_iopath(void)
+{
+ mb_module_t *mod;
+ char errbits = 0;
+ uchar_t *cp1, *cp2;
+ uint_t i, size1, size2;
+
+ /* check # modules */
+ if (mbi->mods_count != 2) {
+ printf("The number of modules is not 2.\n");
+ panic("reboot with modified GRUB menu");
+ }
+
+ /* check module sizes */
+ mod = (mb_module_t *)mbi->mods_addr;
+ cp1 = (uchar_t *)mod[0].mod_start;
+ cp2 = (uchar_t *)mod[1].mod_start;
+ size1 = mod[0].mod_end - mod[0].mod_start;
+ size2 = mod[1].mod_end - mod[1].mod_start;
+ printf("module 1: start = 0x%x, size = 0x%x (%s)\n",
+ cp1, size1, mod[0].string);
+ printf("module 2: start = 0x%x, size = 0x%x (%s)\n",
+ cp2, size2, mod[1].string);
+
+ if (size1 != size2) {
+ printf("Module sizes are different!\n");
+ panic("Check FAILED");
+ }
+
+ for (i = 0; i < size1; i++) {
+ if (cp1[i] != cp2[i]) {
+ printf("byte 0x%x differ: %2x, %2x\n",
+ i, cp1[i], cp2[i]);
+ errbits += count_bits(cp1[i] ^ cp2[i]);
+ }
+ }
+ if (errbits)
+ panic("Check FAILED: err bit rate %d in %d bytes\n",
+ errbits, size1);
+ else
+ panic("Check PASSED: no bit error\n");
+}
diff --git a/usr/src/psm/stand/boot/i386/common/console.c b/usr/src/psm/stand/boot/i386/common/console.c
new file mode 100644
index 0000000000..fd7c4a4b9f
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/console.c
@@ -0,0 +1,592 @@
+/*
+ * 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.
+ *
+ * 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 2005 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/bootsvcs.h>
+#include <sys/varargs.h>
+#include <sys/promif.h>
+#include <sys/salib.h>
+#include "serial.h"
+#include "chario.h"
+#include "vga.h"
+#include "console.h"
+#include "debug.h"
+#include "graphics.h"
+#include "bootprop.h"
+
+static int cons_color = CONS_COLOR;
+int console = CONS_SCREEN_TEXT;
+/* or CONS_SCREEN_GRAPHICS, CONS_TTYA, CONS_TTYB */
+static int serial_ischar(void);
+static int serial_getchar(void);
+static void serial_putchar(int);
+static void serial_adjust_prop(void);
+static int console_state = 0;
+
+/* Clear the screen and initialize VIDEO, XPOS and YPOS. */
+static void
+clear_screen(void)
+{
+ /*
+ * XXX should set vga mode so we don't depend on the
+ * state left by the boot loader
+ */
+ vga_clear(cons_color);
+ vga_setpos(0, 0);
+}
+
+void
+text_init(void)
+{
+ set_videomode(0x3);
+ clear_screen();
+}
+
+/* Put the character C on the screen. */
+static void
+screen_putchar(int c)
+{
+ int row, col;
+
+ vga_getpos(&row, &col);
+ switch (c) {
+ case '\r':
+ vga_setpos(row, 0);
+ break;
+
+ case '\b':
+ if (col > 0)
+ vga_setpos(row, col - 1);
+ break;
+
+ case '\n':
+ if (row < VGA_TEXT_ROWS - 1)
+ vga_setpos(row + 1, col);
+ else
+ vga_scroll(cons_color);
+ break;
+
+ default:
+ vga_drawc(c, cons_color);
+ if (col < VGA_TEXT_COLS -1)
+ vga_setpos(row, col + 1);
+ else if (row < VGA_TEXT_ROWS - 1)
+ vga_setpos(row + 1, 0);
+ else {
+ vga_setpos(row, 0);
+ vga_scroll(cons_color);
+ }
+ break;
+ }
+}
+
+/* serial port stuff */
+static int port;
+
+static void
+serial_init(void)
+{
+ extern void mdelay();
+
+ /* initialize only once */
+ if (port != 0)
+ return;
+
+ /*
+ * wait 2 seconds for serial console redirection to settle
+ * NOTE we only need to wait if BIOS console redirection
+ * is enabled, but we can't really tell without working
+ * through a scary Microsoft license.
+ */
+ mdelay(2000);
+
+ switch (console) {
+ case CONS_TTYA:
+ port = 0x3f8;
+ break;
+ case CONS_TTYB:
+ port = 0x2f8;
+ break;
+ }
+
+ outb(port + ISR, 0x20);
+ if (inb(port + ISR) & 0x20) {
+ /*
+ * 82510 chip is present
+ */
+ outb(port + DAT+7, 0x04); /* clear status */
+ outb(port + ISR, 0x40); /* set to bank 2 */
+ outb(port + MCR, 0x08); /* IMD */
+ outb(port + DAT, 0x21); /* FMD */
+ outb(port + ISR, 0x00); /* set to bank 0 */
+ } else {
+ /*
+ * set the UART in FIFO mode if it has FIFO buffers.
+ * use 16550 fifo reset sequence specified in NS
+ * application note. disable fifos until chip is
+ * initialized.
+ */
+ outb(port + FIFOR, 0x00); /* clear */
+ outb(port + FIFOR, FIFO_ON); /* enable */
+ outb(port + FIFOR, FIFO_ON|FIFORXFLSH); /* reset */
+ outb(port + FIFOR,
+ FIFO_ON|FIFODMA|FIFOTXFLSH|FIFORXFLSH|0x80);
+ if ((inb(port + ISR) & 0xc0) != 0xc0) {
+ /*
+ * no fifo buffers so disable fifos.
+ * this is true for 8250's
+ */
+ outb(port + FIFOR, 0x00);
+ }
+ }
+
+ /* disable interrupts */
+ outb(port + ICR, 0);
+
+ /* adjust setting based on tty properties */
+ serial_adjust_prop();
+
+ /*
+ * Do a full reset to match console behavior.
+ * In verbose mode (-V), we only reset ansi attributes,
+ * leaving existing output on screen.
+ * 0x1B + c - reset everything
+ * 0x1B +
+ * [ - attribute change (blick, inverse, color, etc.)
+ * 0 - attribute value
+ * m - terminate escape sequence
+ *
+ */
+ if (verbosemode) {
+ serial_putchar(0x1B);
+ serial_putchar('[');
+ serial_putchar('0');
+ serial_putchar('m');
+ } else {
+ serial_putchar(0x1B);
+ serial_putchar('c');
+ }
+}
+
+/* adjust serial port based on properties */
+static void
+serial_adjust_prop(void)
+{
+ int plen;
+ char propname[20], propval[20];
+
+ (void) snprintf(propname, sizeof (propname), "tty%c-mode",
+ 'a' + console - CONS_TTYA);
+ plen = bgetproplen(NULL, propname);
+ if (plen > 0 && plen <= sizeof (propval)) {
+ char *p;
+ ulong_t baud;
+ uchar_t lcr = 0;
+
+ /* property is of the form: "9600,8,n,1,-" */
+ bgetprop(NULL, propname, propval);
+ p = strtok(propval, ",");
+ if (strcmp(p, "110") == 0)
+ baud = ASY110;
+ else if (strcmp(p, "150") == 0)
+ baud = ASY150;
+ else if (strcmp(p, "300") == 0)
+ baud = ASY300;
+ else if (strcmp(p, "600") == 0)
+ baud = ASY600;
+ else if (strcmp(p, "1200") == 0)
+ baud = ASY1200;
+ else if (strcmp(p, "2400") == 0)
+ baud = ASY2400;
+ else if (strcmp(p, "4800") == 0)
+ baud = ASY4800;
+ else if (strcmp(p, "19200") == 0)
+ baud = ASY19200;
+ else if (strcmp(p, "38400") == 0)
+ baud = ASY38400;
+ else if (strcmp(p, "57600") == 0)
+ baud = ASY57600;
+ else if (strcmp(p, "115200") == 0)
+ baud = ASY115200;
+ else
+ baud = ASY9600;
+
+ /* set baud */
+ outb(port + LCR, DLAB);
+ outb(port + DAT+DLL, baud & 0xff);
+ outb(port + DAT+DLH, (baud >> 8) & 0xff);
+
+ p = strtok(NULL, ",");
+ if (p) {
+ switch (*p) {
+ case '5':
+ lcr |= BITS5;
+ break;
+ case '6':
+ lcr |= BITS6;
+ break;
+ case '7':
+ lcr |= BITS7;
+ break;
+ case '8':
+ default:
+ lcr |= BITS8;
+ break;
+ }
+ }
+
+ p = strtok(NULL, ",");
+ if (p) {
+ switch (*p) {
+ case 'n':
+ lcr |= PARITY_NONE;
+ break;
+ case 'o':
+ lcr |= PARITY_ODD;
+ break;
+ case 'e':
+ default:
+ lcr |= PARITY_EVEN;
+ break;
+ }
+ }
+
+ p = strtok(NULL, ",");
+ if (p) {
+ switch (*p) {
+ case '1':
+ /* STOP1 is 0 */
+ break;
+ default:
+ lcr |= STOP2;
+ break;
+ }
+ }
+
+ /* set parity bits */
+ outb(port + LCR, lcr);
+ }
+
+ (void) snprintf(propname, sizeof (propname),
+ "tty%c-rts-dtr-off", 'a' + console - CONS_TTYA);
+ plen = bgetproplen(NULL, propname);
+ if (plen > 0 && plen <= sizeof (propval)) {
+ char *p;
+ uchar_t mcr = DTR | RTS;
+ bgetprop(NULL, propname, propval);
+ if (propval[0] != 'f' && propval[0] != 'F')
+ mcr = 0;
+ /* set modem control bits */
+ outb(port + MCR, mcr | OUT2);
+ }
+}
+
+void
+console_init(char *bootstr)
+{
+ char *cons;
+
+ console = CONS_INVALID;
+
+ cons = strstr(bootstr, "console=");
+ if (cons) {
+ cons += strlen("console=");
+ if (strncmp(cons, "ttya", 4) == 0)
+ console = CONS_TTYA;
+ else if (strncmp(cons, "ttyb", 4) == 0)
+ console = CONS_TTYB;
+ else if (strncmp(cons, "graphics", 9) == 0)
+ console = CONS_SCREEN_GRAPHICS;
+ else if (strncmp(cons, "text", 4) == 0)
+ console = CONS_SCREEN_TEXT;
+ }
+
+ /*
+ * If no console device specified, default to text.
+ * Remember what was specified for second phase.
+ */
+ console_state = console;
+ if (console == CONS_INVALID)
+ console = CONS_SCREEN_TEXT;
+
+ switch (console) {
+ case CONS_TTYA:
+ case CONS_TTYB:
+ /* leave initialization till later, when we know tty mode */
+ break;
+ case CONS_SCREEN_TEXT:
+ default:
+ clear_screen();
+ kb_init();
+ break;
+ /*
+ * if console is CONS_SCREEN_GRAPHICS,
+ * initialize it in console_init2()
+ */
+ }
+}
+
+/*
+ * Second phase of possible console redirection,
+ * based on input-device & output-device eeprom(1M) properties.
+ * Also support a unified "console" property.
+ */
+void
+console_init2(char *inputdev, char *outputdev, char *consoledev)
+{
+ int cons = CONS_INVALID;
+
+ if (console_state == CONS_INVALID) {
+
+ if (consoledev) {
+ if (strcmp(consoledev, "ttya") == 0)
+ cons = CONS_TTYA;
+ else if (strcmp(consoledev, "ttyb") == 0)
+ cons = CONS_TTYB;
+ else if (strcmp(consoledev, "text") == 0)
+ cons = CONS_SCREEN_TEXT;
+ else if (strcmp(consoledev, "graphics") == 0)
+ cons = CONS_SCREEN_GRAPHICS;
+ }
+
+ if (cons == CONS_INVALID) {
+ if (inputdev) {
+ if (strcmp(inputdev, "ttya") == 0)
+ cons = CONS_TTYA;
+ else if (strcmp(inputdev, "ttyb") == 0)
+ cons = CONS_TTYB;
+ }
+ if (outputdev) {
+ if (strcmp(outputdev, "ttya") == 0)
+ cons = CONS_TTYA;
+ else if (strcmp(outputdev, "ttyb") == 0)
+ cons = CONS_TTYB;
+ }
+ }
+
+ if (cons == CONS_INVALID)
+ cons = CONS_SCREEN_TEXT;
+ console = cons;
+
+ switch (console) {
+ case CONS_TTYA:
+ case CONS_TTYB:
+ if (console_state != CONS_TTYA &&
+ console_state != CONS_TTYB) {
+ serial_init();
+ }
+ break;
+ case CONS_SCREEN_TEXT:
+ if (console_state != CONS_SCREEN_TEXT) {
+ clear_screen();
+ kb_init();
+ }
+ break;
+ }
+ }
+
+ /* special handling for graphics boot and serial console */
+ switch (console) {
+ case CONS_TTYA:
+ case CONS_TTYB:
+ serial_init();
+ break;
+ case CONS_SCREEN_GRAPHICS:
+ if (!graphics_init())
+ printf("failed to initialize "
+ "console to graphics mode\n");
+ break;
+ };
+}
+
+static void
+serial_putchar(int c)
+{
+ int checks = 10000;
+
+ while (((inb(port + LSR) & XHRE) == 0) && checks--)
+ ;
+ outb(port + DAT, (char)c);
+}
+
+static int
+serial_getchar(void)
+{
+ uchar_t lsr;
+
+ while (serial_ischar() == 0)
+ ;
+
+ lsr = inb(port + LSR);
+ if (lsr & (SERIAL_BREAK | SERIAL_FRAME |
+ SERIAL_PARITY | SERIAL_OVERRUN)) {
+ if (lsr & SERIAL_OVERRUN) {
+ printf("silo overflow\n");
+ return (inb(port + DAT));
+ } else {
+ /* Toss the garbage */
+ (void) inb(port + DAT);
+ return (0);
+ }
+ }
+ return (inb(port + DAT));
+}
+
+static int
+serial_ischar(void)
+{
+ return (inb(port + LSR) & RCA);
+}
+
+static void
+_doputchar(int c)
+{
+ switch (console) {
+ case CONS_TTYA:
+ case CONS_TTYB:
+ serial_putchar(c);
+ return;
+ case CONS_SCREEN_TEXT:
+ screen_putchar(c);
+ return;
+ case CONS_SCREEN_GRAPHICS:
+ if (verbosemode)
+ graphics_putchar(c);
+ }
+}
+
+void
+putchar(int c)
+{
+ static int bhcharpos = 0;
+
+ if (c == '\t') {
+ do {
+ _doputchar(' ');
+ } while (++bhcharpos % 8);
+ return;
+ } else if (c == '\n' || c == '\r') {
+ bhcharpos = 0;
+ _doputchar('\r');
+ _doputchar(c);
+ return;
+ } else if (c == '\b') {
+ if (bhcharpos)
+ bhcharpos--;
+ _doputchar(c);
+ return;
+ }
+
+ bhcharpos++;
+ _doputchar(c);
+}
+
+
+int
+getchar(void)
+{
+ switch (console) {
+ case CONS_TTYA:
+ case CONS_TTYB:
+ return (serial_getchar());
+ default:
+ return (kb_getchar());
+ }
+}
+
+int
+ischar(void)
+{
+ switch (console) {
+ case CONS_TTYA:
+ case CONS_TTYB:
+ return (serial_ischar());
+ default:
+ return (kb_ischar());
+ }
+}
+
+/*
+ * Read from the console (using getchar) into string str,
+ * until a carriage return or until n-1 characters are read.
+ * Null terminate the string, and return.
+ * This all is made complicated by the fact that we must
+ * do our own echoing during input.
+ * N.B.: Returns the *number of characters in str*.
+ */
+
+int
+cons_gets(char *str, int n)
+{
+ int c;
+ int t;
+ char *p;
+
+ p = str;
+ c = 0;
+
+ while ((t = getchar()) != '\r') {
+ putchar(t);
+ if (t == '\b') {
+ if (c) {
+ printf(" \b");
+ c--; p--;
+ } else
+ putchar(' ');
+ continue;
+ }
+ if (c < n - 1) {
+ *p++ = t;
+ c++;
+ }
+ }
+ putchar('\n');
+ *p = '\0';
+
+ return (c);
+}
+
+/*PRINTFLIKE1*/
+void
+printf(const char *fmt, ...)
+{
+ va_list adx;
+
+ va_start(adx, fmt);
+ prom_vprintf(fmt, adx);
+ va_end(adx);
+}
+
+/* setup boot syscall fields needed by the kernel */
+static struct boot_syscalls sc = {
+ getchar,
+ putchar,
+ ischar
+};
+
+struct boot_syscalls *sysp = &sc;
diff --git a/usr/src/psm/stand/boot/i386/common/console.h b/usr/src/psm/stand/boot/i386/common/console.h
new file mode 100644
index 0000000000..4765780cc6
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/console.h
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _CONSOLE_H
+#define _CONSOLE_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CONS_INVALID -1
+#define CONS_SCREEN_TEXT 0
+#define CONS_SCREEN_GRAPHICS 1
+#define CONS_TTYA 2
+#define CONS_TTYB 3
+
+#define CONS_COLOR 7
+
+extern uchar_t inb(int);
+extern void outb(int, uchar_t);
+extern void kb_init(void);
+extern int kb_getchar(void);
+extern int kb_ischar(void);
+
+extern void console_init(char *);
+extern void console_init2(char *, char *, char *);
+extern void text_init(void);
+extern void putchar(int);
+extern int getchar(void);
+extern int ischar(void);
+extern int cons_gets(char *, int);
+extern void reset();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CONSOLE_H */
diff --git a/usr/src/psm/stand/boot/i386/common/cpu_id.h b/usr/src/psm/stand/boot/i386/common/cpu_id.h
new file mode 100644
index 0000000000..8948d8031b
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/cpu_id.h
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ *
+ * 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 (c) 2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _CPU_ID_H
+#define _CPU_ID_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GenuineIntel 0x1
+#define AuthenticAMD 0x2
+
+#define Genu 0x756e6547
+#define ineI 0x49656e69
+#define ntel 0x6c65746e
+
+#define Auth 0x68747541
+#define enti 0x69746e65
+#define cAMD 0x444d4163
+
+#ifndef _ASM
+
+extern int max_std_cpuid_level;
+extern unsigned int cpu_vendor;
+
+extern int is486(void);
+extern int enable_cpuid(void);
+extern int largepage_supported(void);
+extern int enable_large_pages(void);
+extern int global_bit(void);
+extern int enable_global_pages(void);
+extern int pae_supported(void);
+
+#endif /* !_ASM */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CPU_ID_H */
diff --git a/usr/src/psm/stand/boot/i386/common/debug.h b/usr/src/psm/stand/boot/i386/common/debug.h
new file mode 100644
index 0000000000..858cb21245
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/debug.h
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _DEBUG_H
+#define _DEBUG_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int debug;
+extern int verbosemode;
+
+/* Mask bits for debug */
+#define D_BPROP 0x01
+#define D_MBINFO 0x02
+#define D_KEYBOARD 0x04
+#define D_ALLOC 0x08
+#define D_BOP 0x10
+#define D_BIOS 0x20
+#define D_GRAPHICS 0x40
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DEBUG_H */
diff --git a/usr/src/psm/stand/boot/i386/common/graphics.c b/usr/src/psm/stand/boot/i386/common/graphics.c
new file mode 100644
index 0000000000..d4e1cd9f11
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/graphics.c
@@ -0,0 +1,743 @@
+/*
+ * 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.
+ *
+ * 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 2005 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/psw.h>
+#include <sys/memlist.h>
+#include <sys/bootvfs.h>
+#include "graphics.h"
+#include "biosint.h"
+#include "vga.h"
+#include "util.h"
+#include "multiboot.h"
+#include "console.h"
+#include "standalloc.h"
+#include "debug.h"
+
+typedef int (*func_t)();
+extern int openfile(char *, char *);
+extern int close(int);
+extern int console;
+
+int saved_videomode;
+unsigned char *font8x16;
+
+int graphics_inited = 0;
+static char splashimage[64];
+
+#define VSHADOW VSHADOW1
+unsigned char VSHADOW1[38400];
+unsigned char VSHADOW2[38400];
+unsigned char VSHADOW4[38400];
+unsigned char VSHADOW8[38400];
+
+#define dprintf if (debug & D_GRAPHICS) printf
+
+/*
+ * constants to define the viewable area
+ */
+const int x0 = 0;
+const int x1 = 80;
+const int y0 = 0;
+const int y1 = 30;
+
+/*
+ * text buffer has to be kept around so that we can write things as we
+ * scroll and the like
+ */
+unsigned short text[80 * 30];
+
+/*
+ * why do these have to be kept here?
+ */
+int foreground = (63 << 16) | (63 << 8) | (63), background = 0, border = 0;
+
+/*
+ * current position
+ */
+
+static int fontx = 0;
+static int fonty = 10;
+
+/*
+ * global state so that we don't try to recursively scroll or cursor
+ */
+static int no_scroll = 0;
+
+/*
+ * color state
+ */
+static int graphics_standard_color = A_NORMAL;
+static int graphics_normal_color = A_NORMAL;
+static int graphics_highlight_color = A_REVERSE;
+static int graphics_current_color = A_NORMAL;
+static color_state graphics_color_state = COLOR_STATE_STANDARD;
+
+
+/*
+ * graphics local functions
+ */
+static void graphics_setxy(int col, int row);
+static void graphics_scroll();
+static void graphics_memcpy(void *dest, const void *src, int len);
+static int graphics_memcmp(const char *s1, const char *s2, int n);
+static int read_image(char *s);
+static int hex(int v);
+
+extern uchar_t inb(int);
+extern void outb(int, uchar_t);
+
+static void MapMask(int value) {
+ outb(0x3c4, 2);
+ outb(0x3c5, value);
+}
+
+/* bit mask register */
+static void BitMask(int value) {
+ outb(0x3ce, 8);
+ outb(0x3cf, value);
+}
+
+/* Set the splash image */
+int graphics_set_splash(char *splashfile) {
+ /* filename can only be 64 characters due to our buffer size */
+ if (strlen(splashfile) > 63)
+ return (0);
+ strcpy(splashimage, splashfile);
+ return (1);
+}
+
+/* Get the current splash image */
+char *
+graphics_get_splash(void)
+{
+ return (splashimage);
+}
+
+/*
+ * Initialize a vga16 graphics display with the palette based off of
+ * the image in splashimage. If the image doesn't exist, leave graphics
+ * mode.
+ */
+int
+graphics_init()
+{
+ int fail_n = 0;
+
+ if (!graphics_inited) {
+ saved_videomode = set_videomode(0x12);
+ if (saved_videomode == -1) {
+ fail_n = 1;
+ goto fail;
+ }
+ }
+
+ if (!graphics_set_splash("boot/solaris.xpm")) {
+ fail_n = 2;
+ goto fail;
+ }
+
+ if (!read_image(splashimage)) {
+ fail_n = 3;
+ goto fail;
+ }
+
+ font8x16 = (unsigned char *)graphics_get_font();
+ if (!font8x16) {
+ fail_n = 4;
+ goto fail;
+ }
+
+ graphics_inited = 1;
+
+ /* make sure that the highlight color is set correctly */
+ graphics_highlight_color = ((graphics_normal_color >> 4) |
+ ((graphics_normal_color & 0xf) << 4));
+
+ graphics_cursor(0);
+ graphics_setxy(fontx, fonty);
+ graphics_cursor(1);
+ graphics_cls();
+
+ return (1);
+
+fail :
+ console = CONS_SCREEN_TEXT;
+ text_init();
+ switch (fail_n) {
+ case 1:
+ printf("Failed to set graphics video mode\n");
+ break;
+ case 2:
+ printf("Splash image file name is too long\n");
+ break;
+ case 3:
+ printf("Failed to read splash image\n");
+ break;
+ case 4:
+ printf("Failed to get font address\n");
+ }
+
+ return (0);
+}
+
+/*
+ * int set_videomode(mode)
+ * BIOS call "INT 10H Function 0h" to set video mode
+ * Call with %ah = 0x0
+ * %al = video mode
+ * Return correct : old videomode
+ * error : -1
+ */
+int
+set_videomode(int mode)
+{
+ int ret;
+ struct int_pb ic = {0};
+
+ ic.ax = 0x0f00;
+ ret = bios_doint(0x10, &ic); /* Get Current Video mode */
+ if (ret & PS_C) {
+ dprintf("bios_doint returned: %d\r\n", ret);
+ return (-1);
+ }
+ ret = ic.ax & 0xFF; /* al is the current mode */
+
+ ic.ax = mode & 0xFF; /* ah = 0, al = mode */
+ if (bios_doint(0x10, &ic) & PS_C) {
+ dprintf("bios_doint returned: %d\r\n", ret);
+ return (-1);
+ } /* Set Video mode */
+
+ return (ret);
+}
+
+/*
+ * unsigned char * graphics_get_font()
+ * BIOS call "INT 10H Function 11h" to set font
+ * Call with %ah = 0x11
+ * Return correct : font address
+ * error : 0
+ */
+unsigned char *
+graphics_get_font()
+{
+ int ret;
+ struct int_pb ic = {0};
+
+ ic.ax = 0x1130;
+ ic.bx = 0x0600; /* font 8x16 */
+ ret = bios_doint(0x10, &ic); /* get font address */
+ if (ret & PS_C) {
+ dprintf("bios_doint returned: %d\r\n", ret);
+ return (0);
+ }
+
+ ret = (ic.es << 4) + ic.bp;
+ return ((unsigned char *) ret);
+}
+
+/*
+ * int graphics_set_palette(unsigned index, unsigned red,
+ * unsigned green,unsigned blue)
+ * BIOS call "INT 10H Function 10h" to set individual dac register
+ * Call with %ah = 0x10
+ * %bx = register number
+ * %ch = new value for green (0-63)
+ * %cl = new value for blue (0-63)
+ * %dh = new value for red (0-63)
+ * Return correct : 1
+ * error : 0
+ */
+int
+graphics_set_palette(int index, int red, int green, int blue)
+{
+ int ret;
+ struct int_pb ic = {0};
+ /* wait vertical active display */
+ while (((inb(VGA_IO_IS) & 0x8)) == 0x8) {}
+ /* wait vertical retrace */
+ while (((inb(VGA_IO_IS) & 0x8)) == 0x8) {}
+
+ outb(VGA_IO_WMR, (index & 0xFF));
+ outb(VGA_IO_DR, (red & 0xFF));
+ outb(VGA_IO_DR, (green & 0xFF));
+ outb(VGA_IO_DR, (blue & 0xFF));
+
+ ic.ax = 0x1000;
+ ic.bx = ((index & 0xFF) <<8) | (index & 0xFF); /* ?? */
+ ic.cx = ((green & 0xFF) <<8) | (blue & 0xFF);
+ ic.dx = (red & 0xFF) <<8;
+ ret = bios_doint(0x10, &ic); /* set palette registert */
+ if (ret & PS_C) {
+ dprintf("bios_doint returned: %d\r\n", ret);
+ return (0);
+ } else
+ return (1);
+}
+
+/* Leave graphics mode */
+void
+graphics_end(void)
+{
+ if (graphics_inited) {
+ set_videomode(saved_videomode);
+ graphics_inited = 0;
+ }
+}
+
+/* Print ch on the screen. Handle any needed scrolling or the like */
+void
+graphics_putchar(int ch)
+{
+ ch &= 0xff;
+
+ graphics_cursor(0);
+
+ if (ch == '\n') {
+ if (fonty + 1 < y1)
+ graphics_setxy(fontx, fonty + 1);
+ else
+ graphics_scroll();
+ graphics_cursor(1);
+ return;
+ } else if (ch == '\r') {
+ graphics_setxy(x0, fonty);
+ graphics_cursor(1);
+ return;
+ }
+
+ graphics_cursor(0);
+
+ text[fonty * 80 + fontx] = ch;
+ text[fonty * 80 + fontx] &= 0x00ff;
+ if (graphics_current_color & 0xf0)
+ text[fonty * 80 + fontx] |= 0x100;
+
+ graphics_cursor(0);
+
+ if ((fontx + 1) >= x1) {
+ graphics_setxy(x0, fonty);
+ if (fonty + 1 < y1)
+ graphics_setxy(x0, fonty + 1);
+ else
+ graphics_scroll();
+ } else {
+ graphics_setxy(fontx + 1, fonty);
+ }
+
+ graphics_cursor(1);
+}
+
+/* get the current location of the cursor */
+int
+graphics_getxy(void)
+{
+ return ((fontx << 8) | fonty);
+}
+
+void
+graphics_gotoxy(int x, int y)
+{
+ graphics_cursor(0);
+
+ graphics_setxy(x, y);
+
+ graphics_cursor(1);
+}
+
+void
+graphics_cls(void)
+{
+ int i;
+ unsigned char *mem, *s1, *s2, *s4, *s8;
+
+ graphics_cursor(0);
+ graphics_gotoxy(x0, y0);
+
+ mem = (unsigned char *)VIDEOMEM;
+ s1 = (unsigned char *)VSHADOW1;
+ s2 = (unsigned char *)VSHADOW2;
+ s4 = (unsigned char *)VSHADOW4;
+ s8 = (unsigned char *)VSHADOW8;
+
+ for (i = 0; i < 80 * 30; i++)
+ text[i] = ' ';
+ graphics_cursor(1);
+
+ BitMask(0xff);
+
+ /* plano 1 */
+ MapMask(1);
+ graphics_memcpy(mem, s1, 38400);
+
+ /* plano 2 */
+ MapMask(2);
+ graphics_memcpy(mem, s2, 38400);
+
+ /* plano 3 */
+ MapMask(4);
+ graphics_memcpy(mem, s4, 38400);
+
+ /* plano 4 */
+ MapMask(8);
+ graphics_memcpy(mem, s8, 38400);
+
+ MapMask(15);
+}
+
+void
+graphics_setcolorstate(color_state state)
+{
+ switch (state) {
+ case COLOR_STATE_STANDARD:
+ graphics_current_color = graphics_standard_color;
+ break;
+ case COLOR_STATE_NORMAL:
+ graphics_current_color = graphics_normal_color;
+ break;
+ case COLOR_STATE_HIGHLIGHT:
+ graphics_current_color = graphics_highlight_color;
+ break;
+ default:
+ graphics_current_color = graphics_standard_color;
+ break;
+ }
+
+ graphics_color_state = state;
+}
+
+void
+graphics_setcolor(int normal_color, int highlight_color)
+{
+ graphics_normal_color = normal_color;
+ graphics_highlight_color = highlight_color;
+
+ graphics_setcolorstate(graphics_color_state);
+}
+
+void
+graphics_setcursor(int on)
+{
+ /* FIXME: we don't have a cursor in graphics */
+}
+
+/*
+ * Read in the splashscreen image and set the palette up appropriately.
+ * Format of splashscreen is an xpm (can be gzipped) with 16 colors and
+ * 640x480.
+ */
+static int
+read_image(char *s)
+{
+ char buf[32], pal[16];
+ unsigned char c, base, mask, *s1, *s2, *s4, *s8;
+ unsigned i, len, idx, colors, x, y, width, height;
+ int fd;
+ ssize_t count;
+
+ fd = openfile(s, 0);
+ if (fd == -1) {
+ dprintf("error opening %s\n", s);
+ return (0);
+ }
+
+ /* read header */
+ count = read(fd, (char *)&buf, 10);
+ if ((count < 10) || graphics_memcmp(buf, "/* XPM */\n", 10)) {
+ close(fd);
+ dprintf("read header error\n");
+ return (0);
+ }
+
+ /* parse info */
+ while (read(fd, &c, 1)) {
+ if (c == '"')
+ break;
+ }
+
+ while (read(fd, &c, 1) && (c == ' ' || c == '\t'))
+ ;
+
+ i = 0;
+ width = c - '0';
+ while (read(fd, &c, 1)) {
+ if (c >= '0' && c <= '9')
+ width = width * 10 + c - '0';
+ else
+ break;
+ }
+ while (read(fd, &c, 1) && (c == ' ' || c == '\t'))
+ ;
+
+ height = c - '0';
+ while (read(fd, &c, 1)) {
+ if (c >= '0' && c <= '9')
+ height = height * 10 + c - '0';
+ else
+ break;
+ }
+ while (read(fd, &c, 1) && (c == ' ' || c == '\t'))
+ ;
+
+ colors = c - '0';
+ while (read(fd, &c, 1)) {
+ if (c >= '0' && c <= '9')
+ colors = colors * 10 + c - '0';
+ else
+ break;
+ }
+
+ base = 0;
+ while (read(fd, &c, 1) && c != '"')
+ ;
+ /* palette */
+ for (i = 0, idx = 1; i < colors; i++) {
+ len = 0;
+
+ while (read(fd, &c, 1) && c != '"')
+ ;
+ read(fd, &c, 1); /* char */
+ base = c;
+ read(fd, buf, 4); /* \t c # */
+
+ while (read(fd, &c, 1) && c != '"') {
+ if (len < sizeof (buf))
+ buf[len++] = c;
+ }
+
+ if (len == 6 && idx < 15) {
+ int r = ((hex(buf[0]) << 4) | hex(buf[1])) >> 2;
+ int g = ((hex(buf[2]) << 4) | hex(buf[3])) >> 2;
+ int b = ((hex(buf[4]) << 4) | hex(buf[5])) >> 2;
+ pal[idx] = base;
+ graphics_set_palette(idx, r, g, b);
+ ++idx;
+ }
+ }
+
+ x = y = len = 0;
+
+ s1 = (unsigned char *)VSHADOW1;
+ s2 = (unsigned char *)VSHADOW2;
+ s4 = (unsigned char *)VSHADOW4;
+ s8 = (unsigned char *)VSHADOW8;
+
+ for (i = 0; i < 38400; i++)
+ s1[i] = s2[i] = s4[i] = s8[i] = 0;
+
+ /* parse xpm data */
+ while (y < height) {
+ while (1) {
+ if (!read(fd, &c, 1)) {
+ close(fd);
+ return (0);
+ }
+ if (c == '"')
+ break;
+ }
+
+ while (read(fd, &c, 1) && c != '"') {
+ for (i = 1; i < 15; i++)
+ if (pal[i] == c) {
+ c = i;
+ break;
+ }
+
+ mask = 0x80 >> (x & 7);
+ if (c & 1)
+ s1[len + (x >> 3)] |= mask;
+ if (c & 2)
+ s2[len + (x >> 3)] |= mask;
+ if (c & 4)
+ s4[len + (x >> 3)] |= mask;
+ if (c & 8)
+ s8[len + (x >> 3)] |= mask;
+
+ if (++x >= 640) {
+ x = 0;
+
+ if (y < 480)
+ len += 80;
+ ++y;
+ }
+ }
+ }
+
+ close(fd);
+
+ graphics_set_palette(0, (background >> 16), (background >> 8) & 63,
+ background & 63);
+ graphics_set_palette(15, (foreground >> 16), (foreground >> 8) & 63,
+ foreground & 63);
+ graphics_set_palette(0x11, (border >> 16), (border >> 8) & 63,
+ border & 63);
+
+ return (1);
+}
+
+/* Convert a character which is a hex digit to the appropriate integer */
+static int
+hex(int v)
+{
+ if (v >= 'A' && v <= 'F')
+ return (v - 'A' + 10);
+ if (v >= 'a' && v <= 'f')
+ return (v - 'a' + 10);
+ return (v - '0');
+}
+
+
+/* move the graphics cursor location to col, row */
+static void
+graphics_setxy(int col, int row)
+{
+ if (col >= x0 && col < x1) {
+ fontx = col;
+ cursorX = col << 3;
+ }
+ if (row >= y0 && row < y1) {
+ fonty = row;
+ cursorY = row << 4;
+ }
+}
+
+static void
+graphics_memcpy(void *dest, const void *src, int len)
+{
+ int i;
+ register char *d = (char *)dest, *s = (char *)src;
+
+ for (i = 0; i < len; i++)
+ d[i] = s[i];
+}
+
+static int
+graphics_memcmp(const char *s1, const char *s2, int n)
+{
+ while (n) {
+ if (*s1 < *s2)
+ return (-1);
+ else if (*s1 > *s2)
+ return (1);
+ s1++;
+ s2++;
+ n--;
+ }
+
+ return (0);
+}
+
+/* scroll the screen */
+static void
+graphics_scroll()
+{
+ int i, j;
+
+ /* we don't want to scroll recursively... that would be bad */
+ if (no_scroll)
+ return;
+ no_scroll = 1;
+
+ /* move everything up a line */
+ for (j = y0 + 1; j < y1; j++) {
+ graphics_gotoxy(x0, j - 1);
+ for (i = x0; i < x1; i++) {
+ graphics_putchar(text[j * 80 + i]);
+ }
+ }
+
+ /* last line should be blank */
+ graphics_gotoxy(x0, y1 - 1);
+ for (i = x0; i < x1; i++)
+ graphics_putchar(' ');
+ graphics_setxy(x0, y1 - 1);
+
+ no_scroll = 0;
+}
+
+
+void graphics_cursor(int set) {
+ unsigned char *pat, *mem, *ptr, chr[16 << 2];
+ int i, ch, invert, offset;
+
+ if (set && no_scroll)
+ return;
+
+ offset = cursorY * 80 + fontx;
+ ch = text[fonty * 80 + fontx] & 0xff;
+ invert = (text[fonty * 80 + fontx] & 0xff00) != 0;
+ pat = font8x16 + (ch << 4);
+
+ mem = (unsigned char *)VIDEOMEM + offset;
+
+ if (set) {
+ MapMask(15);
+ ptr = mem;
+ for (i = 0; i < 16; i++, ptr += 80) {
+ cursorBuf[i] = pat[i];
+ *ptr = ~pat[i];
+ }
+ return;
+ }
+
+ for (i = 0; i < 16; i++) {
+ unsigned char mask = pat[i];
+
+ if (!invert) {
+ chr[i ] = ((unsigned char *)VSHADOW1)[offset];
+ chr[16 + i] = ((unsigned char *)VSHADOW2)[offset];
+ chr[32 + i] = ((unsigned char *)VSHADOW4)[offset];
+ chr[48 + i] = ((unsigned char *)VSHADOW8)[offset];
+
+ chr[i ] |= mask;
+ chr[16 + i] |= mask;
+ chr[32 + i] |= mask;
+ chr[48 + i] |= mask;
+
+ offset += 80;
+ } else {
+ chr[i ] = mask;
+ chr[16 + i] = mask;
+ chr[32 + i] = mask;
+ chr[48 + i] = mask;
+ }
+ }
+
+ offset = 0;
+ for (i = 1; i < 16; i <<= 1, offset += 16) {
+ int j;
+
+ MapMask(i);
+ ptr = mem;
+ for (j = 0; j < 16; j++, ptr += 80)
+ *ptr = chr[j + offset];
+ }
+
+ MapMask(15);
+}
diff --git a/usr/src/psm/stand/boot/i386/common/graphics.h b/usr/src/psm/stand/boot/i386/common/graphics.h
new file mode 100644
index 0000000000..d589d8b38a
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/graphics.h
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _GRAPHICS_H
+#define _GRAPHICS_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* magic constant */
+#define VIDEOMEM 0xA0000
+
+/* code for getchar */
+#define A_NORMAL 0x7
+#define A_REVERSE 0x70
+
+/* These are used to represent the various color states we use */
+typedef enum
+{
+/*
+ * represents the color used to display all text that does not use the user
+ * defined colors below
+ */
+COLOR_STATE_STANDARD,
+/* represents the user defined colors for normal text */
+COLOR_STATE_NORMAL,
+/* represents the user defined colors for highlighted text */
+COLOR_STATE_HIGHLIGHT
+} color_state;
+
+void graphics_cursor(int set);
+void graphics_putchar(int c);
+int graphics_getxy(void);
+void graphics_gotoxy(int x, int y);
+void graphics_cls(void);
+void graphics_setcolorstate(color_state state);
+void graphics_setcolor(int normal_color, int highlight_color);
+void graphics_setcursor(int on);
+int set_videomode(int mode);
+int graphics_init(void);
+void graphics_end(void);
+unsigned char *graphics_get_font(void);
+int graphics_set_palette(int idx, int red, int green, int blue);
+int graphics_set_splash(char *splashfile);
+
+short cursorX, cursorY;
+char cursorBuf[16];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GRAPHICS_H */
diff --git a/usr/src/psm/stand/boot/i386/common/i86.il b/usr/src/psm/stand/boot/i386/common/i86.il
new file mode 100644
index 0000000000..180cb5135a
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/i86.il
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ *
+ * 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 (c) 1992,2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/
+/ In-line functions for i86 calls.
+/
+
+
+/
+/ in and out
+/
+ .inline inb,4
+ movl (%esp), %edx
+ xorl %eax, %eax
+ inb (%dx)
+ .end
+
+ .inline inw,4
+ movl (%esp), %edx
+ xorl %eax, %eax
+ inw (%dx)
+ .end
+
+ .inline inl,4
+ movl (%esp), %edx
+ xorl %eax, %eax
+ inl (%dx)
+ .end
+
+ .inline outb,8
+ movl (%esp), %edx
+ movl 4(%esp), %eax
+ outb (%dx)
+ .end
+
+ .inline outw,8
+ movl (%esp), %edx
+ movl 4(%esp), %eax
+ outw (%dx)
+ .end
+
+ .inline outl,8
+ movl (%esp), %edx
+ movl 4(%esp), %eax
+ outl (%dx)
+ .end
+
+/
+/ Networking byte order functions (too bad, Intel has the wrong byte order)
+/
+
+ .inline htonl,4
+ movl (%esp), %eax
+ bswap %eax
+ .end
+
+ .inline ntohl,4
+ movl (%esp), %eax
+ bswap %eax
+ .end
+
+ .inline htons,4
+ movl (%esp), %eax
+ bswap %eax
+ shrl $16, %eax
+ .end
+
+ .inline ntohs,4
+ movl (%esp), %eax
+ bswap %eax
+ shrl $16, %eax
+ .end
+
+/
+/ disable interrupts and return value describing if interrupts were enabled
+/
+ .inline clear_int_flag,0
+ pushfl
+ cli
+ popl %eax
+ .end
+
+/
+/ restore interrupt enable flag to value returned from 'clear_int_flag' above
+/
+ .inline restore_int_flag,4
+ pushl (%esp)
+ popfl
+ .end
+
+/
+/ stub function.
+/ i386 arch currently has a unified cache
+/
+ .inline sync_instruction_memory,8
+ nop
+ .end
diff --git a/usr/src/psm/stand/boot/i386/common/keyboard.c b/usr/src/psm/stand/boot/i386/common/keyboard.c
new file mode 100644
index 0000000000..095a46b432
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/keyboard.c
@@ -0,0 +1,554 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Miniature keyboard driver for bootstrap. This allows keyboard
+ * support to continue after we take over interrupts and disable
+ * BIOS keyboard support.
+ */
+
+#include <sys/types.h>
+#include "chario.h"
+#include "keyboard_table.h"
+#include "console.h"
+#include "util.h"
+#include "debug.h"
+
+/*
+ * Definitions for BIOS keyboard state. We use BIOS's variable to store
+ * state, ensuring that we stay in sync with it.
+ */
+#define BIOS_KB_FLAG 0x417
+#define BIOS_RIGHT_SHIFT 0x01
+#define BIOS_LEFT_SHIFT 0x02
+#define BIOS_EITHER_SHIFT (BIOS_LEFT_SHIFT | BIOS_RIGHT_SHIFT)
+#define BIOS_CTL_SHIFT 0x04
+#define BIOS_ALT_SHIFT 0x08
+#define BIOS_SCROLL_STATE 0x10
+#define BIOS_NUM_STATE 0x20
+#define BIOS_CAPS_STATE 0x40
+#define BIOS_INS_STATE 0x80
+
+#define BIOS_KB_FLAG_1 0x418
+#define BIOS_SYS_SHIFT 0x04
+#define BIOS_HOLD_STATE 0x08
+#define BIOS_SCROLL_SHIFT 0x10
+#define BIOS_NUM_SHIFT 0x20
+#define BIOS_CAPS_SHIFT 0x40
+#define BIOS_INS_SHIFT 0x80
+
+#define kb_flag ((unsigned char *)BIOS_KB_FLAG)
+#define kb_flag_1 ((unsigned char *)BIOS_KB_FLAG_1)
+
+/*
+ * Keyboard controller registers
+ */
+#define I8042_DATA 0x60
+#define I8042_STAT 0x64
+#define I8042_CMD 0x64
+
+/*
+ * Keyboard controller status register bits
+ */
+#define I8042_STAT_OUTBF 0x01
+#define I8042_STAT_INBF 0x02
+#define I8042_STAT_AUXBF 0x20
+
+/*
+ * Keyboard controller commands
+ */
+#define I8042_RCB 0x20
+#define I8042_WCB 0x60
+
+/*
+ * Keyboard commands
+ */
+#define KB_SET_LED 0xED /* LED byte follows... */
+#define KB_LED_SCROLL_LOCK 0x01 /* Bits for LED byte */
+#define KB_LED_NUM_LOCK 0x02
+#define KB_LED_CAPS_LOCK 0x04
+
+#ifndef ASSERT
+#define ASSERT(x)
+#endif
+
+#define peek8(p) (*(p))
+#define poke8(p, val) (*(p) = (val))
+#define peeks(p) (*(p))
+#define pokes(p, val) (*(p) = (val))
+
+static struct {
+ boolean_t initialized;
+ enum { KB_LED_IDLE, KB_LED_COMMAND_SENT, KB_LED_VALUE_SENT }
+ led_state;
+ int led_commanded;
+ /*
+ * Possible values:
+ *
+ * -1 Nothing pending
+ * 0x000-0x0ff Pending byte
+ * 0x100-0x1ff Needs leading zero, then low byte next.
+ *
+ * Others undefined.
+ */
+ int pending;
+} kb = {
+ B_FALSE, /* initialized? */
+ KB_LED_IDLE, /* LED command state */
+ -1, /* commanded LEDs - force refresh */
+ -1, /* pending */
+};
+
+#define kb_debug (debug & D_KEYBOARD)
+
+static int kb_translate(unsigned char code);
+static void kb_send(unsigned char cmd);
+static void kb_update_leds(void);
+static uchar_t kb_calculate_leds(void);
+
+int
+kb_getchar(void)
+{
+ int ret;
+
+ if (kb_debug)
+ printf(" getchar()");
+
+ while (!kb_ischar())
+ /* LOOP */;
+
+ /*
+ * kb_ischar() doesn't succeed without leaving kb.pending
+ * set.
+ */
+ ASSERT(kb.pending >= 0);
+
+ if (kb.pending & 0x100) {
+ ret = 0;
+ kb.pending &= 0xff;
+ } else {
+ ret = kb.pending;
+ kb.pending = -1;
+ }
+
+ if (kb_debug)
+ printf("=0x%x ", ret);
+
+ return (ret);
+}
+
+int
+kb_ischar(void)
+{
+ unsigned char buffer_stat;
+ unsigned char code;
+ unsigned char leds;
+ static int cnt = 0;
+
+ if (!kb.initialized) {
+ kb_init();
+ kb.initialized = B_TRUE;
+ }
+
+ if (kb_debug)
+ printf("%c\b", "/-\\|"[cnt++ % 4]);
+
+ if (kb.pending >= 0)
+ return (1);
+
+ for (;;) {
+ buffer_stat =
+ inb(I8042_STAT) & (I8042_STAT_OUTBF | I8042_STAT_AUXBF);
+
+ switch (buffer_stat) {
+ case 0:
+ case I8042_STAT_AUXBF:
+ return (0);
+ case (I8042_STAT_OUTBF | I8042_STAT_AUXBF):
+ /*
+ * Discard unwanted mouse data.
+ */
+ (void) inb(I8042_DATA);
+ continue;
+ }
+
+ code = inb(I8042_DATA);
+
+ if (kb_debug)
+ printf("0x%x->", code);
+
+ switch (code) {
+ /*
+ * case 0xAA:
+ *
+ * You might think that we should ignore 0xAA on the
+ * grounds that it is the BAT Complete response and will
+ * occur on keyboard detach/reattach. Unfortunately,
+ * it is ambiguous - this is also the code for a break
+ * of the left shift key. Since it will be harmless for
+ * us to "spuriously" process a break of Left Shift,
+ * we just let the normal code handle it. Perhaps we
+ * should take a hint and refresh the LEDs, but I
+ * refuse to get very worried about hot-plug issues
+ * in this mini-driver.
+ */
+ case 0xFA:
+ if (kb_debug)
+ printf("ack ");
+
+ switch (kb.led_state) {
+ case KB_LED_IDLE:
+ /*
+ * Spurious. Oh well, ignore it.
+ */
+ break;
+ case KB_LED_COMMAND_SENT:
+ leds = kb_calculate_leds();
+ kb_send(leds);
+ kb.led_commanded = leds;
+ kb.led_state = KB_LED_VALUE_SENT;
+ break;
+ case KB_LED_VALUE_SENT:
+ kb.led_state = KB_LED_IDLE;
+ /*
+ * Check for changes made while we were
+ * working on the last change.
+ */
+ kb_update_leds();
+ break;
+ }
+ continue;
+
+ case 0xE0:
+ case 0xE1:
+ /*
+ * These are used to distinguish the keys added on
+ * the AT-101 keyboard from the original 84 keys.
+ * We don't care, and the codes are carefully arranged
+ * so that we don't have to.
+ */
+ if (kb_debug)
+ printf("ignored ");
+ continue;
+
+ default:
+ if (code & 0x80) {
+ if (kb_debug)
+ printf("release->");
+ /* Release */
+ code &= 0x7f;
+ switch (keyboard_translate[code].normal) {
+ case KBTYPE_SPEC_LSHIFT:
+ poke8(kb_flag, peek8(kb_flag) &
+ ~BIOS_LEFT_SHIFT);
+ if (kb_debug)
+ printf("lshift ");
+ break;
+ case KBTYPE_SPEC_RSHIFT:
+ poke8(kb_flag, peek8(kb_flag) &
+ ~BIOS_RIGHT_SHIFT);
+ if (kb_debug)
+ printf("rshift ");
+ break;
+ case KBTYPE_SPEC_CTRL:
+ poke8(kb_flag, peek8(kb_flag) &
+ ~BIOS_CTL_SHIFT);
+ if (kb_debug)
+ printf("ctrl ");
+ break;
+ case KBTYPE_SPEC_ALT:
+ poke8(kb_flag, peek8(kb_flag) &
+ ~BIOS_ALT_SHIFT);
+ if (kb_debug)
+ printf("alt ");
+ break;
+ case KBTYPE_SPEC_CAPS_LOCK:
+ poke8(kb_flag_1, peek8(kb_flag_1) &
+ ~BIOS_CAPS_SHIFT);
+ if (kb_debug)
+ printf("caps ");
+ break;
+ case KBTYPE_SPEC_NUM_LOCK:
+ poke8(kb_flag_1, peek8(kb_flag_1) &
+ ~BIOS_NUM_SHIFT);
+ if (kb_debug)
+ printf("num ");
+ break;
+ case KBTYPE_SPEC_SCROLL_LOCK:
+ poke8(kb_flag_1, peek8(kb_flag_1) &
+ ~BIOS_SCROLL_SHIFT);
+ if (kb_debug)
+ printf("scroll ");
+ break;
+ default:
+ /*
+ * Ignore all other releases.
+ */
+ if (kb_debug)
+ printf("ignored ");
+ break;
+ }
+ } else {
+ /* Press */
+ if (kb_debug)
+ printf("press->");
+
+ kb.pending = kb_translate(code);
+ if (kb.pending >= 0) {
+ if (kb_debug)
+ printf("0x%x ", kb.pending);
+ return (1);
+ } else {
+ if (kb_debug)
+ printf("ignored ");
+ }
+ }
+ }
+ }
+}
+
+int
+kb_translate(unsigned char code)
+{
+ struct keyboard_translate *k;
+ unsigned short action;
+ boolean_t shifted;
+
+ k = keyboard_translate + code;
+
+ shifted = (peek8(kb_flag) & BIOS_EITHER_SHIFT) != 0;
+
+ switch (k->normal & 0xFF00) {
+ case KBTYPE_NUMPAD:
+ if (peek8(kb_flag) & BIOS_NUM_STATE)
+ shifted = !shifted;
+ break;
+ case KBTYPE_ALPHA:
+ if (peek8(kb_flag) & BIOS_CAPS_STATE)
+ shifted = !shifted;
+ break;
+ }
+
+ if (peek8(kb_flag) & BIOS_ALT_SHIFT)
+ action = k->alted;
+ else if (peek8(kb_flag) & BIOS_CTL_SHIFT)
+ action = k->ctrled;
+ else if (shifted)
+ action = k->shifted;
+ else
+ action = k->normal;
+
+ switch (action & 0xFF00) {
+ case KBTYPE_NORMAL:
+ case KBTYPE_ALPHA:
+ return (action & 0xFF);
+
+ case KBTYPE_NUMPAD:
+ case KBTYPE_FUNC:
+ return ((action & 0xFF) | 0x100);
+
+ case KBTYPE_SPEC:
+ break;
+
+ default:
+ /*
+ * Bad entry.
+ */
+ ASSERT(0);
+ return (-1);
+ }
+
+ /*
+ * Handle special keys, mostly shifts.
+ */
+ switch (action) {
+ case KBTYPE_SPEC_NOP:
+ case KBTYPE_SPEC_UNDEF:
+ break;
+
+ case KBTYPE_SPEC_LSHIFT:
+ poke8(kb_flag, peek8(kb_flag) | BIOS_LEFT_SHIFT);
+ break;
+
+ case KBTYPE_SPEC_RSHIFT:
+ poke8(kb_flag, peek8(kb_flag) | BIOS_RIGHT_SHIFT);
+ break;
+
+ case KBTYPE_SPEC_CTRL:
+ poke8(kb_flag, peek8(kb_flag) | BIOS_CTL_SHIFT);
+ break;
+
+ case KBTYPE_SPEC_ALT:
+ poke8(kb_flag, peek8(kb_flag) | BIOS_ALT_SHIFT);
+ break;
+
+ case KBTYPE_SPEC_CAPS_LOCK:
+ if (!(peek8(kb_flag_1) & BIOS_CAPS_SHIFT)) {
+ poke8(kb_flag_1, peek8(kb_flag_1) | BIOS_CAPS_SHIFT);
+ poke8(kb_flag, peek8(kb_flag) ^ BIOS_CAPS_STATE);
+ }
+ break;
+
+ case KBTYPE_SPEC_NUM_LOCK:
+ if (!(peek8(kb_flag_1) & BIOS_NUM_SHIFT)) {
+ poke8(kb_flag_1, peek8(kb_flag_1) | BIOS_NUM_SHIFT);
+ poke8(kb_flag, peek8(kb_flag) ^ BIOS_NUM_STATE);
+ }
+ break;
+
+ case KBTYPE_SPEC_SCROLL_LOCK:
+ if (!(peek8(kb_flag_1) & BIOS_SCROLL_SHIFT)) {
+ poke8(kb_flag_1, peek8(kb_flag_1) | BIOS_SCROLL_SHIFT);
+ poke8(kb_flag, peek8(kb_flag) ^ BIOS_SCROLL_STATE);
+ }
+ break;
+
+ case KBTYPE_SPEC_MAYBE_REBOOT:
+ if ((peek8(kb_flag) & (BIOS_CTL_SHIFT|BIOS_ALT_SHIFT)) ==
+ (BIOS_CTL_SHIFT|BIOS_ALT_SHIFT)) {
+ reset();
+ /* NOTREACHED */
+ }
+ break;
+
+ default:
+ /*
+ * Bad entry
+ */
+ ASSERT(0);
+ break;
+ }
+
+ /*
+ * Consider updating the LEDs. This does nothing if nothing
+ * needs to be done.
+ */
+ kb_update_leds();
+
+ return (-1);
+}
+
+void
+kb_send(unsigned char cmd)
+{
+ while (inb(I8042_STAT) & I8042_STAT_INBF)
+ /* LOOP */;
+ outb(I8042_DATA, cmd);
+}
+
+void
+kb_update_leds(void)
+{
+ if (kb.led_state != KB_LED_IDLE) {
+ /*
+ * The state machine will take care of any additional
+ * changes that are necessary.
+ */
+ return;
+ }
+
+ if (kb_calculate_leds() == kb.led_commanded) {
+ kb.led_state = KB_LED_IDLE;
+ } else {
+ kb_send(KB_SET_LED);
+ kb.led_state = KB_LED_COMMAND_SENT;
+ }
+}
+
+#define MIMR_PORT 0x21 /* Mask register for master PIC */
+#define MIMR_KB 2 /* Keyboard mask bit in master PIC */
+
+void
+kb_init(void)
+{
+ unsigned char pic_mask;
+
+ /*
+ * Write the command byte to turn off interrupts and
+ * disable the auxiliary port.
+ *
+ * 0x80: 0 = Reserved, must be zero.
+ * 0x40: 1 = Translate to XT codes.
+ * Solaris turns this off later, but we have a legacy
+ * of using XT codes.
+ * 0x20: 1 = Disable aux (mouse) port.
+ * 0x10: 0 = Enable main (keyboard) port.
+ * 0x08: 0 = Reserved, must be zero.
+ * 0x04: 1 = System flag, 1 means passed self-test.
+ * Caution: setting this bit to zero causes some
+ * systems (HP Kayak XA) to fail to reboot without
+ * a hard reset.
+ * 0x02: 0 = Disable aux interrupts.
+ * 0x01: 0 = Disable aux interrupts.
+ */
+
+ while (inb(I8042_STAT) & I8042_STAT_INBF)
+ /* LOOP */;
+ outb(I8042_CMD, I8042_WCB);
+
+ while (inb(I8042_STAT) & I8042_STAT_INBF)
+ /* LOOP */;
+ outb(I8042_DATA, 0x64);
+
+ /*
+ * If we're running on a system with an emulated 8042 (with
+ * USB and SMI emulation), the above command *might* not
+ * have turned off keyboard interrupts. If it didn't,
+ * we will lose keystrokes to the BIOS int handler every
+ * time someone hits a key while BIOS and STI are active..
+ * that is, every time we're in bootconf.exe, for example.
+ * Turn off ints at the PIC to prevent this from happening.
+ *
+ * Yes, this is yet another workaround for buggy BIOS
+ * emulation.
+ */
+
+ pic_mask = inb(MIMR_PORT);
+ outb(MIMR_PORT, pic_mask | MIMR_KB);
+
+ kb_update_leds();
+}
+
+unsigned char
+kb_calculate_leds(void)
+{
+ int res;
+
+ res = 0;
+
+ if (peek8(kb_flag) & BIOS_CAPS_STATE)
+ res |= KB_LED_CAPS_LOCK;
+
+ if (peek8(kb_flag) & BIOS_NUM_STATE)
+ res |= KB_LED_NUM_LOCK;
+
+ if (peek8(kb_flag) & BIOS_SCROLL_STATE)
+ res |= KB_LED_SCROLL_LOCK;
+
+ return (res);
+}
diff --git a/usr/src/psm/stand/boot/i386/common/keyboard_table.c b/usr/src/psm/stand/boot/i386/common/keyboard_table.c
new file mode 100644
index 0000000000..64d57720df
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/keyboard_table.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, Version 1.0 only
+ * (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 (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Keyboard table for bootstrap's miniature keyboard driver.
+ */
+
+#include "keyboard_table.h"
+
+#define A | KBTYPE_ALPHA
+#define C & 0x1f
+#define F | KBTYPE_FUNC
+#define N | KBTYPE_NUMPAD
+
+#define ALT KBTYPE_SPEC_ALT
+#define CTRL KBTYPE_SPEC_CTRL
+#define LSHIFT KBTYPE_SPEC_LSHIFT
+#define NOP KBTYPE_SPEC_NOP
+#define NUMLK KBTYPE_SPEC_NUM_LOCK
+#define SCRLLK KBTYPE_SPEC_SCROLL_LOCK
+#define CAPSLK KBTYPE_SPEC_CAPS_LOCK
+#define RSHIFT KBTYPE_SPEC_RSHIFT
+#define REBOOT KBTYPE_SPEC_MAYBE_REBOOT
+#define UNDEF KBTYPE_SPEC_UNDEF
+
+struct keyboard_translate keyboard_translate[128] = {
+ /* Normal Shifted Ctrled Alted */
+ /* 00 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 01 */ '['C, '['C, NOP, NOP,
+ /* 02 */ '1', '!', NOP, 0x78 F,
+ /* 03 */ '2', '@', NOP, 0x79 F,
+ /* 04 */ '3', '#', NOP, 0x7a F,
+ /* 05 */ '4', '$', NOP, 0x7b F,
+ /* 06 */ '5', '%', NOP, 0x7c F,
+ /* 07 */ '6', '^', '^'C, 0x7d F,
+ /* 08 */ '7', '&', NOP, 0x7e F,
+ /* 09 */ '8', '*', NOP, 0x7f F,
+ /* 0a */ '9', '(', NOP, 0x80 F,
+ /* 0b */ '0', ')', NOP, 0x81 F,
+ /* 0c */ '-', '_', NOP, 0x82 F,
+ /* 0d */ '=', '+', NOP, 0x83 F,
+ /* 0e */ 'h'C, 0x0e F, 0x7f, NOP,
+ /* 0f */ 'i'C, 0x0f F, NOP, NOP,
+ /* 10 */ 'q'A, 'Q', 'q'C, 0x10 F,
+ /* 11 */ 'w'A, 'W', 'w'C, 0x11 F,
+ /* 12 */ 'e'A, 'E', 'e'C, 0x12 F,
+ /* 13 */ 'r'A, 'R', 'r'C, 0x13 F,
+ /* 14 */ 't'A, 'T', 't'C, 0x14 F,
+ /* 15 */ 'y'A, 'Y', 'y'C, 0x15 F,
+ /* 16 */ 'u'A, 'U', 'u'C, 0x16 F,
+ /* 17 */ 'i'A, 'I', 'i'C, 0x17 F,
+ /* 18 */ 'o'A, 'O', 'o'C, 0x18 F,
+ /* 19 */ 'p'A, 'P', 'p'C, 0x19 F,
+ /* 1a */ '[', '{', '['C, NOP,
+ /* 1b */ ']', '}', ']'C, NOP,
+ /* 1c */ 'm'C, 'm'C, NOP, NOP,
+ /* 1d */ CTRL, CTRL, CTRL, CTRL,
+ /* 1e */ 'a'A, 'A', 'a'C, 0x1e F,
+ /* 1f */ 's'A, 'S', 's'C, 0x1f F,
+ /* 20 */ 'd'A, 'D', 'd'C, 0x20 F,
+ /* 21 */ 'f'A, 'F', 'f'C, 0x21 F,
+ /* 22 */ 'g'A, 'G', 'g'C, 0x22 F,
+ /* 23 */ 'h'A, 'H', 'h'C, 0x23 F,
+ /* 24 */ 'j'A, 'J', 'j'C, 0x24 F,
+ /* 25 */ 'k'A, 'K', 'k'C, 0x25 F,
+ /* 26 */ 'l'A, 'L', 'l'C, 0x26 F,
+ /* 27 */ ';', ':', NOP, NOP,
+ /* 28 */ '\'', '"', NOP, NOP,
+ /* 29 */ '`', '~', NOP, NOP,
+ /* 2a */ LSHIFT, LSHIFT, LSHIFT, LSHIFT,
+ /* 2b */ '\\', '|', '\\'C, NOP,
+ /* 2c */ 'z'A, 'Z', 'z'C, 0x2c F,
+ /* 2d */ 'x'A, 'X', 'x'C, 0x2d F,
+ /* 2e */ 'c'A, 'C', 'c'C, 0x2e F,
+ /* 2f */ 'v'A, 'V', 'v'C, 0x2f F,
+ /* 30 */ 'b'A, 'B', 'b'C, 0x30 F,
+ /* 31 */ 'n'A, 'N', 'n'C, 0x31 F,
+ /* 32 */ 'm'A, 'M', 'm'C, 0x32 F,
+ /* 33 */ ',', '<', NOP, NOP,
+ /* 34 */ '.', '>', NOP, NOP,
+ /* 35 */ '/', '?', NOP, NOP,
+ /* 36 */ RSHIFT, RSHIFT, RSHIFT, RSHIFT,
+ /* 37 */ '*', NOP, NOP, NOP, /* * PrtSc */
+ /* 38 */ ALT, ALT, ALT, ALT,
+ /* 39 */ ' ', ' ', NOP, NOP,
+ /* 3a */ CAPSLK, CAPSLK, CAPSLK, CAPSLK,
+ /* 3b */ 0x3b F, 0x54 F, 0x5e F, 0x68 F,
+ /* 3c */ 0x3c F, 0x55 F, 0x5f F, 0x69 F,
+ /* 3d */ 0x3d F, 0x56 F, 0x60 F, 0x6a F,
+ /* 3e */ 0x3e F, 0x57 F, 0x61 F, 0x6b F,
+ /* 3f */ 0x3f F, 0x58 F, 0x62 F, 0x6c F,
+ /* 40 */ 0x40 F, 0x59 F, 0x63 F, 0x6d F,
+ /* 41 */ 0x41 F, 0x5a F, 0x64 F, 0x6e F,
+ /* 42 */ 0x42 F, 0x5b F, 0x65 F, 0x6f F,
+ /* 43 */ 0x43 F, 0x5c F, 0x66 F, 0x70 F,
+ /* 44 */ 0x44 F, 0x5d F, 0x67 F, 0x71 F,
+ /* 45 */ NUMLK, NUMLK, NUMLK, NUMLK,
+ /* 46 */ SCRLLK, SCRLLK, SCRLLK, SCRLLK,
+ /* 47 */ 0x47 N, '7', NOP, NOP,
+ /* 48 */ 0x48 N, '8', NOP, NOP,
+ /* 49 */ 0x49 N, '9', NOP, NOP,
+ /* 4a */ '-', '-', NOP, NOP,
+ /* 4b */ 0x4b N, '4', NOP, NOP,
+ /* 4c */ NOP, '5', NOP, NOP,
+ /* 4d */ 0x4d N, '6', NOP, NOP,
+ /* 4e */ '+', '+', NOP, NOP,
+ /* 4f */ 0x4f N, '1', NOP, NOP,
+ /* 50 */ 0x50 N, '2', NOP, NOP,
+ /* 51 */ 0x51 N, '3', NOP, NOP,
+ /* 52 */ 0x52 N, '0', NOP, NOP,
+ /* 53 */ 0x53 N, '.', REBOOT, REBOOT,
+ /* 54 */ NOP, NOP, NOP, NOP, /* SysReq */
+ /* 55 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 56 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 57 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 58 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 59 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 5a */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 5b */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 5c */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 5d */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 5e */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 5f */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 60 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 61 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 62 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 63 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 64 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 65 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 66 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 67 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 68 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 69 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 6a */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 6b */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 6c */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 6d */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 6e */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 6f */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 70 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 71 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 72 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 73 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 74 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 75 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 76 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 77 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 78 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 79 */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 7a */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 7b */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 7c */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 7d */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 7e */ UNDEF, UNDEF, UNDEF, UNDEF,
+ /* 7f */ UNDEF, UNDEF, UNDEF, UNDEF,
+};
diff --git a/usr/src/psm/stand/boot/i386/common/keyboard_table.h b/usr/src/psm/stand/boot/i386/common/keyboard_table.h
new file mode 100644
index 0000000000..2b72bdc0a3
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/keyboard_table.h
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ *
+ * 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 (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _KEYBOARD_TABLE_H
+#define _KEYBOARD_TABLE_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Structure of the keyboard table for the bootstrap miniature
+ * keyboard driver.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define KBTYPE_NORMAL 0x000 /* Normal keys, process mindlessly. */
+#define KBTYPE_ALPHA 0x100 /* Alpha. If CapsLock is set, swap */
+ /* shifted and unshifted meanings. */
+ /* Set this on the unshifted character */
+#define KBTYPE_NUMPAD 0x200 /* Numeric/Arrow Pad. If NumLock is set, */
+ /* swap shifted and unshifted meanings. */
+ /* Set this on the unshifted character. */
+#define KBTYPE_FUNC 0x300 /* Extended Function. Send this code, */
+ /* prefixed with zero. */
+#define KBTYPE_SPEC 0x400 /* One-of-a-kind codes. Self-explanatory. */
+#define KBTYPE_SPEC_NOP (KBTYPE_SPEC | 0x00)
+#define KBTYPE_SPEC_UNDEF (KBTYPE_SPEC | 0x01)
+#define KBTYPE_SPEC_LSHIFT (KBTYPE_SPEC | 0x02)
+#define KBTYPE_SPEC_RSHIFT (KBTYPE_SPEC | 0x03)
+#define KBTYPE_SPEC_CTRL (KBTYPE_SPEC | 0x04)
+#define KBTYPE_SPEC_ALT (KBTYPE_SPEC | 0x05)
+#define KBTYPE_SPEC_CAPS_LOCK (KBTYPE_SPEC | 0x06)
+#define KBTYPE_SPEC_NUM_LOCK (KBTYPE_SPEC | 0x07)
+#define KBTYPE_SPEC_SCROLL_LOCK (KBTYPE_SPEC | 0x08)
+#define KBTYPE_SPEC_MAYBE_REBOOT (KBTYPE_SPEC | 0x09)
+
+struct keyboard_translate {
+ unsigned short normal;
+ unsigned short shifted;
+ unsigned short ctrled;
+ unsigned short alted;
+};
+
+extern struct keyboard_translate keyboard_translate[128];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _KEYBOARD_TABLE_H */
diff --git a/usr/src/psm/stand/boot/i386/common/machine.h b/usr/src/psm/stand/boot/i386/common/machine.h
new file mode 100644
index 0000000000..d841cb8526
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/machine.h
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
+/* All Rights Reserved */
+
+/*
+ * Copyrighted as an unpublished work.
+ * (c) Copyright INTERACTIVE Systems Corporation 1986, 1988, 1990
+ * All rights reserved.
+ */
+
+#ifndef _MACHINE_H
+#define _MACHINE_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct machconfig {
+ char *sigaddr; /* Machine signature location */
+ unsigned char siglen; /* Signature length */
+ unsigned char sigid[10]; /* Signature to match */
+ unsigned char old_mt; /* OLD Machine type */
+ unsigned char machine; /* Machine type */
+ ulong_t m_flag; /* status flag */
+ int (*m_entry)(); /* machine entry point */
+};
+
+#define M_FLG_SRGE 1 /* sig scattered in a range of memory */
+
+#define M_ID_AT386 0
+#define M_ID_MC386 1
+#define M_ID_EISA 2
+
+#define SYS_MODEL() *(char *)0xFFFFE
+#define MODEL_AT (uchar_t)0xFC
+#define MODEL_MC (uchar_t)0xF8
+#define USER_START 0x100000
+
+#define NPTEPERPT 1024
+typedef struct ptbl {
+ int page[NPTEPERPT];
+} ptbl_t;
+
+/* combine later with ../../../uts/i86/sys/pte.h */
+#define PG_P 0x1 /* page is present */
+#define PG_RW 0x2 /* page is read/write */
+#define PG_SIZE 0x80 /* page is 4MB */
+#define PG_GLOBAL 0x100 /* page is persistent */
+
+/*
+ * keyboard controller I/O port addresses
+ */
+
+#define KB_OUT 0x60 /* output buffer R/O */
+#define KB_IDAT 0x60 /* input buffer data write W/O */
+#define KB_STAT 0x64 /* keyboard controller status R/O */
+#define KB_ICMD 0x64 /* input buffer command write W/O */
+
+/*
+ * keyboard controller commands and flags
+ */
+#define KB_INBF 0x02 /* input buffer full flag */
+#define KB_OUTBF 0x01 /* output buffer full flag */
+#define KB_GATE20 0x02 /* set this bit to allow addresses > 1Mb */
+#define KB_ROP 0xD0 /* read output port command */
+#define KB_WOP 0xD1 /* write output port command */
+#define KB_RCB 0x20 /* read command byte command */
+#define KB_WCB 0x60 /* write command byte command */
+#define KB_ENAB 0xae /* enable keyboard interface */
+#define KB_DISAB 0x10 /* disable keyboard */
+#define KB_EOBFI 0x01 /* enable interrupt on output buffer full */
+#define KB_ACK 0xFA /* Acknowledgement byte from keyboard */
+#define KB_RESETCPU 0xFE /* command to reset AT386 cpu */
+#define KB_READID 0xF2 /* command to read keyboard id */
+#define KB_RESEND 0xFE /* response from keyboard to resend data */
+#define KB_ERROR 0xFF /* response from keyboard to resend data */
+#define KB_RESET 0xFF /* command to reset keyboard */
+/*
+ * command to to enable keyboard
+ * this is different from KB_ENAB above in
+ * that KB_ENAB is a command to the 8042 to
+ * enable the keyboard interface, not the
+ * keyboard itself
+ */
+#define KB_ENABLE 0xF4
+
+/* move later into immu.h */
+#ifndef PTSIZE
+#define PTSIZE 4096
+#endif
+
+#define ptround(p) ((int *)(((int)p + PTSIZE-1) & ~(PTSIZE-1)))
+#define FOURMEG 4194304
+#define FOURMB_PTE (PG_P | PG_RW | PG_SIZE)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MACHINE_H */
diff --git a/usr/src/psm/stand/boot/i386/common/mapfile b/usr/src/psm/stand/boot/i386/common/mapfile
new file mode 100644
index 0000000000..85a3c88c5d
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/mapfile
@@ -0,0 +1,28 @@
+#
+# Copyright 2005 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.
+#
+# 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"
+
+multiboot = LOAD ?RWX V0x1000000 P0x1000000 A0x1000;
+multiboot : ?A;
diff --git a/usr/src/psm/stand/boot/i386/common/memory.c b/usr/src/psm/stand/boot/i386/common/memory.c
new file mode 100644
index 0000000000..31857fb248
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/memory.c
@@ -0,0 +1,216 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * i86pc memory routines
+ *
+ * This file contains memory management routines to provide
+ * functionality found in proms on Sparc machines
+ */
+
+#include <sys/types.h>
+#include <sys/sysmacros.h>
+struct cpu; /* get around mmu.h warning */
+#include <sys/mmu.h>
+#include <sys/promif.h>
+#include <sys/memlist.h>
+#include "standalloc.h"
+#include "util.h"
+#include "machine.h"
+#include "debug.h"
+#include "cpu_id.h"
+
+/* These are the various memory lists in boot.c */
+extern struct memlist *pfreelistp, /* physmem available */
+ *vfreelistp, /* virtmem available */
+ *pinstalledp, /* physmem installed */
+ *pbooterp, /* booter occupied */
+ *pramdiskp; /* ramdisk memory */
+
+extern uint_t magic_phys;
+extern uint_t bpd_loc;
+extern int use_align;
+
+extern void start_paging(void);
+extern int map_phys(int, size_t, caddr_t, uint64_t);
+
+static int global_pages;
+static void fiximp(void);
+
+#define ALIGN(x, a) ((a) == 0 ? (intptr_t)(x) : \
+ (((intptr_t)(x) + (intptr_t)(a) - 1l) & ~((intptr_t)(a) - 1l)))
+
+#define MMU_L1_INDEX(a) (((uint_t)(a)) >> 22)
+#define MMU_L2_INDEX(a) ((((uint_t)(a)) >> 12) & 0x3ff)
+
+void
+init_paging(void)
+{
+ ptbl_t *pdp;
+ int mode;
+ struct memlist *entry;
+
+ fiximp(); /* figure out cpu capabilities */
+
+ /* allocate boot page table directory */
+ pdp = (ptbl_t *)resalloc(RES_BOOTSCRATCH, MMU_PAGESIZE, 0, 0);
+ if (pdp == (ptbl_t *)0) {
+ prom_panic("init_paging dir");
+ }
+ bpd_loc = (uint_t)pdp;
+ (void) bzero(pdp, MMU_PAGESIZE);
+
+ /* map in scratch memory */
+ mode = PG_P | PG_RW;
+ (void) map_phys(mode, magic_phys, 0, 0);
+
+ /* map in booter occupied memory */
+ entry = pbooterp;
+ while (entry) {
+ (void) map_phys(mode, (size_t)entry->size,
+ (caddr_t)entry->address, entry->address);
+ entry = entry->next;
+ }
+
+ /* map in ramdisk memory: disallow write */
+ entry = pramdiskp;
+ while (entry) {
+ (void) map_phys(PG_P, (size_t)entry->size,
+ (caddr_t)entry->address, entry->address);
+ entry = entry->next;
+ }
+
+ start_paging();
+ if (verbosemode)
+ printf("start paging\n");
+}
+
+static int
+map_4m_page(caddr_t vaddr, uint64_t paddr)
+{
+ ptbl_t *pdp = (ptbl_t *)bpd_loc;
+ uint_t pdir = MMU_L1_INDEX(vaddr);
+
+ if (pdp->page[pdir] & PG_P)
+ return (-1); /* already mapped */
+
+ /* don't set global flag for Pentium or earlier */
+ pdp->page[pdir] =
+ (FOURMB_PTE | ((uint_t)paddr & FOURMB_PAGEMASK));
+ if (global_pages)
+ pdp->page[pdir] |= PG_GLOBAL;
+
+ return (0);
+}
+
+static int
+map_4k_pages(int mode, size_t bytes, caddr_t vaddr, uint64_t paddr)
+{
+ ptbl_t *pdp, *ptp;
+ uint_t v, vaddr_end;
+
+ pdp = (ptbl_t *)bpd_loc;
+
+ v = (uint_t)vaddr;
+ vaddr_end = (v + bytes + MMU_PAGESIZE - 1) & MMU_STD_PAGEMASK;
+
+ while (v < vaddr_end) {
+ uint_t pdir = MMU_L1_INDEX(v);
+
+ if (pdp->page[pdir] & PG_P) {
+ ptp = (ptbl_t *)
+ ((uint_t)pdp->page[pdir] & MMU_STD_PAGEMASK);
+ } else {
+ /* allocate a new page table */
+ ptp = (ptbl_t *)resalloc(RES_BOOTSCRATCH,
+ MMU_PAGESIZE, 0, 0);
+ pdp->page[pdir] = ((uint_t)ptp | PG_P | PG_RW);
+ (void) bzero(ptp, MMU_PAGESIZE);
+ }
+
+ /* as long as we are on this page table */
+ while ((pdir == MMU_L1_INDEX(v)) && (v < vaddr_end)) {
+ uint_t pndx = MMU_L2_INDEX(v);
+ if (ptp->page[pndx] & PG_P) {
+ /*
+ * If we are already mapped, panic!
+ * This should not happen under the
+ * current memory allocation scheme
+ * where physmem is either mapped 1:1
+ * or mapped above kernelbase.
+ */
+ printf("remapping page at 0x%x\n", v);
+ prom_panic("remapping unsupported in booter");
+ ptp->page[pndx] |= mode;
+ } else {
+ ptp->page[pndx] =
+ (((uint_t)paddr & MMU_STD_PAGEMASK) | mode);
+ }
+ paddr += MMU_PAGESIZE;
+ v += MMU_PAGESIZE;
+ }
+ }
+
+ return (0);
+}
+
+int
+map_phys(int mode, size_t bytes, caddr_t vaddr, uint64_t paddr)
+{
+ if (paddr >> 32) /* don't handle PAE */
+ return (-1);
+
+ if (use_align && (bytes == FOURMB_PAGESIZE) &&
+ ((uint_t)vaddr & (FOURMB_PAGESIZE - 1)) == 0 &&
+ ((uint_t)paddr & (FOURMB_PAGESIZE - 1)) == 0)
+ return (map_4m_page(vaddr, paddr)); /* ignore mode */
+
+ if (mode == 0)
+ mode = PG_P | PG_RW;
+ return (map_4k_pages(mode, bytes, vaddr, paddr));
+}
+
+static void
+fiximp(void)
+{
+ /* need to support at least standard cpuid level 1 to continue */
+ (void) enable_cpuid();
+ if (max_std_cpuid_level < 1)
+ return;
+
+ use_align = largepage_supported();
+
+ if (use_align) {
+ (void) enable_large_pages();
+
+ global_pages = global_bit();
+ }
+
+ if (global_pages)
+ (void) enable_global_pages();
+}
diff --git a/usr/src/psm/stand/boot/i386/common/mkbin.c b/usr/src/psm/stand/boot/i386/common/mkbin.c
new file mode 100644
index 0000000000..423ecec781
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/mkbin.c
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ *
+ * 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 1994, 2002 Sun Microsystems, Inc.
+ * All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#undef _KERNEL
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/exechdr.h>
+#include <sys/elf.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int
+main(int argc, char **argv)
+{
+ int ofd,
+ ifd;
+ struct stat sbuf;
+ void * elffile;
+ unsigned int i,
+ total,
+ bytes;
+ Elf32_Ehdr *ehdr;
+ Elf32_Shdr *s;
+ Elf32_Shdr *first_shdr = NULL,
+ *nobits_shdr = NULL;
+
+ if (argc < 3) {
+ (void) printf("usage: mkbin elf_file binary_file \n");
+ exit(1);
+ }
+ if ((ifd = open(argv[1], O_RDONLY)) == -1) {
+ perror("open elf input");
+ exit(2);
+ }
+
+ if ((ofd = open(argv[2], O_RDWR | O_TRUNC | O_CREAT, 0777)) == -1) {
+ perror("open output binary");
+ exit(3);
+ }
+ if (fstat(ifd, &sbuf) == -1) {
+ perror("fstat");
+ exit(1);
+ }
+
+ /*
+ * mmap in the whole file to work with it.
+ */
+ if ((elffile = (void *)mmap(NULL, sbuf.st_size, PROT_READ,
+ MAP_PRIVATE, ifd, 0)) == MAP_FAILED) {
+ perror("mmap failed");
+ exit(1);
+ }
+ ehdr = (Elf32_Ehdr *)elffile;
+
+ if (*(int *)(ehdr->e_ident) != *(int *)(ELFMAG)) {
+ perror("not elf file ");
+ exit(5);
+ }
+
+ s = (Elf32_Shdr *)((char *)elffile + ehdr->e_shoff);
+ /*
+ * find a pointer to the first allocated section header
+ * and the bss(NOBITS) section header.
+ */
+ for (i = 0; i < ehdr->e_shnum; i++, s++) {
+ if (!(s->sh_flags & SHF_ALLOC))
+ continue;
+ if (!first_shdr) {
+ first_shdr = s;
+ continue;
+ }
+ if (s->sh_type == SHT_NOBITS) {
+ nobits_shdr = s;
+ break;
+ }
+ }
+
+ if ((first_shdr == NULL) || (nobits_shdr == NULL)) {
+ (void) fprintf(stderr, "ERROR: Missing headers in elf file.\n");
+ exit(1);
+ }
+
+ bytes = nobits_shdr->sh_offset - first_shdr->sh_offset;
+ if (write(ofd, (char *)elffile + first_shdr->sh_offset,
+ bytes) != bytes) {
+ perror("write sections");
+ exit(1);
+ }
+ total = bytes + nobits_shdr->sh_size;
+ /*
+ * round up to the next 512k block
+ */
+ if (total % 512 != 0)
+ total += 512 - (total % 512);
+
+ if (ftruncate(ofd, total) == -1) {
+ perror("ftruncate");
+ exit(1);
+ }
+
+ (void) close(ifd);
+ (void) close(ofd);
+ exit(0);
+}
diff --git a/usr/src/psm/stand/boot/i386/common/multiboot.c b/usr/src/psm/stand/boot/i386/common/multiboot.c
new file mode 100644
index 0000000000..618c3b7a1b
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/multiboot.c
@@ -0,0 +1,285 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * This program is loaded and executed by GRUB on x86 platforms.
+ * It is responsible for interpreting the miniroot archive
+ * loaded by GRUB, read unix and krtld, and jump to the kernel.
+ *
+ * Currently the kernel (_kobj_boot) expects a syscall vector,
+ * bootops, and elfbootvec. So we oblige by providing the
+ * same services for now.
+ */
+
+#include <sys/types.h>
+#include <sys/memlist.h>
+#include <sys/reboot.h>
+#include "multiboot.h"
+#include "debug.h"
+#include "standalloc.h"
+#include "bootprop.h"
+#include "util.h"
+#include "console.h"
+
+typedef int (*func_t)();
+extern void setup_bootops();
+extern void setup_memlists();
+extern void init_paging(void);
+extern int mountroot(char *);
+extern int openfile(char *, char *);
+extern int close(int);
+extern void console_init(char *);
+extern void kmem_init(void);
+extern void init_biosprog();
+extern func_t readfile(int fd, int print);
+extern void exitto(func_t);
+
+static void print_mbinfo(void);
+
+int debug;
+
+#define dprintf if (debug & D_MBOOT) printf
+
+multiboot_info_t *mbi;
+multiboot_header_t *mbh;
+void *elfbootvec; /* XXX dummy for 32-bit exitto */
+
+char *bootfile_prop = NULL;
+char *inputdevice_prop = NULL;
+char *outputdevice_prop = NULL;
+char *console_prop = NULL;
+
+extern uint_t bpd_loc;
+extern char *bootfile;
+extern char *module_path;
+extern int boot_verbose;
+int is_amd64;
+
+#ifdef BOOTAMD64
+extern void amd64_handoff(uint64_t);
+extern int amd64_config_cpu();
+
+int amd64_elf64;
+uint64_t elf64_go2;
+#endif /* BOOTAMD64 */
+
+extern int get_bootenv_props(void);
+extern void vga_probe(void);
+
+void
+main(ulong_t magic, ulong_t addr, ulong_t header)
+{
+ int fd;
+ char *grub_bootstr;
+ int (*entry)();
+
+ if (magic != MB_BOOTLOADER_MAGIC) {
+ /* printf isn't working, so we return to loader */
+ return;
+ }
+
+ /* Set MBI to the address of the Multiboot information structure. */
+ mbi = (multiboot_info_t *)addr;
+ mbh = (multiboot_header_t *)header;
+
+ grub_bootstr = (char *)mbi->cmdline;
+ console_init(grub_bootstr); /* so we can do printf */
+ kmem_init(); /* initialize memory allocator */
+ setup_memlists(); /* memory core for the allocator */
+
+ get_grub_bootargs(grub_bootstr); /* get grub cmd options */
+ if (debug & D_MBINFO)
+ print_mbinfo();
+ setup_bootops(); /* 32-bit memory ops and lists */
+ init_paging(); /* turn on paging to before loading kernel */
+
+ if (mountroot("boot") != 0) { /* mount the ramdisk */
+ panic("cannot mount boot archive\n");
+ } else if (verbosemode) {
+ printf("mountroot succeeded\n");
+ }
+
+ init_biosprog(); /* install bios service program */
+ get_bootenv_props(); /* read bootenv.rc properties */
+ vga_probe(); /* probe bios for vga */
+
+ /*
+ * Set console as per eeprom(1M) if not yet specified.
+ * May set graphics mode, for which bios support is required.
+ */
+ console_init2(inputdevice_prop, outputdevice_prop,
+ console_prop);
+
+#ifdef BOOTAMD64
+ /* Test to see if this CPU is an AMD64 */
+ is_amd64 = amd64_config_cpu();
+ if (verbosemode && is_amd64)
+ printf("cpu is amd64 capable\n");
+ if (is_amd64 == 0)
+ bsetprop(NULL, "CPU_not_amd64", "true", sizeof ("true"));
+#endif /* BOOTAMD64 */
+
+ /*
+ * Determine the boot file
+ * precedence given to what's specified via grub,
+ * fall back to boot-file property set by eeprom(1M).
+ * If boot-file not set, fall back to defaults
+ */
+ if (bootfile == NULL) {
+ get_eeprom_bootargs(bootfile_prop);
+ if (bootfile == NULL) {
+ bootfile = is_amd64 ?
+ "kernel/amd64/unix" : "kernel/unix";
+ }
+ }
+ setup_bootprop(); /* set up boot properties for the kernel */
+
+ printf("\n");
+ fd = openfile(bootfile, 0); /* open the kernel file */
+ if (fd == -1) {
+ panic("cannot open %s\n", bootfile);
+ } else {
+ extern char filename[];
+ (void) bsetprop(NULL, "whoami", filename, strlen(filename) + 1);
+ if (verbosemode)
+ printf("open kernel file: %s\n", filename);
+ }
+
+ entry = readfile(fd, verbosemode);
+ (void) close(fd);
+ if (module_path) {
+ (void) bsetprop(NULL, "module-path", module_path,
+ strlen(module_path) + 1);
+ if (verbosemode)
+ printf("module_path set to: %s\n", module_path);
+ }
+ if (entry == (int (*)())-1) {
+ panic("no entry point in %s\n", bootfile);
+ }
+
+#ifdef BOOTAMD64
+ if (amd64_elf64) {
+ if (verbosemode)
+ printf("Boot about to exit to AMD64 image at 0x%llx.\n",
+ (uint64_t)elf64_go2);
+ amd64_handoff(elf64_go2);
+ }
+#endif
+
+ if (verbosemode)
+ printf("Boot about to exit to 32-bit kernel image at 0x%x.\n",
+ entry);
+ exitto(entry);
+
+ panic("failed to boot %s\n", bootfile);
+}
+
+static void
+print_mbinfo(void)
+{
+ int tmp;
+
+ /* multiboot header */
+ printf("header_addr = 0x%x\n", mbh->header_addr);
+ printf("load_addr = 0x%x, end = 0x%x, bss_end = 0x%x\n",
+ mbh->load_addr, mbh->load_end_addr, mbh->bss_end_addr);
+ printf("entry_addr = 0x%x\n", mbh->entry_addr);
+
+ /* multiboot info location */
+ printf("mbi = 0x%x, size = 0x%x\n", mbi, sizeof (*mbi));
+
+ /* flags */
+ printf("flags = 0x%x\n", (unsigned)mbi->flags);
+
+ /* memory range */
+ if (MB_CHECK_FLAG(mbi->flags, 0))
+ printf("mem_lower = %uKB, mem_upper = %uKB\n",
+ (unsigned)mbi->mem_lower, (unsigned)mbi->mem_upper);
+
+ /* Is boot_device valid? */
+ if (MB_CHECK_FLAG(mbi->flags, 1)) {
+ tmp = ((mbi->boot_device >> 24) & 0xff);
+ printf("boot_device = 0x%x", tmp);
+ tmp = ((mbi->boot_device >> 16) & 0xff);
+ printf(", part1 = 0x%x", tmp);
+ tmp = ((mbi->boot_device >> 8) & 0xff);
+ printf(", part2 = 0x%x", tmp);
+ tmp = (mbi->boot_device & 0xff);
+ printf(", part3 = 0x%x\n", tmp);
+ }
+
+ /* Is the command line passed? */
+ if (MB_CHECK_FLAG(mbi->flags, 2))
+ printf("cmdline = %s\n", (char *)mbi->cmdline);
+
+ /* Are mods_* valid? */
+ if (MB_CHECK_FLAG(mbi->flags, 3)) {
+ mb_module_t *mod;
+ int i;
+
+ printf("mods_count = %d, mods_addr = 0x%x\n",
+ (int)mbi->mods_count, (int)mbi->mods_addr);
+ for (i = 0, mod = (mb_module_t *)mbi->mods_addr;
+ i < mbi->mods_count; i++, mod++) {
+ printf(
+ " mod_start = 0x%x, mod_end = 0x%x, string = %s\n",
+ (unsigned)mod->mod_start,
+ (unsigned)mod->mod_end, (char *)mod->string);
+ }
+ }
+
+ /* make sure we are not a.out */
+ if (MB_CHECK_FLAG(mbi->flags, 4)) {
+ printf("Bit 4 is set, we shouldn't be using a.out format.\n");
+ return;
+ }
+
+ /* Is the section header table of ELF valid? */
+ if (MB_CHECK_FLAG(mbi->flags, 5)) {
+ mb_elf_shtable_t *elf_sec = &(mbi->elf_sec);
+
+ printf("elf_sec: num = %u, size = 0x%x,"
+ " addr = 0x%x, shndx = 0x%x\n",
+ (unsigned)elf_sec->num, (unsigned)elf_sec->size,
+ (unsigned)elf_sec->addr, (unsigned)elf_sec->shndx);
+ }
+
+ /* print drives info */
+ if (MB_CHECK_FLAG(mbi->flags, 7)) {
+ printf("drives length %d, driver addr 0x%x\n",
+ mbi->drives_length, mbi->drives_addr);
+ }
+}
+
+/*ARGSUSED*/
+void
+trap(int trapno, int err)
+{
+ printf("trap type %d\n", trapno);
+ panic("unexpected trap in boot loader\n");
+}
diff --git a/usr/src/psm/stand/boot/i386/common/multiboot.h b/usr/src/psm/stand/boot/i386/common/multiboot.h
new file mode 100644
index 0000000000..2b2b1d01cf
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/multiboot.h
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _MULTIBOOT_H
+#define _MULTIBOOT_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Multiboot header must be present withing the first
+ * 8192 bytes of the elf executable. The flag bit fields
+ * are defined to request multiboot info from the boot
+ * loader (see struct multiboot_info below):
+ * flag[0] mem_upper, mem_loader
+ * flag[1] boot_device
+ * flag[2] cmdline (for launching kernel)
+ * flag[3] mods_count, mods_addr
+ * flag[4] symbol table for a.out
+ * flag[5] symbol table for elf
+ * flag[6] mmap_length, mmap_addr
+ * flag[7] drives_length, drivers_addr
+ * flag[8] config_table
+ * flag[9] boot_loader_name
+ * flag[10] apm_table
+ * flag[11] vbe_control_info
+ * vbe_mode_info
+ * vbe_mode
+ * vbe_interface_seg
+ * vbe_interface_off
+ * vbe_interface_len
+ */
+
+#define MB_HEADER_MAGIC 0x1BADB002 /* magic */
+#define MB_HEADER_FLAGS 0x00000003 /* flag */
+#define MB_HEADER_CHECKSUM -0x1BADB005 /* -(magic + flag) */
+
+/* passed by boot loader to kernel */
+#define MB_BOOTLOADER_MAGIC 0x2BADB002
+
+#define MB_NETWORK_DRIVE 0x20 /* not clear if part of spec */
+
+#define STACK_SIZE 0x4000
+
+#ifndef _ASM /* excluded from assembly routines */
+
+#include <sys/types.h>
+
+/* The Multiboot header. */
+typedef struct multiboot_header {
+ ulong_t magic;
+ ulong_t flags;
+ ulong_t checksum;
+ ulong_t header_addr;
+ ulong_t load_addr;
+ ulong_t load_end_addr;
+ ulong_t bss_end_addr;
+ ulong_t entry_addr;
+} multiboot_header_t;
+
+/* The section header table for ELF. */
+typedef struct mb_elf_shtable {
+ ulong_t num;
+ ulong_t size;
+ ulong_t addr;
+ ulong_t shndx;
+} mb_elf_shtable_t;
+
+/* The Multiboot information. */
+typedef struct multiboot_info {
+ ulong_t flags;
+ ulong_t mem_lower;
+ ulong_t mem_upper;
+ ulong_t boot_device;
+ ulong_t cmdline;
+ ulong_t mods_count;
+ ulong_t mods_addr;
+ mb_elf_shtable_t elf_sec;
+ ulong_t mmap_length;
+ ulong_t mmap_addr;
+ ulong_t drives_length; /* overload with dhcpack */
+ ulong_t drives_addr;
+ ulong_t config_table;
+ ulong_t boot_loader_name;
+ ulong_t apm_table;
+ ulong_t vbe_control_info;
+ ulong_t vbe_mode_info;
+ ushort_t vbe_mode;
+ ushort_t vbe_interface_seg;
+ ushort_t vbe_interface_off;
+ ushort_t vbe_interface_len;
+} multiboot_info_t;
+
+/* The module structure. */
+typedef struct mb_module {
+ ulong_t mod_start;
+ ulong_t mod_end;
+ ulong_t string;
+ ulong_t reserved;
+} mb_module_t;
+
+/*
+ * The memory map. Be careful that the offset 0 is base_addr_low
+ * but no size.
+ */
+typedef struct mb_memory_map {
+ ulong_t size;
+ ulong_t base_addr_low;
+ ulong_t base_addr_high;
+ ulong_t length_low;
+ ulong_t length_high;
+ ulong_t type;
+} mb_memory_map_t;
+
+/*
+ * netinfo for Solaris diskless booting
+ * XXX - not part of multiboot spec
+ */
+struct sol_netinfo {
+ uint8_t sn_infotype;
+ uint8_t sn_mactype;
+ uint8_t sn_maclen;
+ uint8_t sn_padding;
+ ulong_t sn_ciaddr;
+ ulong_t sn_siaddr;
+ ulong_t sn_giaddr;
+ ulong_t sn_netmask;
+ uint8_t sn_macaddr[1];
+};
+
+/* identify bootp/dhcp reply or rarp/ifconfig */
+#define SN_TYPE_BOOTP 2
+#define SN_TYPE_RARP 0xf0
+
+/* Check if the bit BIT in FLAGS is set. */
+#define MB_CHECK_FLAG(flags, bit) ((flags) & (1 << (bit)))
+
+#endif /* _ASM */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MULTIBOOT_H */
diff --git a/usr/src/psm/stand/boot/i386/common/serial.h b/usr/src/psm/stand/boot/i386/common/serial.h
new file mode 100644
index 0000000000..d63264fa74
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/serial.h
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ *
+ * 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 (c) 1997, Sun Microsystems, Inc. All Rights Reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* ---- ports on 16550 serial chips ---- */
+#define DAT 0 /* ... data */
+#define ICR 1 /* ... intr control reg */
+#define ISR 2 /* ... intr status reg */
+#define LCR 3 /* ... line control reg */
+#define MCR 4 /* ... modem control reg */
+#define LSR 5 /* ... line status reg */
+#define MSR 6 /* ... modem status reg */
+#define DLL 0 /* ... data latch low (used for baud rate) */
+#define DLH 1 /* ... data latch high (ditto) */
+#define FIFOR ISR /* ... fifo write reg */
+
+/* ---- convenant macros ---- */
+/* this macro uses the _chario_io_p structure */
+#define INB(a, off) \
+ (inb((a) + off))
+#define OUTB(a, off, val) \
+ (outb((a)+(off), (char)(val)))
+
+/* ---- LSR bits ---- */
+#define RCA 0x01 /* ... receive char avail */
+#define XHRE 0x20 /* ... xmit hold buffer empty */
+
+/* ---- Modem bits ---- */
+#define DTR 0x01
+#define RTS 0x02
+#define OUT2 0x08
+
+#define FIFO_ON 0x01
+#define FIFO_OFF 0x00
+#define FIFORXFLSH 0x02
+#define FIFOTXFLSH 0x04
+#define FIFODMA 0x08
+
+/* ---- LCR bits ---- */
+#define STOP1 00
+#define STOP2 0x04
+#define BITS5 0x00 /* 5 bits per char */
+#define BITS6 0x01 /* 6 bits per char */
+#define BITS7 0x02 /* 7 bits per char */
+#define BITS8 0x03 /* 8 bits per char */
+
+/* baud rate definitions */
+#define DLAB 0x80 /* divisor latch access bit */
+#define ASY110 1047 /* 110 baud rate for serial console */
+#define ASY150 768 /* 150 baud rate for serial console */
+#define ASY300 384 /* 300 baud rate for serial console */
+#define ASY600 192 /* 600 baud rate for serial console */
+#define ASY1200 96 /* 1200 baud rate for serial console */
+#define ASY2400 48 /* 2400 baud rate for serial console */
+#define ASY4800 24 /* 4800 baud rate for serial console */
+#define ASY9600 12 /* 9600 baud rate for serial console */
+#define ASY19200 6 /* 19200 baud rate for serial console */
+#define ASY38400 3 /* 38400 baud rate for serial console */
+#define ASY57600 2 /* 57600 baud rate for serial console */
+#define ASY115200 1 /* 115200 baud rate for serial console */
diff --git a/usr/src/psm/stand/boot/i386/common/standalloc.c b/usr/src/psm/stand/boot/i386/common/standalloc.c
new file mode 100644
index 0000000000..018625e773
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/standalloc.c
@@ -0,0 +1,481 @@
+/*
+ * 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.
+ *
+ * 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 2005 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/memlist.h>
+#include <sys/bootconf.h>
+#include "multiboot.h"
+#include "util.h"
+#include "standalloc.h"
+#include "debug.h"
+
+#define dprintf if (debug & D_ALLOC) printf
+
+/* memory lists */
+struct memlist *pinstalledp, *pfreelistp, *vfreelistp, *pbooterp;
+struct memlist *ppcimemp, *pramdiskp;
+
+extern multiboot_info_t *mbi;
+extern multiboot_header_t *mbh;
+extern int verbosemode;
+
+extern int map_phys(int, size_t, caddr_t, uint64_t);
+
+/* scratch memory */
+uint_t magic_phys = MAGIC_PHYS;
+uint_t lomem_phys = 0x1000000; /* try not to use memory below 16M */
+uint64_t scratchmem_start, scratchmem_end;
+uint64_t ramdisk_start, ramdisk_end;
+
+static void
+memlist_dump(struct memlist *listp)
+{
+ while (listp) {
+ dprintf("(0x%x%x, 0x%x%x)",
+ (int)(listp->address >> 32), (int)listp->address,
+ (int)(listp->size >> 32), (int)listp->size);
+ listp = listp->next;
+ }
+ dprintf("\n");
+}
+
+static struct memlist *
+memlist_alloc()
+{
+ return ((struct memlist *)bkmem_alloc(sizeof (struct memlist)));
+}
+
+static void
+memlist_free(struct memlist *buf)
+{
+ bkmem_free(buf, sizeof (struct memlist));
+}
+
+/* insert in the order of addresses */
+static void
+memlist_insert(struct memlist **listp, uint64_t addr, uint64_t size)
+{
+ struct memlist *entry;
+ struct memlist *prev = 0, *next;
+
+ /* find the location in list */
+ next = *listp;
+ while (next && next->address < addr) {
+ prev = next;
+ next = prev->next;
+ }
+
+ if (prev == 0) {
+ entry = memlist_alloc();
+ entry->address = addr;
+ entry->size = size;
+ entry->next = *listp;
+ *listp = entry;
+ return;
+ }
+
+ /* coalesce entries if possible */
+ if (addr == prev->address + prev->size) {
+ prev->size += size;
+ } else {
+ entry = memlist_alloc();
+ entry->address = addr;
+ entry->size = size;
+ entry->next = next;
+ prev->next = entry;
+ }
+}
+
+/* delet memory chunks, assuming list sorted by address */
+static int
+memlist_remove(struct memlist **listp, uint64_t addr, uint64_t size)
+{
+ struct memlist *entry;
+ struct memlist *prev = 0, *next;
+
+ /* find the location in list */
+ next = *listp;
+ while (next && (next->address + next->size < addr)) {
+ prev = next;
+ next = prev->next;
+ }
+
+ if (next == 0 || (addr < next->address)) {
+ dprintf("memlist_remove: addr 0x%x%x, size 0x%x%x"
+ " not contained in list\n",
+ (int)(addr >> 32), (int)addr,
+ (int)(size >> 32), (int)size);
+ memlist_dump(*listp);
+ return (-1);
+ }
+
+ if (addr > next->address) {
+ uint64_t oldsize = next->size;
+ next->size = addr - next->address;
+ if ((next->address + oldsize) > (addr + size)) {
+ entry = memlist_alloc();
+ entry->address = addr + size;
+ entry->size = next->address + oldsize - addr - size;
+ entry->next = next->next;
+ next->next = entry;
+ }
+ } else if ((next->address + next->size) > (addr + size)) {
+ /* addr == next->address */
+ next->address = addr + size;
+ next->size -= size;
+ } else {
+ /* the entire chunk is deleted */
+ if (prev == 0) {
+ *listp = next->next;
+ } else {
+ prev->next = next->next;
+ }
+ memlist_free(next);
+ }
+
+ return (0);
+}
+
+/*
+ * find and claim a memory chunk of given size, bypassing
+ * scratch memory + room below 8MB
+ */
+static uint64_t
+memlist_find(struct memlist **listp, uint_t size, int align)
+{
+ uint_t delta;
+ uint64_t paddr;
+ struct memlist *prev = 0, *next;
+
+ /* find the chunk with sufficient size */
+ next = *listp;
+ while (next &&
+ (next->address < lomem_phys || (next->size < size + align - 1))) {
+ prev = next;
+ next = prev->next;
+ }
+
+ if (next == NULL)
+ return (0);
+
+ paddr = next->address;
+ delta = (uint_t)paddr & (align - 1);
+ if (delta)
+ paddr += align - delta;
+ (void) memlist_remove(listp, paddr, size);
+ return (paddr);
+}
+
+static void
+memlists_print()
+{
+ printf("Installed physical memory:\n");
+ memlist_dump(pinstalledp);
+ printf("BIOS reserved physical memory:\n");
+ memlist_dump(ppcimemp);
+ printf("Booter occupied memory (including modules):\n");
+ memlist_dump(pbooterp);
+ printf("Ramdisk memory:\n");
+ memlist_dump(pramdiskp);
+ printf("Available physical memory:\n");
+ memlist_dump(pfreelistp);
+ printf("Available virtual memory:\n");
+ memlist_dump(vfreelistp);
+}
+
+void
+setup_memlists(void)
+{
+ int i;
+ uint64_t address, size;
+ mb_memory_map_t *mmap;
+ mb_module_t *mod;
+ struct memlist *entry;
+
+ /*
+ * initialize scratch memory so we can call bkmem_alloc
+ * to get memory for keeping track of memory lists
+ */
+ reset_alloc();
+
+ /*
+ * initialize RAM list (pinstalledp) and available pci memory
+ * PCI memory excludes memory below 1M (realmode)
+ */
+ memlist_insert(&ppcimemp, 0x100000, 0xFFF00000ULL);
+ for (mmap = (mb_memory_map_t *)mbi->mmap_addr;
+ (unsigned long) mmap < mbi->mmap_addr + mbi->mmap_length;
+ mmap = (mb_memory_map_t *)((unsigned long)mmap
+ + mmap->size + sizeof (mmap->size))) {
+ address = ((uint64_t)mmap->base_addr_high << 32) +
+ (uint64_t)mmap->base_addr_low;
+ size = ((uint64_t)mmap->length_high << 32) +
+ (uint64_t)mmap->length_low;
+
+ switch (mmap->type) {
+ case 1: /* RAM */
+ memlist_insert(&pinstalledp, address, size);
+ memlist_insert(&pfreelistp, address, size);
+ /*FALLTHROUGH*/
+ default: /* Take out of available pci memory space */
+ memlist_remove(&ppcimemp, address, size);
+ break;
+ }
+ }
+
+ /*
+ * initialize memory occupied by the booter
+ * make the boundary page aligned to simplify
+ * MMU stuff
+ */
+ address = rounddown(mbh->load_addr, PAGESIZE);
+ size = roundup(mbh->bss_end_addr, PAGESIZE) -
+ rounddown(mbh->load_addr, PAGESIZE);
+ memlist_insert(&pbooterp, address, size);
+
+ /* where the modules are in memory */
+ for (i = 0, mod = (mb_module_t *)mbi->mods_addr;
+ i < mbi->mods_count; i++, mod++) {
+ /* round up to page boundaries */
+ address = rounddown(mod->mod_start, PAGESIZE);
+ size = roundup(mod->mod_end, PAGESIZE) -
+ rounddown(mod->mod_start, PAGESIZE);
+
+ /* assume first one is ramdisk */
+ if (ramdisk_end == 0) {
+ ramdisk_start = mod->mod_start;
+ ramdisk_end = mod->mod_end;
+ if (verbosemode) {
+ printf("ramdisk is at 0x%llx-0x%llx\n",
+ ramdisk_start, ramdisk_end);
+ }
+ memlist_insert(&pramdiskp, address, size);
+ } else {
+ memlist_insert(&pbooterp, address, size);
+ }
+ }
+
+ /* delete booter memory from pfreelistp */
+ entry = pbooterp;
+ while (entry) {
+ address = entry->address;
+ size = entry->size;
+ (void) memlist_remove(&pfreelistp, address, size);
+ entry = entry->next;
+ }
+
+ /* delete ramdisk memory */
+ entry = pramdiskp;
+ while (entry) {
+ address = entry->address;
+ size = entry->size;
+ (void) memlist_remove(&pfreelistp, address, size);
+ entry = entry->next;
+ }
+
+ /*
+ * initialize free virtual memory list
+ * start withe the entire range
+ * delete booter memory
+ */
+ memlist_insert(&vfreelistp, 0, 0x100000000LL);
+ entry = pbooterp;
+ while (entry) {
+ address = entry->address;
+ size = entry->size;
+ (void) memlist_remove(&vfreelistp, address, size);
+ entry = entry->next;
+ }
+
+ if (debug & D_ALLOC)
+ memlists_print();
+}
+
+/* resource allocate routines */
+void
+reset_alloc(void)
+{
+ if (verbosemode)
+ printf("initialize scratch memory \n");
+
+ /* reclaim existing scratch memory */
+ if (scratchmem_end > scratchmem_start) {
+ memlist_insert(&pfreelistp, scratchmem_start,
+ (uint64_t)magic_phys - scratchmem_start);
+ }
+
+ /* start allocating at 1MB */
+ scratchmem_end = scratchmem_start = 0x100000;
+}
+
+/*
+ * allocate memory with an identical physical and virtual address
+ */
+caddr_t
+idmap_mem(uint32_t virthint, size_t bytes, int align)
+{
+ caddr_t addr = 0;
+
+ /* sanity checks */
+ if (bytes == 0)
+ return ((caddr_t)0);
+
+ if (virthint == 0) {
+ addr = (caddr_t)memlist_find(&pfreelistp, bytes, align);
+ } else if (memlist_remove(
+ &pfreelistp, (uint64_t)virthint, (uint64_t)bytes) == 0) {
+ addr = (caddr_t)virthint;
+ }
+
+ if (addr == 0) {
+ printf("idmap_mem: failed to find phys 0x%x bytes at 0x%x\n",
+ bytes, virthint);
+ return (0);
+ }
+
+ /*
+ * For any piece of low (< kernelbase) physical memory, we
+ * either map it 1:1 or map it above kernelbase. Hence, the
+ * corresponding virtual memory is always available by design.
+ */
+ if (memlist_remove(&vfreelistp, (uint64_t)addr, (uint64_t)bytes) != 0) {
+ printf("idmap_mem: failed to find virtual 0x%x bytes at 0x%x\n",
+ bytes, addr);
+ (void) memlist_insert(&pfreelistp, (uint64_t)addr,
+ (uint64_t)bytes);
+ return (0);
+ }
+
+ if (map_phys(0, bytes, addr, (uint64_t)addr) == -1) {
+ printf("idmap_mem: failed to 1:1 map 0x%x bytes at 0x%x\n",
+ bytes, addr);
+ (void) memlist_insert(&pfreelistp, (uint64_t)addr,
+ (uint64_t)bytes);
+ (void) memlist_insert(&vfreelistp, (uint64_t)addr,
+ (uint64_t)bytes);
+ return (0);
+ }
+
+ return (addr);
+}
+
+/*
+ * allocate memory with a physical mapping
+ */
+/*ARGSUSED*/
+caddr_t
+phys_alloc_mem(size_t bytes, int align)
+{
+ /* sanity checks */
+ if (bytes == 0)
+ return ((caddr_t)0);
+
+ return ((caddr_t)memlist_find(&pfreelistp, bytes, align));
+}
+
+/*ARGSUSED*/
+caddr_t
+resalloc(enum RESOURCES type, size_t bytes, caddr_t virthint, int align)
+{
+ uint_t delta;
+ caddr_t vaddr;
+ uint64_t paddr;
+
+ /* sanity checks */
+ if (bytes == 0)
+ return ((caddr_t)0);
+
+ if (scratchmem_end == 0)
+ prom_panic("scratch memory uninitialized\n");
+
+ switch (type) {
+ case RES_BOOTSCRATCH:
+
+ /* scratch memory */
+ vaddr = (caddr_t)scratchmem_end;
+ bytes = roundup(bytes, PAGESIZE);
+ scratchmem_end += bytes;
+ if (scratchmem_end > magic_phys)
+ prom_panic("scratch memory overflow!");
+ return (vaddr);
+ /*NOTREACHED*/
+
+ case RES_CHILDVIRT:
+
+ /* program memory */
+
+ delta = (uint_t)virthint & (PAGESIZE - 1);
+ if (delta)
+ goto fail; /* not page aligned */
+
+ vaddr = virthint - delta;
+ bytes += delta;
+ bytes = roundup(bytes, PAGESIZE);
+
+ if (memlist_remove(&vfreelistp,
+ (uint64_t)vaddr, (uint64_t)bytes))
+ goto fail; /* virtual memory not available */
+ if (align == 0)
+ align = 1;
+ paddr = memlist_find(&pfreelistp, bytes, align);
+ if (paddr == -1)
+ goto fail; /* out of physical memory */
+ if (map_phys(0, bytes, vaddr, paddr) == -1)
+ goto fail;
+ return (vaddr);
+ /*NOTREACHED*/
+ }
+
+fail:
+ dprintf("resalloc of 0x%x bytes at 0x%x failed", bytes, virthint);
+ return (0);
+}
+
+void
+resfree(caddr_t addr, size_t bytes)
+{
+ /* scratch memory is freed one one shot */
+ if ((uint_t)addr < magic_phys)
+ return;
+ dprintf("resfree: 0x%x 0x%x not implemented\n", addr, bytes);
+}
+
+int
+get_progmemory(caddr_t vaddr, size_t size, int align)
+{
+ uint_t n = (uint_t)vaddr & (PAGESIZE - 1);
+
+ if (n) {
+ vaddr -= n;
+ size += n;
+ }
+
+ if (resalloc(RES_CHILDVIRT, size, vaddr, align) != vaddr)
+ return (-1);
+ return (0);
+}
diff --git a/usr/src/psm/stand/boot/i386/common/standalloc.h b/usr/src/psm/stand/boot/i386/common/standalloc.h
new file mode 100644
index 0000000000..ee99de104b
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/standalloc.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, Version 1.0 only
+ * (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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_STANDALLOC_H
+#define _SYS_STANDALLOC_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/saio.h>
+
+#define NULL 0
+#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
+#define rounddown(x, y) (((x)/(y))*(y))
+
+/* backing resources for memory allocation */
+caddr_t resalloc(enum RESOURCES type, size_t, caddr_t, int);
+void resfree(caddr_t, size_t);
+void reset_alloc(void);
+
+/* memory allocation */
+void *bkmem_alloc(size_t);
+void *bkmem_zalloc(size_t);
+void bkmem_free(void *, size_t);
+int get_progmemory(caddr_t, size_t, int);
+void *vmx_zalloc_identity(size_t);
+
+/*
+ * BOPF_X86_ALLOC_IDMAP: identical virtual/physical address
+ * BOPF_X86_ALLOC_PHYS: physical address
+ */
+caddr_t idmap_mem(uint32_t, size_t, int);
+caddr_t phys_alloc_mem(size_t, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_STANDALLOC_H */
diff --git a/usr/src/psm/stand/boot/i386/common/util.h b/usr/src/psm/stand/boot/i386/common/util.h
new file mode 100644
index 0000000000..35e8fda205
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/util.h
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _STRINGS_H
+#define _STRINGS_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <sys/varargs.h>
+#include <sys/promif.h>
+
+/*
+ * This header file contains most of the libc-like interfaces
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void bzero(void *, size_t);
+extern void bcopy(const void *, void *, size_t);
+extern uint_t strlen(const char *);
+extern int strcmp(const char *, const char *);
+extern int strncmp(const char *, const char *, size_t);
+extern char *strcat(char *, const char *);
+extern char *strcpy(char *, const char *);
+extern char *strrchr(const char *, int);
+extern char *strstr(const char *, const char *);
+
+extern void printf(const char *, ...);
+extern void panic(const char *, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STRINGS_H */
diff --git a/usr/src/psm/stand/boot/i386/common/vga.c b/usr/src/psm/stand/boot/i386/common/vga.c
new file mode 100644
index 0000000000..c9b0f30443
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/vga.c
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Miniature VGA driver for bootstrap.
+ */
+
+#include <sys/archsystm.h>
+#include <sys/vgareg.h>
+#include "vga.h"
+
+#define VGA_COLOR_CRTC_INDEX 0x3d4
+#define VGA_COLOR_CRTC_DATA 0x3d5
+#define VGA_SCREEN ((unsigned short *)0xb8000)
+
+static void vga_set_crtc(int index, unsigned char val);
+static unsigned char vga_get_crtc(int index);
+
+void
+vga_clear(int color)
+{
+ unsigned short val;
+ int i;
+
+ val = (color << 8) | ' ';
+
+ for (i = 0; i < VGA_TEXT_ROWS * VGA_TEXT_COLS; i++) {
+ VGA_SCREEN[i] = val;
+ }
+}
+
+void
+vga_drawc(int c, int color)
+{
+ int row;
+ int col;
+
+ vga_getpos(&row, &col);
+ VGA_SCREEN[row*VGA_TEXT_COLS + col] = (color << 8) | c;
+}
+
+void
+vga_scroll(int color)
+{
+ unsigned short val;
+ int i;
+
+ val = (color << 8) | ' ';
+
+ for (i = 0; i < (VGA_TEXT_ROWS-1)*VGA_TEXT_COLS; i++) {
+ VGA_SCREEN[i] = VGA_SCREEN[i + VGA_TEXT_COLS];
+ }
+ for (; i < VGA_TEXT_ROWS * VGA_TEXT_COLS; i++) {
+ VGA_SCREEN[i] = val;
+ }
+}
+
+void
+vga_setpos(int row, int col)
+{
+ int off;
+
+ off = row * VGA_TEXT_COLS + col;
+ vga_set_crtc(VGA_CRTC_CLAH, off >> 8);
+ vga_set_crtc(VGA_CRTC_CLAL, off & 0xff);
+}
+
+void
+vga_getpos(int *row, int *col)
+{
+ int off;
+
+ off = (vga_get_crtc(VGA_CRTC_CLAH) << 8) +
+ vga_get_crtc(VGA_CRTC_CLAL);
+ *row = off / VGA_TEXT_COLS;
+ *col = off % VGA_TEXT_COLS;
+}
+
+static void
+vga_set_crtc(int index, unsigned char val)
+{
+ outb(VGA_COLOR_CRTC_INDEX, index);
+ outb(VGA_COLOR_CRTC_DATA, val);
+}
+
+
+static unsigned char
+vga_get_crtc(int index)
+{
+ outb(VGA_COLOR_CRTC_INDEX, index);
+ return (inb(VGA_COLOR_CRTC_DATA));
+}
diff --git a/usr/src/psm/stand/boot/i386/common/vga.h b/usr/src/psm/stand/boot/i386/common/vga.h
new file mode 100644
index 0000000000..ec7fd2c371
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/vga.h
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _VGA_H
+#define _VGA_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Interface to the bootstrap's internal VGA driver.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define VGA_IO_WMR 0x3C8 /* vga io DAC write mode register */
+#define VGA_IO_DR 0x3C9 /* vga io DAC data register */
+#define VGA_IO_IS 0x3DA /* vga io input status register */
+
+#define VGA_TEXT_COLS 80
+#define VGA_TEXT_ROWS 25
+
+extern void vga_setpos(int, int);
+extern void vga_getpos(int *, int *);
+extern void vga_clear(int);
+extern void vga_scroll(int);
+extern void vga_drawc(int, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VGA_H */
diff --git a/usr/src/psm/stand/boot/i386/common/vgaprobe.c b/usr/src/psm/stand/boot/i386/common/vgaprobe.c
new file mode 100644
index 0000000000..833c6014f6
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/common/vgaprobe.c
@@ -0,0 +1,204 @@
+/*
+ * 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.
+ *
+ * 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 2005 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/controlregs.h>
+#include <sys/bootconf.h>
+#include <sys/bootvfs.h>
+#include <sys/psw.h>
+#include "multiboot.h"
+#include "bootprop.h"
+#include "biosint.h"
+#include "machine.h"
+#include "standalloc.h"
+#include "console.h"
+#include "util.h"
+#include "debug.h"
+
+#define FP_SEG(fp) ((((unsigned long)(fp)) >> 16) & 0xffff)
+#define FP_OFF(fp) (((unsigned long)(fp)) & 0xffff)
+
+#define VESABIOS_SUPP_FUNC 0x4f
+#define VESABIOS_DISPLAY_ID_EXT 0x15
+
+#pragma pack(1)
+/*
+ * Structure returned by monitors that support VESA DDC
+ */
+struct EDIFinfo {
+ unsigned char hdr[8];
+ unsigned short mfname; /* EISA style compressed id */
+ unsigned short pid;
+ unsigned long serialno;
+ char mfweek;
+ unsigned char mfyear;
+ unsigned char edidver;
+ unsigned char edidrev;
+ unsigned char vidindef;
+ unsigned char maxHimagesz; /* cm */
+ unsigned char maxVimagesz; /* cm */
+ unsigned char displayxferchar;
+ unsigned char DPMSfeat;
+ unsigned char RGlowbits;
+ unsigned char BWlowbits;
+ unsigned char redx;
+ unsigned char redy;
+ unsigned char greenx;
+ unsigned char greeny;
+ unsigned char bluex;
+ unsigned char bluey;
+ unsigned char whitex;
+ unsigned char whitey;
+ unsigned char esttimings1;
+ unsigned char esttimings2;
+ unsigned char rsvdtimings;
+ short stdtimingid1;
+ short stdtimingid2;
+ short stdtimingid3;
+ short stdtimingid4;
+ short stdtimingid5;
+ short stdtimingid6;
+ short stdtimingid7;
+ short stdtimingid8;
+ unsigned char dettimingdesc1[18];
+ unsigned char dettimingdesc2[18];
+ unsigned char dettimingdesc3[18];
+ unsigned char dettimingdesc4[18];
+ unsigned char extflg;
+ unsigned char chksum;
+};
+#pragma pack()
+
+/*
+ * Address at which we can read/write a structure
+ * in common with the bios.
+ *
+ * Current memory layout:
+ * 1mb: multiboot
+ * 0x6000: our scratch memory
+ * 0x5000: stack, grows downward
+ * 0x2000: biosint
+ * 0x1000: bios
+ */
+#define LOMEM_SCRATCH_ADDR 0x6000
+
+
+#define dprintf if (debug & D_BIOS) printf
+
+int (*bios_doint)(int, struct int_pb *);
+
+
+static const char hextab[] = "0123456789ABCDEF";
+
+static void
+DecompressName(unsigned long id, char *np)
+{
+ /*
+ * Expand an EISA device name
+ *
+ * This converts a 32-bit EISA device "id" to a
+ * 7-byte ASCII device name, which is stored at "np".
+ */
+
+ *np++ = '@' + ((id >> 2) & 0x1F);
+ *np++ = '@' + ((id << 3) & 0x18) + ((id >> 13) & 0x07);
+ *np++ = '@' + ((id >> 8) & 0x1F);
+ *np++ = hextab[(id >> 20) & 0x0F];
+ *np++ = hextab[(id >> 16) & 0x0F];
+ *np++ = hextab[(id >> 28) & 0x0F];
+ *np++ = hextab[(id >> 24) & 0x0F];
+ *np = 0;
+}
+
+void
+vga_probe(void)
+{
+ int ret;
+ struct int_pb ic = {0};
+ char *fp;
+ char name[8];
+ struct EDIFinfo *edifp = (struct EDIFinfo *)LOMEM_SCRATCH_ADDR;
+
+ /*
+ * See what level of VESA DDC is supported (if any)
+ */
+ ic.ax = (VESABIOS_SUPP_FUNC << 8) | VESABIOS_DISPLAY_ID_EXT;
+ ic.bx = 0x00; /* Report DDC Capcbilities */
+ ic.cx = 0;
+ ic.dx = 0;
+ ic.es = 0;
+ ic.dx = 0;
+ ret = bios_doint(0x10, &ic);
+ dprintf("vga probe report ddc: ret=%0x ax=0x%x dx=0x%x\n",
+ ret, ic.ax, ic.dx);
+ if (!(ret & PS_C) && (ic.ax & 0xff) == VESABIOS_SUPP_FUNC) {
+ /*
+ * BIOS supports VBE/DDC extension
+ */
+ if (ic.bx & 0x03) { /* DDC1 or DDC2 supported */
+ unsigned long mfn, compid;
+
+ /*
+ * Get VESA DDC EDIF info
+ */
+ edifp->edidver = 0;
+ ic.ax = (VESABIOS_SUPP_FUNC << 8) |
+ VESABIOS_DISPLAY_ID_EXT;
+ ic.bx = 0x01; /* Read EDID */
+ ic.cx = 0;
+ ic.dx = 0;
+ fp = (char *)edifp;
+ ic.es = FP_SEG(fp);
+ ic.di = FP_OFF(fp);
+ dprintf("addr 0x%x, seg 0x%x, off 0x%x\n",
+ fp, FP_SEG(fp), FP_OFF(fp));
+
+ ret = bios_doint(0x10, &ic);
+ dprintf(
+ "vga probe read edid: ret=%0x ax=0x%x dx=0x%x\n",
+ ret, ic.ax, ic.dx);
+ if (!(ret & PS_C) && edifp->edidver != 0) {
+ dprintf("display-edif-block: len %d\n",
+ sizeof (struct EDIFinfo));
+ (void) bsetprop(NULL, "display-edif-block",
+ edifp, sizeof (struct EDIFinfo));
+ /*
+ * Set edif id as a property
+ */
+ mfn = (long)edifp->mfname;
+ compid = (long)edifp->pid << 24 | mfn |
+ ((long)(edifp->pid & 0xff00) << 8);
+ DecompressName(compid, name);
+ dprintf("display-edif-id: %s\n", name);
+ (void) bsetprop(NULL, "display-edif-id",
+ name, strlen(name) + 1);
+ }
+ }
+ }
+}
diff --git a/usr/src/psm/stand/boot/i386/i86pc/Makefile b/usr/src/psm/stand/boot/i386/i86pc/Makefile
new file mode 100644
index 0000000000..672e381b2c
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/i86pc/Makefile
@@ -0,0 +1,52 @@
+#
+# 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.
+#
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+
+TOPDIR = ../../../../..
+PLATFORM = i86pc
+KARCH = $(PLATFORM)
+ARCHVERS =
+ARCHOPTS = -Di386 -D__i386 -DI386BOOT -DBOOTAMD64 -D_ELF64_SUPPORT
+ARCHOPTS += -DMULTIBOOT
+
+PLAT_C_SRC =
+ARCH_C_SRC =
+ARCH_S_SRC = cpu_id.s idttab.s samuldiv64.s
+START_S_SRC = asm.s
+BIOS_S_SRC = biosint.s
+
+TOOLSRC = $(TOPDIR)/tools
+
+include ../Makefile.com
+
+$(ROOT_PSM_UNIBOOT):= OWNER= root
+$(ROOT_PSM_UNIBOOT):= GROUP= sys
+$(ROOT_PSM_UNIBOOT):= FILEMODE= 755
+
+$(ROOT_PSM_BIOSINT):= OWNER= root
+$(ROOT_PSM_BIOSINT):= GROUP= sys
+$(ROOT_PSM_BIOSINT):= FILEMODE= 755
diff --git a/usr/src/psm/stand/boot/i386/i86pc/asm.s b/usr/src/psm/stand/boot/i386/i86pc/asm.s
new file mode 100644
index 0000000000..7c4e5e9bb6
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/i86pc/asm.s
@@ -0,0 +1,329 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved. */
+/* Use is subject to license terms. */
+
+#if defined(lint)
+
+#include <sys/types.h>
+#include <sys/bootconf.h>
+
+extern void printf(const char *, ...);
+
+uint_t bpd_loc;
+struct bootops *bop;
+
+void start(void) { main(0, 0, 0); }
+void start_paging(void) { return; }
+void halt(char *msg) { printf("%s", msg); }
+void exitto(int (*entrypoint)()) {}
+void reset(void);
+
+/* lint for inline functions in i86.il */
+/*ARGSUSED*/
+uint8_t inb(int port) { return (*(uint8_t *)port); }
+uint16_t inw(int port) { return (*(uint16_t *)port); }
+uint32_t inl(int port) { return (*(uint32_t *)port); }
+void outb(int port, uint8_t v) { *(uint8_t *)port = v; }
+void outw(int port, uint16_t v) { *(uint16_t *)port = v; }
+void outl(int port, uint32_t v) { *(uint32_t *)port = v; }
+
+#else
+
+.ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/asm_linkage.h>
+#include <sys/controlregs.h>
+#include <sys/segment.h>
+#include "../common/multiboot.h"
+
+.file "asm.s"
+.text
+
+.globl _start
+_start:
+ jmp multiboot_entry
+
+/*
+ * The following header must be present within the first 8K of
+ * the binary, according to the Multiboot Specification
+ */
+.align 4
+
+multiboot_header:
+ .long MB_HEADER_MAGIC / multiboot magic
+ .long MB_HEADER_FLAGS / flags
+ .long MB_HEADER_CHECKSUM / checksum
+ .long multiboot_header / header address
+ .long _start / load start addr
+ .long _edata / load end addr
+ .long _end / bss end
+ .long multiboot_entry / entry addr
+
+/*
+ * Start from where GRUB left off. The processor state is
+ * as defined in the Multiboot Specification. We start with:
+ * - initialize the stack, "stack" is declared at the end of file
+ * - push register contents to stack to pass multiboot info
+ * - initialize GDT and (a dummy) IDT
+ * - call main() to load the kernel
+ */
+multiboot_entry:
+ movl $[stack + STACK_SIZE], %esp
+ pushl $0 / reset flags
+ popf
+
+ push $0 / terminate debugger
+ push $0
+ movl %esp, %ebp
+
+ movl $[multiboot_header], %ecx
+ pushl %ecx / multiboot header
+ pushl %ebx / multiboot info
+ pushl %eax / multiboot magic
+
+ lgdt gdtdesc / load gdt
+ mov $0x08, %eax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+ ljmp $0x10, $newgdt
+newgdt:
+
+ movl $slbidt, %eax / load idt
+ movl $0x7ff, %ecx
+ call munge_table
+ lidt IDTptr
+
+ call main / invoke the kernel
+ hlt / shouldn't get here
+
+/ help function
+.globl halt
+halt:
+ pushl $halt_message / halt
+ call printf / defined in kernel
+loop1:
+ hlt
+ jmp loop1
+
+halt_message:
+ .string "Halted."
+
+/ turn on paging
+ ENTRY(start_paging)
+ movl bpd_loc, %eax
+ movl %eax, %cr3
+
+ movl %cr0, %eax
+ orl $[CR0_PG|CR0_PE], %eax
+ movl %eax, %cr0
+
+ jmp page_flush / flush the prefetch queue
+page_flush:
+ nop
+ nop
+ ret
+ SET_SIZE(start_paging)
+
+/ exitto 32-bit kernel
+ ENTRY(exitto)
+ push %ebp / save stack
+ mov %esp, %ebp
+ pushal / protect secondary boot
+
+ movl %esp, %eax
+ movl %eax, save_esp2
+
+ movl $elfbootvec, %eax
+ pushl (%eax)
+
+ movl $bop, %eax
+ movl (%eax), %ebx
+ pushl %ebx
+
+ pushl $0 / no debug vector
+
+ movl $sysp, %eax
+ movl (%eax), %ecx
+ pushl %ecx
+
+ movl 8(%ebp), %eax
+ call *%eax / jump to the kernel
+
+ movl save_esp2, %eax
+ movl %eax, %esp
+
+ popal
+ pop %ebp / restore frame pointer
+ ret
+ SET_SIZE(exitto)
+
+/********************************************************************** */
+/**/
+/* munge_table: */
+/* This procedure will 'munge' a descriptor table to */
+/* change it from initialized format to runtime format. */
+/**/
+/* Assumes: */
+/* %eax -- contains the base address of table. */
+/* %ecx -- contains size of table. */
+/**/
+/* ********************************************************************* */
+ ENTRY(munge_table)
+
+ addl %eax, %ecx /* compute end of IDT array */
+ movl %eax, %esi /* beginning of IDT */
+
+moretable:
+ cmpl %esi, %ecx
+ jl donetable /* Have we done every descriptor?? */
+
+ movl %esi, %ebx /*long-vector/*short-selector/*char-rsrvd/*char-
+type */
+
+ movb 7(%ebx), %al /* Find the byte containing the type field */
+ testb $0x10, %al /* See if this descriptor is a segment */
+ jne notagate
+ testb $0x04, %al /* See if this destriptor is a gate */
+ je notagate
+ /* Rearrange a gate descriptor. */
+ movl 4(%ebx), %edx /* Selector, type lifted out. */
+ movw 2(%ebx), %ax /* Grab Offset 16..31 */
+ movl %edx, 2(%ebx) /* Put back Selector, type */
+ movw %ax, 6(%ebx) /* Offset 16..31 now in right place */
+ jmp descdone
+
+notagate: /* Rearrange a non gate descriptor. */
+ movw 4(%ebx), %dx /* Limit 0..15 lifted out */
+ movw 6(%ebx), %ax /* acc1, acc2 lifted out */
+ movb %ah, 5(%ebx) /* acc2 put back */
+ movw 2(%ebx), %ax /* 16-23, 24-31 picked up */
+ movb %al, 7(%ebx) /* 24-31 put back */
+ movb %ah, 4(%ebx) /* 16-23 put back */
+ movw (%ebx), %ax /* base 0-15 picked up */
+ movw %ax, 2(%ebx) /* base 0-15 put back */
+ movw %dx, (%ebx) /* lim 0-15 put back */
+
+descdone:
+ addl $8, %esi /* Go for the next descriptor */
+ jmp moretable
+
+donetable:
+ ret
+ SET_SIZE(munge_table)
+
+/ reset machine via triple fault
+ ENTRY(reset)
+ movw $0, IDTlimit / generate faulty table
+ lidt IDTptr / load faulty table
+ int $10 / trigger an interrupt
+ SET_SIZE(reset)
+
+/ Data definitions
+.align 4
+.globl bpd_loc
+bpd_loc:
+ .long 0
+.globl save_esp2
+save_esp2:
+ .long 0
+.globl save_esp
+save_esp:
+ .long 0
+.globl bop
+bop:
+ .long 0
+IDTptr:
+IDTlimit:
+ .value 0x7ff
+IDTbase:
+ .long slbidt
+
+.align 4
+gdt_start:
+ .long 0
+ .long 0
+
+flatdesc: / offset = 0x08 (GDT_BOOTFLAT << 3)
+
+ .value 0xFFFF / segment limit 0..15
+ .value 0x0000 / segment base 0..15
+ .byte 0x0 / segment base 16..23; set for 0K
+ .byte 0x92 / flags; A=0, Type=001, DPL=00, P=1
+ / Present expand down
+ .byte 0xCF / flags; Limit (16..19)=1111, AVL=0, G=1, B=1
+ .byte 0x0 / segment base 24..32
+
+codedesc: / offset = 0x10 (GDT_CODESEL << 3)
+
+ .value 0xFFFF / segment limit 0..15
+ .value 0x0000 / segment base 0..15
+ .byte 0x0 / segment base 16..23; set for 0k
+ .byte 0x9E / flags; A=0, Type=111, DPL=00, P=1
+ .byte 0xCF / flags; Limit (16..19)=1111, AVL=0, G=1, D=1
+ .byte 0x0 / segment base 24..32
+
+code16desc: / offset = 0x18
+
+ .value 0xFFFF / segment limit 0..15
+ .value 0x0000 / segment base 0..15
+ .byte 0x0 / segment base 16..23; set for 0k
+ .byte 0x9E / flags; A=0, Type=111, DPL=00, P=1
+ .byte 0x0F / flags; Limit (16..19)=1111, AVL=0, G=0, D=0
+ .byte 0x0 / segment base 24..32
+
+datadesc: / offset = 0x20
+
+ .value 0xFFFF / segment limit 0..15
+ .value 0x0000 / segment base 0..15
+ .byte 0x0 / segment base 16..23; set for 0K
+ .byte 0x92 / flags; A=0, Type=001, DPL=00, P=1
+ / Present expand down
+ .byte 0x4F / flags; Limit (16..19)=1111, AVL=0, G=1, B=1
+ .byte 0x0 / segment base 24..32
+
+dummy_entries:
+ .long 0 / 0x28
+ .long 0
+ .long 0 / 0x30
+ .long 0
+
+gsdesc: / 0x38 - for kmdb
+ .value 0
+ .value 0
+ .byte 0
+ .byte 0x92 / flags; A=0, Type=001, DPL=00, P=1
+ .byte 0xC0 / flags; Limit (16..19)=0000, AVL=0, G=1, B=1
+ .byte 0
+
+gdt_end:
+
+gdtdesc:
+ .value gdt_end - gdt_start
+ .long gdt_start
+
+.comm stack, STACK_SIZE / stack area
+
+#endif
diff --git a/usr/src/psm/stand/boot/i386/i86pc/biosint.s b/usr/src/psm/stand/boot/i386/i86pc/biosint.s
new file mode 100644
index 0000000000..1d70aeb002
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/i86pc/biosint.s
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * biosint.s - installed by kernel to make bios calls
+ *
+ * The kernel jumps here from protected mode to make a bios service call.
+ * Calling syntax: bios_doint(int intnum, struct int_pb *ic)
+ */
+ .globl _start
+_start:
+ pushl %ebp
+ movl %esp, %ebp
+
+ / Save segment registers of caller.
+ movw %cs, call_cs
+ movw %ds, call_ds
+ movw %es, call_es
+ movw %fs, call_fs
+ movw %gs, call_gs
+ movw %ss, call_ss
+ movl %esp, call_esp
+ movl %esi, call_esi
+ movl %ebx, call_ebx
+ movl %ecx, call_ecx
+ movl %edx, call_edx
+ movl %edi, call_edi
+
+ / switch stack to 0x5000
+ movl $0x5000, %eax
+ movl %eax, %esp
+ jmp donelowstack
+donelowstack:
+
+ / copy args from high memory to low memory
+ pushl 12(%ebp)
+ pushl 8(%ebp)
+ call copyin_args
+ addl $8, %esp
+
+ / insert proper interrupt for later.
+ movl ic_int, %eax
+ movb %al, newintcode+1
+
+ / Jump here for P5 94 byte instruction prefetch queue
+ jmp qflush1
+qflush1:
+
+ / call print_regs
+
+ / Switch interrupt descriptor tables.
+ cli
+ sidt kernIDTptr
+ lidt bioIDTptr
+
+ / Save global descriptor table
+ sgdt kernGDTptr
+
+ call goreal
+
+/
+/ NOW in REAL MODE
+/
+ / Clear the upper (extended) half of all registers.
+ / Having stray high bits on causes strange
+ / and unpredictable failures to occur in real mode.
+ /
+ data16; xorl %eax, %eax
+ addr16; movw ic_ds, %eax
+ push %eax / save for later
+ data16; addr16; movw ic_ax, %ax
+ data16; xorl %ebx, %ebx
+ addr16; mov ic_bx, %ebx
+ data16; xorl %ecx, %ecx
+ addr16; mov ic_cx, %ecx
+ data16; xorl %edx, %edx
+ addr16; mov ic_dx, %edx
+ data16; xorl %ebp, %ebp
+ addr16; mov ic_bp, %ebp
+ data16; xorl %edi,%edi
+ addr16; mov ic_di, %edi
+ data16; xorl %esi,%esi
+ addr16; mov ic_si, %esi
+ addr16; movw ic_es, %es
+
+ sti
+ addr16; pop %ds / set effective ds
+newintcode:
+ int $0x10 / do BIOS call
+ cli
+ pushf / save carry for later
+
+ / save results of the BIOS call
+ /
+ addr16; movw %ax, ic_ax
+ addr16; movw %bx, ic_bx
+ addr16; movw %cx, ic_cx
+ addr16; movw %dx, ic_dx
+ addr16; movw %bp, ic_bp
+ addr16; movw %si, ic_si
+ addr16; movw %di, ic_di
+ addr16; movw %ds, ic_ds / real mode - stack 2-bytes word
+ addr16; movw %es, ic_es
+
+ data16; movw %cs, %eax
+ movw %eax, %ds / restore entry ds, es
+ movw %eax, %es
+
+ data16; call goprot / protect mode
+
+/
+/ NOW back in PROTECTED MODE.
+/
+ / copy results to caller's location
+ movl call_esp, %eax
+ pushl 12(%eax)
+ call copyout_args
+ addl $4, %esp
+
+ xorl %eax, %eax / initialize return to zero
+ popw %ax / get eflags
+
+ / Interrupt descriptor table
+ lidt kernIDTptr
+
+ movl call_edx, %edx
+ movl call_ecx, %ecx
+ movl call_ebx, %ebx
+ movl call_edi, %edi
+ movl call_esi, %esi
+ / switch back to caller's stack
+ movl call_esp, %esp
+ popl %ebp
+ ret
+
+/ ----------------------------------------------------
+/ Enter real mode.
+/
+/ Real mode GDT descriptors are always present as code 0x18, data 0x20
+/
+ .globl goreal
+goreal:
+
+ / Transfer control to a 16 bit code segment
+ / This relies on knowledge of kernel's GDT
+ ljmp $0x18, $set16cs
+set16cs:
+
+ / need to have all segment regs sane
+ / before we can enter real mode
+ data16; movl $0x20, %eax
+ movw %ax, %es
+ movw %ax, %ds
+ movw %ax, %fs
+ movw %ax, %gs
+
+ / clear the protection and paging bits
+ / jump should clear prefetch q
+ mov %cr0, %eax
+ data16; and $0x7ffffffe, %eax
+ mov %eax, %cr0
+
+ / Do a long jump here to establish %cs in real mode.
+ / It appears that this has to be a ljmp as opposed to
+ / a lret probably due to the way Intel fixed errata #25
+ / on the A2 step. This leads to self modifying code.
+
+ ljmp $0x0, $restorecs
+restorecs:
+ / flush tlb
+ mov %cr3, %eax
+ mov %eax, %cr3
+
+ / we are loading in first 64K, so all segment reg should be zero
+ movw %cs, %ax
+ movw %ax, %ss
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ data16; ret
+
+/ ----------------------------------------------------
+/ Enter protected mode.
+/
+ .globl goprot
+goprot:
+
+ / Workaround for BIOSes that mess with GDT during INT call without
+ / restoring original value on the way back. Hence restore it here.
+
+ data16; addr16; lgdt kernGDTptr
+
+ data16; popl %ebx / get return %eip, for later use
+
+ / set protect mode and page mode
+ mov %cr0, %eax
+ data16; addr16; orl $0x80000001, %eax
+ mov %eax, %cr0
+
+ jmp qflush2 / flush the prefetch queue
+qflush2:
+
+ / Restore caller's segment registers.
+ / Still in 16-bit mode till %cs is restored
+ addr16; movw call_ds, %ds
+ addr16; movw call_es, %es
+ addr16; movw call_fs, %fs
+ addr16; movw call_gs, %gs
+ addr16; movw call_ss, %ss
+
+ / Now, set up %cs by fiddling with the return stack and doing an lret
+
+ data16; addr16; movw call_cs, %eax / push %cs
+ data16; pushl %eax
+ data16; pushl %ebx / push %eip
+ data16; lret
+
+/ Data definitions
+ .align 4
+bioIDTptr:
+bioIDTlimit:
+ .value 0x3ff
+bioIDTbase:
+ .long 0
+
+kernGDTptr:
+kernGDTlimit:
+ .value 0
+kernGDTbase:
+ .long 0
+
+kernIDTptr:
+kernIDTlimit:
+ .value 0
+kernIDTbase:
+ .long 0
+
+/ BIOS int call arguments
+.globl ic_int
+ic_int:
+ .long 0
+.globl ic_ax
+ic_ax:
+ .value 0
+.globl ic_bx
+ic_bx:
+ .value 0
+.globl ic_cx
+ic_cx:
+ .value 0
+.globl ic_dx
+ic_dx:
+ .value 0
+.globl ic_bp
+ic_bp:
+ .value 0
+.globl ic_si
+ic_si:
+ .value 0
+.globl ic_di
+ic_di:
+ .value 0
+.globl ic_ds
+ic_ds:
+ .value 0
+.globl ic_es
+ic_es:
+ .value 0
+
+/ Caller's registers
+.globl call_cs
+call_cs:
+ .value 0
+call_ds:
+ .value 0
+call_es:
+ .value 0
+call_fs:
+ .value 0
+call_gs:
+ .value 0
+.globl call_ss
+call_ss:
+ .value 0
+.globl call_esp
+call_esp:
+ .long 0
+call_ebp:
+ .long 0
+call_esi:
+ .long 0
+call_edi:
+ .long 0
+call_ebx:
+ .long 0
+call_ecx:
+ .long 0
+call_edx:
+ .long 0
diff --git a/usr/src/psm/stand/boot/i386/i86pc/cpu_id.s b/usr/src/psm/stand/boot/i386/i86pc/cpu_id.s
new file mode 100644
index 0000000000..8301a2a3b0
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/i86pc/cpu_id.s
@@ -0,0 +1,246 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/regset.h>
+#include <sys/psw.h>
+#include <sys/privregs.h>
+#include "../common/cpu_id.h"
+
+#ifdef __lint
+int is486(void) { return (1); }
+#else
+
+ .file "cpu_id.s"
+
+ .ident "%Z%%M% %I% %E% SMI"
+
+ .text
+
+/ We only support 486 or better. So just return 1.
+
+ .globl is486
+is486:
+ movl $1, %eax
+ ret
+
+#endif /* !lint */
+
+#ifdef lint
+/*
+ * Enable cpuid. Set max_std_cpuid_level and cpu_vendor appropriately. Returns
+ * 1 if cpuid present and enabled, 0 otherwise.
+ */
+int enable_cpuid(void) { return(1); }
+int max_std_cpuid_level;
+unsigned int cpu_vendor;
+#else
+ .text
+ .globl enable_cpuid
+enable_cpuid:
+ / Since no documented Cyrix cpu supports PSE, we do not care about
+ / enabling cpuid, yet. This routine is currently only responsible
+ / for setting max_std_cpuid_level and cpu_vendor.
+ pushl %esp
+ pushfl
+ popl %eax
+ movl %eax, %ecx
+ xorl $PS_ID, %eax
+ pushl %eax
+ popfl
+ pushfl
+ popl %eax / The above all lifted from locore.s
+ cmpl %eax, %ecx
+ jne has_it
+ movl $0, %eax / cpuid is not present or enabled
+ jmp enable_cpuid_out
+has_it:
+ / store maxium standard cpuid level
+ movl $0, %eax
+ cpuid
+ movl %eax, max_std_cpuid_level
+
+ / check to see if we are a GenuineIntel
+ cmpl $Genu, %ebx
+ jne not_intel
+ cmpl $ineI, %edx
+ jne not_intel
+ cmpl $ntel, %ecx
+ jne not_intel
+ movl $GenuineIntel, cpu_vendor
+ jmp vendor_done
+not_intel:
+ / check to see if we are an AuthenticAMD
+ cmpl $Auth, %ebx
+ jne not_amd
+ cmpl $enti, %edx
+ jne not_amd
+ cmpl $cAMD, %ecx
+ jne not_amd
+ movl $AuthenticAMD, cpu_vendor
+not_amd:
+vendor_done:
+ movl $1, %eax / cpuid present and enabled
+enable_cpuid_out:
+ popl %esp
+ ret
+
+ .data
+ .align 4
+ .globl max_std_cpuid_level
+ .globl cpu_vendor
+max_std_cpuid_level: .long 0xffffffff
+cpu_vendor: .long 0
+#endif
+
+#ifdef lint
+int largepage_supported(void) { return(1); }
+#else
+ .text
+ .globl largepage_supported
+largepage_supported:
+ pushl %esp / save our stack value
+
+ / test to see if cpuid level 1 supported
+ cmpl $1, max_std_cpuid_level
+ jl no
+
+ / are we a vendor for which we know how to test for PSE
+ testl $[GenuineIntel|AuthenticAMD], cpu_vendor
+ jz no
+
+ movl $1, %eax / capability test. Mov 1 to eax for cpuid
+ cpuid
+ andl $0x8, %edx / do you have large pages?
+ jz no
+ movl $1, %eax / yes we do have large pages
+ popl %esp
+ ret
+no:
+ movl $0, %eax / no we don't have large pages
+ popl %esp
+ ret
+#endif
+
+#ifdef lint
+int enable_large_pages(void) { return(1); }
+#else
+ .text
+ .globl enable_large_pages
+enable_large_pages:
+ movl %cr4, %eax
+ orl $CR4_PSE, %eax / since we have large pages enable them
+ movl %eax, %cr4
+#endif
+
+#ifdef lint
+int global_bit(void) { return(1); }
+#else
+ .text
+ .globl global_bit
+global_bit:
+ pushl %esp / save our stack value
+
+ / test to see if cpuid level 1 supported
+ cmpl $1, max_std_cpuid_level
+ jl nogbit
+
+ / are we a vendor for which we know how to test for PGE
+ testl $[GenuineIntel|AuthenticAMD], cpu_vendor
+ jz nogbit
+
+ movl $1, %eax / capability test. Mov 1 to eax for cpuid
+ cpuid
+
+ / are we an AMD
+ testl $AuthenticAMD, cpu_vendor
+ jz pge_at_13
+
+ / test to see if we are an AMD-K5 model 0
+ andw $0xff0, %ax
+ cmpw $0x500, %ax
+ jl nogbit
+ jne pge_at_13
+
+ / we are an AMD-K5 model 0, so GPE is at bit 9
+ testl $0x200, %edx / do you have GPE?
+ jmp test_pge
+
+pge_at_13:
+ testl $0x2000, %edx / do you have PGE?
+test_pge:
+ jnz hasgbit
+nogbit:
+ movl $0, %eax / no we don't have global pdtes
+ jmp global_bit_out
+hasgbit:
+ movl $1, %eax / yes we do have global pdtes
+global_bit_out:
+ popl %esp
+ ret
+#endif
+
+#ifdef lint
+int enable_global_pages(void) { return(1); }
+#else
+ .text
+ .globl enable_global_pages
+enable_global_pages:
+ movl %cr4, %eax
+ orl $CR4_PGE, %eax / since we have global pages enable them
+ movl %eax, %cr4
+#endif
+
+#ifdef lint
+int pae_supported(void) { return (1); }
+#else
+.set PAE_AND_CXS, 0x140 / PAE = 0x40 & CXS = 0x100
+
+ .text
+ .globl pae_supported
+pae_supported:
+ pushl %esp / save our stack value
+
+ / test to see if cpuid level 1 supported
+ cmpl $1, max_std_cpuid_level
+ jl nopae
+
+ / are we a vendor for which we know how to test for PAE and CXS
+ testl $[GenuineIntel|AuthenticAMD], cpu_vendor
+ jz nopae
+
+ movl $1, %eax / capability test. Mov 1 to eax for cpuid
+ cpuid
+ andl $PAE_AND_CXS, %edx / do you support pae and cmpxchg8b?
+ cmpl $PAE_AND_CXS, %edx
+ jne nopae
+ movl $1, %eax / yes we do support pae and cmpxchg8b
+ popl %esp
+ ret
+nopae:
+ movl $0, %eax / no we don't support pae and cmpxchg8b
+ popl %esp
+ ret
+#endif
diff --git a/usr/src/psm/stand/boot/i386/i86pc/idttab.s b/usr/src/psm/stand/boot/i386/i86pc/idttab.s
new file mode 100644
index 0000000000..9f851fd295
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/i86pc/idttab.s
@@ -0,0 +1,700 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#if defined(__lint)
+
+void *slbidt;
+
+#else
+ .file "idttab.s"
+ .ident "%Z%%M% %I% %E% SMI"
+
+ .text
+
+#define VECT(label, num) \
+ .align 4; \
+ .globl label; \
+label: \
+ push $0; \
+ push $num; \
+ call trap
+
+ VECT(div0trap, 0)
+ VECT(dbgtrap, 1)
+ VECT(nmiint, 2)
+ VECT(brktrap, 3)
+ VECT(ovflotrap, 4)
+ VECT(boundstrap, 5)
+ VECT(invoptrap, 6)
+ VECT(ndptrap0, 7)
+ VECT(dbfault, 8)
+ VECT(overrun, 9)
+ VECT(invtsstrap, 10)
+ VECT(segnptrap, 11)
+ VECT(stktrap, 12)
+ VECT(gptrap, 13)
+ VECT(pftrap, 14)
+ VECT(resvtrap, 15)
+ VECT(ndperr, 16)
+ VECT(inval17, 17)
+ VECT(inval18, 18)
+ VECT(inval19, 19)
+ VECT(progent, 20)
+ VECT(inval21, 21)
+ VECT(inval22, 22)
+ VECT(inval23, 23)
+ VECT(inval24, 24)
+ VECT(inval25, 25)
+ VECT(inval26, 26)
+ VECT(inval27, 27)
+ VECT(inval28, 28)
+ VECT(inval29, 29)
+ VECT(inval30, 30)
+ VECT(inval31, 31)
+ VECT(ndptrap2, 32)
+ VECT(inval33, 33)
+ VECT(inval34, 34)
+ VECT(inval35, 35)
+ VECT(inval36, 36)
+ VECT(inval37, 37)
+ VECT(inval38, 38)
+ VECT(inval39, 39)
+ VECT(inval40, 40)
+ VECT(inval41, 41)
+ VECT(inval42, 42)
+ VECT(inval43, 43)
+ VECT(inval44, 44)
+ VECT(inval45, 45)
+ VECT(inval46, 46)
+ VECT(inval47, 47)
+ VECT(inval48, 48)
+ VECT(inval49, 49)
+ VECT(inval50, 50)
+ VECT(inval51, 51)
+ VECT(inval52, 52)
+ VECT(inval53, 53)
+ VECT(inval54, 54)
+ VECT(inval55, 55)
+ VECT(inval56, 56)
+ VECT(inval57, 57)
+ VECT(inval58, 58)
+ VECT(inval59, 59)
+ VECT(inval60, 60)
+ VECT(inval61, 61)
+ VECT(inval62, 62)
+ VECT(inval63, 63)
+ VECT(ivctM0, 64)
+ VECT(ivctM1, 65)
+ VECT(ivctM2, 66)
+ VECT(ivctM3, 67)
+ VECT(ivctM4, 68)
+ VECT(ivctM5, 69)
+ VECT(ivctM6, 70)
+ VECT(ivctM7, 71)
+ VECT(ivctM0S0, 72)
+ VECT(ivctM0S1, 73)
+ VECT(ivctM0S2, 74)
+ VECT(ivctM0S3, 75)
+ VECT(ivctM0S4, 76)
+ VECT(ivctM0S5, 77)
+ VECT(ivctM0S6, 78)
+ VECT(ivctM0S7, 79)
+ VECT(ivctM1S0, 80)
+ VECT(ivctM1S1, 81)
+ VECT(ivctM1S2, 82)
+ VECT(ivctM1S3, 83)
+ VECT(ivctM1S4, 84)
+ VECT(ivctM1S5, 85)
+ VECT(ivctM1S6, 86)
+ VECT(ivctM1S7, 87)
+ VECT(ivctM2S0, 88)
+ VECT(ivctM2S1, 89)
+ VECT(ivctM2S2, 90)
+ VECT(ivctM2S3, 91)
+ VECT(ivctM2S4, 92)
+ VECT(ivctM2S5, 93)
+ VECT(ivctM2S6, 94)
+ VECT(ivctM2S7, 95)
+ VECT(ivctM3S0, 96)
+ VECT(ivctM3S1, 97)
+ VECT(ivctM3S2, 98)
+ VECT(ivctM3S3, 99)
+ VECT(ivctM3S4, 100)
+ VECT(ivctM3S5, 101)
+ VECT(ivctM3S6, 102)
+ VECT(ivctM3S7, 103)
+ VECT(ivctM4S0, 104)
+ VECT(ivctM4S1, 105)
+ VECT(ivctM4S2, 106)
+ VECT(ivctM4S3, 107)
+ VECT(ivctM4S4, 108)
+ VECT(ivctM4S5, 109)
+ VECT(ivctM4S6, 110)
+ VECT(ivctM4S7, 111)
+ VECT(ivctM5S0, 112)
+ VECT(ivctM5S1, 113)
+ VECT(ivctM5S2, 114)
+ VECT(ivctM5S3, 115)
+ VECT(ivctM5S4, 116)
+ VECT(ivctM5S5, 117)
+ VECT(ivctM5S6, 118)
+ VECT(ivctM5S7, 119)
+ VECT(ivctM6S0, 120)
+ VECT(ivctM6S1, 121)
+ VECT(ivctM6S2, 122)
+ VECT(ivctM6S3, 123)
+ VECT(ivctM6S4, 124)
+ VECT(ivctM6S5, 125)
+ VECT(ivctM6S6, 126)
+ VECT(ivctM6S7, 127)
+ VECT(ivctM7S0, 128)
+ VECT(ivctM7S1, 129)
+ VECT(ivctM7S2, 130)
+ VECT(ivctM7S3, 131)
+ VECT(ivctM7S4, 132)
+ VECT(ivctM7S5, 133)
+ VECT(ivctM7S6, 134)
+ VECT(ivctM7S7, 135)
+ VECT(invaltrap, 255)
+
+ .data
+ .align 4
+ .globl slbidt
+slbidt:
+ .4byte div0trap
+ .4byte 0x8f000010
+ .4byte dbgtrap
+ .4byte 0x8f000010
+ .4byte nmiint
+ .4byte 0x8e000010
+ .4byte brktrap
+ .4byte 0x8f000010
+ .4byte ovflotrap
+ .4byte 0x8f000010
+ .4byte boundstrap
+ .4byte 0x8f000010
+ .4byte invoptrap
+ .4byte 0x8f000010
+ .4byte ndptrap0
+ .4byte 0x8f000010
+ .4byte dbfault
+ .4byte 0x8f000010
+ .4byte overrun
+ .4byte 0x8f000010
+ .4byte invtsstrap
+ .4byte 0x8f000010
+ .4byte segnptrap
+ .4byte 0x8f000010
+ .4byte stktrap
+ .4byte 0x8f000010
+ .4byte gptrap
+ .4byte 0x8f000010
+ .4byte pftrap
+ .4byte 0x8f000010
+ .4byte resvtrap
+ .4byte 0x8f000010
+ .4byte ndperr
+ .4byte 0x8f000010
+ .4byte inval17
+ .4byte 0x8f000010
+ .4byte inval18
+ .4byte 0x8f000010
+ .4byte inval19
+ .4byte 0x8f000010
+ .4byte progent
+ .4byte 0x8f000010
+ .4byte inval21
+ .4byte 0x8f000010
+ .4byte inval22
+ .4byte 0x8f000010
+ .4byte inval23
+ .4byte 0x8f000010
+ .4byte inval24
+ .4byte 0x8f000010
+ .4byte inval25
+ .4byte 0x8f000010
+ .4byte inval26
+ .4byte 0x8f000010
+ .4byte inval27
+ .4byte 0x8f000010
+ .4byte inval28
+ .4byte 0x8f000010
+ .4byte inval29
+ .4byte 0x8f000010
+ .4byte inval30
+ .4byte 0x8f000010
+ .4byte inval31
+ .4byte 0x8f000010
+ .4byte ndptrap2
+ .4byte 0x8f000010
+ .4byte inval33
+ .4byte 0x8f000010
+ .4byte inval34
+ .4byte 0x8f000010
+ .4byte inval35
+ .4byte 0x8f000010
+ .4byte inval36
+ .4byte 0x8f000010
+ .4byte inval37
+ .4byte 0x8f000010
+ .4byte inval38
+ .4byte 0x8f000010
+ .4byte inval39
+ .4byte 0x8f000010
+ .4byte inval40
+ .4byte 0x8f000010
+ .4byte inval41
+ .4byte 0x8f000010
+ .4byte inval42
+ .4byte 0x8f000010
+ .4byte inval43
+ .4byte 0x8f000010
+ .4byte inval44
+ .4byte 0x8f000010
+ .4byte inval45
+ .4byte 0x8f000010
+ .4byte inval46
+ .4byte 0x8f000010
+ .4byte inval47
+ .4byte 0x8f000010
+ .4byte inval48
+ .4byte 0x8f000010
+ .4byte inval49
+ .4byte 0x8f000010
+ .4byte inval50
+ .4byte 0x8f000010
+ .4byte inval51
+ .4byte 0x8f000010
+ .4byte inval52
+ .4byte 0x8f000010
+ .4byte inval53
+ .4byte 0x8f000010
+ .4byte inval54
+ .4byte 0x8f000010
+ .4byte inval55
+ .4byte 0x8f000010
+ .4byte inval56
+ .4byte 0x8f000010
+ .4byte inval57
+ .4byte 0x8f000010
+ .4byte inval58
+ .4byte 0x8f000010
+ .4byte inval59
+ .4byte 0x8f000010
+ .4byte inval60
+ .4byte 0x8f000010
+ .4byte inval61
+ .4byte 0x8f000010
+ .4byte inval62
+ .4byte 0x8f000010
+ .4byte inval63
+ .4byte 0x8f000010
+ .4byte ivctM0
+ .4byte 0x8e000010
+ .4byte ivctM1
+ .4byte 0x8e000010
+ .4byte ivctM2
+ .4byte 0x8e000010
+ .4byte ivctM3
+ .4byte 0x8e000010
+ .4byte ivctM4
+ .4byte 0x8e000010
+ .4byte ivctM5
+ .4byte 0x8e000010
+ .4byte ivctM6
+ .4byte 0x8e000010
+ .4byte ivctM7
+ .4byte 0x8e000010
+ .4byte ivctM0S0
+ .4byte 0x8e000010
+ .4byte ivctM0S1
+ .4byte 0x8e000010
+ .4byte ivctM0S2
+ .4byte 0x8e000010
+ .4byte ivctM0S3
+ .4byte 0x8e000010
+ .4byte ivctM0S4
+ .4byte 0x8e000010
+ .4byte ivctM0S5
+ .4byte 0x8e000010
+ .4byte ivctM0S6
+ .4byte 0x8e000010
+ .4byte ivctM0S7
+ .4byte 0x8e000010
+ .4byte ivctM1S0
+ .4byte 0x8e000010
+ .4byte ivctM1S1
+ .4byte 0x8e000010
+ .4byte ivctM1S2
+ .4byte 0x8e000010
+ .4byte ivctM1S3
+ .4byte 0x8e000010
+ .4byte ivctM1S4
+ .4byte 0x8e000010
+ .4byte ivctM1S5
+ .4byte 0x8e000010
+ .4byte ivctM1S6
+ .4byte 0x8e000010
+ .4byte ivctM1S7
+ .4byte 0x8e000010
+ .4byte ivctM2S0
+ .4byte 0x8e000010
+ .4byte ivctM2S1
+ .4byte 0x8e000010
+ .4byte ivctM2S2
+ .4byte 0x8e000010
+ .4byte ivctM2S3
+ .4byte 0x8e000010
+ .4byte ivctM2S4
+ .4byte 0x8e000010
+ .4byte ivctM2S5
+ .4byte 0x8e000010
+ .4byte ivctM2S6
+ .4byte 0x8e000010
+ .4byte ivctM2S7
+ .4byte 0x8e000010
+ .4byte ivctM3S0
+ .4byte 0x8e000010
+ .4byte ivctM3S1
+ .4byte 0x8e000010
+ .4byte ivctM3S2
+ .4byte 0x8e000010
+ .4byte ivctM3S3
+ .4byte 0x8e000010
+ .4byte ivctM3S4
+ .4byte 0x8e000010
+ .4byte ivctM3S5
+ .4byte 0x8e000010
+ .4byte ivctM3S6
+ .4byte 0x8e000010
+ .4byte ivctM3S7
+ .4byte 0x8e000010
+ .4byte ivctM4S0
+ .4byte 0x8e000010
+ .4byte ivctM4S1
+ .4byte 0x8e000010
+ .4byte ivctM4S2
+ .4byte 0x8e000010
+ .4byte ivctM4S3
+ .4byte 0x8e000010
+ .4byte ivctM4S4
+ .4byte 0x8e000010
+ .4byte ivctM4S5
+ .4byte 0x8e000010
+ .4byte ivctM4S6
+ .4byte 0x8e000010
+ .4byte ivctM4S7
+ .4byte 0x8e000010
+ .4byte ivctM5S0
+ .4byte 0x8e000010
+ .4byte ivctM5S1
+ .4byte 0x8e000010
+ .4byte ivctM5S2
+ .4byte 0x8e000010
+ .4byte ivctM5S3
+ .4byte 0x8e000010
+ .4byte ivctM5S4
+ .4byte 0x8e000010
+ .4byte ivctM5S5
+ .4byte 0x8e000010
+ .4byte ivctM5S6
+ .4byte 0x8e000010
+ .4byte ivctM5S7
+ .4byte 0x8e000010
+ .4byte ivctM6S0
+ .4byte 0x8e000010
+ .4byte ivctM6S1
+ .4byte 0x8e000010
+ .4byte ivctM6S2
+ .4byte 0x8e000010
+ .4byte ivctM6S3
+ .4byte 0x8e000010
+ .4byte ivctM6S4
+ .4byte 0x8e000010
+ .4byte ivctM6S5
+ .4byte 0x8e000010
+ .4byte ivctM6S6
+ .4byte 0x8e000010
+ .4byte ivctM6S7
+ .4byte 0x8e000010
+ .4byte ivctM7S0
+ .4byte 0x8e000010
+ .4byte ivctM7S1
+ .4byte 0x8e000010
+ .4byte ivctM7S2
+ .4byte 0x8e000010
+ .4byte ivctM7S3
+ .4byte 0x8e000010
+ .4byte ivctM7S4
+ .4byte 0x8e000010
+ .4byte ivctM7S5
+ .4byte 0x8e000010
+ .4byte ivctM7S6
+ .4byte 0x8e000010
+ .4byte ivctM7S7
+ .4byte 0x8e000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+ .4byte invaltrap
+ .4byte 0x8f000010
+
+#endif /*__lint*/
diff --git a/usr/src/psm/stand/boot/i386/i86pc/samuldiv64.s b/usr/src/psm/stand/boot/i386/i86pc/samuldiv64.s
new file mode 100644
index 0000000000..76fc0b1360
--- /dev/null
+++ b/usr/src/psm/stand/boot/i386/i86pc/samuldiv64.s
@@ -0,0 +1,1077 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright (c) 1990, 1991 UNIX System Laboratories, Inc.
+ * Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T
+ * All Rights Reserved
+ *
+ * this file includes portions of uts/i86/ml/i86_subr.s
+ */
+
+#ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/asm_linkage.h>
+#include <sys/asm_misc.h>
+#include <sys/regset.h>
+
+#if defined(lint) || defined(__lint)
+#include <sys/types.h>
+#include <sys/thread.h>
+#include <sys/archsystm.h>
+#endif /* lint */
+
+#if defined(lint) || defined(__lint)
+
+/* ARGSUSED */
+long long
+__mul64(long long a, long long b)
+{ return (0); }
+
+#else /* lint */
+
+/
+/ function __mul64(A,B:Longint):Longint;
+/ {Overflow is not checked}
+/
+/ We essentially do multiply by longhand, using base 2**32 digits.
+/ a b parameter A
+/ x c d parameter B
+/ ---------
+/ ad bd
+/ ac bc
+/ -----------------
+/ ac ad+bc bd
+/
+/ We can ignore ac and top 32 bits of ad+bc: if <> 0, overflow happened.
+/
+ ENTRY(__mul64)
+ push %ebp
+ mov %esp,%ebp
+ pushl %esi
+ mov 12(%ebp),%eax / A.hi (a)
+ mull 16(%ebp) / Multiply A.hi by B.lo (produces ad)
+ xchg %ecx,%eax / ecx = bottom half of ad.
+ movl 8(%ebp),%eax / A.Lo (b)
+ movl %eax,%esi / Save A.lo for later
+ mull 16(%ebp) / Multiply A.Lo by B.LO (dx:ax = bd.)
+ addl %edx,%ecx / cx is ad
+ xchg %eax,%esi / esi is bd, eax = A.lo (d)
+ mull 20(%ebp) / Multiply A.lo * B.hi (producing bc)
+ addl %ecx,%eax / Produce ad+bc
+ movl %esi,%edx
+ xchg %eax,%edx
+ popl %esi
+ movl %ebp,%esp
+ popl %ebp
+ ret $16
+ SET_SIZE(__mul64)
+
+#endif /* lint */
+
+/*
+ * multiply two long numbers and yield a u_longlong_t result, callable from C.
+ * Provided to manipulate hrtime_t values.
+ */
+#if defined(lint) || defined(__lint)
+
+/* result = a * b; */
+
+/* ARGSUSED */
+unsigned long long
+mul32(ulong a, ulong b)
+{ return (0); }
+
+#else /* lint */
+
+ ENTRY(mul32)
+ movl 8(%esp), %eax
+ movl 4(%esp), %ecx
+ mull %ecx
+ ret
+ SET_SIZE(mul32)
+
+#endif /* lint */
+
+/*
+ * C support for 64-bit modulo and division.
+ * Hand-customized compiler output - see comments for details.
+ */
+
+#if defined(lint) || defined(__lint)
+
+/* ARGSUSED */
+uint64_t
+__udiv64(uint64_t a, uint64_t b)
+{ return (0); }
+
+/* ARGSUSED */
+uint64_t __udivrem64(uint64_t a, uint64_t b)
+{ return (0); }
+
+/* ARGSUSED */
+uint64_t
+__urem64(int64_t a, int64_t b)
+{ return (0); }
+
+/* ARGSUSED */
+int64_t
+__div64(int64_t a, int64_t b)
+{ return (0); }
+
+/* ARGSUSED */
+int64_t __divrem64(int64_t a, int64_t b)
+{ return (0); }
+
+/* ARGSUSED */
+int64_t
+__rem64(int64_t a, int64_t b)
+
+{ return (0); }
+
+#else /* lint */
+
+/*
+ * int32_t/int64_t division/manipulation
+ *
+ * Hand-customized compiler output: the non-GCC entry points depart from
+ * the SYS V ABI by requiring their arguments to be popped, and in the
+ * [u]divrem64 cases returning the remainder in %ecx:%esi. Note the
+ * compiler-generated use of %edx:%eax for the first argument of
+ * internal entry points.
+ *
+ * Inlines for speed:
+ * - counting the number of leading zeros in a word
+ * - multiplying two 32-bit numbers giving a 64-bit result
+ * - dividing a 64-bit number by a 32-bit number, giving both quotient
+ * and remainder
+ * - subtracting two 64-bit results
+ */
+/ #define LO(X) ((uint32_t)(X) & 0xffffffff)
+/ #define HI(X) ((uint32_t)((X) >> 32) & 0xffffffff)
+/ #define HILO(H, L) (((uint64_t)(H) << 32) + (L))
+/
+/ /* give index of highest bit */
+/ #define HIBIT(a, r) \
+/ asm("bsrl %1,%0": "=r"((uint32_t)(r)) : "g" (a))
+/
+/ /* multiply two uint32_ts resulting in a uint64_t */
+/ #define A_MUL32(a, b, lo, hi) \
+/ asm("mull %2" \
+/ : "=a"((uint32_t)(lo)), "=d"((uint32_t)(hi)) : "g" (b), "0"(a))
+/
+/ /* divide a uint64_t by a uint32_t */
+/ #define A_DIV32(lo, hi, b, q, r) \
+/ asm("divl %2" \
+/ : "=a"((uint32_t)(q)), "=d"((uint32_t)(r)) \
+/ : "g" (b), "0"((uint32_t)(lo)), "1"((uint32_t)hi))
+/
+/ /* subtract two uint64_ts (with borrow) */
+/ #define A_SUB2(bl, bh, al, ah) \
+/ asm("subl %4,%0\n\tsbbl %5,%1" \
+/ : "=&r"((uint32_t)(al)), "=r"((uint32_t)(ah)) \
+/ : "0"((uint32_t)(al)), "1"((uint32_t)(ah)), "g"((uint32_t)(bl)), \
+/ "g"((uint32_t)(bh)))
+/
+/ /*
+/ * Unsigned division with remainder.
+/ * Divide two uint64_ts, and calculate remainder.
+/ */
+/ uint64_t
+/ UDivRem(uint64_t x, uint64_t y, uint64_t * pmod)
+/ {
+/ /* simple cases: y is a single uint32_t */
+/ if (HI(y) == 0) {
+/ uint32_t div_hi, div_rem;
+/ uint32_t q0, q1;
+/
+/ /* calculate q1 */
+/ if (HI(x) < LO(y)) {
+/ /* result is a single uint32_t, use one division */
+/ q1 = 0;
+/ div_hi = HI(x);
+/ } else {
+/ /* result is a double uint32_t, use two divisions */
+/ A_DIV32(HI(x), 0, LO(y), q1, div_hi);
+/ }
+/
+/ /* calculate q0 and remainder */
+/ A_DIV32(LO(x), div_hi, LO(y), q0, div_rem);
+/
+/ /* return remainder */
+/ *pmod = div_rem;
+/
+/ /* return result */
+/ return (HILO(q1, q0));
+/
+/ } else if (HI(x) < HI(y)) {
+/ /* HI(x) < HI(y) => x < y => result is 0 */
+/
+/ /* return remainder */
+/ *pmod = x;
+/
+/ /* return result */
+/ return (0);
+/
+/ } else {
+/ /*
+/ * uint64_t by uint64_t division, resulting in a one-uint32_t
+/ * result
+/ */
+/ uint32_t y0, y1;
+/ uint32_t x1, x0;
+/ uint32_t q0;
+/ uint32_t normshift;
+/
+/ /* normalize by shifting x and y so MSB(y) == 1 */
+/ HIBIT(HI(y), normshift); /* index of highest 1 bit */
+/ normshift = 31 - normshift;
+/
+/ if (normshift == 0) {
+/ /* no shifting needed, and x < 2*y so q <= 1 */
+/ y1 = HI(y);
+/ y0 = LO(y);
+/ x1 = HI(x);
+/ x0 = LO(x);
+/
+/ /* if x >= y then q = 1 (note x1 >= y1) */
+/ if (x1 > y1 || x0 >= y0) {
+/ q0 = 1;
+/ /* subtract y from x to get remainder */
+/ A_SUB2(y0, y1, x0, x1);
+/ } else {
+/ q0 = 0;
+/ }
+/
+/ /* return remainder */
+/ *pmod = HILO(x1, x0);
+/
+/ /* return result */
+/ return (q0);
+/
+/ } else {
+/ /*
+/ * the last case: result is one uint32_t, but we need to
+/ * normalize
+/ */
+/ uint64_t dt;
+/ uint32_t t0, t1, x2;
+/
+/ /* normalize y */
+/ dt = (y << normshift);
+/ y1 = HI(dt);
+/ y0 = LO(dt);
+/
+/ /* normalize x (we need 3 uint32_ts!!!) */
+/ x2 = (HI(x) >> (32 - normshift));
+/ dt = (x << normshift);
+/ x1 = HI(dt);
+/ x0 = LO(dt);
+/
+/ /* estimate q0, and reduce x to a two uint32_t value */
+/ A_DIV32(x1, x2, y1, q0, x1);
+/
+/ /* adjust q0 down if too high */
+/ /*
+/ * because of the limited range of x2 we can only be
+/ * one off
+/ */
+/ A_MUL32(y0, q0, t0, t1);
+/ if (t1 > x1 || (t1 == x1 && t0 > x0)) {
+/ q0--;
+/ A_SUB2(y0, y1, t0, t1);
+/ }
+/ /* return remainder */
+/ /* subtract product from x to get remainder */
+/ A_SUB2(t0, t1, x0, x1);
+/ *pmod = (HILO(x1, x0) >> normshift);
+/
+/ /* return result */
+/ return (q0);
+/ }
+/ }
+/ }
+ ENTRY(UDivRem)
+ pushl %ebp
+ pushl %edi
+ pushl %esi
+ subl $48, %esp
+ movl 68(%esp), %edi / y,
+ testl %edi, %edi / tmp63
+ movl %eax, 40(%esp) / x, x
+ movl %edx, 44(%esp) / x, x
+ movl %edi, %esi /, tmp62
+ movl %edi, %ecx / tmp62, tmp63
+ jne .LL2
+ movl %edx, %eax /, tmp68
+ cmpl 64(%esp), %eax / y, tmp68
+ jae .LL21
+.LL4:
+ movl 72(%esp), %ebp / pmod,
+ xorl %esi, %esi / <result>
+ movl 40(%esp), %eax / x, q0
+ movl %ecx, %edi / <result>, <result>
+ divl 64(%esp) / y
+ movl %edx, (%ebp) / div_rem,
+ xorl %edx, %edx / q0
+ addl %eax, %esi / q0, <result>
+ movl $0, 4(%ebp)
+ adcl %edx, %edi / q0, <result>
+ addl $48, %esp
+ movl %esi, %eax / <result>, <result>
+ popl %esi
+ movl %edi, %edx / <result>, <result>
+ popl %edi
+ popl %ebp
+ ret
+ .align 16
+.LL2:
+ movl 44(%esp), %eax / x,
+ xorl %edx, %edx
+ cmpl %esi, %eax / tmp62, tmp5
+ movl %eax, 32(%esp) / tmp5,
+ movl %edx, 36(%esp)
+ jae .LL6
+ movl 72(%esp), %esi / pmod,
+ movl 40(%esp), %ebp / x,
+ movl 44(%esp), %ecx / x,
+ movl %ebp, (%esi)
+ movl %ecx, 4(%esi)
+ xorl %edi, %edi / <result>
+ xorl %esi, %esi / <result>
+.LL22:
+ addl $48, %esp
+ movl %esi, %eax / <result>, <result>
+ popl %esi
+ movl %edi, %edx / <result>, <result>
+ popl %edi
+ popl %ebp
+ ret
+ .align 16
+.LL21:
+ movl %edi, %edx / tmp63, div_hi
+ divl 64(%esp) / y
+ movl %eax, %ecx /, q1
+ jmp .LL4
+ .align 16
+.LL6:
+ movl $31, %edi /, tmp87
+ bsrl %esi,%edx / tmp62, normshift
+ subl %edx, %edi / normshift, tmp87
+ movl %edi, 28(%esp) / tmp87,
+ jne .LL8
+ movl 32(%esp), %edx /, x1
+ cmpl %ecx, %edx / y1, x1
+ movl 64(%esp), %edi / y, y0
+ movl 40(%esp), %esi / x, x0
+ ja .LL10
+ xorl %ebp, %ebp / q0
+ cmpl %edi, %esi / y0, x0
+ jb .LL11
+.LL10:
+ movl $1, %ebp /, q0
+ subl %edi,%esi / y0, x0
+ sbbl %ecx,%edx / tmp63, x1
+.LL11:
+ movl %edx, %ecx / x1, x1
+ xorl %edx, %edx / x1
+ xorl %edi, %edi / x0
+ addl %esi, %edx / x0, x1
+ adcl %edi, %ecx / x0, x1
+ movl 72(%esp), %esi / pmod,
+ movl %edx, (%esi) / x1,
+ movl %ecx, 4(%esi) / x1,
+ xorl %edi, %edi / <result>
+ movl %ebp, %esi / q0, <result>
+ jmp .LL22
+ .align 16
+.LL8:
+ movb 28(%esp), %cl
+ movl 64(%esp), %esi / y, dt
+ movl 68(%esp), %edi / y, dt
+ shldl %esi, %edi /, dt, dt
+ sall %cl, %esi /, dt
+ andl $32, %ecx
+ jne .LL23
+.LL17:
+ movl $32, %ecx /, tmp102
+ subl 28(%esp), %ecx /, tmp102
+ movl %esi, %ebp / dt, y0
+ movl 32(%esp), %esi
+ shrl %cl, %esi / tmp102,
+ movl %edi, 24(%esp) / tmp99,
+ movb 28(%esp), %cl
+ movl %esi, 12(%esp) /, x2
+ movl 44(%esp), %edi / x, dt
+ movl 40(%esp), %esi / x, dt
+ shldl %esi, %edi /, dt, dt
+ sall %cl, %esi /, dt
+ andl $32, %ecx
+ je .LL18
+ movl %esi, %edi / dt, dt
+ xorl %esi, %esi / dt
+.LL18:
+ movl %edi, %ecx / dt,
+ movl %edi, %eax / tmp2,
+ movl %ecx, (%esp)
+ movl 12(%esp), %edx / x2,
+ divl 24(%esp)
+ movl %edx, %ecx /, x1
+ xorl %edi, %edi
+ movl %eax, 20(%esp)
+ movl %ebp, %eax / y0, t0
+ mull 20(%esp)
+ cmpl %ecx, %edx / x1, t1
+ movl %edi, 4(%esp)
+ ja .LL14
+ je .LL24
+.LL15:
+ movl %ecx, %edi / x1,
+ subl %eax,%esi / t0, x0
+ sbbl %edx,%edi / t1,
+ movl %edi, %eax /, x1
+ movl %eax, %edx / x1, x1
+ xorl %eax, %eax / x1
+ xorl %ebp, %ebp / x0
+ addl %esi, %eax / x0, x1
+ adcl %ebp, %edx / x0, x1
+ movb 28(%esp), %cl
+ shrdl %edx, %eax /, x1, x1
+ shrl %cl, %edx /, x1
+ andl $32, %ecx
+ je .LL16
+ movl %edx, %eax / x1, x1
+ xorl %edx, %edx / x1
+.LL16:
+ movl 72(%esp), %ecx / pmod,
+ movl 20(%esp), %esi /, <result>
+ xorl %edi, %edi / <result>
+ movl %eax, (%ecx) / x1,
+ movl %edx, 4(%ecx) / x1,
+ jmp .LL22
+ .align 16
+.LL24:
+ cmpl %esi, %eax / x0, t0
+ jbe .LL15
+.LL14:
+ decl 20(%esp)
+ subl %ebp,%eax / y0, t0
+ sbbl 24(%esp),%edx /, t1
+ jmp .LL15
+.LL23:
+ movl %esi, %edi / dt, dt
+ xorl %esi, %esi / dt
+ jmp .LL17
+ SET_SIZE(UDivRem)
+
+/*
+ * Unsigned division without remainder.
+ */
+/ uint64_t
+/ UDiv(uint64_t x, uint64_t y)
+/ {
+/ if (HI(y) == 0) {
+/ /* simple cases: y is a single uint32_t */
+/ uint32_t div_hi, div_rem;
+/ uint32_t q0, q1;
+/
+/ /* calculate q1 */
+/ if (HI(x) < LO(y)) {
+/ /* result is a single uint32_t, use one division */
+/ q1 = 0;
+/ div_hi = HI(x);
+/ } else {
+/ /* result is a double uint32_t, use two divisions */
+/ A_DIV32(HI(x), 0, LO(y), q1, div_hi);
+/ }
+/
+/ /* calculate q0 and remainder */
+/ A_DIV32(LO(x), div_hi, LO(y), q0, div_rem);
+/
+/ /* return result */
+/ return (HILO(q1, q0));
+/
+/ } else if (HI(x) < HI(y)) {
+/ /* HI(x) < HI(y) => x < y => result is 0 */
+/
+/ /* return result */
+/ return (0);
+/
+/ } else {
+/ /*
+/ * uint64_t by uint64_t division, resulting in a one-uint32_t
+/ * result
+/ */
+/ uint32_t y0, y1;
+/ uint32_t x1, x0;
+/ uint32_t q0;
+/ unsigned normshift;
+/
+/ /* normalize by shifting x and y so MSB(y) == 1 */
+/ HIBIT(HI(y), normshift); /* index of highest 1 bit */
+/ normshift = 31 - normshift;
+/
+/ if (normshift == 0) {
+/ /* no shifting needed, and x < 2*y so q <= 1 */
+/ y1 = HI(y);
+/ y0 = LO(y);
+/ x1 = HI(x);
+/ x0 = LO(x);
+/
+/ /* if x >= y then q = 1 (note x1 >= y1) */
+/ if (x1 > y1 || x0 >= y0) {
+/ q0 = 1;
+/ /* subtract y from x to get remainder */
+/ /* A_SUB2(y0, y1, x0, x1); */
+/ } else {
+/ q0 = 0;
+/ }
+/
+/ /* return result */
+/ return (q0);
+/
+/ } else {
+/ /*
+/ * the last case: result is one uint32_t, but we need to
+/ * normalize
+/ */
+/ uint64_t dt;
+/ uint32_t t0, t1, x2;
+/
+/ /* normalize y */
+/ dt = (y << normshift);
+/ y1 = HI(dt);
+/ y0 = LO(dt);
+/
+/ /* normalize x (we need 3 uint32_ts!!!) */
+/ x2 = (HI(x) >> (32 - normshift));
+/ dt = (x << normshift);
+/ x1 = HI(dt);
+/ x0 = LO(dt);
+/
+/ /* estimate q0, and reduce x to a two uint32_t value */
+/ A_DIV32(x1, x2, y1, q0, x1);
+/
+/ /* adjust q0 down if too high */
+/ /*
+/ * because of the limited range of x2 we can only be
+/ * one off
+/ */
+/ A_MUL32(y0, q0, t0, t1);
+/ if (t1 > x1 || (t1 == x1 && t0 > x0)) {
+/ q0--;
+/ }
+/ /* return result */
+/ return (q0);
+/ }
+/ }
+/ }
+ ENTRY(UDiv)
+ pushl %ebp
+ pushl %edi
+ pushl %esi
+ subl $40, %esp
+ movl %edx, 36(%esp) / x, x
+ movl 60(%esp), %edx / y,
+ testl %edx, %edx / tmp62
+ movl %eax, 32(%esp) / x, x
+ movl %edx, %ecx / tmp61, tmp62
+ movl %edx, %eax /, tmp61
+ jne .LL26
+ movl 36(%esp), %esi / x,
+ cmpl 56(%esp), %esi / y, tmp67
+ movl %esi, %eax /, tmp67
+ movl %esi, %edx / tmp67, div_hi
+ jb .LL28
+ movl %ecx, %edx / tmp62, div_hi
+ divl 56(%esp) / y
+ movl %eax, %ecx /, q1
+.LL28:
+ xorl %esi, %esi / <result>
+ movl %ecx, %edi / <result>, <result>
+ movl 32(%esp), %eax / x, q0
+ xorl %ecx, %ecx / q0
+ divl 56(%esp) / y
+ addl %eax, %esi / q0, <result>
+ adcl %ecx, %edi / q0, <result>
+.LL25:
+ addl $40, %esp
+ movl %esi, %eax / <result>, <result>
+ popl %esi
+ movl %edi, %edx / <result>, <result>
+ popl %edi
+ popl %ebp
+ ret
+ .align 16
+.LL26:
+ movl 36(%esp), %esi / x,
+ xorl %edi, %edi
+ movl %esi, 24(%esp) / tmp1,
+ movl %edi, 28(%esp)
+ xorl %esi, %esi / <result>
+ xorl %edi, %edi / <result>
+ cmpl %eax, 24(%esp) / tmp61,
+ jb .LL25
+ bsrl %eax,%ebp / tmp61, normshift
+ movl $31, %eax /, tmp85
+ subl %ebp, %eax / normshift, normshift
+ jne .LL32
+ movl 24(%esp), %eax /, x1
+ cmpl %ecx, %eax / tmp62, x1
+ movl 56(%esp), %esi / y, y0
+ movl 32(%esp), %edx / x, x0
+ ja .LL34
+ xorl %eax, %eax / q0
+ cmpl %esi, %edx / y0, x0
+ jb .LL35
+.LL34:
+ movl $1, %eax /, q0
+.LL35:
+ movl %eax, %esi / q0, <result>
+ xorl %edi, %edi / <result>
+.LL45:
+ addl $40, %esp
+ movl %esi, %eax / <result>, <result>
+ popl %esi
+ movl %edi, %edx / <result>, <result>
+ popl %edi
+ popl %ebp
+ ret
+ .align 16
+.LL32:
+ movb %al, %cl
+ movl 56(%esp), %esi / y,
+ movl 60(%esp), %edi / y,
+ shldl %esi, %edi
+ sall %cl, %esi
+ andl $32, %ecx
+ jne .LL43
+.LL40:
+ movl $32, %ecx /, tmp96
+ subl %eax, %ecx / normshift, tmp96
+ movl %edi, %edx
+ movl %edi, 20(%esp) /, dt
+ movl 24(%esp), %ebp /, x2
+ xorl %edi, %edi
+ shrl %cl, %ebp / tmp96, x2
+ movl %esi, 16(%esp) /, dt
+ movb %al, %cl
+ movl 32(%esp), %esi / x, dt
+ movl %edi, 12(%esp)
+ movl 36(%esp), %edi / x, dt
+ shldl %esi, %edi /, dt, dt
+ sall %cl, %esi /, dt
+ andl $32, %ecx
+ movl %edx, 8(%esp)
+ je .LL41
+ movl %esi, %edi / dt, dt
+ xorl %esi, %esi / dt
+.LL41:
+ xorl %ecx, %ecx
+ movl %edi, %eax / tmp1,
+ movl %ebp, %edx / x2,
+ divl 8(%esp)
+ movl %edx, %ebp /, x1
+ movl %ecx, 4(%esp)
+ movl %eax, %ecx /, q0
+ movl 16(%esp), %eax / dt,
+ mull %ecx / q0
+ cmpl %ebp, %edx / x1, t1
+ movl %edi, (%esp)
+ movl %esi, %edi / dt, x0
+ ja .LL38
+ je .LL44
+.LL39:
+ movl %ecx, %esi / q0, <result>
+.LL46:
+ xorl %edi, %edi / <result>
+ jmp .LL45
+.LL44:
+ cmpl %edi, %eax / x0, t0
+ jbe .LL39
+.LL38:
+ decl %ecx / q0
+ movl %ecx, %esi / q0, <result>
+ jmp .LL46
+.LL43:
+ movl %esi, %edi
+ xorl %esi, %esi
+ jmp .LL40
+ SET_SIZE(UDiv)
+/*
+ * __udiv64
+ *
+ * Perform division of two unsigned 64-bit quantities, returning the
+ * quotient in %edx:%eax. __udiv64 pops the arguments on return,
+ */
+ ENTRY(__udiv64)
+ movl 4(%esp), %eax / x, x
+ movl 8(%esp), %edx / x, x
+ pushl 16(%esp) / y
+ pushl 16(%esp)
+ call UDiv
+ addl $8, %esp
+ ret $16
+ SET_SIZE(__udiv64)
+
+/*
+ * __urem64
+ *
+ * Perform division of two unsigned 64-bit quantities, returning the
+ * remainder in %edx:%eax. __urem64 pops the arguments on return
+ */
+ ENTRY(__urem64)
+ subl $12, %esp
+ movl %esp, %ecx /, tmp65
+ movl 16(%esp), %eax / x, x
+ movl 20(%esp), %edx / x, x
+ pushl %ecx / tmp65
+ pushl 32(%esp) / y
+ pushl 32(%esp)
+ call UDivRem
+ movl 12(%esp), %eax / rem, rem
+ movl 16(%esp), %edx / rem, rem
+ addl $24, %esp
+ ret $16
+ SET_SIZE(__urem64)
+
+/*
+ * __div64
+ *
+ * Perform division of two signed 64-bit quantities, returning the
+ * quotient in %edx:%eax. __div64 pops the arguments on return.
+ */
+/ int64_t
+/ __div64(int64_t x, int64_t y)
+/ {
+/ int negative;
+/ uint64_t xt, yt, r;
+/
+/ if (x < 0) {
+/ xt = -(uint64_t) x;
+/ negative = 1;
+/ } else {
+/ xt = x;
+/ negative = 0;
+/ }
+/ if (y < 0) {
+/ yt = -(uint64_t) y;
+/ negative ^= 1;
+/ } else {
+/ yt = y;
+/ }
+/ r = UDiv(xt, yt);
+/ return (negative ? (int64_t) - r : r);
+/ }
+ ENTRY(__div64)
+ pushl %ebp
+ pushl %edi
+ pushl %esi
+ subl $8, %esp
+ movl 28(%esp), %edx / x, x
+ testl %edx, %edx / x
+ movl 24(%esp), %eax / x, x
+ movl 32(%esp), %esi / y, y
+ movl 36(%esp), %edi / y, y
+ js .LL84
+ xorl %ebp, %ebp / negative
+ testl %edi, %edi / y
+ movl %eax, (%esp) / x, xt
+ movl %edx, 4(%esp) / x, xt
+ movl %esi, %eax / y, yt
+ movl %edi, %edx / y, yt
+ js .LL85
+.LL82:
+ pushl %edx / yt
+ pushl %eax / yt
+ movl 8(%esp), %eax / xt, xt
+ movl 12(%esp), %edx / xt, xt
+ call UDiv
+ popl %ecx
+ testl %ebp, %ebp / negative
+ popl %esi
+ je .LL83
+ negl %eax / r
+ adcl $0, %edx /, r
+ negl %edx / r
+.LL83:
+ addl $8, %esp
+ popl %esi
+ popl %edi
+ popl %ebp
+ ret $16
+ .align 16
+.LL84:
+ negl %eax / x
+ adcl $0, %edx /, x
+ negl %edx / x
+ testl %edi, %edi / y
+ movl %eax, (%esp) / x, xt
+ movl %edx, 4(%esp) / x, xt
+ movl $1, %ebp /, negative
+ movl %esi, %eax / y, yt
+ movl %edi, %edx / y, yt
+ jns .LL82
+ .align 16
+.LL85:
+ negl %eax / yt
+ adcl $0, %edx /, yt
+ negl %edx / yt
+ xorl $1, %ebp /, negative
+ jmp .LL82
+ SET_SIZE(__div64)
+
+/*
+ * __rem64
+ *
+ * Perform division of two signed 64-bit quantities, returning the
+ * remainder in %edx:%eax. __rem64 pops the arguments on return.
+ */
+/ int64_t
+/ __rem64(int64_t x, int64_t y)
+/ {
+/ uint64_t xt, yt, rem;
+/
+/ if (x < 0) {
+/ xt = -(uint64_t) x;
+/ } else {
+/ xt = x;
+/ }
+/ if (y < 0) {
+/ yt = -(uint64_t) y;
+/ } else {
+/ yt = y;
+/ }
+/ (void) UDivRem(xt, yt, &rem);
+/ return (x < 0 ? (int64_t) - rem : rem);
+/ }
+ ENTRY(__rem64)
+ pushl %edi
+ pushl %esi
+ subl $20, %esp
+ movl 36(%esp), %ecx / x,
+ movl 32(%esp), %esi / x,
+ movl 36(%esp), %edi / x,
+ testl %ecx, %ecx
+ movl 40(%esp), %eax / y, y
+ movl 44(%esp), %edx / y, y
+ movl %esi, (%esp) /, xt
+ movl %edi, 4(%esp) /, xt
+ js .LL92
+ testl %edx, %edx / y
+ movl %eax, %esi / y, yt
+ movl %edx, %edi / y, yt
+ js .LL93
+.LL90:
+ leal 8(%esp), %eax /, tmp66
+ pushl %eax / tmp66
+ pushl %edi / yt
+ pushl %esi / yt
+ movl 12(%esp), %eax / xt, xt
+ movl 16(%esp), %edx / xt, xt
+ call UDivRem
+ addl $12, %esp
+ movl 36(%esp), %edi / x,
+ testl %edi, %edi
+ movl 8(%esp), %eax / rem, rem
+ movl 12(%esp), %edx / rem, rem
+ js .LL94
+ addl $20, %esp
+ popl %esi
+ popl %edi
+ ret $16
+ .align 16
+.LL92:
+ negl %esi
+ adcl $0, %edi
+ negl %edi
+ testl %edx, %edx / y
+ movl %esi, (%esp) /, xt
+ movl %edi, 4(%esp) /, xt
+ movl %eax, %esi / y, yt
+ movl %edx, %edi / y, yt
+ jns .LL90
+ .align 16
+.LL93:
+ negl %esi / yt
+ adcl $0, %edi /, yt
+ negl %edi / yt
+ jmp .LL90
+ .align 16
+.LL94:
+ negl %eax / rem
+ adcl $0, %edx /, rem
+ addl $20, %esp
+ popl %esi
+ negl %edx / rem
+ popl %edi
+ ret $16
+ SET_SIZE(__rem64)
+
+/*
+ * __udivrem64
+ *
+ * Perform division of two unsigned 64-bit quantities, returning the
+ * quotient in %edx:%eax, and the remainder in %ecx:%esi. __udivrem64
+ * pops the arguments on return.
+ */
+ ENTRY(__udivrem64)
+ subl $12, %esp
+ movl %esp, %ecx /, tmp64
+ movl 16(%esp), %eax / x, x
+ movl 20(%esp), %edx / x, x
+ pushl %ecx / tmp64
+ pushl 32(%esp) / y
+ pushl 32(%esp)
+ call UDivRem
+ movl 16(%esp), %ecx / rem, tmp63
+ movl 12(%esp), %esi / rem
+ addl $24, %esp
+ ret $16
+ SET_SIZE(__udivrem64)
+
+/*
+ * Signed division with remainder.
+ */
+/ int64_t
+/ SDivRem(int64_t x, int64_t y, int64_t * pmod)
+/ {
+/ int negative;
+/ uint64_t xt, yt, r, rem;
+/
+/ if (x < 0) {
+/ xt = -(uint64_t) x;
+/ negative = 1;
+/ } else {
+/ xt = x;
+/ negative = 0;
+/ }
+/ if (y < 0) {
+/ yt = -(uint64_t) y;
+/ negative ^= 1;
+/ } else {
+/ yt = y;
+/ }
+/ r = UDivRem(xt, yt, &rem);
+/ *pmod = (x < 0 ? (int64_t) - rem : rem);
+/ return (negative ? (int64_t) - r : r);
+/ }
+ ENTRY(SDivRem)
+ pushl %ebp
+ pushl %edi
+ pushl %esi
+ subl $24, %esp
+ testl %edx, %edx / x
+ movl %edx, %edi / x, x
+ js .LL73
+ movl 44(%esp), %esi / y,
+ xorl %ebp, %ebp / negative
+ testl %esi, %esi
+ movl %edx, 12(%esp) / x, xt
+ movl %eax, 8(%esp) / x, xt
+ movl 40(%esp), %edx / y, yt
+ movl 44(%esp), %ecx / y, yt
+ js .LL74
+.LL70:
+ leal 16(%esp), %eax /, tmp70
+ pushl %eax / tmp70
+ pushl %ecx / yt
+ pushl %edx / yt
+ movl 20(%esp), %eax / xt, xt
+ movl 24(%esp), %edx / xt, xt
+ call UDivRem
+ movl %edx, 16(%esp) /, r
+ movl %eax, 12(%esp) /, r
+ addl $12, %esp
+ testl %edi, %edi / x
+ movl 16(%esp), %edx / rem, rem
+ movl 20(%esp), %ecx / rem, rem
+ js .LL75
+.LL71:
+ movl 48(%esp), %edi / pmod, pmod
+ testl %ebp, %ebp / negative
+ movl %edx, (%edi) / rem,* pmod
+ movl %ecx, 4(%edi) / rem,
+ movl (%esp), %eax / r, r
+ movl 4(%esp), %edx / r, r
+ je .LL72
+ negl %eax / r
+ adcl $0, %edx /, r
+ negl %edx / r
+.LL72:
+ addl $24, %esp
+ popl %esi
+ popl %edi
+ popl %ebp
+ ret
+ .align 16
+.LL73:
+ negl %eax
+ adcl $0, %edx
+ movl 44(%esp), %esi / y,
+ negl %edx
+ testl %esi, %esi
+ movl %edx, 12(%esp) /, xt
+ movl %eax, 8(%esp) /, xt
+ movl $1, %ebp /, negative
+ movl 40(%esp), %edx / y, yt
+ movl 44(%esp), %ecx / y, yt
+ jns .LL70
+ .align 16
+.LL74:
+ negl %edx / yt
+ adcl $0, %ecx /, yt
+ negl %ecx / yt
+ xorl $1, %ebp /, negative
+ jmp .LL70
+ .align 16
+.LL75:
+ negl %edx / rem
+ adcl $0, %ecx /, rem
+ negl %ecx / rem
+ jmp .LL71
+ SET_SIZE(SDivRem)
+
+/*
+ * __divrem64
+ *
+ * Perform division of two signed 64-bit quantities, returning the
+ * quotient in %edx:%eax, and the remainder in %ecx:%esi. __divrem64
+ * pops the arguments on return.
+ */
+ ENTRY(__divrem64)
+ subl $20, %esp
+ movl %esp, %ecx /, tmp64
+ movl 24(%esp), %eax / x, x
+ movl 28(%esp), %edx / x, x
+ pushl %ecx / tmp64
+ pushl 40(%esp) / y
+ pushl 40(%esp)
+ call SDivRem
+ movl 16(%esp), %ecx
+ movl 12(%esp),%esi / rem
+ addl $32, %esp
+ ret $16
+ SET_SIZE(__divrem64)
+#endif /* lint */
diff --git a/usr/src/psm/stand/boot/inc.flg b/usr/src/psm/stand/boot/inc.flg
new file mode 100644
index 0000000000..87b058d63e
--- /dev/null
+++ b/usr/src/psm/stand/boot/inc.flg
@@ -0,0 +1,48 @@
+#!/bin/sh
+#
+# 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.
+#
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Get required header files
+#
+find_files "s.*.h"\
+ usr/src/uts/sparc\
+ usr/src/uts/sun\
+ usr/src/uts/common/sys\
+ usr/src/uts/common/vm\
+ usr/src/uts/common/rpc\
+ usr/src/uts/common/nfs\
+ usr/src/stand/sys
+#
+# Get required directories
+#
+find_files "s.*"\
+ usr/src/psm/promif\
+ usr/src/stand/lib
+
+echo_file usr/src/lib/Makefile.lib
diff --git a/usr/src/psm/stand/boot/sparc/common/boot.c b/usr/src/psm/stand/boot/sparc/common/boot.c
new file mode 100644
index 0000000000..acfbad580b
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/boot.c
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ *
+ * 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 2003 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/salib.h>
+#include <sys/stat.h>
+#include <sys/promif.h>
+#include <sys/bootvfs.h>
+#include <sys/boot_redirect.h>
+#include "boot_plat.h"
+
+/*
+ * This implementation of bootprog() is used by all bootloaders except wanboot.
+ */
+
+#define SUCCESS 0
+#define FAILURE -1
+
+/*
+ * 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)
+{
+ boolean_t once = B_FALSE;
+
+ systype = set_fstype(v2path, bpath);
+
+loop:
+ /*
+ * Beware: the following code may be executed twice, with different
+ * bpath's if we discover a redirection file.
+ */
+
+ 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);
+
+ if (!once &&
+ (strcmp(systype, "ufs") == 0 || strcmp(systype, "hsfs") == 0)) {
+ char redirect[OBP_MAXPATHLEN];
+
+ post_mountroot(filename, redirect);
+
+ /*
+ * If we return at all, it's because we discovered
+ * a redirection file - the 'redirect' string now contains
+ * the name of the disk slice we should be looking at.
+ *
+ * Unmount the filesystem, tweak the boot path and retry
+ * the whole operation one more time.
+ */
+ closeall(1);
+ once = B_TRUE;
+ redirect_boot_path(bpath, redirect);
+ if (verbosemode)
+ printf("%sboot: using '%s'\n", systype, bpath);
+
+ goto loop;
+ /*NOTREACHED*/
+ }
+
+ return (0);
+}
diff --git a/usr/src/psm/stand/boot/sparc/common/boot_plat.c b/usr/src/psm/stand/boot/sparc/common/boot_plat.c
new file mode 100644
index 0000000000..0a74ed0980
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/boot_plat.c
@@ -0,0 +1,682 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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"
+
+#define SUCCESS 0
+#define FAILURE -1
+
+#define ISSPACE(c) (c == ' ' || c == '\t')
+#define SKIP_WHITESPC(cp) while (*cp && ISSPACE(*cp)) cp++;
+
+
+#ifdef DEBUG
+int debug = 0;
+#else
+static const int debug = 0;
+#endif
+
+#define dprintf if (debug) printf
+
+#ifdef DEBUG_LISTS
+void print_memlist(struct memlist *av);
+#endif
+
+extern int (*readfile(int fd, int print))();
+extern void kmem_init(void);
+extern void *kmem_alloc(size_t, int);
+extern void kmem_free(void *, size_t);
+extern void get_boot_args(char *buf);
+extern void setup_bootops(void);
+extern struct bootops bootops;
+extern void exitto(int (*entrypoint)());
+extern void exitto64(int (*entrypoint)(), void *bootvec);
+
+int openfile(char *filename);
+
+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";
+
+/*
+ * We enable the cache by default
+ * but boot -n will leave it alone...
+ * that is, we use whatever state the PROM left it in.
+ */
+char *mfg_name;
+int cache_state = 1;
+char filename2[MAXPATHLEN];
+
+int boothowto = 0;
+int verbosemode = 0;
+
+
+/*
+ * Copy filename and bargs into v2args_buf, which will be exported as the
+ * boot-args boot property. We should probably warn the user if anything gets
+ * cut off.
+ */
+void
+set_client_bootargs(const char *filename, const char *bargs)
+{
+ int i = 0;
+ const char *s;
+
+ s = filename;
+ while (*s != '\0' && i < V2ARGS_BUF_SZ - 1)
+ v2args_buf[i++] = *s++;
+
+ if (i >= V2ARGS_BUF_SZ - 2) {
+ /* Not enough room for a space and any of bargs. */
+ v2args_buf[i] = '\0';
+ return;
+ }
+
+ v2args_buf[i++] = ' ';
+
+ s = bargs;
+ while (*s != '\0' && i < V2ARGS_BUF_SZ - 1)
+ v2args_buf[i++] = *s++;
+
+ v2args_buf[i] = '\0';
+}
+
+/*
+ * The slice redirection file is used on the install CD
+ */
+static int
+read_redirect(char *redirect)
+{
+ int fd;
+ char slicec;
+ size_t nread = 0;
+
+ if ((fd = open(BOOT_REDIRECT, O_RDONLY)) != -1) {
+ /*
+ * Read the character out of the file - this is the
+ * slice to use, in base 36.
+ */
+ nread = read(fd, &slicec, 1);
+ (void) close(fd);
+ if (nread == 1)
+ *redirect++ = slicec;
+ }
+ *redirect = '\0';
+
+ return (nread == 1);
+}
+
+void
+post_mountroot(char *bootfile, char *redirect)
+{
+ int (*go2)();
+ int fd;
+
+ /* Save the bootfile, just in case we need it again */
+ (void) strcpy(filename2, bootfile);
+
+ for (;;) {
+ if (boothowto & RB_ASKNAME) {
+ char tmpname[MAXPATHLEN];
+
+ printf("Enter filename [%s]: ", bootfile);
+ (void) cons_gets(tmpname, sizeof (tmpname));
+ if (tmpname[0] != '\0')
+ (void) strcpy(bootfile, tmpname);
+ }
+
+ if (boothowto & RB_HALT) {
+ printf("Boot halted.\n");
+ prom_enter_mon();
+ }
+
+ if ((fd = openfile(bootfile)) == FAILURE) {
+
+ /*
+ * There are many reasons why this might've
+ * happened .. but one of them is that we're
+ * on the installation CD, and we need to
+ * revector ourselves off to a different partition
+ * of the CD. Check for the redirection file.
+ */
+ if (redirect != NULL &&
+ read_redirect(redirect)) {
+ /* restore bootfile */
+ (void) strcpy(bootfile, filename2);
+ return;
+ /*NOTREACHED*/
+ }
+
+ printf("%s: cannot open %s\n", my_own_name, bootfile);
+ boothowto |= RB_ASKNAME;
+
+ /* restore bootfile */
+ (void) strcpy(bootfile, filename2);
+ continue;
+ }
+
+ if ((go2 = readfile(fd, boothowto & RB_VERBOSE)) !=
+ (int(*)()) -1) {
+#ifdef MPSAS
+ sas_bpts();
+#endif
+ (void) close(fd);
+ } else {
+ printf("boot failed\n");
+ boothowto |= RB_ASKNAME;
+ continue;
+ }
+
+ if (boothowto & RB_HALT) {
+ printf("Boot halted before exit to 0x%p.\n",
+ (void *)go2);
+ prom_enter_mon();
+ }
+
+ my_own_name = bootfile;
+
+ dprintf("Calling exitto64(%p, %p)\n", (void *)go2,
+ (void *)elfbootvecELF64);
+ exitto64(go2, (void *)elfbootvecELF64);
+ }
+}
+
+/*ARGSUSED*/
+static int
+boot_open(char *pathname, void *arg)
+{
+ dprintf("trying '%s'\n", pathname);
+ 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.
+ *
+ * Boot supports OBP and IEEE1275.
+ *
+ * XXX: Move side effects out of this function!
+ */
+int
+openfile(char *filename)
+{
+ static char *fullpath;
+ static char *iarch;
+ static char *orig_impl_arch_name;
+ static int once;
+ int fd;
+
+ if (once == 0) {
+
+ ++once;
+
+ /*
+ * Setup exported 'boot' properties: 'mfg-name'.
+ * XXX: This shouldn't be a side effect of openfile().
+ */
+ 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);
+ if (fd == -1)
+ return (-1);
+
+ /*
+ * Copy back the name we actually found
+ */
+ (void) strcpy(filename, fullpath);
+ return (fd);
+}
+
+/*
+ * Get the boot arguments from the PROM and split it into filename and
+ * options components.
+ *
+ * As per IEEE1275 and boot(1M), the boot arguments will have the syntax
+ * "[filename] [-options]". If filename is specified, it is copied into the
+ * first buffer. (Otherwise, the buffer is left alone.) The rest of the string
+ * is copied into the second buffer.
+ */
+static void
+init_bootargs(char *fname_buf, int fname_buf_sz, char *bargs_buf,
+ int bargs_buf_sz)
+{
+ const char *tp = prom_bootargs();
+
+ if (!tp || *tp == '\0') {
+ *bargs_buf = '\0';
+ return;
+ }
+
+ SKIP_WHITESPC(tp);
+
+ /*
+ * If we don't have an option indicator, then we
+ * already have our filename prepended.
+ */
+ if (*tp && *tp != '-') {
+ int i;
+
+ /*
+ * Copy the filename into fname_buf.
+ */
+ for (i = 0; i < fname_buf_sz && *tp && !ISSPACE(*tp); ++i)
+ *fname_buf++ = *tp++;
+
+ if (i >= fname_buf_sz) {
+ printf("boot: boot filename too long!\n");
+ printf("boot halted.\n");
+ prom_enter_mon();
+ /*NOTREACHED*/
+ } else {
+ *fname_buf = '\0';
+ }
+
+ SKIP_WHITESPC(tp);
+ }
+
+ /* The rest of the line is the options. */
+ while (bargs_buf_sz > 1 && *tp) {
+ *bargs_buf++ = *tp++;
+ --bargs_buf_sz;
+ }
+ *bargs_buf = '\0';
+
+ if (bargs_buf_sz == 1) {
+ printf("boot: boot arguments too long!\n");
+ printf("boot halted.\n");
+ prom_enter_mon();
+ /*NOTREACHED*/
+ }
+}
+
+boolean_t
+is_netdev(char *devpath)
+{
+ dnode_t node = prom_finddevice(devpath);
+ char *options;
+
+ if ((node == OBP_NONODE) || (node == OBP_BADNODE))
+ return (B_FALSE);
+ if (prom_devicetype(node, "network") != 0)
+ return (B_TRUE);
+
+ /*
+ * For Infiniband, network device names will be of the
+ * format XXX/ib@0:port=1,pkey=1234,protocol=ip[,YYY] where
+ * XXX is typically /pci@8,700000/pci@1. The device_type
+ * property will be "ib".
+ */
+ if (prom_devicetype(node, "ib") != 0) {
+ options = prom_path_options(devpath);
+ if (options != NULL) {
+
+#define SEARCHSTRING ",protocol=ip"
+#define SEARCHSTRLEN strlen(SEARCHSTRING)
+
+ if (strstr(options, ",protocol=ip,") != NULL)
+ return (B_TRUE);
+ while ((options = strstr(options, SEARCHSTRING)) !=
+ NULL) {
+ char nextc;
+
+ nextc = options[SEARCHSTRLEN];
+ if ((nextc == ',') || (nextc == 0))
+ return (B_TRUE);
+ options += SEARCHSTRLEN;
+ }
+ }
+ }
+ return (B_FALSE);
+}
+
+/*
+ * Hook for modifying the OS boot path. This hook allows us to handle
+ * device arguments that the OS can't handle.
+ */
+void
+mangle_os_bootpath(char *bpath)
+{
+ dnode_t node;
+ char *stripped_pathname;
+
+ node = prom_finddevice(bpath);
+ if (prom_devicetype(node, "network") == 0)
+ return;
+
+ /*
+ * The OS can't handle network device arguments
+ * eg: boot net:promiscuous,speed=100,duplex=full
+ * So, we remove any argument strings in the device
+ * pathname we hand off to the OS for network devices.
+ *
+ * Internally, within boot, bpath is used to access
+ * the device, but v2path (as the boot property "boot-path")
+ * is the pathname passed to the OS.
+ */
+
+ stripped_pathname = kmem_alloc(OBP_MAXPATHLEN, 0);
+ prom_strip_options(bpath, stripped_pathname);
+ v2path = stripped_pathname;
+}
+
+/*
+ * Given the boot path in the native firmware format use
+ * the redirection string to mutate the boot path to the new device.
+ * Fix up the 'v2path' so that it matches the new firmware path.
+ */
+void
+redirect_boot_path(char *bpath, char *redirect)
+{
+ char slicec = *redirect;
+ char *p = bpath + strlen(bpath);
+
+ /*
+ * If the redirection character doesn't fall in this
+ * range, something went horribly wrong.
+ */
+ if (slicec < '0' || slicec > '7') {
+ printf("boot: bad redirection slice '%c'\n", slicec);
+ return;
+ }
+
+ /*
+ * Handle fully qualified OpenBoot pathname.
+ */
+ while (--p >= bpath && *p != '@' && *p != '/')
+ if (*p == ':')
+ break;
+ if (*p++ == ':') {
+ /*
+ * Convert slice number to partition 'letter'.
+ */
+ *p++ = 'a' + slicec - '0';
+ *p = '\0';
+ v2path = bpath;
+ return;
+ }
+ prom_panic("redirect_boot_path: mangled boot path!");
+}
+
+#define PROM_VERS_MAX_LEN 64
+
+void
+system_check(void)
+{
+ char buf[PROM_VERS_MAX_LEN];
+
+ if (cpu_is_ultrasparc_1()) {
+ printf("UltraSPARC I processors are not supported by this "
+ "release of Solaris.\n");
+ prom_exit_to_mon();
+ }
+
+ if (prom_version_check(buf, PROM_VERS_MAX_LEN, NULL) != PROM_VER64_OK) {
+ printf("The firmware on this system does not support the 64-bit"
+ " OS.\n\tPlease upgrade to at least the following version:"
+ "\n\n\t%s\n", buf);
+ prom_exit_to_mon();
+ }
+}
+
+/*
+ * Reads in the standalone (client) program and jumps to it. If this
+ * attempt fails, prints "boot failed" and returns to its caller.
+ *
+ * It will try to determine if it is loading a Unix file by
+ * looking at what should be the magic number. If it makes
+ * sense, it will use it; otherwise it jumps to the first
+ * address of the blocks that it reads in.
+ *
+ * This new boot program will open a file, read the ELF header,
+ * attempt to allocate and map memory at the location at which
+ * the client desires to be linked, and load the program at
+ * that point. It will then jump there.
+ */
+/*ARGSUSED*/
+int
+main(void *cookie, char **argv, int argc)
+{
+ /*
+ * bpath is the boot device path buffer.
+ * bargs is the boot arguments buffer.
+ */
+ static char bpath[OBP_MAXPATHLEN], bargs[OBP_MAXPATHLEN];
+ boolean_t user_specified_filename;
+
+ prom_init("boot", cookie);
+ fiximp();
+
+ system_check();
+
+ dprintf("\nboot: V%d /boot interface.\n", BO_VERSION);
+#ifdef HALTBOOT
+ prom_enter_mon();
+#endif /* HALTBOOT */
+
+ init_memlists();
+
+#ifdef DEBUG_LISTS
+ dprintf("Physmem avail:\n");
+ if (debug) print_memlist(pfreelistp);
+ dprintf("Virtmem avail:\n");
+ if (debug) print_memlist(vfreelistp);
+ dprintf("Phys installed:\n");
+ if (debug) print_memlist(pinstalledp);
+ prom_enter_mon();
+#endif /* DEBUG_LISTS */
+
+ /*
+ * Initialize the default filename (exported as "default-name" and
+ * used by kadb).
+ */
+ set_default_filename(defname);
+
+ /*
+ * Parse the arguments ASAP in case there are any flags which may
+ * affect execution.
+ */
+
+ /*
+ * filename is the path to the standalone. Initialize it to the empty
+ * string so we can tell whether the user specified it in the
+ * arguments.
+ */
+ filename[0] = '\0';
+
+ /*
+ * Fetch the boot arguments from the PROM and split the filename off
+ * if it's there.
+ */
+ init_bootargs(filename, sizeof (filename), bargs, sizeof (bargs));
+
+ /*
+ * kadb was delivered as a standalone, and as such, people got used to
+ * typing `boot kadb'. kmdb isn't a standalone - it is loaded by krtld
+ * as just another kernel module. For compatibility, though, when we
+ * see an attempt to `boot kadb' or `boot kmdb', we'll transform that
+ * into a `boot -k' (or equivalent).
+ */
+ if (strcmp(filename, "kmdb") == 0 || strcmp(filename, "kadb") == 0) {
+ boothowto |= RB_KMDB;
+ *filename = '\0'; /* let boot figure out which unix to use */
+ }
+
+ bootflags(bargs, sizeof (bargs));
+
+ user_specified_filename = (filename[0] != '\0');
+
+ /* Fetch the boot path from the PROM. */
+ (void) strncpy(bpath, prom_bootpath(), sizeof (bpath) - 1);
+ bpath[sizeof (bpath) - 1] = '\0';
+
+ dprintf("bootpath: 0x%p %s\n", (void *)bpath, bpath);
+ dprintf("bootargs: 0x%p %s\n", (void *)bargs, bargs);
+ dprintf("filename: 0x%p %s\n", (void *)filename, filename);
+ dprintf("kernname: 0x%p %s\n", (void *)kernname, kernname);
+
+ /*
+ * *v2path will be exported to the standalone as the boot-path boot
+ * property.
+ */
+ v2path = bpath;
+
+ /*
+ * Our memory lists should be "up" by this time
+ */
+
+ setup_bootops();
+
+ /*
+ * If bpath is a network card, set v2path to a copy of bpath with the
+ * options stripped off.
+ */
+ mangle_os_bootpath(bpath);
+
+#ifdef sun4u
+ retain_nvram_page();
+#endif
+
+ if (bootprog(bpath, bargs, user_specified_filename) == 0) {
+ post_mountroot(filename, NULL);
+ /*NOTREACHED*/
+ }
+
+ return (0);
+}
diff --git a/usr/src/psm/stand/boot/sparc/common/boot_plat.h b/usr/src/psm/stand/boot/sparc/common/boot_plat.h
new file mode 100644
index 0000000000..99066f70bb
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/boot_plat.h
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _BOOT_PLAT_H
+#define _BOOT_PLAT_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+/* boot_plat.c */
+extern char *cmd_line_default_path;
+extern int verbosemode;
+extern char filename[];
+extern char *const defname;
+extern char *const defname64;
+extern char wanboot_arguments[];
+
+extern int bootprog(char *, char *, boolean_t);
+extern char *choose_default_filename(char *, char *);
+extern char *get_default_filename(void);
+extern void post_mountroot(char *, char *);
+extern void redirect_boot_path(char *, char *);
+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);
+
+
+/*
+ * bootprop.c. These variables will be exported to the standalone as boot
+ * properties.
+ */
+extern char *v2path, *kernname, *systype, *my_own_name;
+extern char v2args_buf[];
+#define V2ARGS_BUF_SZ OBP_MAXPATHLEN
+extern char *v2args;
+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;
+
+extern void set_default_filename(char *filename);
+
+
+/* get.c */
+extern int cons_gets(char *, int);
+
+
+/* machdep.c */
+extern int vac;
+
+extern void fiximp(void);
+extern void retain_nvram_page();
+
+#ifdef MPSAS
+extern void sas_bpts(void);
+#endif
+
+extern int cpu_is_ultrasparc_1(void);
+
+
+/* memlist.c */
+extern void init_memlists(void);
+extern struct memlist *fill_memlists(char *name, char *prop,
+ struct memlist *old);
+
+
+/* srt0.c */
+extern void _start(void *romp, ...);
+extern void exitto(int (*entrypoint)());
+extern void exitto64(int (*entrypoint)(), void *bootvec);
+
+
+/* standalloc.c */
+extern caddr_t memlistpage;
+extern caddr_t scratchmemp;
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _BOOT_PLAT_H */
diff --git a/usr/src/psm/stand/boot/sparc/common/boot_services.c b/usr/src/psm/stand/boot/sparc/common/boot_services.c
new file mode 100644
index 0000000000..16a7acaebe
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/boot_services.c
@@ -0,0 +1,713 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Definitions of interfaces that provide services from the secondary
+ * boot program to its clients (primarily unix, krtld and their successors.)
+ * This interface replaces the bootops (BOP) implementation as the interface
+ * to be called by boot clients. The BOP macros are still used to make the
+ * integration easier.
+ *
+ * The bootops vector is vestigial.
+ *
+ * The kern_* routines used to implement many of the services here
+ * are in the usr/src/stand/lib/ modules.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/bootconf.h>
+#include <sys/reboot.h>
+#include <sys/param.h>
+#include <sys/varargs.h>
+#include <sys/obpdefs.h>
+#include <sys/promif.h>
+#include <sys/salib.h>
+#include <sys/stat.h>
+#include <sys/bootvfs.h>
+
+extern void kern_killboot(void);
+extern int bgetprop(struct bootops *, char *name, void *buf);
+extern int bgetproplen(struct bootops *, char *name);
+extern char *bnextprop(struct bootops *, char *prev);
+extern caddr_t resalloc_virt(caddr_t virt, size_t size);
+
+static int boot1275_serviceavail(void *p);
+
+static struct boot_nm2svc *nm2svcp(char *name);
+
+/*
+ * Implementation of the "version" service.
+ * Return the compiled version number of this implementation of boot.
+ *
+ * Calling spec:
+ * args[0] Service name string
+ * args[1] #argument cells
+ * args[2] #result cells
+ * args[3] Res0: returned version number
+ */
+static int boot_version = BO_VERSION;
+static int
+boot1275_getversion(void *p)
+{
+ boot_cell_t *args = (boot_cell_t *)p;
+
+ args[3] = boot_int2cell(boot_version);
+ return (BOOT_SVC_OK);
+}
+
+/*
+ * 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
+ *
+ */
+static int
+boot1275_open(void *p)
+{
+ int rc;
+ int flags;
+ char *name;
+ boot_cell_t *args = (boot_cell_t *)p;
+
+ name = boot_cell2ptr(args[3]);
+ flags = boot_cell2int(args[4]);
+ rc = kern_open(name, flags);
+ args[5] = boot_int2cell(rc);
+ return (BOOT_SVC_OK);
+}
+
+/*
+ * 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
+ *
+ */
+static int
+boot1275_read(void *p)
+{
+ int rc;
+ boot_cell_t *args = (boot_cell_t *)p;
+
+ /* XXX use different routine to support larger I/O ? */
+ int fd;
+ caddr_t buf;
+ size_t size;
+
+ fd = boot_cell2int(args[3]);
+ buf = boot_cell2ptr(args[4]);
+ size = boot_cell2size(args[5]);
+ rc = kern_read(fd, buf, size);
+ args[6] = boot_int2cell(rc);
+ return (BOOT_SVC_OK);
+}
+
+/*
+ * 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
+ *
+ */
+static int
+boot1275_seek(void *p)
+{
+ off_t rc;
+ int fd;
+ off_t hi, lo;
+ boot_cell_t *args = (boot_cell_t *)p;
+
+ fd = boot_cell2int(args[3]);
+ hi = boot_cell2offt(args[4]);
+ lo = boot_cell2offt(args[5]);
+ rc = kern_lseek(fd, hi, lo);
+ args[6] = boot_offt2cell(rc);
+ return (BOOT_SVC_OK);
+}
+
+/*
+ * 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
+ *
+ */
+static int
+boot1275_close(void *p)
+{
+ int rc;
+ int fd;
+ boot_cell_t *args = (boot_cell_t *)p;
+
+ fd = boot_cell2int(args[3]);
+ rc = kern_close(fd);
+ args[4] = boot_int2cell(rc);
+ return (BOOT_SVC_OK);
+}
+
+/*
+ * Implementation of the "alloc" 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 allocate
+ * args[5] alignment
+ * args[6] Res0: returned result
+ */
+static int
+boot1275_alloc(void *p)
+{
+ caddr_t virthint, addr;
+ size_t size;
+ int align;
+ boot_cell_t *args = (boot_cell_t *)p;
+
+ virthint = boot_cell2ptr(args[3]);
+ size = boot_cell2size(args[4]);
+ align = boot_cell2int(args[5]);
+ addr = kern_resalloc(virthint, size, align);
+ args[6] = boot_ptr2cell(addr);
+ return (BOOT_SVC_OK);
+}
+
+/*
+ * Implementation of the "alloc_virt" boot service.
+ *
+ * Calling spec:
+ * args[0] Service name string
+ * args[1] #arguments cells
+ * args[2] #result cells
+ * args[3] virtual address
+ * args[4] size to allocate
+ * args[5] Res0: returned result
+ */
+static int
+boot1275_alloc_virt(void *p)
+{
+ caddr_t virt, addr;
+ size_t size;
+ boot_cell_t *args = (boot_cell_t *)p;
+
+ virt = boot_cell2ptr(args[3]);
+ size = boot_cell2size(args[4]);
+ addr = resalloc_virt(virt, size);
+ args[5] = boot_ptr2cell(addr);
+ return (BOOT_SVC_OK);
+}
+
+/*
+ * Implementation of the "free" boot service.
+ *
+ * Calling spec:
+ * args[0] Service name string
+ * args[1] #argument cells
+ * args[2] #result cells
+ * args[3] virtual addr
+ * args[4] size to free
+ * args[5] Res0: returned result
+ */
+/*ARGSUSED*/
+static int
+boot1275_free(void *p)
+{
+ caddr_t virtaddr;
+ size_t size;
+ boot_cell_t *args = (boot_cell_t *)p;
+
+ virtaddr = boot_cell2ptr(args[3]);
+ size = boot_cell2size(args[4]);
+ kern_resfree(virtaddr, size);
+ args[5] = (boot_cell_t)0;
+ return (BOOT_SVC_OK);
+}
+
+/*
+ * 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
+ */
+/*ARGSUSED*/
+static int
+boot1275_map(void *p)
+{
+ boot_cell_t *args = (boot_cell_t *)p;
+
+ args[6] = (boot_cell_t)0;
+ return (BOOT_SVC_OK);
+}
+
+/*
+ * 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
+ */
+/*ARGSUSED*/
+static int
+boot1275_unmap(void *p)
+{
+ boot_cell_t *args = (boot_cell_t *)p;
+
+ args[5] = (boot_cell_t)0;
+ return (BOOT_SVC_OK);
+}
+
+/*
+ * 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
+ */
+/*ARGSUSED*/
+static int
+boot1275_quiesce(void *p)
+{
+ boot_cell_t *args = (boot_cell_t *)p;
+
+ kern_killboot();
+ args[3] = (boot_cell_t)0;
+ return (BOOT_SVC_OK);
+}
+
+/*
+ * 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*/
+static int
+boot1275_getproplen(void *p)
+{
+ int rc;
+ char *name;
+ boot_cell_t *args = (boot_cell_t *)p;
+
+
+ name = boot_cell2ptr(args[3]);
+ rc = bgetproplen((struct bootops *)0, name);
+ args[4] = boot_int2cell(rc);
+ return (BOOT_SVC_OK);
+}
+
+/*
+ * 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*/
+static int
+boot1275_getprop(void *p)
+{
+ int rc;
+ char *name;
+ void *buf;
+ boot_cell_t *args = (boot_cell_t *)p;
+
+
+ name = boot_cell2ptr(args[3]);
+ buf = boot_cell2ptr(args[4]);
+ rc = bgetprop((struct bootops *)0, name, buf);
+ args[5] = boot_int2cell(rc);
+ return (BOOT_SVC_OK);
+}
+
+/*
+ * 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
+ *
+ * The bootops interface can only pass one additional
+ * argument. Abusing the format string can cause failures
+ * in interesting ways that could be hard to debug when
+ * an argument is pulled off the stack or dereferenced,
+ * so if the format string indicates more than one argument,
+ * we note the problem rather print garbage or panic.
+ */
+/*ARGSUSED*/
+static int
+boot1275_putsarg(void *p)
+{
+ const char *string;
+ boot_cell_t *args = (boot_cell_t *)p;
+ const char *fmt;
+ int ells = 0;
+ int arg_is_ptr = 0;
+ int nargs = 0;
+ uint64_t arg;
+
+
+ string = boot_cell2ptr(args[3]);
+ arg = boot_cell2uint64(args[4]);
+
+ /*
+ * We need to do the minimum printf-like stuff here to figure
+ * out the size of argument, if present.
+ */
+ for (fmt = string; *fmt; fmt++) {
+ if (*fmt != '%')
+ continue;
+ if (*(++fmt) == '%')
+ continue;
+
+ nargs++;
+ while (*fmt >= '0' && *fmt <= '9')
+ fmt++;
+ for (ells = 0; *fmt == 'l'; fmt++)
+ ells++;
+
+ switch (*fmt) {
+ case 's':
+ case 'p':
+ arg_is_ptr = 1;
+ break;
+ }
+ }
+
+ if (nargs > 1) {
+ printf("boot1275_putsarg: unsupported format: \"%s\"\n",
+ string);
+ } else if (arg_is_ptr) {
+ printf(string, (void *)arg);
+ } else {
+ switch (ells) {
+ case 0:
+ printf(string, (uint_t)arg);
+ break;
+ case 1:
+ printf(string, (ulong_t)arg);
+ break;
+ default:
+ printf(string, arg);
+ break;
+ }
+ }
+
+ return (BOOT_SVC_OK);
+}
+/*
+ * 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
+ */
+/*ARGSUSED*/
+static int
+boot1275_puts(void *p)
+{
+ char *string;
+ boot_cell_t *args = (boot_cell_t *)p;
+
+
+ string = boot_cell2ptr(args[3]);
+ printf("%s", string);
+ return (BOOT_SVC_OK);
+}
+
+/*
+ * 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
+ */
+/*ARGSUSED*/
+static int
+boot1275_nextprop(void *p)
+{
+ char *name, *np;
+ boot_cell_t *args = (boot_cell_t *)p;
+
+ name = boot_cell2ptr(args[3]);
+ np = bnextprop((struct bootops *)0, name);
+ args[4] = boot_ptr2cell(np);
+ return (BOOT_SVC_OK);
+}
+
+/*
+ * 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*/
+static int
+boot1275_mountroot(void *p)
+{
+ int rc;
+ char *name;
+ boot_cell_t *args = (boot_cell_t *)p;
+
+ name = boot_cell2ptr(args[3]);
+ rc = kern_mountroot(name);
+ args[4] = boot_cell2int(rc);
+ return (BOOT_SVC_OK);
+}
+
+/*
+ * Implementation of the "unmount" boot service.
+ *
+ * Calling spec:
+ * args[0] Service name string
+ * args[1] #argument cells
+ * args[2] #result cells
+ * args[3] Res0: returned result
+ */
+/*ARGSUSED*/
+static int
+boot1275_unmountroot(void *p)
+{
+ int rc;
+ boot_cell_t *args = (boot_cell_t *)p;
+
+ rc = kern_unmountroot();
+ args[3] = boot_cell2int(rc);
+ return (BOOT_SVC_OK);
+}
+
+/*
+ * 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
+ */
+int
+boot1275_fstat(void *p)
+{
+ boot_cell_t *args = (boot_cell_t *)p;
+ int fd = boot_cell2int(args[3]);
+ struct bootstat *st = boot_cell2ptr(args[4]);
+ int rc = kern_fstat(fd, st);
+
+ args[5] = boot_int2cell(rc);
+ return (BOOT_SVC_OK);
+}
+
+/*
+ * Implementation of the "interpret" boot service.
+ *
+ * Calling spec:
+ * args[0] Service name string
+ * args[1] #argument cells (1)
+ * args[2] #result cells (0)
+ * args[3] string to interpret
+ */
+int
+boot1275_interpret(void *p)
+{
+ boot_cell_t *args = (boot_cell_t *)p;
+ char *str = boot_cell2ptr(args[3]);
+
+ prom_interpret(str, 0, 0, 0, 0, 0);
+
+ return (BOOT_SVC_OK);
+}
+
+/*
+ * Implementation of the "enter_mon" boot service.
+ *
+ * Calling spec:
+ * args[0] Service name string
+ * args[1] #argument cells (0)
+ * args[2] #result cells (0)
+ */
+/*ARGSUSED*/
+int
+boot1275_enter_mon(void *p)
+{
+ prom_enter_mon();
+
+ return (BOOT_SVC_OK);
+}
+
+/*
+ * The lookup table akin to the old bootops vec
+ * for boot. Not part of the exported interface.
+ */
+static struct boot_nm2svc {
+ char *b_name;
+ int (*b_funcptr)(void *);
+ int b_svcversion;
+} boot_nm2svc[] = {
+ { "version", boot1275_getversion, 1 },
+ { "open", boot1275_open, 1 },
+ { "read", boot1275_read, 1 },
+ { "seek", boot1275_seek, 1 },
+ { "close", boot1275_close, 1 },
+ { "alloc", boot1275_alloc, 1 },
+ { "alloc_virt", boot1275_alloc_virt, 1 },
+ { "free", boot1275_free, 1 },
+ { "map", boot1275_map, 1 },
+ { "unmap", boot1275_unmap, 1 },
+ { "quiesce", boot1275_quiesce, 1 },
+ { "getproplen", boot1275_getproplen, 1 },
+ { "getprop", boot1275_getprop, 1 },
+ { "nextprop", boot1275_nextprop, 1 },
+ { "mountroot", boot1275_mountroot, 1 },
+ { "unmountroot", boot1275_unmountroot, 1 },
+ { "serviceavail", boot1275_serviceavail, 1 },
+ { "puts", boot1275_puts, 1 },
+ { "putsarg", boot1275_putsarg, 1 },
+ { "fstat", boot1275_fstat, 1 },
+ { "interpret", boot1275_interpret, 1 },
+ { "enter_mon", boot1275_enter_mon, 1 },
+ { 0, 0, 0 }
+};
+
+static struct boot_nm2svc *
+nm2svcp(char *name)
+{
+ struct boot_nm2svc *pnm2svc = &boot_nm2svc[0];
+
+ while (pnm2svc->b_name != 0) {
+ if (strcmp(pnm2svc->b_name, name))
+ pnm2svc++;
+ else {
+ return (pnm2svc);
+ }
+ }
+ return (NULL);
+}
+
+/*
+ * 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
+ */
+/*ARGSUSED*/
+static int
+boot1275_serviceavail(void *p)
+{
+ boot_cell_t *args = (boot_cell_t *)p;
+ char *name;
+ struct boot_nm2svc *pnm2svc;
+ int version = 0; /* 0 means service not avail */
+
+ name = boot_cell2ptr(args[3]);
+ pnm2svc = nm2svcp(name);
+ if (pnm2svc != 0)
+ version = pnm2svc->b_svcversion;
+ args[4] = boot_int2cell(version);
+ return (BOOT_SVC_OK);
+}
+
+int
+boot1275_entry(void *p)
+{
+ int rc = 0;
+ char *name;
+ int (*fp)();
+ boot_cell_t *args = (boot_cell_t *)p;
+ struct boot_nm2svc *pnm2svc;
+
+ name = boot_cell2ptr(args[0]);
+ pnm2svc = nm2svcp(name);
+ if (pnm2svc != NULL) {
+ fp = (int(*)())(pnm2svc->b_funcptr);
+ rc = (*fp)(args);
+ } else {
+ prom_printf("call to undefined service \"%s\"\n", name);
+ }
+ return (rc);
+}
diff --git a/usr/src/psm/stand/boot/sparc/common/bootflags.c b/usr/src/psm/stand/boot/sparc/common/bootflags.c
new file mode 100644
index 0000000000..abb4573d24
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/bootflags.c
@@ -0,0 +1,274 @@
+/*
+ * 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.
+ *
+ * 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 2004 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/bootconf.h>
+#include <sys/reboot.h>
+#include <sys/param.h>
+#include <sys/salib.h>
+#include <sys/debug.h>
+#include <sys/promif.h>
+#include <sys/boot.h>
+#include <sys/sysmacros.h>
+#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" */
+
+/*
+ * 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
+bootflags(char *args, size_t argsz)
+{
+ static char newargs[OBP_MAXPATHLEN];
+ struct gos_params params;
+ const char *cp;
+ char *np;
+ size_t npres;
+ int c;
+
+ impl_arch_name = NULL;
+ cmd_line_default_path = NULL;
+
+ params.gos_opts = "HXF:VnI:D:advhko:";
+ params.gos_strp = args;
+ getoptstr_init(&params);
+ while ((c = getoptstr(&params)) != -1) {
+ switch (c) {
+ /*
+ * Bootblock flags: ignore.
+ */
+ case 'H':
+ case 'X':
+ case 'F':
+ break;
+
+ /*
+ * Boot flags.
+ */
+ case 'V':
+ verbosemode = 1;
+ break;
+ case 'n':
+ cache_state = 0;
+ 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. "
+ "Ignoring.\n");
+ break;
+ }
+ (void) strncpy(default_path_buf, params.gos_optargp,
+ params.gos_optarglen);
+ default_path_buf[params.gos_optarglen] = '\0';
+ cmd_line_default_path = default_path_buf;
+ break;
+
+ case 'o':
+ if (params.gos_optarglen >=
+ sizeof (wanboot_arguments)) {
+ printf("boot: -o argument too long. "
+ "Ignoring.\n");
+ break;
+ }
+ (void) strncpy(wanboot_arguments, params.gos_optargp,
+ params.gos_optarglen);
+ wanboot_arguments[params.gos_optarglen] = '\0';
+ break;
+
+ case 'a':
+ boothowto |= RB_ASKNAME;
+ break;
+
+ case 'd':
+ boothowto |= RB_DEBUGENTER;
+ break;
+ case 'v':
+ boothowto |= RB_VERBOSE;
+ break;
+ case 'h':
+ boothowto |= RB_HALT;
+ break;
+
+ /* Consumed by the kernel */
+ case 'k':
+ boothowto |= RB_KMDB;
+ break;
+
+ /*
+ * Unrecognized flags: stop.
+ */
+ case '?':
+ /*
+ * Error. Either an unrecognized option, or an option
+ * without an argument. Check for the latter.
+ */
+ switch (params.gos_last_opt) {
+ case 'F':
+ /* -F is a bootblock flag, so ignore. */
+ break;
+ case 'I':
+ case 'D':
+ case 'o':
+ printf("boot: -%c flag missing required "
+ "argument. Ignoring.\n",
+ params.gos_last_opt);
+ break;
+ default:
+ /* Unrecognized option. Stop. */
+ goto done;
+ }
+ break;
+
+ default:
+ printf("boot: Ignoring unimplemented option -%c.\n", c);
+ }
+ }
+done:
+
+ /*
+ * Construct the arguments for the standalone.
+ */
+
+ *newargs = '\0';
+ np = newargs;
+
+ /*
+ * We need a dash if we encountered an unrecognized option or if we
+ * need to pass flags on.
+ */
+ if (c == '?' || (boothowto &
+ /* These flags are to be passed to the standalone. */
+ (RB_ASKNAME | RB_DEBUGENTER | RB_VERBOSE | RB_HALT | RB_KMDB))) {
+ *np++ = '-';
+
+ /*
+ * boot(1M) says to pass these on.
+ */
+ if (boothowto & RB_ASKNAME)
+ *np++ = 'a';
+
+ /*
+ * boot isn't documented as consuming these flags, so pass
+ * them on.
+ */
+ if (boothowto & RB_DEBUGENTER)
+ *np++ = 'd';
+ if (boothowto & RB_KMDB)
+ *np++ = 'k';
+ if (boothowto & RB_VERBOSE)
+ *np++ = 'v';
+ if (boothowto & RB_HALT)
+ *np++ = 'h';
+
+ /*
+ * If we didn't encounter an unrecognized flag and there's
+ * more to copy, add a space to separate these flags.
+ * (Otherwise, unrecognized flags can be appended since we
+ * started this word with a dash.)
+ */
+ if (c == -1 && params.gos_strp[0] != '\0')
+ *np++ = ' ';
+ }
+
+ npres = sizeof (newargs) - (size_t)(np - newargs);
+
+ if (c == '?') {
+ /*
+ * Unrecognized flag: Copy gos_errp to end of line or a "--"
+ * word.
+ */
+ cp = params.gos_errp;
+ while (*cp && npres > 0) {
+ if (cp[0] == '-' && cp[1] == '-' &&
+ (cp[2] == '\0' || ISSPACE(cp[2]))) {
+ cp += 2;
+ SKIP_SPC(cp);
+ break;
+ } else {
+ const char *sp = cp;
+ size_t sz;
+
+ /* Copy until the next word. */
+ while (*cp && !ISSPACE(*cp))
+ cp++;
+ while (ISSPACE(*cp))
+ cp++;
+
+ sz = MIN(npres, (size_t)(cp - sp));
+ npres -= sz;
+ bcopy(sp, np, sz);
+ np += sz;
+ }
+ }
+ } else {
+ cp = params.gos_strp;
+ }
+
+ while (npres > 0 && (*np++ = *cp++) != '\0')
+ npres--;
+
+ newargs[sizeof (newargs) - 1] = '\0';
+ (void) strlcpy(args, newargs, argsz);
+
+ /*
+ * If a default filename was specified in the args, set it.
+ */
+ if (cmd_line_default_path)
+ set_default_filename(cmd_line_default_path);
+}
diff --git a/usr/src/psm/stand/boot/sparc/common/bootops.c b/usr/src/psm/stand/boot/sparc/common/bootops.c
new file mode 100644
index 0000000000..662fcfaedc
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/bootops.c
@@ -0,0 +1,213 @@
+/*
+ * 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.
+ *
+ * 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 1996-2003 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>
+#include <sys/obpdefs.h>
+#include <sys/promif.h>
+#include <sys/salib.h>
+#include <sys/boot.h>
+#include <stddef.h>
+#include "boot_plat.h"
+
+#ifdef DEBUG
+extern int debug;
+#else
+static const int debug = 0;
+#endif
+
+#define dprintf if (debug) printf
+
+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;
+
+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;
+
+ if (!memlistpage) /* paranoia runs rampant */
+ prom_panic("\nMemlistpage not setup yet.");
+ /*
+ * The memory list should always be updated last. The prom
+ * calls which are made to update a memory list may have the
+ * undesirable affect of claiming physical memory. This may
+ * happen after the kernel has created its page free list.
+ * The kernel deals with this by comparing the n and n-1
+ * snapshots of memory. Updating the memory available list
+ * last guarantees we will have a current, accurate snapshot.
+ * See bug #1260786.
+ */
+ update_memlist("virtual-memory", "available", &vfreelistp);
+ update_memlist("memory", "available", &pfreelistp);
+
+ dprintf("\nPhysinstalled: ");
+ if (debug) print_memlist(pinstalledp);
+ dprintf("\nPhysfree: ");
+ if (debug) print_memlist(pfreelistp);
+ dprintf("\nVirtfree: ");
+ if (debug) print_memlist(vfreelistp);
+}
+
+void
+install_memlistptrs(void)
+{
+
+ /* prob only need 1 page for now */
+ memlistextent = tablep - memlistpage;
+
+ dprintf("physinstalled = %p\n", (void *)pinstalledp);
+ dprintf("physavail = %p\n", (void *)pfreelistp);
+ dprintf("virtavail = %p\n", (void *)vfreelistp);
+ dprintf("extent = 0x%lx\n", memlistextent);
+}
+
+/*
+ * A word of explanation is in order.
+ * This routine is meant to be called during
+ * boot_release(), when the kernel is trying
+ * to ascertain the current state of memory
+ * so that it can use a memlist to walk itself
+ * thru kvm_init().
+ */
+
+void
+update_memlist(char *name, char *prop, struct memlist **list)
+{
+ /* Just take another prom snapshot */
+ *list = fill_memlists(name, prop, *list);
+ install_memlistptrs();
+}
+
+/*
+ * This routine is meant to be called by the
+ * kernel to shut down all boot and prom activity.
+ * After this routine is called, PROM or boot IO is no
+ * longer possible, nor is memory allocation.
+ */
+void
+kern_killboot(void)
+{
+ if (verbosemode) {
+ dprintf("Entering boot_release()\n");
+ dprintf("\nPhysinstalled: ");
+ if (debug) print_memlist(pinstalledp);
+ dprintf("\nPhysfree: ");
+ if (debug) print_memlist(pfreelistp);
+ dprintf("\nVirtfree: ");
+ if (debug) print_memlist(vfreelistp);
+ }
+ if (debug) {
+ dprintf("Calling quiesce_io()\n");
+ prom_enter_mon();
+ }
+
+ /* close all open devices */
+ closeall(1);
+
+ /*
+ * Now we take YAPS (yet another Prom snapshot) of
+ * memory, just for safety sake.
+ *
+ * The memory list should always be updated last. The prom
+ * calls which are made to update a memory list may have the
+ * undesirable affect of claiming physical memory. This may
+ * happen after the kernel has created its page free list.
+ * The kernel deals with this by comparing the n and n-1
+ * snapshots of memory. Updating the memory available list
+ * last guarantees we will have a current, accurate snapshot.
+ * See bug #1260786.
+ */
+ update_memlist("virtual-memory", "available", &vfreelistp);
+ update_memlist("memory", "available", &pfreelistp);
+
+ if (verbosemode) {
+ dprintf("physinstalled = %p\n", (void *)pinstalledp);
+ dprintf("physavail = %p\n", (void *)pfreelistp);
+ dprintf("virtavail = %p\n", (void *)vfreelistp);
+ dprintf("extent = 0x%lx\n", memlistextent);
+ dprintf("Leaving boot_release()\n");
+
+ dprintf("Physinstalled: \n");
+ if (debug)
+ print_memlist(pinstalledp);
+
+ dprintf("Physfree:\n");
+ if (debug)
+ print_memlist(pfreelistp);
+
+ dprintf("Virtfree: \n");
+ if (debug)
+ print_memlist(vfreelistp);
+ }
+
+#ifdef DEBUG_MMU
+ dump_mmu();
+ 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/bootprop.c b/usr/src/psm/stand/boot/sparc/common/bootprop.c
new file mode 100644
index 0000000000..dcc69fa593
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/bootprop.c
@@ -0,0 +1,263 @@
+/*
+ * 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.
+ *
+ * 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 2004 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/promif.h>
+#include <sys/bootconf.h>
+#include <sys/salib.h>
+#include <sys/boot.h>
+#include "boot_plat.h"
+
+char *v2path, *kernname, *systype;
+char *my_own_name = "boot";
+char v2args_buf[V2ARGS_BUF_SZ];
+char *v2args = v2args_buf;
+char *mfg_name;
+char *impl_arch_name;
+char *bootp_response;
+char *module_path;
+int cache_state;
+uint64_t memlistextent; /* replacement for old member of bootops */
+
+/* These are the various memory lists */
+struct memlist *pfreelistp, /* physmem available */
+ *vfreelistp, /* virtmem available */
+ *pinstalledp; /* physmem installed */
+
+char *boot_message;
+
+char *netdev_path;
+
+/*
+ * Support new boot properties "boot-start" and "boot-end" for
+ * Freeze/Thaw project.
+ */
+caddr_t start_addr, end_addr;
+
+#define BOOT_BADPROP -1
+#define BOOT_SUCCESS 0
+#define BOOT_FAILURE -1
+#define NIL 0
+
+#define strequal(p, q) (strcmp((p), (q)) == 0)
+
+
+/*
+ * This routine is used by stand/lib/$PROC/libnfs.a in case it comes up with a
+ * default filename, and by bootflags() if a default filename is specified in
+ * the boot arguments.
+ */
+void
+set_default_filename(char *filename)
+{
+ kernname = filename;
+}
+
+
+static const struct bplist {
+ char *name;
+ void *val;
+ uint_t size;
+} bprop_tab[] = {
+ "boot-args", &v2args, 0,
+ "boot-path", &v2path, 0,
+ "fstype", &systype, 0,
+ "whoami", &my_own_name, 0,
+ "mfg-name", &mfg_name, 0,
+ "impl-arch-name", &impl_arch_name, 0,
+ "module-path", &module_path, 0,
+ "virt-avail", &vfreelistp, 0,
+ "phys-avail", &pfreelistp, 0,
+ "phys-installed", &pinstalledp, 0,
+ "default-name", &kernname, 0,
+ "extent", &memlistextent, sizeof (memlistextent),
+ "vac", &vac, sizeof (vac),
+ "cache-on?", &cache_state, sizeof (int),
+ "memory-update", 0, 0,
+ "boot-start", &start_addr, sizeof (start_addr),
+ "boot-end", &scratchmemp, sizeof (scratchmemp),
+ "boot-message", &boot_message, 0,
+ "bootp-response", &bootp_response, 0,
+ "netdev-path", &netdev_path, 0,
+ 0, 0, 0
+};
+
+/*
+ * These routines implement the boot getprop interface.
+ * They are designed to mimic the corresponding devr_{getprop,getproplen}
+ * functions.
+ * The assumptions is that the basic property is an unsigned int. Other
+ * types (including lists) are special cases.
+ */
+
+/*ARGSUSED*/
+int
+bgetproplen(struct bootops *bop, char *name)
+{
+ int size = 0;
+ struct bplist *p;
+ struct memlist *ml;
+
+ /* this prop has side effects only. No length. */
+ if (strequal(name, "memory-update"))
+ return (BOOT_SUCCESS);
+
+ for (p = (struct bplist *)bprop_tab; p->name != (char *)0; p++) {
+
+ /* got a linked list? */
+ if ((strequal(name, "virt-avail") && strequal(name, p->name)) ||
+ (strequal(name, "phys-avail") && strequal(name, p->name)) ||
+ (strequal(name, "phys-installed") &&
+ strequal(name, p->name))) {
+
+ for (ml = *((struct memlist **)p->val);
+ ml != NIL;
+ ml = ml->next)
+
+ /*
+ * subtract out the ptrs for our local
+ * linked list. The application will
+ * only see an array.
+ */
+ size += (int)(sizeof (struct memlist) -
+ 2*sizeof (struct memlist *));
+ return (size);
+
+ } else if (strequal(name, p->name)) {
+
+ /* if we already know the size, return it */
+ if (p->size != 0)
+ return (p->size);
+ else {
+ if (*((char **)p->val) == NIL)
+ return (0); /* NULL is allowed */
+
+ /* don't forget the null termination */
+ return (strlen(*((char **)p->val)) + 1);
+ }
+ }
+ }
+ printf("Property (%s) not supported by %s\n", name, my_own_name);
+ return (BOOT_BADPROP);
+}
+
+/*ARGSUSED*/
+int
+bgetprop(struct bootops *bop, char *name, void *buf)
+{
+ struct bplist *p;
+ struct memlist *ml;
+
+ if (strequal(name, "memory-update")) {
+/*
+ * dprintf("bgetprop: updating memlists.\n");
+ */
+ update_memlist("virtual-memory", "available", &vfreelistp);
+ update_memlist("memory", "available", &pfreelistp);
+ return (BOOT_SUCCESS);
+ }
+
+ if (strequal(name, "boot-start")) {
+ start_addr = (caddr_t)_start;
+ bcopy((char *)(&start_addr), buf, sizeof (start_addr));
+ return (BOOT_SUCCESS);
+ }
+
+ if (strequal(name, "boot-end")) {
+ /*
+ * The true end of boot should be scratchmemp,
+ * boot gets its dynamic memory from the scratchmem
+ * which is the first 4M of the physical memory,
+ * and they are mapped 1:1.
+ */
+ end_addr = scratchmemp;
+ bcopy((char *)(&end_addr), buf, sizeof (scratchmemp));
+ return (BOOT_SUCCESS);
+ }
+
+ for (p = (struct bplist *)bprop_tab; p->name != (char *)0; p++) {
+
+ /* gotta linked list? */
+ if ((strequal(name, "virt-avail") && strequal(name, p->name)) ||
+ (strequal(name, "phys-avail") && strequal(name, p->name)) ||
+ (strequal(name, "phys-installed") &&
+ strequal(name, p->name))) {
+
+ u_longlong_t *t = buf;
+
+ for (ml = *((struct memlist **)p->val);
+ ml != NIL;
+ ml = ml->next) {
+
+ /* copy out into an array */
+ *t++ = ml->address;
+ *t++ = ml->size;
+ }
+ return (BOOT_SUCCESS);
+ } else if (strequal(name, p->name)) {
+ if (p->size != 0) {
+ bcopy(p->val, buf, p->size);
+ } else {
+ (void) strcpy((char *)buf, *((char **)p->val));
+ }
+ return (BOOT_SUCCESS);
+ }
+ }
+ return (BOOT_FAILURE);
+}
+
+/*
+ * If the user wants the first property in the list, he passes in a
+ * null string. The routine will always return a ptr to the name of the
+ * next prop, except when there are no more props. In that case, it will
+ * return a null string.
+ */
+
+/*ARGSUSED*/
+char *
+bnextprop(struct bootops *bop, char *prev)
+{
+ struct bplist *p;
+
+ /* user wants the firstprop */
+ if (*prev == 0)
+ return (bprop_tab->name);
+
+ for (p = (struct bplist *)bprop_tab; p->name != (char *)0; p++) {
+
+ if (strequal(prev, p->name))
+ /*
+ * if prev is the last valid prop,
+ * we will return our terminator (0).
+ */
+ return ((++p)->name);
+
+
+ }
+ return ((char *)0);
+}
diff --git a/usr/src/psm/stand/boot/sparc/common/get.c b/usr/src/psm/stand/boot/sparc/common/get.c
new file mode 100644
index 0000000000..2fa5b99c0e
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/get.c
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ *
+ * 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 2003 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/promif.h>
+
+int
+getchar(void)
+{
+ register int c;
+
+ while ((c = prom_mayget()) == -1)
+ ;
+ if (c == '\r') {
+ prom_putchar(c);
+ c = '\n';
+ }
+ if (c == 0177 || c == '\b') {
+ prom_putchar('\b');
+ prom_putchar(' ');
+ c = '\b';
+ }
+ prom_putchar(c);
+ return (c);
+}
+
+int
+cons_gets(char *buf, int n)
+{
+ char *lp;
+ char *limit;
+ int c;
+
+ lp = buf;
+ limit = &buf[n - 1];
+ for (;;) {
+ c = getchar() & 0177;
+ switch (c) {
+ case '\n':
+ case '\r':
+ *lp = '\0';
+ return (0);
+ case '\b':
+ if (lp > buf)
+ lp--;
+ continue;
+ case 'u'&037: /* ^U */
+ lp = buf;
+ prom_putchar('\r');
+ prom_putchar('\n');
+ continue;
+ default:
+ if (lp < limit)
+ *lp++ = (char)c;
+ else
+ prom_putchar('\a'); /* bell */
+ }
+ }
+}
diff --git a/usr/src/psm/stand/boot/sparc/common/hsfsconf.c b/usr/src/psm/stand/boot/sparc/common/hsfsconf.c
new file mode 100644
index 0000000000..2f71220391
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/hsfsconf.c
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/param.h>
+#include <sys/sysmacros.h>
+#include <sys/stat.h>
+#include <sys/bootvfs.h>
+
+/* HSFS Support */
+extern struct boot_fs_ops boot_hsfs_ops;
+
+struct boot_fs_ops *boot_fsw[] = {
+ &boot_hsfs_ops,
+};
+
+int boot_nfsw = sizeof (boot_fsw) / sizeof (boot_fsw[0]);
+static char *fstype = "hsfs";
+
+/*ARGSUSED*/
+char *
+set_fstype(char *v2path, char *bpath)
+{
+ set_default_fs(fstype);
+ return (fstype);
+}
diff --git a/usr/src/psm/stand/boot/sparc/common/mapfile b/usr/src/psm/stand/boot/sparc/common/mapfile
new file mode 100644
index 0000000000..069b68aa7e
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/mapfile
@@ -0,0 +1,36 @@
+#
+# 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.
+#
+# 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 2003 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+text = LOAD ?RX V0x120000;
+text : $PROGBITS ?A!W;
+
+data = LOAD ?RWX A0x8;
+data : $PROGBITS ?AW;
+data : $NOBITS ?AW;
+
+note = NOTE;
+note : $NOTE;
+
diff --git a/usr/src/psm/stand/boot/sparc/common/nfsconf.c b/usr/src/psm/stand/boot/sparc/common/nfsconf.c
new file mode 100644
index 0000000000..ea9a8c5eb7
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/nfsconf.c
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/param.h>
+#include <sys/sysmacros.h>
+#include <sys/obpdefs.h>
+#include <sys/stat.h>
+#include <sys/bootvfs.h>
+#include <sys/bootdebug.h>
+#include <sys/promif.h>
+#include <sys/salib.h>
+#include "boot_plat.h"
+
+/*
+ * filesystem switch table, NFS
+ */
+extern struct boot_fs_ops boot_nfs_ops;
+struct boot_fs_ops *boot_fsw[] = {
+ &boot_nfs_ops,
+};
+
+int boot_nfsw = sizeof (boot_fsw) / sizeof (boot_fsw[0]);
+int nfs_readsize = 0;
+
+static char *nfsname = "nfs";
+
+/* ARGSUSED */
+char *
+set_fstype(char *v2path, char *bpath)
+{
+ set_default_fs(nfsname);
+ return (nfsname);
+}
diff --git a/usr/src/psm/stand/boot/sparc/common/ramdisk.c b/usr/src/psm/stand/boot/sparc/common/ramdisk.c
new file mode 100644
index 0000000000..bba9f4b5d2
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/ramdisk.c
@@ -0,0 +1,567 @@
+/*
+ * 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.
+ *
+ * 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 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/param.h>
+#include <sys/promif.h>
+#include <sys/salib.h>
+/* EXPORT DELETE START */
+#include <bootlog.h>
+/* 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 */
+" \" 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"
+" ; "
+"finish-device "
+
+"pop-package"
+
+; /* end of ramdisk_fth[] initialization */
+
+
+/*
+ * Create an actual ramdisk instance.
+ */
+static void
+create_ramdisk_node(const char *ramdisk_name)
+{
+ char *fth_buf;
+ size_t buf_size;
+
+ buf_size = sizeof (ramdisk_fth) + strlen(ramdisk_name);
+
+ 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_fth, ramdisk_name);
+
+ prom_interpret(fth_buf, 0, 0, 0, 0, 0);
+
+ bkmem_free(fth_buf, buf_size);
+}
+
+int
+create_ramdisk(const char *ramdisk_name, size_t size, char **device_path)
+{
+ static int first_time = 1;
+ char buf[OBP_MAXPATHLEN];
+ ihandle_t ih;
+
+ /*
+ * Ensure that size is a multiple of page size (rounded up).
+ */
+ size = ptob(btopr(size));
+
+/* 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) {
+
+ if (first_time) {
+ first_time = 0;
+
+ create_ramdisk_node(RD_ROOTFS);
+ create_ramdisk_node(RD_BOOTFS);
+ }
+
+ (void) snprintf(buf, sizeof (buf), "/%s:nolabel", ramdisk_name);
+ *device_path = strdup(buf);
+
+ if (*device_path != NULL) {
+ (void) snprintf(buf, sizeof (buf), "/%s:size=%x,%x",
+ ramdisk_name,
+ (uint32_t)(size >> 32), (uint32_t)size);
+
+ if ((ih = prom_open(buf)) != 0) {
+ return (ih);
+ }
+ }
+ }
+
+/* EXPORT DELETE START */
+ bootlog("wanboot", BOOTLOG_CRIT, "Cannot create ramdisk \"%s\"",
+ ramdisk_name);
+/* EXPORT DELETE END */
+ prom_panic("create_ramdisk: fatal error");
+ /* NOTREACHED */
+}
diff --git a/usr/src/psm/stand/boot/sparc/common/ramdisk.h b/usr/src/psm/stand/boot/sparc/common/ramdisk.h
new file mode 100644
index 0000000000..77eb021a11
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/ramdisk.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ *
+ * 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 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _RAMDISK_H
+#define _RAMDISK_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Ramdisk names
+ */
+#define RD_BOOTFS "ramdisk-bootfs"
+#define RD_ROOTFS "ramdisk-rootfs"
+
+extern int create_ramdisk(const char *, size_t, char **);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RAMDISK_H */
diff --git a/usr/src/psm/stand/boot/sparc/common/sparc.il b/usr/src/psm/stand/boot/sparc/common/sparc.il
new file mode 100644
index 0000000000..0065a5f9b4
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/sparc.il
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ *
+ * 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 (c) 1995 by Sun Microsystems, Inc. All Rights Reserved.
+ */
+#pragma ident "%Z%%M% %I% %E% SMI"
+!
+! In-line functions for sparc kernels.
+!
+
+! stub function for now
+ .inline sync_instruction_memory,8
+ nop
+ .end
diff --git a/usr/src/psm/stand/boot/sparc/common/sparcv9_subr.s b/usr/src/psm/stand/boot/sparc/common/sparcv9_subr.s
new file mode 100644
index 0000000000..bddd426161
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/sparcv9_subr.s
@@ -0,0 +1,293 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/asm_linkage.h>
+#include <sys/machparam.h> /* To get SYSBASE and PAGESIZE */
+#include <sys/privregs.h>
+
+#if !defined(lint)
+
+ .seg ".text"
+ .align 4
+
+#define PSR_PIL_BIT 0x8
+
+/*
+ * Macro to raise processor priority level.
+ * Avoid dropping processor priority if already at high level.
+ * Also avoid going below CPU->cpu_base_spl, which could've just been set by
+ * a higher-level interrupt thread that just blocked.
+ * XXX4U: bring splr inline
+ */
+#define RAISE(level) \
+ b splr; \
+ mov ((level) << PSR_PIL_BIT), %o0
+/*
+ * Macro to set the priority to a specified level.
+ * Avoid dropping the priority below CPU->cpu_base_spl.
+ * XXX4U: bring splx inline
+ */
+#define SETPRI(level) \
+ b splx; \
+ mov ((level) << PSR_PIL_BIT), %o0
+
+#endif /* lint */
+
+ /*
+ * Berkley 4.3 introduced symbolically named interrupt levels
+ * as a way deal with priority in a machine independent fashion.
+ * Numbered priorities are machine specific, and should be
+ * discouraged where possible.
+ *
+ * Note, for the machine specific priorities there are
+ * examples listed for devices that use a particular priority.
+ * It should not be construed that all devices of that
+ * type should be at that priority. It is currently were
+ * the current devices fit into the priority scheme based
+ * upon time criticalness.
+ *
+ * The underlying assumption of these assignments is that
+ * SPARC9 IPL 10 is the highest level from which a device
+ * routine can call wakeup. Devices that interrupt from higher
+ * levels are restricted in what they can do. If they need
+ * kernels services they should schedule a routine at a lower
+ * level (via software interrupt) to do the required
+ * processing.
+ *
+ * Examples of this higher usage:
+ * Level Usage
+ * 15 Asynchronous memory exceptions
+ * 14 Profiling clock (and PROM uart polling clock)
+ * 13 Audio device
+ * 12 Serial ports
+ * 11 Floppy controller
+ *
+ * The serial ports request lower level processing on level 6.
+ * Audio and floppy request lower level processing on level 4.
+ *
+ * Also, almost all splN routines (where N is a number or a
+ * mnemonic) will do a RAISE(), on the assumption that they are
+ * never used to lower our priority.
+ * The exceptions are:
+ * spl8() Because you can't be above 15 to begin with!
+ * splzs() Because this is used at boot time to lower our
+ * priority, to allow the PROM to poll the uart.
+ * spl0() Used to lower priority to 0.
+ * splsoftclock() Used by hardclock to lower priority.
+ */
+
+#if defined(lint)
+
+int splimp(void) { return (0); }
+int splnet(void) { return (0); }
+
+#ifdef notdef
+int spl6(void) { return (0); }
+int spl5(void) { return (0); }
+#endif notdef
+
+#else /* lint */
+
+ /* locks out all interrupts, including memory errors */
+ ENTRY(spl8)
+ SETPRI(15)
+ SET_SIZE(spl8)
+
+ /* just below the level that profiling runs */
+ ALTENTRY(splaudio)
+ ENTRY(spl7)
+ RAISE(13)
+ SET_SIZE(spl7)
+ SET_SIZE(splaudio)
+
+ /* sun specific - highest priority onboard serial i/o zs ports */
+ ALTENTRY(splzs)
+ SETPRI(12) /* Can't be a RAISE, as it's used to lower us */
+ SET_SIZE(splzs)
+
+ /*
+ * should lock out clocks and all interrupts,
+ * as you can see, there are exceptions
+ */
+ ALTENTRY(splhigh)
+ ALTENTRY(splhi)
+
+ /* the standard clock interrupt priority */
+ ALTENTRY(splclock)
+
+ /* highest priority for any tty handling */
+ ALTENTRY(spltty)
+
+ /* highest priority required for protection of buffered io system */
+ ALTENTRY(splbio)
+
+ /* machine specific */
+ ENTRY2(spl6,spl5)
+ RAISE(10)
+ SET_SIZE(splhigh)
+ SET_SIZE(splhi)
+ SET_SIZE(splclock)
+ SET_SIZE(spltty)
+ SET_SIZE(splbio)
+ SET_SIZE(spl5)
+ SET_SIZE(spl6)
+
+ /*
+ * machine specific
+ * for sun, some frame buffers must be at this priority
+ */
+ ENTRY(spl4)
+ RAISE(8)
+ SET_SIZE(spl4)
+
+ /* highest level that any network device will use */
+ ALTENTRY(splimp)
+
+ /*
+ * machine specific
+ * for sun, devices with limited buffering: tapes, ethernet
+ */
+ ENTRY(spl3)
+ RAISE(6)
+ SET_SIZE(splimp)
+ SET_SIZE(spl3)
+
+ /*
+ * machine specific - not as time critical as above
+ * for sun, disks
+ */
+ ENTRY(spl2)
+ RAISE(4)
+ SET_SIZE(spl2)
+
+ ENTRY(spl1)
+ RAISE(2)
+ SET_SIZE(spl1)
+
+ /* highest level that any protocol handler will run */
+ ENTRY(splnet)
+ RAISE(1)
+ SET_SIZE(splnet)
+
+ /* softcall priority */
+ /* used by hardclock to LOWER priority */
+ ENTRY(splsoftclock)
+ SETPRI(1)
+ SET_SIZE(splsoftclock)
+
+ /* allow all interrupts */
+ ENTRY(spl0)
+ SETPRI(0)
+ SET_SIZE(spl0)
+
+#endif /* lint */
+
+/*
+ * splx - set PIL back to that indicated by the old %PSR passed as an argument,
+ * or to the CPU's base priority, whichever is higher.
+ * sys_rtt (in locore.s) relies on this not to use %g1 or %g2.
+ */
+
+#if defined(lint)
+
+/* ARGSUSED */
+void
+splx(int level)
+{
+}
+
+#else /* lint */
+
+ ENTRY(splx)
+ rdpr %pil, %o1 ! get current pil
+ wrpr %o0, %pil
+ retl
+ mov %o1, %o0
+ SET_SIZE(splx)
+
+#endif /* level */
+
+/*
+ * splr()
+ *
+ * splr is like splx but will only raise the priority and never drop it
+ * Be careful not to set priority lower than CPU->cpu_base_pri,
+ * even though it seems we're raising the priority, it could be set higher
+ * at any time by an interrupt routine, so we must block interrupts and
+ * look at CPU->cpu_base_pri.
+ *
+ */
+
+#if defined(lint)
+#ifdef notdef
+
+/* ARGSUSED */
+int
+splr(int level)
+{ return (0); }
+
+#endif notdef
+#else /* lint */
+
+/*
+ * splr(psr_pri_field)
+ * splr is like splx but will only raise the priority and never drop it
+ */
+
+ ENTRY(splr)
+ rdpr %pil, %o1 ! get current pil
+ cmp %o0, %o1
+ ble 1f
+ nop
+ wrpr %o0, %pil
+1: retl
+ mov %o1, %o0 ! return the old pil
+ SET_SIZE(splr)
+
+#endif /* lint */
+
+/*
+ * get_ticks()
+ */
+#if defined(lint)
+
+/* ARGSUSED */
+uint64_t
+get_ticks(void)
+{ return (0); }
+
+#else /* lint */
+
+ ENTRY(get_ticks)
+ rdpr %tick, %o0
+ sllx %o0, 1, %o0
+ retl
+ srlx %o0, 1, %o0 ! shake off npt bit
+ SET_SIZE(get_ticks)
+
+#endif /* lint */
diff --git a/usr/src/psm/stand/boot/sparc/common/sun4dep.c b/usr/src/psm/stand/boot/sparc/common/sun4dep.c
new file mode 100644
index 0000000000..b18456a47b
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/sun4dep.c
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ *
+ * 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 2005 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/promif.h>
+#include <sys/prom_plat.h>
+#include <sys/salib.h>
+
+int pagesize = PAGESIZE;
+
+void
+fiximp(void)
+{
+ extern int use_align;
+
+ use_align = 1;
+}
+
+void
+setup_aux(void)
+{
+ dnode_t node;
+ /* big enough for OBP_NAME and for a reasonably sized OBP_COMPATIBLE. */
+ static char cpubuf[5 * OBP_MAXDRVNAME];
+ extern uint_t icache_flush;
+ extern char *cpulist;
+
+ icache_flush = 1;
+ node = prom_findnode_bydevtype(prom_rootnode(), OBP_CPU);
+ if (node != OBP_NONODE && node != OBP_BADNODE) {
+ int nlen, clen, i;
+
+ 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 */
+ if ((clen = prom_getproplen(node, OBP_COMPATIBLE)) > 0) {
+ 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] = ':';
+ }
+ cpulist = cpubuf;
+ } else
+ prom_panic("no cpu node");
+}
+
+
+#ifdef MPSAS
+
+void sas_symtab(int start, int end);
+extern int sas_command(char *cmdstr);
+
+/*
+ * SAS support - inform SAS of new symbols being dynamically added
+ * during simulation via the first standalone.
+ */
+
+#ifndef BUFSIZ
+#define BUFSIZ 1024 /* for cmd string buffer allocation */
+#endif
+
+int sas_symdebug = 0; /* SAS support */
+
+void
+sas_symtab(int start, int end)
+{
+ char *addstr = "symtab add $LD_KERNEL_PATH/%s%s 0x%x 0x%x\n";
+ char *file, *prefix, cmdstr[BUFSIZ];
+ extern char filename[];
+
+ file = filename;
+ prefix = *file == '/' ? "../../.." : "";
+
+ (void) sprintf(cmdstr, addstr, prefix, file, start, end);
+
+ /* add the symbol table */
+ if (sas_symdebug) (void) printf("sas_symtab: %s", cmdstr);
+ sas_command(cmdstr);
+}
+
+void
+sas_bpts()
+{
+ sas_command("file $KERN_SCRIPT_FILE\n");
+}
+#endif /* MPSAS */
+
+/*
+ * Allocate a region of virtual address space, unmapped.
+ */
+caddr_t
+resalloc_virt(caddr_t virt, size_t size)
+{
+ if (prom_claim_virt(size, virt) == (caddr_t)-1)
+ return ((caddr_t)0);
+
+ return (virt);
+}
diff --git a/usr/src/psm/stand/boot/sparc/common/sun4u_memlist.c b/usr/src/psm/stand/boot/sparc/common/sun4u_memlist.c
new file mode 100644
index 0000000000..e25ea32d71
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/sun4u_memlist.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, Version 1.0 only
+ * (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 1992-2003 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/promif.h>
+#include <sys/memlist.h>
+#include <sys/bootconf.h>
+#include <sys/salib.h>
+
+/*
+ * This file defines the interface from the prom and platform-dependent
+ * form of the memory lists, to boot's more generic form of the memory
+ * list. For sun4u, the memory list properties are {hi, lo, size_hi, size_lo},
+ * which is similar to boot's format, except boot's format is a linked
+ * list, and the prom's is an array of these structures. Note that the
+ * native property on sparc machines is identical to the property encoded
+ * format, so no property decoding is required.
+ *
+ * Note that the format of the memory lists is really 4 encoded integers,
+ * but the encoding is the same as that given in the following structure
+ * on SPARC systems ...
+ */
+
+struct sun4u_prom_memlist {
+ u_longlong_t addr;
+ u_longlong_t size;
+};
+
+struct sun4u_prom_memlist scratch_memlist[200];
+
+struct memlist *fill_memlists(char *name, char *prop, struct memlist *);
+extern struct memlist *pfreelistp, *vfreelistp, *pinstalledp;
+
+static struct memlist *reg_to_list(struct sun4u_prom_memlist *a, size_t size,
+ struct memlist *old);
+static void sort_reglist(struct sun4u_prom_memlist *ar, size_t size);
+extern void kmem_init(void);
+
+void
+init_memlists(void)
+{
+ /* this list is a map of pmem actually installed */
+ pinstalledp = fill_memlists("memory", "reg", pinstalledp);
+
+ vfreelistp = fill_memlists("virtual-memory", "available", vfreelistp);
+ pfreelistp = fill_memlists("memory", "available", pfreelistp);
+
+ kmem_init();
+}
+
+struct memlist *
+fill_memlists(char *name, char *prop, struct memlist *old)
+{
+ static dnode_t pmem = 0;
+ static dnode_t pmmu = 0;
+ dnode_t node;
+ size_t links;
+ struct memlist *al;
+ struct sun4u_prom_memlist *pm = scratch_memlist;
+
+ if (pmem == (dnode_t)0) {
+
+ /*
+ * Figure out the interesting phandles, one time
+ * only.
+ */
+
+ ihandle_t ih;
+
+ if ((ih = prom_mmu_ihandle()) == (ihandle_t)-1)
+ prom_panic("Can't get mmu ihandle");
+ pmmu = prom_getphandle(ih);
+
+ if ((ih = prom_memory_ihandle()) == (ihandle_t)-1)
+ prom_panic("Can't get memory ihandle");
+ pmem = prom_getphandle(ih);
+ }
+
+ if (strcmp(name, "memory") == 0)
+ node = pmem;
+ else
+ node = pmmu;
+
+ /*
+ * Read memory node and calculate the number of entries
+ */
+ if ((links = prom_getproplen(node, prop)) == -1)
+ prom_panic("Cannot get list.\n");
+ if (links > sizeof (scratch_memlist)) {
+ prom_printf("%s list <%s> exceeds boot capabilities\n",
+ name, prop);
+ prom_panic("fill_memlists - memlist size");
+ }
+ links = links / sizeof (struct sun4u_prom_memlist);
+
+
+ (void) prom_getprop(node, prop, (caddr_t)pm);
+ sort_reglist(pm, links);
+ al = reg_to_list(pm, links, old);
+ return (al);
+}
+
+/*
+ * Simple selection sort routine.
+ * Sorts platform dependent memory lists into ascending order
+ */
+
+static void
+sort_reglist(struct sun4u_prom_memlist *ar, size_t n)
+{
+ int i, j, min;
+ struct sun4u_prom_memlist temp;
+
+ for (i = 0; i < n; i++) {
+ min = i;
+
+ for (j = i+1; j < n; j++) {
+ if (ar[j].addr < ar[min].addr)
+ min = j;
+ }
+
+ if (i != min) {
+ /* Swap ar[i] and ar[min] */
+ temp = ar[min];
+ ar[min] = ar[i];
+ ar[i] = temp;
+ }
+ }
+}
+
+/*
+ * This routine will convert our platform dependent memory list into
+ * struct memlists's. And it will also coalesce adjacent nodes if
+ * possible.
+ */
+static struct memlist *
+reg_to_list(struct sun4u_prom_memlist *ar, size_t n, struct memlist *old)
+{
+ struct memlist *ptr, *head, *last;
+ int i;
+ u_longlong_t size = 0;
+ u_longlong_t addr = 0;
+ u_longlong_t start1, start2;
+ int flag = 0;
+
+ if (n == 0)
+ return ((struct memlist *)0);
+
+ /*
+ * if there was a memory list allocated before, free it first.
+ */
+ if (old)
+ (void) add_to_freelist(old);
+
+ head = NULL;
+ last = NULL;
+
+ for (i = 0; i < n; i++) {
+ start1 = ar[i].addr;
+ start2 = ar[i+1].addr;
+ if (i < n-1 && (start1 + ar[i].size == start2)) {
+ size += ar[i].size;
+ if (!flag) {
+ addr = start1;
+ flag++;
+ }
+ continue;
+ } else if (flag) {
+ /*
+ * catch the last one on the way out of
+ * this iteration
+ */
+ size += ar[i].size;
+ }
+
+ ptr = (struct memlist *)get_memlist_struct();
+ if (!head)
+ head = ptr;
+ if (last)
+ last->next = ptr;
+ ptr->address = flag ? addr : start1;
+ ptr->size = size ? size : ar[i].size;
+ ptr->prev = last;
+ last = ptr;
+
+ size = 0;
+ flag = 0;
+ addr = 0;
+ }
+
+ last->next = NULL;
+ return (head);
+}
diff --git a/usr/src/psm/stand/boot/sparc/common/sun4u_srt0.s b/usr/src/psm/stand/boot/sparc/common/sun4u_srt0.s
new file mode 100644
index 0000000000..78a2d480c7
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/sun4u_srt0.s
@@ -0,0 +1,214 @@
+/*
+ * 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.
+ *
+ * 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 (c) 1986-1997, Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * standalone startup code for sun4u LP64 secondary booters.
+ */
+
+#include <sys/asm_linkage.h>
+#include <sys/privregs.h>
+#include <sys/stack.h>
+
+#if defined(lint)
+
+/*ARGSUSED*/
+void
+_start(void *a, ...)
+{}
+
+#else
+ .seg ".text"
+ .align 8
+ .global end
+ .global edata
+ .global main
+
+ .seg ".bss"
+ .align 8
+
+_local_p1275cif:
+ .skip 8
+
+!
+! Create a stack just below _start.
+!
+#define STACK_SIZE 0x14000
+
+ .skip STACK_SIZE
+.ebootstack: ! end --top-- of boot stack
+
+!
+! Enter here for all disk/secondary booters loaded by a bootblk program or
+! inetboot loaded by OBP.
+! Careful: don't touch %o4 until the save, since it contains the
+! address of the IEEE 1275 SPARC v9 CIF handler; the linkage to the prom.
+!
+ .seg ".text"
+ .global prom_exit_to_mon
+ .type prom_exit_to_mon, #function
+
+ ENTRY(_start)
+
+ !
+ ! The stacks in bss now; use the stack we came in on (prom is supposed
+ ! to call us with a minimum of an 8k stack, bzero bss (and thus our
+ ! new stack), then switch to the new stack. Do all this without losing
+ ! track of the p1275cif address cached in %o4.
+ !
+
+ save %sp, -SA(MINFRAME), %sp
+
+ !
+ ! Zero the bss [edata to end]
+ !
+ setn edata, %g1, %o0
+ setn end, %g1, %i2
+ call bzero
+ sub %i2, %o0, %o1 ! size
+
+ restore %g0, %g0, %g0 ! Trivial restore
+
+ !
+ ! Switch to our new stack.
+ !
+ setn (.ebootstack - STACK_BIAS), %g1, %o1
+ save %o1, -SA(MINFRAME), %sp
+
+ !
+ ! Set supervisor mode, interrupt level >= 13, traps enabled
+ ! We don't set PSTATE_AM even though all our addresses are under 4G.
+ !
+ wrpr %g0, PSTATE_PEF+PSTATE_PRIV+PSTATE_IE, %pstate
+
+ sethi %hi(_local_p1275cif), %o1
+ stx %i4, [%o1 + %lo(_local_p1275cif)]
+ call main ! main(prom-cookie)
+ mov %i4, %o0 ! SPARCV9/CIF
+
+ ! print stupid error message here!
+
+ call prom_enter_mon ! can't happen .. :-)
+ nop
+ SET_SIZE(_start)
+
+#endif /* lint */
+
+#if defined(lint)
+
+/* ARGSUSED */
+void
+exitto(int (*entrypoint)(void *romvec, void *dvec, void *bootops,
+ void *bootvec))
+{}
+
+/* ARGSUSED */
+void
+exitto64(int (*entrypoint)(void *romvec, void *dvec, void *bootops,
+ void *bootvec), void *bootvec)
+{}
+
+#else /* lint */
+
+ ENTRY(exitto)
+ !
+ ! Setup args for client.
+ !
+ ! 32 bit frame, 64 bit sized
+ sub %g0, SA(MINFRAME) - STACK_BIAS, %g1
+ save %sp, %g1, %sp
+ sethi %hi(_local_p1275cif), %o0 ! 1275 CIF handler for callee.
+ ldx [%o0 + %lo(_local_p1275cif)], %o0
+ clr %o1 ! boot passes no dvec
+ setn bootops, %g1, %o2
+ sethi %hi(elfbootvec), %o3 ! pass elf bootstrap vector
+ ldx [%o3 + %lo(elfbootvec)], %o3
+ rdpr %pstate, %l1 ! Get the present pstate value
+ wrpr %l1, PSTATE_AM, %pstate ! Set PSTATE_AM = 1
+ jmpl %i0, %o7 ! call thru register to the standalone
+ mov %o0, %o4 ! 1210378: Pass cif in both %o0 & %o4
+
+ ! eek - we returned -- switch back to a 64-bit frame
+ ! then panic in a slightly informative way.
+
+ restore %g0, %g0, %g0
+ save %sp, -SA(MINFRAME), %sp
+ sethi %hi(.msg), %o0
+ call prom_panic
+ or %o0, %lo(.msg), %o0
+.msg: .asciz "exitto returned from client program"
+ SET_SIZE(exitto)
+
+ ENTRY(exitto64)
+ !
+ ! Setup args for client.
+ !
+ save %sp, -SA(MINFRAME), %sp
+ sethi %hi(_local_p1275cif), %o0 ! 1275 CIF handler for callee.
+ ldx [%o0 + %lo(_local_p1275cif)], %o0
+ mov %i1, %o3 ! bootvec
+ clr %o1 ! boot passes no dvec
+ setn bootops, %g1, %o2
+ jmpl %i0, %o7 ! call thru register to the standalone
+ mov %o0, %o4 ! 1210378: Pass cif in both %o0 & %o4
+
+ ! eek - we returned -- panic in a slightly informative way.
+
+ sethi %hi(.msg64), %o0
+ call prom_panic
+ or %o0, %lo(.msg64), %o0
+.msg64: .asciz "exitto64 returned from client program"
+ SET_SIZE(exitto64)
+
+#endif /* lint */
+
+#if defined(lint)
+
+/*
+ * The interface for our 64-bit client program
+ * calling the 64-bit romvec OBP.
+ */
+
+#include <sys/promif.h>
+#include <sys/prom_isa.h>
+
+/* ARGSUSED */
+int
+client_handler(void *cif_handler, void *arg_array)
+{ return (0); }
+
+#else /* lint */
+
+ ENTRY(client_handler)
+ mov %o7, %g1
+ mov %o0, %g5
+ mov %o1, %o0
+ jmp %g5
+ mov %g1, %o7
+ SET_SIZE(client_handler)
+
+#endif /* lint */
diff --git a/usr/src/psm/stand/boot/sparc/common/sun4x_standalloc.c b/usr/src/psm/stand/boot/sparc/common/sun4x_standalloc.c
new file mode 100644
index 0000000000..5f4d258565
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/sun4x_standalloc.c
@@ -0,0 +1,339 @@
+/*
+ * 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.
+ *
+ * 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 2005 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/saio.h>
+#include <sys/sysmacros.h>
+#include <sys/promif.h>
+#include <sys/bootconf.h>
+#include <sys/salib.h>
+
+#define NIL 0
+
+#ifdef DEBUG
+static int resalloc_debug = 1;
+#else /* DEBUG */
+static int resalloc_debug = 0;
+#endif /* DEBUG */
+#define dprintf if (resalloc_debug) printf
+
+extern struct memlist *vfreelistp, *pfreelistp;
+extern void reset_alloc(void);
+extern void alloc_segment(caddr_t);
+
+caddr_t memlistpage;
+caddr_t le_page;
+caddr_t ie_page;
+caddr_t scratchmemp;
+extern int pagesize;
+
+#define N_FREELIST 20 /* keep the largest 20 free regions */
+static size_t free_size[N_FREELIST];
+static caddr_t free_addr[N_FREELIST];
+
+/*
+ * OBP sets up a 1:1 mapping of virtual to physical in the range 8KB-10MB. The
+ * standalone is free to use any or all of this during its lifetime.
+ * Unfortunately, some platforms (Serengeti and LW8) can't use the full range.
+ * See 4799331 for more details. Limited platforms can use up to
+ * MAPPEDMEM_MINTOP; everyone else can use up to MAPPEDMEM_FULLTOP.
+ * resalloc_init makes the determination as to how much the machine being booted
+ * can use.
+ *
+ * But wait! There's more! resalloc handles three types of allocations: Two
+ * flavors of RES_BOOTSCRATCH (RES_BOOTSCRATCH and RES_BOOTSCRATCH_NOFAIL), and
+ * one of RES_CHILDVIRT. RES_CHILDVIRT is handled by prom_alloc, and is boring.
+ * We handle RES_BOOTSCRATCH allocations ourselves using the portion of the 1:1
+ * range not consumed by boot. The unconsumed range is subdivided into two
+ * portions - the general area from top_resvmem to top_bootmem and the reserved
+ * area from above memlistpage to top_resvmem. Both RES_BOOTSCRATCH flavors are
+ * satisfied by the general area until said area is exhausted, at which point
+ * RES_BOOTSCRATCH allocations return failure. RES_BOOTSCRATCH_NOFAIL
+ * allocations can't fail, so we'll try to satisfy them from the reserved area
+ * if the general area is full. If we still can't satisfy the nofail
+ * allocation, we'll call prom_panic.
+ *
+ * This whole boot memory allocation thing needs some serious rethinking.
+ *
+ * Memory layout:
+ *
+ * |-------| top_bootmem
+ * | | } MAPPEDMEM_FULLTOP (only on non-serengeti, lw8)
+ * | | } MAPPEDMEM_MINTOP
+ * |-------| top_resvmem/scratchmemp
+ * | | } MAPPEDMEM_RESERVE
+ * |-------| scratchresvp
+ * | | } one page
+ * |-------| memlistpage (at roundup(_end, pagesize))
+ * |-------| _end
+ * | boot |
+ * : :
+ *
+ */
+
+#define MAPPEDMEM_RESERVE (512*1024) /* reserved for NOFAIL allocs */
+
+#define MAPPEDMEM_MINTOP (caddr_t)(6*1024*1024)
+#define MAPPEDMEM_FULLTOP (caddr_t)(10*1024*1024)
+
+static caddr_t top_bootmem = MAPPEDMEM_MINTOP;
+static caddr_t top_resvmem, scratchresvp;
+
+static int
+impl_name(char *buf, size_t bufsz)
+{
+ dnode_t n = prom_rootnode();
+ size_t len = prom_getproplen(n, "name");
+
+ if (len == 0 || len >= bufsz)
+ return (-1);
+
+ (void) prom_getprop(n, "name", buf);
+ buf[len] = '\0';
+
+ return (0);
+}
+
+static caddr_t
+vpage_from_freelist(size_t bytes)
+{
+ caddr_t v;
+ int i;
+
+ /* find first region which fits */
+ for (i = 0; i < N_FREELIST && free_size[i] < bytes; i++)
+ continue;
+
+ if (i == N_FREELIST) {
+ dprintf("boot: failed to allocate %lu bytes from scratch "
+ "memory\n", bytes);
+ return (NULL);
+ }
+
+ v = free_addr[i];
+ free_addr[i] += bytes;
+ free_size[i] -= bytes;
+ dprintf("reuse freed temp scratch: bytes = %lu at %p\n", bytes,
+ (void *)v);
+ return (v);
+}
+
+/*
+ * This routine will find the next PAGESIZE chunk in the
+ * low MAPPEDMEM_MINTOP. It is analogous to valloc(). It is only for boot
+ * scratch memory, because child scratch memory goes up in
+ * the the high memory. We just need to verify that the
+ * pages are on the list. The calling routine will actually
+ * remove them.
+ */
+static caddr_t
+get_low_vpage(size_t numpages, enum RESOURCES type)
+{
+ size_t bytes;
+ caddr_t v;
+
+ if (!numpages)
+ return (0);
+
+ /* We know the page is mapped because the 1st MAPPEDMEM_MINTOP is 1:1 */
+ bytes = numpages * pagesize;
+ if (scratchmemp + bytes <= top_bootmem) {
+ v = scratchmemp;
+ scratchmemp += bytes;
+ return (v);
+ }
+
+ /*
+ * If we run out of scratch memory, look in the freelist
+ */
+ if ((v = vpage_from_freelist(bytes)) != NULL)
+ return (v);
+
+ /*
+ * Try really hard for allocations that can't fail. Look in the area
+ * that we've reserved for them.
+ */
+ if (type == RES_BOOTSCRATCH_NOFAIL) {
+ if (scratchresvp + bytes <= top_resvmem) {
+ v = scratchresvp;
+ scratchresvp += bytes;
+ dprintf("using %lu bytes of reserved mem (%lu left)\n",
+ bytes, top_resvmem - scratchresvp);
+ return (v);
+ } else {
+ printf("boot: failed to allocate %lu bytes from "
+ "reserved scratch memory\n", bytes);
+ prom_panic("boot: scratch memory overflow.\n");
+ }
+ }
+
+ return (NULL);
+}
+
+void
+resalloc_init(void)
+{
+ char iarch[128];
+
+ if (impl_name(iarch, sizeof (iarch)) < 0) {
+ dprintf("boot: resalloc_init: failed to read iarch\n");
+ return;
+ }
+
+ dprintf("boot: resalloc_init: got iarch %s\n", iarch);
+
+ /*
+ * Some versions of SG/LW8 firmware can actually handle the entire 10MB,
+ * 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;
+
+ top_bootmem = MAPPEDMEM_FULLTOP;
+
+ dprintf("boot: resalloc_init: boosted top_bootmem to %p\n",
+ (void *)top_bootmem);
+}
+
+caddr_t
+resalloc(enum RESOURCES type, size_t bytes, caddr_t virthint, int align)
+{
+ caddr_t vaddr;
+ long pmap = 0;
+
+ if (memlistpage == (caddr_t)0)
+ reset_alloc();
+
+ if (bytes == 0)
+ return ((caddr_t)0);
+
+ /* extend request to fill a page */
+ bytes = roundup(bytes, pagesize);
+
+ dprintf("resalloc: bytes = %lu\n", bytes);
+
+ switch (type) {
+
+ /*
+ * even V2 PROMs never bother to indicate whether the
+ * first MAPPEDMEM_MINTOP is taken or not. So we do it all here.
+ * Smart PROM or no smart PROM.
+ */
+ case RES_BOOTSCRATCH:
+ case RES_BOOTSCRATCH_NOFAIL:
+ vaddr = get_low_vpage((bytes/pagesize), type);
+
+ if (resalloc_debug) {
+ dprintf("vaddr = %p, paddr = %lx\n", (void *)vaddr,
+ ptob(pmap));
+ print_memlist(vfreelistp);
+ print_memlist(pfreelistp);
+ }
+ return (vaddr);
+ /*NOTREACHED*/
+
+ case RES_CHILDVIRT:
+ vaddr = (caddr_t)prom_alloc(virthint, bytes, align);
+
+ if (vaddr == (caddr_t)virthint)
+ return (vaddr);
+ printf("Alloc of 0x%lx bytes at 0x%p refused.\n",
+ bytes, (void *)virthint);
+ return ((caddr_t)0);
+ /*NOTREACHED*/
+
+ default:
+ printf("Bad resurce type\n");
+ return ((caddr_t)0);
+ }
+}
+
+#ifdef lint
+static char _end[1]; /* defined by the linker! */
+#endif /* lint */
+
+void
+reset_alloc(void)
+{
+ extern char _end[];
+
+ /* Cannot be called multiple times */
+ if (memlistpage != (caddr_t)0)
+ return;
+
+ /*
+ * Due to kernel history and ease of programming, we
+ * want to keep everything private to /boot BELOW MAPPEDMEM_MINTOP.
+ * In this way, the kernel can just snarf it all when
+ * when it is ready, and not worry about snarfing lists.
+ */
+ memlistpage = (caddr_t)roundup((uintptr_t)_end, pagesize);
+
+ /*
+ * This next is for scratch memory only
+ * We only need 1 page in memlistpage for now
+ */
+ scratchresvp = (caddr_t)(memlistpage + pagesize);
+ scratchmemp = top_resvmem = scratchresvp + MAPPEDMEM_RESERVE;
+ le_page = (caddr_t)(scratchmemp + pagesize);
+ ie_page = (caddr_t)(le_page + pagesize);
+
+ bzero(memlistpage, pagesize);
+ bzero(scratchmemp, pagesize);
+ dprintf("memlistpage = %p\n", (void *)memlistpage);
+ dprintf("le_page = %p\n", (void *)le_page);
+}
+
+void
+resfree(enum RESOURCES type, caddr_t virtaddr, size_t size)
+{
+ int i;
+
+ /* make sure this is boot scratch memory */
+ switch (type) {
+ case RES_BOOTSCRATCH:
+ if (virtaddr + size > top_bootmem)
+ return;
+ break;
+ default:
+ return;
+ }
+
+ /*
+ * Add this to the end of the free list
+ * NOTE: This relies on the fact that KRTLD calls BOP_FREE
+ * from largest to smallest chunks.
+ */
+ for (i = 0; i < N_FREELIST && free_size[i]; i++)
+ ;
+ if (i == N_FREELIST)
+ return;
+ free_size[i] = size;
+ free_addr[i] = virtaddr;
+}
diff --git a/usr/src/psm/stand/boot/sparc/common/ufsconf.c b/usr/src/psm/stand/boot/sparc/common/ufsconf.c
new file mode 100644
index 0000000000..5d0195e5f3
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/ufsconf.c
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/param.h>
+#include <sys/sysmacros.h>
+#include <sys/obpdefs.h>
+#include <sys/stat.h>
+#include <sys/bootvfs.h>
+#include <sys/bootdebug.h>
+#include <sys/promif.h>
+#include <sys/salib.h>
+#include "boot_plat.h"
+
+/*
+ * filesystem switch table, UFS
+ */
+extern struct boot_fs_ops boot_ufs_ops;
+struct boot_fs_ops *boot_fsw[] = {
+ &boot_ufs_ops,
+};
+
+int boot_nfsw = sizeof (boot_fsw) / sizeof (boot_fsw[0]);
+int nfs_readsize = 0;
+
+static char *ufsname = "ufs";
+
+/* ARGSUSED */
+char *
+set_fstype(char *v2path, char *bpath)
+{
+ set_default_fs(ufsname);
+ return (ufsname);
+}
diff --git a/usr/src/psm/stand/boot/sparc/common/wanboot.c b/usr/src/psm/stand/boot/sparc/common/wanboot.c
new file mode 100644
index 0000000000..b1f3ae836f
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/wanboot.c
@@ -0,0 +1,1762 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+/* EXPORT DELETE START */
+#include <sys/promif.h>
+#include <sys/obpdefs.h>
+#include <sys/bootvfs.h>
+#include <sys/bootconf.h>
+#include <netinet/in.h>
+#include <sys/wanboot_impl.h>
+#include <boot_http.h>
+#include <aes.h>
+#include <des3.h>
+#include <cbc.h>
+#include <hmac_sha1.h>
+#include <sys/sha1.h>
+#include <sys/sha1_consts.h>
+#include <bootlog.h>
+#include <parseURL.h>
+#include <netboot_paths.h>
+#include <netinet/inetutil.h>
+#include <sys/salib.h>
+#include <inet/mac.h>
+#include <inet/ipv4.h>
+#include <dhcp_impl.h>
+#include <inet/dhcpv4.h>
+#include <bootinfo.h>
+#include <wanboot_conf.h>
+#include "boot_plat.h"
+#include "ramdisk.h"
+#include "wbcli.h"
+
+/*
+ * Types of downloads
+ */
+#define MINIINFO "miniinfo"
+#define MINIROOT "miniroot"
+#define WANBOOTFS "wanbootfs"
+
+#define WANBOOT_RETRY_NOMAX -1
+#define WANBOOT_RETRY_ROOT_MAX 50
+#define WANBOOT_RETRY_MAX 5
+#define WANBOOT_RETRY_SECS 5
+#define WANBOOT_RETRY_MAX_SECS 30
+
+/*
+ * Our read requests should timeout after 25 seconds
+ */
+#define SOCKET_READ_TIMEOUT 25
+
+/*
+ * Experimentation has shown that an 8K download buffer is optimal
+ */
+static char buffer[8192];
+
+bc_handle_t bc_handle;
+
+extern int determine_fstype_and_mountroot(char *);
+extern uint64_t get_ticks(void);
+
+/*
+ * The following is used to determine whether the certs and private key
+ * files will be in PEM format or PKCS12 format. 'use_p12' is zero
+ * to use PEM format, and 1 when PKCS12 format is to be used. It is
+ * done this way, as a global, so that it can be patched if needs be
+ * using the OBP debugger.
+ */
+uint32_t use_p12 = 1;
+
+#define CONTENT_LENGTH "Content-Length"
+
+#define NONCELEN (2 * HMAC_DIGEST_LEN) /* two hex nibbles/byte */
+#define WANBOOTFS_NONCE_FILE "/nonce"
+
+static char nonce[NONCELEN + 1];
+
+enum URLtype {
+ URLtype_wanbootfs = 0,
+ URLtype_miniroot = 1
+};
+
+static char *URLtoCGIcontent[] = {
+ "bootfs",
+ "rootfs"
+};
+#define CGIcontent(urltype) URLtoCGIcontent[urltype]
+
+/* Encryption algorithms */
+typedef enum {
+ ENCR_NONE,
+ ENCR_3DES,
+ ENCR_AES
+} encr_type_t;
+
+/* Hash algorithms */
+typedef enum {
+ HASH_NONE,
+ HASH_HMAC_SHA1
+} hash_type_t;
+
+/*
+ * Keys ...
+ */
+static encr_type_t encr_type = ENCR_NONE;
+static unsigned char *g_encr_key = NULL;
+
+static hash_type_t hash_type = HASH_NONE;
+static unsigned char *g_hash_key = NULL;
+
+void
+print_errors(const char *func, http_handle_t handle)
+{
+ char const *msg;
+ ulong_t err;
+ uint_t src;
+
+ while ((err = http_get_lasterr(handle, &src)) != 0) {
+ msg = http_errorstr(src, err);
+ bootlog("wanboot", BOOTLOG_ALERT,
+ "%s: errsrc %u, err %lu (0x%lx)", func, src, err, err);
+ bootlog("wanboot", BOOTLOG_ALERT, "%s", msg);
+ }
+}
+
+/*
+ * This routine is called by a consumer to determine whether or not a
+ * retry should be attempted. If a retry is in order (depends upon the
+ * 'retry_cnt' and 'retry_max' arguments), then this routine will print a
+ * message indicating this is the case and will determine an appropriate
+ * "sleep" time before retrying. The "sleep" time will depend upon the
+ * 'retry_cnt' and will max out at WANBOOT_RETRY_MAX_SECS.
+ *
+ * Returns:
+ * B_TRUE = retry is in order
+ * B_FALSE = retry limit exceeded
+ */
+boolean_t
+wanboot_retry(int retry_cnt, int retry_max)
+{
+ unsigned int seconds;
+
+ if (retry_max == WANBOOT_RETRY_NOMAX || retry_cnt <= retry_max) {
+ seconds = WANBOOT_RETRY_SECS * retry_cnt;
+ if (seconds > WANBOOT_RETRY_MAX_SECS) {
+ seconds = WANBOOT_RETRY_MAX_SECS;
+ }
+ bootlog("wanboot", BOOTLOG_INFO,
+ "Will retry in %d seconds ...", seconds);
+ (void) sleep(seconds);
+ return (B_TRUE);
+ } else {
+ bootlog("wanboot", BOOTLOG_INFO,
+ "Maximum retries exceeded.");
+ return (B_FALSE);
+ }
+}
+
+/*
+ * Determine which encryption algorithm the client is configured to use.
+ * WAN boot determines which key to use by order of priority. That is
+ * multiple encryption keys may exist in the PROM, but the first one found
+ * (while searching in a preferred order) is the one that will be used.
+ */
+static void
+init_encryption(void)
+{
+ static unsigned char key[WANBOOT_MAXKEYLEN];
+ size_t len = sizeof (key);
+
+ if (bootinfo_get(BI_AES_KEY, (char *)&key, &len, NULL) ==
+ BI_E_SUCCESS) {
+ encr_type = ENCR_AES;
+ g_encr_key = key;
+ } else if (bootinfo_get(BI_3DES_KEY, (char *)&key, &len, NULL) ==
+ BI_E_SUCCESS) {
+ encr_type = ENCR_3DES;
+ g_encr_key = key;
+ }
+}
+
+/*
+ * Determine whether the client is configured to use hashing.
+ */
+static void
+init_hashing(void)
+{
+ static unsigned char key[WANBOOT_HMAC_KEY_SIZE];
+ size_t len = sizeof (key);
+
+ if (bootinfo_get(BI_SHA1_KEY, (char *)&key, &len, NULL) ==
+ BI_E_SUCCESS) {
+ hash_type = HASH_HMAC_SHA1;
+ g_hash_key = key;
+ }
+}
+
+/*
+ * Read some CPU-specific rapidly-varying data (assumed to be of length
+ * sizeof (hrtime_t) in the non-SPARC case), and digestify it to further
+ * randomize the output.
+ */
+char *
+generate_nonce(void)
+{
+ uint64_t t;
+ SHA1_CTX c;
+ unsigned char digest[HMAC_DIGEST_LEN];
+ uint_t nlen = sizeof (nonce);
+
+ int err;
+
+ /*
+ * Read SPARC %tick register or x86 TSC
+ */
+ t = get_ticks();
+ SHA1Init(&c);
+ SHA1Update(&c, (const uint8_t *)&t, sizeof (t));
+ SHA1Final(digest, &c);
+
+ err = octet_to_hexascii(digest, sizeof (digest), nonce, &nlen);
+ if (err != 0) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "cannot convert nonce to ASCII: error %d", err);
+ return (NULL);
+ }
+ nonce[NONCELEN] = '\0';
+ return (nonce);
+}
+
+/*
+ * Given a server URL, builds a URL to request one of the wanboot
+ * datastreams.
+ *
+ * Returns:
+ * -1 = Non-recoverable error
+ * 0 = Success
+ */
+static int
+build_request_url(url_t *req_url, enum URLtype ut, const url_t *server_url)
+{
+ char clid[WB_MAX_CID_LEN];
+ size_t clen;
+ char wid[WB_MAX_CID_LEN * 2 + 1];
+ uint_t wlen;
+ struct in_addr ip;
+ struct in_addr mask;
+ char *netstr;
+ char *ppath;
+ size_t plen;
+ const char reqstr[] = "/?CONTENT=%s&IP=%s&CID=%s";
+
+ /*
+ * Initialize the request
+ */
+ *req_url = *server_url;
+
+ /*
+ * Build the network number string
+ */
+ ipv4_getipaddr(&ip);
+ ipv4_getnetmask(&mask);
+ ip.s_addr = ip.s_addr & mask.s_addr;
+ netstr = inet_ntoa(ip);
+
+ /*
+ * Get the wan id
+ */
+ clen = sizeof (clid);
+ if (bootinfo_get(BI_CLIENT_ID, clid, &clen, NULL) != BI_E_SUCCESS) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "Cannot retrieve the client ID");
+ return (-1);
+ }
+ wlen = sizeof (wid);
+ (void) octet_to_hexascii(clid, clen, wid, &wlen);
+
+ /*
+ * Build the request, making sure that the length of the
+ * constructed URL falls within the supported maximum.
+ */
+ plen = strlen(req_url->abspath);
+ ppath = req_url->abspath + plen;
+ if (snprintf(ppath, URL_MAX_PATHLEN - plen, reqstr,
+ CGIcontent(ut), netstr, wid) >= URL_MAX_PATHLEN - plen) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "The URL path length of the %s request is greater than "
+ "the maximum of %d", CGIcontent(ut), URL_MAX_PATHLEN);
+ return (-1);
+ }
+
+ /*
+ * If the URL type requires a nonce, then supply it.
+ * It will be returned in the reply to detect attempted
+ * replays.
+ */
+ if (ut == URLtype_wanbootfs) {
+ char *n = generate_nonce();
+
+ if (n != NULL) {
+ plen += strlen("&NONCE=") + NONCELEN;
+ if (plen > URL_MAX_PATHLEN)
+ return (-1);
+ (void) strcat(req_url->abspath, "&NONCE=");
+ (void) strcat(req_url->abspath, n);
+ }
+ }
+
+ return (0);
+}
+
+/*
+ * This routine reads data from an HTTP connection into a buffer.
+ *
+ * Returns:
+ * 0 = Success
+ * 1 = HTTP download error
+ */
+static int
+read_bytes(http_handle_t handle, char *buffer, size_t cnt)
+{
+ int len;
+ size_t i;
+
+ for (i = 0; i < cnt; i += len) {
+ len = http_read_body(handle, &buffer[i], cnt - i);
+ if (len <= 0) {
+ print_errors("http_read_body", handle);
+ return (1);
+ }
+ }
+ return (0);
+}
+
+/*
+ * This routine compares two hash digests, one computed by the server and
+ * the other computed by the client to verify that a transmitted message
+ * was received without corruption.
+ *
+ * Notes:
+ * The client only computes a digest if it is configured with a
+ * hash key. If it is not, then the server should not have a hash
+ * key for the client either and therefore should have sent a
+ * zero filled digest.
+ *
+ * Returns:
+ * B_TRUE = digest was verified
+ * B_FALSE = digest did not verify
+ */
+static boolean_t
+verify_digests(const char *what, unsigned char *cdigest, unsigned char *sdigest)
+{
+ static char null_digest[HMAC_DIGEST_LEN];
+
+ if (bcmp(sdigest, cdigest, HMAC_DIGEST_LEN) != 0) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "%s: invalid hash digest", what);
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "This may signify a client/server key mismatch");
+ if (bcmp(sdigest, null_digest, HMAC_DIGEST_LEN) == 0) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "(client has key but wrong signature_type?)");
+ } else if (bcmp(cdigest, null_digest, HMAC_DIGEST_LEN) == 0) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "(signature_type specified but no client key?)");
+ }
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "or possible corruption of the image in transit");
+ return (B_FALSE);
+ }
+
+ return (B_TRUE);
+}
+
+/*
+ * This routine reads the part of a multipart message that contains a
+ * hash digest. Errors in reading the digest are differentiated from
+ * other kinds of errors so that the caller can decide whether or
+ * not a retry is worthwhile.
+ *
+ * Note:
+ * The hash digest can either be an HMAC digest or it can be
+ * a zero length message (representing no hash digest).
+ *
+ * Returns:
+ * -1 = Non-recoverable error
+ * 0 = Success
+ * 1 = HTTP download error
+ */
+static int
+read_digest(const char *what, http_handle_t handle, unsigned char *sdigest)
+{
+ char *lenstr;
+ size_t digest_size;
+
+ /*
+ * Process the HMAC digest header.
+ */
+ if (http_process_part_headers(handle, NULL) != 0) {
+ print_errors("http_process_part_headers", handle);
+ return (1);
+ }
+ lenstr = http_get_header_value(handle, CONTENT_LENGTH);
+ if (lenstr == NULL) {
+ bootlog("wanboot", BOOTLOG_ALERT,
+ "%s: error getting digest length", what);
+ return (1);
+ }
+ digest_size = (size_t)strtol(lenstr, NULL, 10);
+ free(lenstr);
+
+ /*
+ * Validate the HMAC digest length.
+ */
+ if (digest_size != HMAC_DIGEST_LEN) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "%s: error validating response - invalid digest size",
+ what);
+ return (-1);
+ }
+
+ /*
+ * Read the HMAC digest.
+ */
+ if (read_bytes(handle, (char *)sdigest, digest_size) != 0) {
+ bootlog("wanboot", BOOTLOG_ALERT,
+ "%s: error reading digest", what);
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
+ * This routine reads data from an HTTP connection and writes the data
+ * to a ramdisk. It also, optionally computes a hash digest of the processed
+ * data. This routine may be called to continue writing a previously aborted
+ * write. If this is the case, then the offset will be non-zero and the write
+ * pointer into the ramdisk will be positioned correctly by the caller.
+ *
+ * Returns:
+ * -1 = Non-recoverable error
+ * 0 = Success
+ * 1 = HTTP download error
+ */
+static int
+write_msg_to_ramdisk(const char *what, int fd, http_handle_t handle,
+ size_t ramdisk_size, off_t *offset, SHA1_CTX *sha)
+{
+ int len;
+ long nleft;
+ static int bootlog_message_interval;
+ static int bootlog_progress;
+ int ret;
+
+ /*
+ * Read the data and write it to the ramdisk.
+ */
+ if (*offset == 0) {
+ bootlog_progress = 0;
+ bootlog_message_interval = ramdisk_size / sizeof (buffer);
+ if (bootlog_message_interval < 500)
+ bootlog_message_interval /= 5;
+ else
+ bootlog_message_interval /= 50;
+
+ bootlog("wanboot", BOOTLOG_VERBOSE,
+ "Reading %s file system (%ld kB)",
+ what, ramdisk_size / 1024);
+ } else {
+ bootlog("wanboot", BOOTLOG_VERBOSE,
+ "Continuing read of %s file system (%ld kB)",
+ what, ramdisk_size / 1024);
+ }
+ for (ret = 0; ret == 0 && *offset < ramdisk_size; *offset += len) {
+ nleft = ramdisk_size - *offset;
+
+ if (nleft > sizeof (buffer))
+ nleft = sizeof (buffer);
+
+ len = http_read_body(handle, buffer, nleft);
+ if (len <= 0) {
+ print_errors("http_read_body", handle);
+ /*
+ * In the case of a partial failure, http_read_body()
+ * returns into 'len', 1 - the number of bytes read.
+ * So, a -65 means 64 bytes read and an error occurred.
+ */
+ if (len != 0) {
+ len = -(len + 1);
+ }
+ 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;
+ }
+ if (bootlog_progress == bootlog_message_interval) {
+ bootlog("wanboot", BOOTLOG_PROGRESS,
+ "%s: Read %ld of %ld kB (%ld%%)", what,
+ *offset / 1024, ramdisk_size / 1024,
+ *offset * 100 / ramdisk_size);
+ bootlog_progress = 0;
+ } else {
+ bootlog_progress++;
+ }
+ }
+ if (ret == 0) {
+ bootlog("wanboot", BOOTLOG_PROGRESS,
+ "%s: Read %ld of %ld kB (%ld%%)", what,
+ *offset / 1024, ramdisk_size / 1024,
+ *offset * 100 / ramdisk_size);
+ bootlog("wanboot", BOOTLOG_INFO, "%s: Download complete", what);
+ }
+ return (ret);
+}
+
+/*
+ * This routine is called with a bootinfo parameter name. If the parameter
+ * has a value it should be a URL, and this will be used to initialize the
+ * http_url structure.
+ *
+ * Returns:
+ * -1 = Non-recoverable error
+ * 0 = Success
+ * 1 = DHCP option not set
+ */
+static int
+get_url(char *name, url_t *url)
+{
+ char buf[URL_MAX_STRLEN];
+ size_t len;
+ int ret;
+
+ bzero(buf, sizeof (buf));
+ len = sizeof (buf) - 1;
+ if (bootinfo_get(name, buf, &len, NULL) != BI_E_SUCCESS || len == 0) {
+ return (1);
+ }
+
+ /*
+ * Parse the URL.
+ */
+ ret = url_parse(buf, url);
+ if (ret != URL_PARSE_SUCCESS) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "Unable to parse URL %s", buf);
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*
+ * This routine initiates an HTTP request and returns a handle so that
+ * the caller can process the response.
+ *
+ * Notes:
+ * Requests may be either secure or not. If the request is secure, then
+ * this routine assumes that a wanboot file system exists and
+ * uses its contents to provide the HTTP library with the information
+ * that will be required by SSL.
+ *
+ * In order to facilitate transmission retries, this routine supports
+ * range requests. A caller may request a range by providing a non-zero
+ * offset. In which case, a range request is made that ranges from the
+ * offet to the end of the file.
+ *
+ * If the client is configured to use an HTTP proxy, then this routine
+ * will make the HTTP library aware of the proxy.
+ *
+ * Any HTTP errors encountered in downloading or processing the message
+ * are not deemed unrecoverable errors. The caller can simply try the
+ * request once again.
+ *
+ * Returns:
+ * -1 = Non-recoverable error
+ * 0 = Success
+ * 1 = HTTP download error
+ */
+static int
+establish_http_connection(const char *what, http_handle_t *handlep,
+ url_t *url, off_t offset)
+{
+ static boolean_t is_auth_file_init = B_FALSE;
+ static boolean_t is_proxy_init = B_FALSE;
+ static boolean_t proxy_exists = B_FALSE;
+ static url_hport_t proxy_hp;
+ http_respinfo_t *resp;
+ char buf[URL_MAX_STRLEN];
+ size_t len = sizeof (buf) - 1;
+ int ret;
+
+ /* Check for HTTP proxy */
+ if (!is_proxy_init &&
+ bootinfo_get(BI_HTTP_PROXY, buf, &len, NULL) == BI_E_SUCCESS &&
+ strlen(buf) > 0) {
+ /*
+ * Parse the hostport.
+ */
+ ret = url_parse_hostport(buf, &proxy_hp, URL_DFLT_PROXY_PORT);
+ if (ret == URL_PARSE_SUCCESS) {
+ proxy_exists = B_TRUE;
+ } else {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "%s is not set to a valid hostport value",
+ BI_HTTP_PROXY);
+ return (-1);
+ }
+ is_proxy_init = B_TRUE;
+ }
+
+ http_set_p12_format(use_p12);
+
+ /*
+ * Initialize the handle that will be used for the request.
+ */
+ *handlep = http_srv_init(url);
+ if (*handlep == NULL) {
+ print_errors("http_srv_init", NULL);
+ return (-1);
+ }
+
+ /*
+ * Is the request a secure one? If it is, then we need to do further
+ * setup. Search the wanboot file system for files that will be
+ * needed by SSL.
+ */
+ if (url->https) {
+ char *cas;
+ boolean_t client_authentication = B_FALSE;
+
+ if (http_set_random_file(*handlep, "/dev/urandom") < 0) {
+ print_errors("http_set_random_file", *handlep);
+ (void) http_srv_close(*handlep);
+ return (-1);
+ }
+
+ /*
+ * We only need to initialize the CA once as it is not handle
+ * specific.
+ */
+ if (!is_auth_file_init) {
+ if (http_set_certificate_authority_file(NB_CA_CERT_PATH)
+ < 0) {
+ print_errors(
+ "http_set_certificate_authority_file",
+ *handlep);
+ (void) http_srv_close(*handlep);
+ return (-1);
+ }
+
+ is_auth_file_init = B_TRUE;
+ }
+
+ /*
+ * The client certificate and key will not exist unless
+ * client authentication has been configured. If it is
+ * configured then the webserver will have added these
+ * files to the wanboot file system and the HTTP library
+ * needs to be made aware of their existence.
+ */
+ if ((cas = bootconf_get(&bc_handle,
+ BC_CLIENT_AUTHENTICATION)) != NULL &&
+ strcmp(cas, "yes") == 0) {
+ client_authentication = B_TRUE;
+
+ if (http_set_client_certificate_file(*handlep,
+ NB_CLIENT_CERT_PATH) < 0) {
+ print_errors("http_set_client_certificate_file",
+ *handlep);
+ (void) http_srv_close(*handlep);
+ return (-1);
+ }
+
+ if (http_set_private_key_file(*handlep,
+ NB_CLIENT_KEY_PATH) < 0) {
+ print_errors("http_set_private_key_file",
+ *handlep);
+ (void) http_srv_close(*handlep);
+ return (-1);
+ }
+ }
+
+ /*
+ * We do not really need to set this unless client
+ * authentication is configured or unless pkcs12 files
+ * are used.
+ */
+ if ((client_authentication || use_p12) &&
+ http_set_password(*handlep, WANBOOT_PASSPHRASE) < 0) {
+ print_errors("http_set_password", *handlep);
+ (void) http_srv_close(*handlep);
+ return (-1);
+ }
+ }
+
+ /*
+ * If the client is using a proxy, tell the library.
+ */
+ if (proxy_exists) {
+ if (http_set_proxy(*handlep, &proxy_hp) != 0) {
+ print_errors("http_set_proxy", *handlep);
+ (void) http_srv_close(*handlep);
+ return (-1);
+ }
+ }
+
+ (void) http_set_socket_read_timeout(*handlep, SOCKET_READ_TIMEOUT);
+
+ /*
+ * Ok, connect to the webserver.
+ */
+ if (http_srv_connect(*handlep) == -1) {
+ print_errors("http_srv_connect", *handlep);
+ (void) http_srv_close(*handlep);
+ return (1);
+ }
+
+ /*
+ * If the offset is 0, then we assume that we want the entire
+ * message. If the offset is not 0, then we assume that we are
+ * retrying a previously interrupted transfer and thus we make
+ * a range request.
+ */
+ if (offset == 0) {
+ if ((ret = http_get_request(*handlep, url->abspath)) == 0) {
+ bootlog("wanboot", BOOTLOG_VERBOSE,
+ "%s: http_get_request: sent", what);
+ } else {
+ print_errors("http_get_request", *handlep);
+ (void) http_srv_close(*handlep);
+ return (1);
+ }
+ } else {
+ if ((ret = http_get_range_request(*handlep, url->abspath,
+ offset, 0)) == 0) {
+ bootlog("wanboot", BOOTLOG_VERBOSE,
+ "%s: http_get_range_request: sent", what);
+ } else {
+ print_errors("http_get_range_request", *handlep);
+ (void) http_srv_close(*handlep);
+ return (1);
+ }
+ }
+
+ /*
+ * Tell the library to read in the response headers.
+ */
+ ret = http_process_headers(*handlep, &resp);
+ if (ret == -1) {
+ print_errors("http_process_headers", *handlep);
+ (void) http_srv_close(*handlep);
+ return (1);
+ }
+
+ /*
+ * Check for a valid response code.
+ */
+ if ((offset == 0 && resp->code != 200) ||
+ (offset != 0 && resp->code != 206)) {
+ bootlog("wanboot", BOOTLOG_ALERT,
+ "%s: Request returned code %d", what, resp->code);
+ if (resp->statusmsg != NULL && resp->statusmsg[0] != '\0')
+ bootlog("wanboot", BOOTLOG_ALERT,
+ "%s", resp->statusmsg);
+ http_free_respinfo(resp);
+ (void) http_srv_close(*handlep);
+ return (1);
+ }
+ http_free_respinfo(resp);
+
+ /*
+ * Success.
+ */
+ return (0);
+}
+
+/*
+ * This routine is called by get_miniinfo() to receive the reply
+ * to the request for the miniroot metadata. The reply is a two
+ * part multipart message. The first part of the message contains
+ * the miniroot file size. The second part of the message contains
+ * a hash digest of the miniroot as computed by the server. This
+ * routine receives both message parts and returns them to the caller.
+ *
+ * Notes:
+ * If the miniroot is going to be downloaded securely or if the
+ * the server has no hash key for the client, then the hash digest
+ * downloaded contains all zeros.
+ *
+ * Any HTTP errors encountered in downloading or processing the message
+ * are not deemed unrecoverable errors. That is, get_miniinfo()
+ * tries re-requesting the message and tries processing it again.
+ *
+ * Returns:
+ * -1 = Non-recoverable error
+ * 0 = Success
+ * 1 = HTTP download error
+ */
+static int
+process_miniinfo(http_handle_t handle, size_t *mini_size,
+ unsigned char *sdigest)
+{
+ char *lenstr;
+ size_t cnt;
+
+ /*
+ * Process the file size header.
+ */
+ if (http_process_part_headers(handle, NULL) != 0) {
+ print_errors("http_process_part_headers", handle);
+ return (1);
+ }
+ lenstr = http_get_header_value(handle, CONTENT_LENGTH);
+ if (lenstr == NULL) {
+ bootlog("wanboot", BOOTLOG_ALERT, "%s: error getting length "
+ "of first part of multipart message", MINIINFO);
+ return (1);
+ }
+ cnt = (size_t)strtol(lenstr, NULL, 10);
+ free(lenstr);
+ if (cnt == 0 || cnt >= sizeof (buffer)) {
+ bootlog("wanboot", BOOTLOG_ALERT, "%s: length of first part "
+ "of multipart message not a legal size", MINIINFO);
+ return (1);
+ }
+
+ if (read_bytes(handle, buffer, cnt) != 0) {
+ bootlog("wanboot", BOOTLOG_ALERT,
+ "%s: error reading miniroot size", MINIINFO);
+ return (1);
+ }
+ buffer[cnt] = '\0';
+
+ *mini_size = (size_t)strtol(buffer, NULL, 10);
+ if (*mini_size == 0) {
+ bootlog("wanboot", BOOTLOG_ALERT, "%s: body of first part "
+ "of multipart message not a legal size", MINIINFO);
+ return (1);
+ }
+
+ return (read_digest(MINIINFO, handle, sdigest));
+}
+
+/*
+ * This routine is called by get_miniroot() to retrieve the miniroot
+ * metadata (miniroot size and a hash digest). This routine sends an
+ * HTTP GET request to the webserver to request the download of the
+ * miniroot metadata and relies on process_miniinfo() to receive the
+ * reply, process it and ultimately return to it the miniroot size and
+ * the hash digest.
+ *
+ * Note:
+ * Any HTTP errors encountered in downloading or processing the message
+ * are not deemed unrecoverable errors. That is, get_miniinfo() should
+ * try re-requesting the message and try processing again.
+ *
+ * Returns:
+ * -1 = Non-recoverable error
+ * 0 = Success
+ */
+int
+get_miniinfo(const url_t *server_url, size_t *mini_size,
+ unsigned char *sdigest)
+{
+ http_handle_t handle;
+ url_t req_url;
+ int retry_cnt = 0;
+ int retry_max = WANBOOT_RETRY_MAX;
+ int ret;
+
+ /*
+ * Build the URL to request the miniroot info.
+ */
+ if (build_request_url(&req_url, URLtype_miniroot, server_url) == -1) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "Can't build the URL to make the %s request",
+ CGIcontent(URLtype_miniroot));
+ return (-1);
+ }
+
+ /*
+ * Go get the miniroot info. If we fail reading the
+ * response we re-request the info in its entirety.
+ */
+ bootlog("wanboot", BOOTLOG_VERBOSE, "Downloading miniroot info");
+
+ do {
+ if ((ret = establish_http_connection(MINIINFO, &handle,
+ &req_url, 0)) < 0) {
+ break;
+ } else if (ret > 0) {
+ if (wanboot_retry(++retry_cnt, retry_max)) {
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ if ((ret = process_miniinfo(handle, mini_size,
+ sdigest)) > 0) {
+ if (!wanboot_retry(++retry_cnt, retry_max)) {
+ (void) http_srv_close(handle);
+ break;
+ }
+ }
+
+ (void) http_srv_close(handle);
+
+ } while (ret > 0);
+
+ /*
+ * Success.
+ */
+ if (ret == 0) {
+ bootlog("wanboot", BOOTLOG_VERBOSE,
+ "Miniroot info download successful");
+ return (0);
+ } else {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "Miniroot info download aborted");
+ return (-1);
+ }
+}
+
+/*
+ * This routine is called by get_miniroot() to receive the reply to
+ * the request for the miniroot download. The miniroot is written
+ * to ramdisk as it is received and a hash digest is optionally computed
+ * as it does so. The miniroot is downloaded as one large message.
+ * Because the message is so large, this routine is prepared to deal
+ * with errors in the middle of download. If an error occurs during
+ * download, then this message processes all received data up to the
+ * point of the error and returns to get_miniroot() an error signifying
+ * that a download error has occurred. Presumably, get_miniroot()
+ * re-requests the remaining part of the miniroot not yet processed and
+ * calls this routine back to process the reply. When this routine
+ * returns succesfully, it returns a devpath to the ramdisk and the
+ * computed hash (if computed).
+ *
+ * Note:
+ * In order to facilitate reentry, the ramdisk is left open
+ * and the original miniroot_size and HMAC handle are kept
+ * static.
+ *
+ * Returns:
+ * -1 = Non-recoverable error
+ * 0 = Success
+ * 1 = HTTP download error
+ */
+static int
+process_miniroot(http_handle_t handle, hash_type_t htype,
+ size_t length, char **devpath, off_t *offset, unsigned char *cdigest)
+{
+ static SHA1_CTX sha;
+ static size_t miniroot_size;
+ static int fd = -1;
+ int ret;
+
+ if (fd == -1) {
+ if (htype == HASH_HMAC_SHA1) {
+ bootlog("wanboot", BOOTLOG_INFO,
+ "%s: Authentication will use HMAC-SHA1", MINIROOT);
+ HMACInit(&sha, g_hash_key, WANBOOT_HMAC_KEY_SIZE);
+ }
+
+ miniroot_size = length;
+
+ fd = create_ramdisk(RD_ROOTFS, miniroot_size, devpath);
+ }
+
+ if (prom_seek(fd, *offset) == -1) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "%s: prom_seek error", MINIROOT);
+ return (-1);
+ }
+
+ 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);
+ }
+ return (ret);
+ }
+
+ if (htype != HASH_NONE) {
+ HMACFinal(&sha, g_hash_key, WANBOOT_HMAC_KEY_SIZE, cdigest);
+ }
+
+ (void) prom_close(fd);
+
+ return (0);
+}
+
+/*
+ * This routine retrieves the miniroot from the webserver. The miniroot
+ * is retrieved in two steps. First a request is made to the server
+ * to retrieve miniroot metadata (miniroot size and a hash digest).
+ * The second request actually results in the download of the miniroot.
+ *
+ * This routine relies on get_miniinfo() to make and process
+ * the request for the miniroot metadata and returns the
+ * miniroot size and the hash digest of the miniroot as computed by
+ * the server.
+ *
+ * If get_miniinfo() returns successfully, then this routine sends
+ * an HTTP GET request to the webserver to request download of the
+ * miniroot. This routine relies on process_miniroot() to receive
+ * the reply, process it and ultimately return to it a device path to
+ * a ramdisk containing the miniroot and a client computed hash digest.
+ * This routine verifies that the client computed hash digest matches
+ * the one retrieved by get_miniinfo().
+ *
+ * If an error occurs in the transfer of the miniroot from the server
+ * to the client, then the client re-requests the download of the
+ * miniroot using a range request and only requests the part of the
+ * miniroot not previously downloaded and written to ramdisk. The
+ * process_miniroot() routine has the intelligence to recognize that
+ * it is processing a range request. Errors not related to the actual
+ * message download are deemed unrecoverable.
+ *
+ * Note:
+ * If the client request for the miniroot is a secure request or
+ * if the server is not configured with a hash key for the client,
+ * then the hash digest downloaded from the server will contain
+ * all zeros. This routine verifies that the server and client are
+ * in-sync with respect to the need for hash verification.
+ *
+ * Returns:
+ * -1 = Non-recoverable error
+ * 0 = Success
+ */
+int
+get_miniroot(char **devpath)
+{
+ http_handle_t handle;
+ unsigned char cdigest[HMAC_DIGEST_LEN];
+ unsigned char sdigest[HMAC_DIGEST_LEN];
+ char *urlstr;
+ url_t server_url;
+ size_t mini_size;
+ off_t offset;
+ int plen;
+ int retry_cnt = 0;
+ int retry_max = WANBOOT_RETRY_ROOT_MAX;
+ int ret;
+
+ /*
+ * Get the miniroot URL.
+ */
+ if ((urlstr = bootconf_get(&bc_handle, BC_ROOT_SERVER)) == NULL) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "Missing root_server URL");
+ return (-1);
+ } else if (url_parse(urlstr, &server_url) != URL_PARSE_SUCCESS) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "Unable to parse URL %s", urlstr);
+ return (-1);
+ }
+
+ /*
+ * We must get the miniroot info before we can request
+ * the miniroot itself.
+ */
+ if (get_miniinfo(&server_url, &mini_size, sdigest) != 0) {
+ return (-1);
+ }
+
+ plen = sizeof (server_url.abspath);
+ if ((urlstr = bootconf_get(&bc_handle, BC_ROOT_FILE)) == NULL ||
+ strlcpy(server_url.abspath, urlstr, plen) >= plen) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "Cannot retrieve the miniroot path");
+ return (-1);
+ }
+
+ /*
+ * Go get the miniroot. If we fail reading the response
+ * then we re-request only the range we have yet to read,
+ * unless the error was "unrecoverable" in which case we
+ * re-request the entire file system.
+ */
+ bootlog("wanboot", BOOTLOG_VERBOSE, "Downloading miniroot");
+
+ bzero(cdigest, sizeof (cdigest));
+ offset = 0;
+ do {
+ if ((ret = establish_http_connection(MINIROOT, &handle,
+ &server_url, offset)) < 0) {
+ break;
+ } else if (ret > 0) {
+ if (wanboot_retry(++retry_cnt, retry_max)) {
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ if ((ret = process_miniroot(handle,
+ server_url.https ? HASH_NONE : hash_type,
+ mini_size, devpath, &offset, cdigest)) > 0) {
+ if (!wanboot_retry(++retry_cnt, retry_max)) {
+ (void) http_srv_close(handle);
+ break;
+ }
+ }
+
+ (void) http_srv_close(handle);
+
+ } while (ret > 0);
+
+ /*
+ * Validate the computed digest against the one received.
+ */
+ if (ret != 0 || !verify_digests(MINIROOT, cdigest, sdigest)) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "Miniroot download aborted");
+ return (-1);
+ }
+
+ bootlog("wanboot", BOOTLOG_VERBOSE, "Miniroot download successful");
+ return (0);
+}
+
+/*
+ * This routine is called to finish the decryption process.
+ * Its purpose is to free the resources allocated by the
+ * encryption init routines.
+ */
+static void
+encr_fini(encr_type_t etype, void *eh)
+{
+ switch (etype) {
+ case ENCR_3DES:
+ des3_fini(eh);
+ break;
+ case ENCR_AES:
+ aes_fini(eh);
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ * 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
+ * (algorithm) will have already been determined by process_wanbootfs()
+ * and the cbc_handle passed to this routine will already have been
+ * initialized appropriately.
+ *
+ * Returns:
+ * -1 = Non-recoverable error
+ * 0 = Success
+ */
+static int
+decrypt_wanbootfs(int fd, cbc_handle_t *ch, uint8_t *iv,
+ size_t block_size, 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);
+ }
+ }
+ return (0);
+}
+
+/*
+ * This routine is called by get_wanbootfs() to receive the reply to
+ * the request for the wanboot file system. The reply is a multipart message.
+ * The first part of the message is the file system (which may or may
+ * not be encrypted). If encrypted, then the first block of the message
+ * part is the CBC IV value used by the server to encrypt the remaining
+ * part of the message part and is used by the client to decrypt it. The
+ * second message part is a hash digest of the first part (the file
+ * system) as computed by the server. If no hash key is configured
+ * for the client, then the hash digest simply contains all zeros. This
+ * routine receives both message parts. The file system is written to ramdisk
+ * as it is received and simultaneously computes a hash digest (if a hash
+ * key exists). Once the entire part is received, if the file system is
+ * encrypted, it is read from ramdisk, decrypted and rewritten back to
+ * ramdisk. The server computed hash digest is then read and along with the
+ * ramdisk device path and the client computed hash digest is returned to the
+ * caller.
+ *
+ * Notes:
+ * In order to decrypt the file system and to compute the client
+ * hash digest, an encryption key and a hash key is retrieved from
+ * the PROM (or the wanboot interpreter). The non-existence of these
+ * keys has implications on how the message response is processed and
+ * it is assumed that the server is configured identically.
+ *
+ * Any HTTP errors encountered in downloading or processing the message
+ * are not deemed unrecoverable errors. That is, get_wanbootfs() will
+ * try re-requesting the message and will try processing it again.
+ *
+ * Returns:
+ * -1 = Non-recoverable error
+ * 0 = Success
+ * 1 = HTTP download error
+ */
+static int
+process_wanbootfs(http_handle_t handle, char **devpath,
+ unsigned char *cdigest, unsigned char *sdigest)
+{
+ /* iv[] must be sized to store the largest possible encryption block */
+ uint8_t iv[WANBOOT_MAXBLOCKLEN];
+ cbc_handle_t ch;
+ void *eh;
+ SHA1_CTX sha;
+ char *lenstr;
+ size_t wanbootfs_size;
+ size_t block_size;
+ off_t offset;
+ static int fd = -1;
+ int ret;
+
+ switch (hash_type) {
+ case HASH_HMAC_SHA1:
+ bootlog("wanboot", BOOTLOG_INFO,
+ "%s: Authentication will use HMAC-SHA1", WANBOOTFS);
+ HMACInit(&sha, g_hash_key, WANBOOT_HMAC_KEY_SIZE);
+ break;
+ case HASH_NONE:
+ break;
+ default:
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "%s: unrecognized hash type", WANBOOTFS);
+ return (-1);
+ }
+
+ switch (encr_type) {
+ case ENCR_3DES:
+ bootlog("wanboot",
+ BOOTLOG_INFO, "%s: Decryption will use 3DES", WANBOOTFS);
+ if (des3_init(&eh) != 0) {
+ return (-1);
+ }
+ block_size = DES3_BLOCK_SIZE;
+ des3_key(eh, g_encr_key);
+ cbc_makehandle(&ch, eh, DES3_KEY_SIZE, block_size,
+ DES3_IV_SIZE, des3_encrypt, des3_decrypt);
+
+ break;
+ case ENCR_AES:
+ bootlog("wanboot",
+ BOOTLOG_INFO, "%s: Decryption will use AES", WANBOOTFS);
+ if (aes_init(&eh) != 0) {
+ return (-1);
+ }
+ block_size = AES_BLOCK_SIZE;
+ aes_key(eh, g_encr_key, AES_128_KEY_SIZE);
+ cbc_makehandle(&ch, eh, AES_128_KEY_SIZE, block_size,
+ AES_IV_SIZE, aes_encrypt, aes_decrypt);
+ break;
+ case ENCR_NONE:
+ break;
+ default:
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "%s: unrecognized encryption type", WANBOOTFS);
+ return (-1);
+ }
+
+ /*
+ * Process the header.
+ */
+ if (http_process_part_headers(handle, NULL) != 0) {
+ print_errors("http_process_part_headers", handle);
+ return (1);
+ }
+ lenstr = http_get_header_value(handle, CONTENT_LENGTH);
+ if (lenstr == NULL) {
+ bootlog("wanboot", BOOTLOG_ALERT, "%s: error getting length "
+ "of first part of multipart message", WANBOOTFS);
+ return (1);
+ }
+ wanbootfs_size = (size_t)strtol(lenstr, NULL, 10);
+ free(lenstr);
+ if (wanbootfs_size == 0) {
+ bootlog("wanboot", BOOTLOG_ALERT, "%s: length of first part "
+ "of multipart message not a legal size", WANBOOTFS);
+ return (1);
+ }
+
+ /*
+ * If encrypted, then read the iv.
+ */
+ if (encr_type != ENCR_NONE) {
+ if (read_bytes(handle, (char *)iv, block_size) != 0) {
+ bootlog("wanboot", BOOTLOG_ALERT,
+ "%s: error reading hash iv", WANBOOTFS);
+ return (1);
+ }
+ wanbootfs_size -= block_size;
+ if (hash_type != HASH_NONE) {
+ HMACUpdate(&sha, (uchar_t *)iv, block_size);
+ }
+ }
+
+ /*
+ * We can only create the ramdisk once. So, if we've
+ * already created it, then it means we've re-entered
+ * this routine from an earlier partial failure. Use
+ * the already existing ramdisk and seek back to the
+ * beginning of the file.
+ */
+ if (fd == -1) {
+ fd = 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);
+ }
+ return (ret);
+ }
+
+ if (hash_type != HASH_NONE) {
+ HMACFinal(&sha, g_hash_key, WANBOOT_HMAC_KEY_SIZE, cdigest);
+ }
+
+ /*
+ * If encrypted, then decrypt it.
+ */
+ if (encr_type != ENCR_NONE) {
+ ret = decrypt_wanbootfs(fd, &ch, iv, block_size,
+ 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));
+}
+
+/*
+ * This routine sends an HTTP GET request to the webserver to
+ * request the wanboot file system for the client. The server
+ * will reply by sending a multipart message. This routine will rely
+ * on process_wanbootfs() to receive the multipart message, process it
+ * and ultimately return to it a device path to a ramdisk containing
+ * the wanboot file system, a client computed hash digest and a
+ * server computed hash digest. This routine will verify that the
+ * client computed hash digest matches the one sent by the server. This
+ * routine will also verify that the nonce received in the reply matches
+ * the one sent in the request.
+ *
+ * If an error occurs in the transfer of the message from the server
+ * to the client, then the client re-requests the download in its
+ * entirety. Errors not related to the actual message download are
+ * deemed unrecoverable.
+ *
+ * Returns:
+ * -1 = Non-recoverable error
+ * 0 = Success
+ */
+int
+get_wanbootfs(const url_t *server_url)
+{
+ http_handle_t handle;
+ unsigned char cdigest[HMAC_DIGEST_LEN];
+ unsigned char sdigest[HMAC_DIGEST_LEN];
+ url_t req_url;
+ char *devpath;
+ int ret;
+ int fd;
+ char buf[NONCELEN + 1];
+ int retry_cnt = 0;
+ int retry_max = WANBOOT_RETRY_MAX;
+
+ /*
+ * Build the URL to request the wanboot file system. This URL
+ * will include the CGI script name and the IP, CID, and
+ * NONCE parameters.
+ */
+ if (build_request_url(&req_url, URLtype_wanbootfs, server_url) == -1) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "Can't build the URL to make the %s request",
+ CGIcontent(URLtype_wanbootfs));
+ return (-1);
+ }
+
+ /*
+ * Go get the wanboot file system. If we fail reading the
+ * response we re-request the entire file system.
+ */
+ bootlog("wanboot", BOOTLOG_VERBOSE, "Downloading wanboot file system");
+
+ bzero(cdigest, sizeof (cdigest));
+ do {
+ if ((ret = establish_http_connection(WANBOOTFS, &handle,
+ &req_url, 0)) < 0) {
+ break;
+ } else if (ret > 0) {
+ if (wanboot_retry(++retry_cnt, retry_max)) {
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ if ((ret = process_wanbootfs(handle, &devpath,
+ cdigest, sdigest)) > 0) {
+ if (!wanboot_retry(++retry_cnt, retry_max)) {
+ (void) http_srv_close(handle);
+ break;
+ }
+ }
+
+ (void) http_srv_close(handle);
+
+ } while (ret > 0);
+
+ /*
+ * Validate the computed digest against the one received.
+ */
+ if (ret != 0 ||
+ !verify_digests(WANBOOTFS, cdigest, sdigest)) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "The wanboot file system download aborted");
+ return (-1);
+ }
+
+ /*
+ * Mount the wanboot file system.
+ */
+ if (determine_fstype_and_mountroot(devpath) != VFS_SUCCESS) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "Could not mount the wanboot filesystem.");
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "This may signify a client/server key mismatch");
+ if (encr_type != ENCR_NONE) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "(client has key but wrong encryption_type?)");
+ } else {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "(encryption_type specified but no client key?)");
+ }
+ return (-1);
+ }
+ bootlog("wanboot", BOOTLOG_VERBOSE,
+ "The wanboot file system has been mounted");
+
+ /*
+ * The wanboot file system should contain a nonce. Read it
+ * and compare it against the nonce sent in the request.
+ */
+ if ((fd = open(WANBOOTFS_NONCE_FILE, O_RDONLY)) == -1) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "No nonce found in the wanboot file system");
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "The wanboot file system download aborted");
+ return (-1);
+ }
+
+ if (read(fd, buf, NONCELEN) != NONCELEN ||
+ bcmp(nonce, buf, NONCELEN) != 0) {
+ (void) close(fd);
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "Invalid nonce found in the wanboot file system");
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "The wanboot file system download aborted");
+ return (-1);
+ }
+
+ (void) close(fd);
+
+ bootlog("wanboot", BOOTLOG_VERBOSE,
+ "The wanboot file system download was successful");
+ return (0);
+}
+
+static boolean_t
+init_netdev(char *bpath)
+{
+ dnode_t anode;
+ int proplen;
+ static char netalias[OBP_MAXPATHLEN];
+
+ /*
+ * Wanboot will either have loaded over the network (in which case
+ * bpath will name a network device), or from CD-ROM or disk. In
+ * both cases ensure that the 'net' alias corresponds to a network
+ * device, and that if a network boot was performed that it is
+ * identical to bpath. This is so that the interface name can always
+ * be determined for CD-ROM or disk boots, and for manually-configured
+ * network boots. The latter restriction may be relaxed in the future.
+ */
+ anode = prom_alias_node();
+ if ((proplen = prom_getproplen(anode, "net")) > 0 &&
+ proplen < sizeof (netalias)) {
+ (void) prom_getprop(anode, "net", (caddr_t)netalias);
+
+ if (is_netdev(netalias)) {
+ char *p;
+
+ /*
+ * Strip device arguments from netalias[].
+ */
+ if ((p = strchr(netalias, ':')) != NULL) {
+ *p = '\0';
+ }
+
+ /*
+ * If bpath is a network device path, then v2path
+ * will be a copy of this sans device arguments.
+ */
+ if (!is_netdev(bpath) ||
+ strcmp(v2path, netalias) == 0) {
+ /*
+ * Stash the netdev_path bootprop value, then
+ * initialize the hardware and return success.
+ */
+ netdev_path = netalias;
+ mac_init(netalias);
+ return (B_TRUE);
+ }
+
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "wanboot requires that the 'net' alias refers to ");
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "the network device path from which it loaded");
+ return (B_FALSE);
+ }
+ }
+
+ /*
+ * If we haven't established a device path for a network interface,
+ * then we're doomed.
+ */
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "No network device available for wanboot!");
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "(Ensure that the 'net' alias is set correctly)");
+ return (B_FALSE);
+}
+
+/*
+ * This implementation of bootprog() is used solely by wanboot.
+ *
+ * The basic algorithm is as follows:
+ *
+ * - The wanboot options (those specified using the "-o" flag) are processed,
+ * and if necessary the wanboot interpreter is invoked to collect other
+ * options.
+ *
+ * - The wanboot filesystem (containing certificates, wanboot.conf file, etc.)
+ * is then downloaded into the bootfs ramdisk, which is mounted for use
+ * by OpenSSL, access to wanboot.conf, etc.
+ *
+ * - The wanboot miniroot is downloaded over http/https into the rootfs
+ * ramdisk. The bootfs filesystem is unmounted, and the rootfs filesystem
+ * is mounted.
+ */
+/* EXPORT DELETE END */
+/*ARGSUSED*/
+int
+bootprog(char *bpath, char *bargs, boolean_t user_specified_filename)
+{
+/* EXPORT DELETE START */
+ char *miniroot_path;
+ url_t server_url;
+ int ret;
+
+ if (!init_netdev(bpath)) {
+ return (-1);
+ }
+
+ if (!bootinfo_init()) {
+ bootlog("wanboot", BOOTLOG_CRIT, "Cannot initialize bootinfo");
+ return (-1);
+ }
+
+ /*
+ * Get default values from PROM, etc., process any boot arguments
+ * (specified with the "-o" option), and initialize the interface.
+ */
+ if (!wanboot_init_interface(wanboot_arguments)) {
+ return (-1);
+ }
+
+ /*
+ * Determine which encryption and hashing algorithms the client
+ * is configured to use.
+ */
+ init_encryption();
+ init_hashing();
+
+ /*
+ * Get the bootserver value. Should be of the form:
+ * http://host[:port]/abspath.
+ */
+ ret = get_url(BI_BOOTSERVER, &server_url);
+ if (ret != 0) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "Unable to retrieve the bootserver URL");
+ return (-1);
+ }
+
+ /*
+ * Get the wanboot file system and mount it. Contains metdata
+ * needed by wanboot.
+ */
+ if (get_wanbootfs(&server_url) != 0) {
+ return (-1);
+ }
+
+ /*
+ * Check that there is a valid wanboot.conf file in the wanboot
+ * file system.
+ */
+ if (bootconf_init(&bc_handle, NULL) != BC_E_NOERROR) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "wanboot.conf error (code=%d)", bc_handle.bc_error_code);
+ return (-1);
+ }
+
+ /*
+ * Set the time
+ */
+ init_boot_time();
+
+ /*
+ * Verify that URLs in wanboot.conf can be reached, etc.
+ */
+ if (!wanboot_verify_config()) {
+ return (-1);
+ }
+
+ /*
+ * Retrieve the miniroot.
+ */
+ if (get_miniroot(&miniroot_path) != 0) {
+ return (-1);
+ }
+
+ /*
+ * We don't need the wanboot file system mounted anymore and
+ * should unmount it so that we can mount the miniroot.
+ */
+ (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();
+
+/* EXPORT DELETE END */
+ return (0);
+}
diff --git a/usr/src/psm/stand/boot/sparc/common/wbcli.c b/usr/src/psm/stand/boot/sparc/common/wbcli.c
new file mode 100644
index 0000000000..f6d6d9a00a
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/wbcli.c
@@ -0,0 +1,1425 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* EXPORT DELETE START */
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/salib.h>
+#include <sys/promif.h>
+#include <sys/wanboot_impl.h>
+#include <netinet/in.h>
+#include <parseURL.h>
+#include <bootlog.h>
+#include <sys/socket.h>
+#include <netinet/inetutil.h>
+#include <netinet/dhcp.h>
+#include <dhcp_impl.h>
+#include <lib/inet/mac.h>
+#include <lib/inet/ipv4.h>
+#include <lib/inet/dhcpv4.h>
+#include <lib/sock/sock_test.h>
+#include <sys/sunos_dhcp_class.h>
+#include <aes.h>
+#include <des3.h>
+#include <hmac_sha1.h>
+#include <netdb.h>
+#include <wanboot_conf.h>
+#include <bootinfo.h>
+/* EXPORT DELETE END */
+
+#include "wbcli.h"
+
+/* EXPORT DELETE START */
+
+#define skipspace(p) while (isspace(*(p))) ++p
+
+#define skiptext(p) while (*(p) != '\0' && !isspace(*(p)) && \
+ *(p) != '=' && *(p) != ',') ++p
+
+#define PROMPT "boot> "
+#define TEST_PROMPT "boot-test> "
+
+#define CLI_SET 0
+#define CLI_FAIL (-1)
+#define CLI_EXIT (-2)
+#define CLI_CONT (-3)
+
+#define CLF_CMD 0x00000001 /* builtin command */
+#define CLF_ARG 0x00000002 /* boot argument directive */
+
+#define CLF_IF 0x00000100 /* interface parameter */
+#define CLF_BM 0x00000200 /* bootmisc parameter */
+
+#define CLF_VALSET 0x00010000 /* value set, may be null */
+#define CLF_HIDDEN 0x00020000 /* don't show its value (key) */
+#define CLF_VALMOD 0x00040000 /* value modified by the user */
+
+/*
+ * Macros for use in managing the flags in the cli_list[].
+ * The conventions we follow are:
+ *
+ * CLF_VALSET is cleared if a value is removed from varptr
+ * CLF_VALSET is set if a value has been placed in varptr
+ * (that value need not be vetted)
+ * CLF_HIDDEN is set if a value must not be exposed to the user
+ * CLF_HIDDEN is cleared if a value can be exposed to the user
+ * CLF_VALMOD is cleared if a value in varptr has not been modified
+ * CLF_VALMOD is set if a value in varptr has been modified by
+ * the user
+ */
+#ifdef DEBUG
+#define CLF_SETVAL(var) { \
+ (((var)->flags) |= CLF_VALSET); \
+ printf("set %s\n", var->varname);\
+ }
+
+#define CLF_ISSET(var) (printf("%s\n", \
+ (((var)->flags) & CLF_VALSET) != 0 \
+ ? "is set" : "not set"), \
+ ((((var)->flags) & CLF_VALSET) != 0))
+
+#define CLF_CLRHIDDEN(var) { \
+ (((var)->flags) &= ~CLF_HIDDEN); \
+ printf("unhide %s\n", var->varname); \
+ }
+
+#define CLF_ISHIDDEN(var) (printf("%s\n", \
+ (((var)->flags) & CLF_HIDDEN) != 0 \
+ ? "is hidden" : "not hidden"), \
+ ((((var)->flags) & CLF_HIDDEN) != 0))
+
+#define CLF_MODVAL(var) { \
+ (((var)->flags) |= \
+ (CLF_VALMOD | CLF_VALSET)); \
+ printf("modified %s\n", var->varname);\
+ }
+
+#define CLF_ISMOD(var) (printf("%s\n", \
+ (((var)->flags) & CLF_VALMOD) != 0 \
+ ? "is set" : "not set"), \
+ ((((var)->flags) & CLF_VALMOD) != 0))
+#else /* DEBUG */
+
+#define CLF_SETVAL(var) (((var)->flags) |= CLF_VALSET)
+#define CLF_ISSET(var) ((((var)->flags) & CLF_VALSET) != 0)
+#define CLF_CLRHIDDEN(var) (((var)->flags) &= ~CLF_HIDDEN)
+#define CLF_ISHIDDEN(var) ((((var)->flags) & CLF_HIDDEN) != 0)
+#define CLF_MODVAL(var) (((var)->flags) |= (CLF_VALMOD | CLF_VALSET))
+#define CLF_ISMOD(var) ((((var)->flags) & CLF_VALMOD) != 0)
+
+#endif /* DEBUG */
+
+/*
+ * The width of the widest varname below - currently "subnet_mask".
+ */
+#define VAR_MAXWIDTH strlen(BI_SUBNET_MASK)
+
+struct cli_ent;
+typedef int claction_t(struct cli_ent *, char *, boolean_t);
+
+typedef struct cli_ent {
+ char *varname;
+ claction_t *action;
+ int flags;
+ void *varptr;
+ uint_t varlen;
+ uint_t varmax;
+} cli_ent_t;
+
+static cli_ent_t *find_cli_ent(char *varstr);
+
+static char cmdbuf[2048]; /* interpreter buffer */
+static char hostip[INET_ADDRSTRLEN];
+static char subnet[INET_ADDRSTRLEN];
+static char router[INET_ADDRSTRLEN];
+static char hostname[MAXHOSTNAMELEN];
+static char httpproxy[INET_ADDRSTRLEN + 5]; /* a.b.c.d:p */
+static char bootserverURL[URL_MAX_STRLEN + 1];
+static unsigned char clientid[WB_MAX_CID_LEN];
+static unsigned char aeskey[AES_128_KEY_SIZE];
+static unsigned char des3key[DES3_KEY_SIZE];
+static unsigned char sha1key[WANBOOT_HMAC_KEY_SIZE];
+static boolean_t args_specified_prompt = B_FALSE;
+
+extern bc_handle_t bc_handle;
+extern int getchar(void);
+
+static claction_t clcid, clkey, clip, clstr, clurl, clhp;
+static claction_t clhelp, cllist, clprompt, cldhcp, cltest, clgo, clexit;
+
+static cli_ent_t cli_list[] = {
+ /*
+ * Commands/bootargs:
+ */
+ { "test", cltest, CLF_ARG,
+ NULL, 0, 0 },
+ { "dhcp", cldhcp, CLF_ARG,
+ NULL, 0, 0 },
+ { "prompt", clprompt, CLF_CMD | CLF_ARG,
+ NULL, 0, 0 },
+ { "list", cllist, CLF_CMD,
+ NULL, 0, 0 },
+ { "help", clhelp, CLF_CMD,
+ NULL, 0, 0 },
+ { "go", clgo, CLF_CMD,
+ NULL, 0, 0 },
+ { "exit", clexit, CLF_CMD,
+ NULL, 0, 0 },
+
+ /*
+ * Interface:
+ */
+ { BI_HOST_IP, clip, CLF_IF,
+ hostip, 0, sizeof (hostip) },
+ { BI_SUBNET_MASK, clip, CLF_IF,
+ subnet, 0, sizeof (subnet) },
+ { BI_ROUTER_IP, clip, CLF_IF,
+ router, 0, sizeof (router) },
+ { BI_HOSTNAME, clstr, CLF_IF,
+ hostname, 0, sizeof (hostname) },
+ { BI_HTTP_PROXY, clhp, CLF_IF,
+ httpproxy, 0, sizeof (httpproxy) },
+ { BI_CLIENT_ID, clcid, CLF_IF,
+ clientid, 0, sizeof (clientid) },
+
+ /*
+ * Bootmisc:
+ */
+ { BI_AES_KEY, clkey, CLF_BM | CLF_HIDDEN,
+ aeskey, 0, sizeof (aeskey) },
+ { BI_3DES_KEY, clkey, CLF_BM | CLF_HIDDEN,
+ des3key, 0, sizeof (des3key) },
+ { BI_SHA1_KEY, clkey, CLF_BM | CLF_HIDDEN,
+ sha1key, 0, sizeof (sha1key) },
+ { BI_BOOTSERVER, clurl, CLF_BM,
+ bootserverURL, 0, sizeof (bootserverURL) },
+};
+
+static int num_cli_ent = (sizeof (cli_list) / sizeof (cli_ent_t));
+
+/*
+ * Fetch a line from the user, handling backspace appropriately.
+ */
+static int
+editline(char *buf, int count)
+{
+ int i = 0;
+ char c;
+
+ while (i < count - 1) {
+ c = getchar();
+ if (c == '\n') {
+ break;
+ } else if (c == '\b') {
+ /* Clear for backspace. */
+ if (i > 0)
+ i--;
+ continue;
+ } else {
+ buf[i++] = c;
+ }
+ }
+ buf[i] = '\0';
+ return (i);
+}
+
+/*
+ * Assign a client-id to cliptr, or output cliptr's value as a client-id.
+ * On assignment the value is specified in valstr, either in hexascii or
+ * as a quoted string; on output its value is printed in hexascii.
+ */
+static int
+clcid(cli_ent_t *cliptr, char *valstr, boolean_t out)
+{
+ uint_t len, vmax;
+ boolean_t hexascii = B_TRUE;
+ char buffer[2 * WB_MAX_CID_LEN + 1];
+
+ if (out) {
+ len = cliptr->varlen * 2 + 1;
+ (void) octet_to_hexascii(cliptr->varptr, cliptr->varlen,
+ buffer, &len);
+ printf("%s", buffer);
+ return (CLI_CONT);
+ } else {
+ len = strlen(valstr);
+ vmax = cliptr->varmax - 1; /* space for the prefix */
+
+ /*
+ * Check whether the value is a quoted string; if so, strip
+ * the quotes and note that it's not in hexascii.
+ */
+ if ((valstr[0] == '"' || valstr[0] == '\'') &&
+ valstr[len-1] == valstr[0]) {
+ hexascii = B_FALSE;
+ ++valstr;
+ len -= 2;
+ valstr[len] = '\0';
+ } else {
+ /*
+ * If the value contains any non-hex digits assume
+ * that it's not in hexascii.
+ */
+ char *p;
+
+ for (p = valstr; *p != '\0'; ++p) {
+ if (!isxdigit(*p)) {
+ hexascii = B_FALSE;
+ break;
+ }
+ }
+ }
+
+ if (hexascii) {
+ if (len > vmax * 2 ||
+ hexascii_to_octet(valstr, len,
+ (char *)(cliptr->varptr), &vmax) != 0) {
+ return (CLI_FAIL);
+ }
+ cliptr->varlen = vmax;
+ } else {
+ if (len > vmax) {
+ return (CLI_FAIL);
+ }
+ bcopy(valstr, cliptr->varptr, len);
+ cliptr->varlen = len;
+ }
+
+ return (CLI_SET);
+ }
+}
+
+/*
+ * Assign a key to cliptr, or output cliptr's value as a key.
+ * On assignment the value is specified in valstr in hexascii;
+ * on output its value is printed in hexascii, provided the key
+ * was entered at the interpreter (not obtained from OBP and
+ * thus hidden).
+ */
+static int
+clkey(cli_ent_t *cliptr, char *valstr, boolean_t out)
+{
+ uint_t len, vmax;
+
+ if (out) {
+ char buffer[2 * WANBOOT_MAXKEYLEN + 1];
+
+ if (!CLF_ISHIDDEN(cliptr)) {
+ len = cliptr->varlen * 2 + 1;
+ (void) octet_to_hexascii(cliptr->varptr,
+ cliptr->varlen, buffer, &len);
+ printf("%s", buffer);
+ } else {
+ printf("*HIDDEN*");
+ }
+ return (CLI_CONT);
+ } else {
+ len = strlen(valstr);
+ vmax = cliptr->varmax;
+ if (len != vmax * 2 || hexascii_to_octet(valstr, len,
+ cliptr->varptr, &vmax) != 0) {
+ return (CLI_FAIL);
+ }
+ cliptr->varlen = vmax;
+ CLF_CLRHIDDEN(cliptr);
+ return (CLI_SET);
+ }
+}
+
+/*
+ * Assign an IP address to cliptr, or output cliptr's value as an
+ * IP address. On assignment the value is specified in valstr in
+ * dotted-decimal format; on output its value is printed in dotted-
+ * decimal format.
+ */
+static int
+clip(cli_ent_t *cliptr, char *valstr, boolean_t out)
+{
+ uint_t len;
+
+ if (out) {
+ printf("%s", (char *)cliptr->varptr);
+ return (CLI_CONT);
+ }
+
+ if (inet_addr(valstr) == (in_addr_t)-1 ||
+ (len = strlen(valstr)) >= cliptr->varmax) {
+ return (CLI_FAIL);
+ }
+
+ (void) strcpy(cliptr->varptr, valstr);
+ cliptr->varlen = len + 1;
+ return (CLI_SET);
+}
+
+/*
+ * Assign an arbitrary string to cliptr, or output cliptr's value as a string.
+ */
+static int
+clstr(cli_ent_t *cliptr, char *valstr, boolean_t out)
+{
+ uint_t len;
+
+ if (out) {
+ printf("%s", (char *)cliptr->varptr);
+ return (CLI_CONT);
+ } else {
+ if ((len = strlen(valstr)) >= cliptr->varmax) {
+ return (CLI_FAIL);
+ } else {
+ (void) strcpy(cliptr->varptr, valstr);
+ cliptr->varlen = len + 1;
+ return (CLI_SET);
+ }
+ }
+}
+
+/*
+ * Assign a URL to cliptr (having verified the format), or output cliptr's
+ * value as a URL. The host must be specified in dotted-decimal, and the
+ * scheme must not be https.
+ */
+static int
+clurl(cli_ent_t *cliptr, char *valstr, boolean_t out)
+{
+ url_t u;
+ uint_t len;
+
+ if (out) {
+ printf("%s", (char *)cliptr->varptr);
+ return (CLI_CONT);
+ }
+
+ if (url_parse(valstr, &u) != URL_PARSE_SUCCESS ||
+ u.https || inet_addr(u.hport.hostname) == (in_addr_t)-1 ||
+ (len = strlen(valstr)) >= cliptr->varmax) {
+ return (CLI_FAIL);
+ }
+
+ (void) strcpy(cliptr->varptr, valstr);
+ cliptr->varlen = len + 1;
+ return (CLI_SET);
+}
+
+/*
+ * Assign a hostport to cliptr (having verified the format), or output cliptr's
+ * value as a hostport. The host must be specified in dotted-decimal.
+ */
+static int
+clhp(cli_ent_t *cliptr, char *valstr, boolean_t out)
+{
+ url_hport_t u;
+ uint_t len;
+
+ if (out) {
+ printf("%s", (char *)cliptr->varptr);
+ return (CLI_CONT);
+ }
+
+ if (url_parse_hostport(valstr, &u, URL_DFLT_PROXY_PORT) !=
+ URL_PARSE_SUCCESS ||
+ inet_addr(u.hostname) == (in_addr_t)-1 ||
+ (len = strlen(valstr)) >= cliptr->varmax) {
+ return (CLI_FAIL);
+ }
+
+ (void) strcpy(cliptr->varptr, valstr);
+ cliptr->varlen = len + 1;
+ return (CLI_SET);
+}
+
+/*
+ * Exit the interpreter and return to the booter.
+ */
+/*ARGSUSED*/
+static int
+clgo(cli_ent_t *cliptr, char *valstr, boolean_t out)
+{
+ return (CLI_EXIT);
+}
+
+/*
+ * Exit the interpreter and return to OBP.
+ */
+/*ARGSUSED*/
+static int
+clexit(cli_ent_t *cliptr, char *valstr, boolean_t out)
+{
+ prom_exit_to_mon();
+ /*NOTREACHED*/
+ return (CLI_EXIT);
+}
+
+/*
+ * Provide simple help information.
+ */
+/*ARGSUSED*/
+static int
+clhelp(cli_ent_t *cliptr, char *valstr, boolean_t out)
+{
+ printf("var=val - set variable\n");
+ printf("var= - unset variable\n");
+ printf("var - print variable\n");
+ printf("list - list variables and their values\n");
+ printf("prompt - prompt for unset variables\n");
+ printf("go - continue booting\n");
+ printf("exit - quit boot interpreter and return to OBP\n");
+
+ return (CLI_CONT);
+}
+
+/*
+ * List variables and their current values.
+ */
+/*ARGSUSED*/
+static int
+cllist(cli_ent_t *cliptr, char *valstr, boolean_t out)
+{
+ int wanted = (int)valstr;
+ int i;
+
+ wanted &= ~(CLF_CMD | CLF_ARG);
+
+ for (cliptr = cli_list; cliptr < &cli_list[num_cli_ent]; cliptr++) {
+ if ((cliptr->flags & (CLF_CMD | CLF_ARG)) != 0 ||
+ (cliptr->flags & wanted) == 0) {
+ continue;
+ }
+ printf("%s: ", cliptr->varname);
+ /*
+ * Line the values up - space to the width of the widest
+ * varname + 1 for the ':'.
+ */
+ for (i = VAR_MAXWIDTH + 1 - strlen(cliptr->varname);
+ i > 0; --i) {
+ printf(" ");
+ }
+
+ if (CLF_ISSET(cliptr) || CLF_ISHIDDEN(cliptr)) {
+ (void) cliptr->action(cliptr, NULL, B_TRUE);
+ printf("\n");
+ } else {
+ printf("UNSET\n");
+ }
+ }
+
+ return (CLI_CONT);
+}
+
+/*
+ * Prompt for wanted values.
+ */
+/*ARGSUSED*/
+static int
+clprompt(cli_ent_t *cliptr, char *valstr, boolean_t out)
+{
+ char *p;
+ int wanted = (int)valstr;
+
+ /*
+ * If processing boot arguments, simply note the fact that clprompt()
+ * should be invoked later when other parameters may be supplied.
+ */
+ if ((wanted & CLF_ARG) != 0) {
+ args_specified_prompt = B_TRUE;
+ return (CLI_CONT);
+ }
+ wanted &= ~(CLF_CMD | CLF_ARG);
+
+ for (cliptr = cli_list; cliptr < &cli_list[num_cli_ent]; ++cliptr) {
+ if ((cliptr->flags & wanted) == 0) {
+ continue;
+ }
+
+ printf("%s", cliptr->varname);
+ if (CLF_ISSET(cliptr)) {
+ printf(" [");
+ (void) cliptr->action(cliptr, NULL, B_TRUE);
+ printf("]");
+ }
+ printf("? ");
+ (void) editline(cmdbuf, sizeof (cmdbuf));
+ printf("\n");
+
+ p = cmdbuf;
+ skipspace(p);
+ if (*p == '\0') { /* nothing there */
+ continue;
+ }
+
+ /* Get valstr and nul terminate */
+ valstr = p;
+ ++p;
+ skiptext(p);
+ *p = '\0';
+
+ /* If empty value, do nothing */
+ if (strlen(valstr) == 0) {
+ continue;
+ }
+
+ switch (cliptr->action(cliptr, valstr, B_FALSE)) {
+ case CLI_SET:
+ CLF_MODVAL(cliptr);
+ break;
+ case CLI_FAIL:
+ printf("Incorrect format, parameter unchanged!\n");
+ break;
+ case CLI_EXIT:
+ return (CLI_EXIT);
+ case CLI_CONT:
+ break;
+ }
+ }
+
+ return (CLI_CONT);
+}
+
+/*
+ * If the PROM has done DHCP, bind the interface; otherwise do the full
+ * DHCP packet exchange.
+ */
+/*ARGSUSED*/
+static int
+cldhcp(cli_ent_t *cliptr, char *valstr, boolean_t out)
+{
+ static boolean_t first_time = B_TRUE;
+ static int ret = CLI_CONT;
+
+ if (first_time) {
+ /*
+ * Set DHCP's idea of the client_id from our cached value.
+ */
+ cliptr = find_cli_ent(BI_CLIENT_ID);
+ if (CLF_ISMOD(cliptr)) {
+ dhcp_set_client_id(cliptr->varptr, cliptr->varlen);
+ }
+
+ bootlog("wanboot", BOOTLOG_INFO, "Starting DHCP configuration");
+
+ (void) ipv4_setpromiscuous(B_TRUE);
+ if (dhcp() == 0) {
+ bootlog("wanboot", BOOTLOG_INFO,
+ "DHCP configuration succeeded");
+ } else {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "DHCP configuration failed");
+ ret = CLI_FAIL;
+ }
+ (void) ipv4_setpromiscuous(B_FALSE);
+
+ first_time = B_FALSE;
+ }
+
+ return (ret);
+}
+
+/*
+ * Invoke the socket test interpreter (for testing purposes only).
+ */
+/*ARGSUSED*/
+static int
+cltest(cli_ent_t *cliptr, char *valstr, boolean_t out)
+{
+ (void) ipv4_setpromiscuous(B_FALSE);
+ printf("\n");
+ for (;;) {
+ printf(TEST_PROMPT);
+ if (editline(cmdbuf, sizeof (cmdbuf)) > 0) {
+ printf("\n");
+ (void) st_interpret(cmdbuf);
+ } else {
+ prom_exit_to_mon();
+ /* NOTREACHED */
+ }
+ }
+
+ /* NOTREACHED */
+ return (CLI_CONT);
+}
+
+/*
+ * Return the cliptr corresponding to the named variable.
+ */
+static cli_ent_t *
+find_cli_ent(char *varstr)
+{
+ cli_ent_t *cliptr;
+
+ for (cliptr = cli_list; cliptr < &cli_list[num_cli_ent]; ++cliptr) {
+ if (strcmp(varstr, cliptr->varname) == 0) {
+ return (cliptr);
+ }
+ }
+
+ return (NULL);
+}
+
+/*
+ * Evaluate the commands provided by the user (either as "-o" boot arguments
+ * or interactively at the boot interpreter).
+ */
+static int
+cli_eval_buf(char *inbuf, int wanted)
+{
+ char *p, *varstr, *end_varstr, *valstr, *end_valstr;
+ boolean_t assign;
+ cli_ent_t *cliptr;
+
+ for (p = inbuf; *p != '\0'; ) {
+ skipspace(p);
+
+ /* If nothing more on line, go get the next one */
+ if (*p == '\0') {
+ break;
+ } else if (*p == ',') { /* orphan ',' ? */
+ ++p;
+ continue;
+ }
+
+ /* Get ptrs to start & end of variable */
+ varstr = p;
+ ++p;
+ skiptext(p);
+ end_varstr = p;
+ skipspace(p);
+
+ /* See if we're doing an assignment */
+ valstr = NULL;
+ if (*p != '=') { /* nope, just printing */
+ assign = B_FALSE;
+ } else {
+ assign = B_TRUE;
+ ++p; /* past '=' */
+ skipspace(p);
+
+ /* Assigning something? (else clear variable) */
+ if (*p != '\0' && *p != ',') {
+ /* Get ptrs to start & end of valstr */
+ valstr = p;
+ ++p;
+ skiptext(p);
+ end_valstr = p;
+ skipspace(p);
+ }
+ }
+
+ /* Skip ',' delimiter if present */
+ if (*p == ',') {
+ ++p;
+ }
+
+ /* Nul-terminate varstr and valstr (if appropriate) */
+ *end_varstr = '\0';
+ if (valstr != NULL) {
+ *end_valstr = '\0';
+ }
+
+ if ((cliptr = find_cli_ent(varstr)) == NULL) {
+ printf("Unknown variable '%s'; ignored\n", varstr);
+ continue;
+ }
+
+ /*
+ * It's an error to specify a parameter which can only be a
+ * boot argument (and not a command) when not processing the
+ * boot arguments.
+ */
+ if ((cliptr->flags & (CLF_CMD | CLF_ARG)) == CLF_ARG &&
+ (wanted & CLF_ARG) == 0) {
+ printf("'%s' may only be specified as a "
+ "boot argument; ignored\n", varstr);
+ continue;
+ }
+
+ /*
+ * When doing an assignment, verify that it's not a command
+ * or argument name, and that it is permissible in the current
+ * context. An 'empty' assignment (var=) is treated the same
+ * as a null assignment (var="").
+ *
+ * If processing the boot arguments, it is an error to not
+ * assign a value to a non-argument parameter.
+ */
+ if (assign) {
+ if ((cliptr->flags & (CLF_CMD | CLF_ARG)) != 0) {
+ printf("'%s' is a command and cannot "
+ "be assigned\n", varstr);
+ return (CLI_FAIL);
+ }
+ if ((cliptr->flags & wanted) == 0) {
+ printf("'%s' cannot be assigned\n", varstr);
+ return (CLI_FAIL);
+ }
+
+ if (valstr == NULL) {
+ cliptr->varlen = 0;
+ CLF_MODVAL(cliptr);
+ continue;
+ }
+ } else if ((wanted & CLF_ARG) != 0 &&
+ (cliptr->flags & (CLF_CMD | CLF_ARG)) == 0) {
+ printf("'%s' must be assigned when specified in "
+ " the boot arguments\n", varstr);
+ return (CLI_FAIL);
+ }
+
+ /*
+ * Pass 'wanted' to command-handling functions, in particular
+ * clprompt() and cllist().
+ */
+ if ((cliptr->flags & CLF_CMD) != 0) {
+ valstr = (char *)wanted;
+ }
+
+ /*
+ * Call the parameter's action function.
+ */
+ switch (cliptr->action(cliptr, valstr, !assign)) {
+ case CLI_SET:
+ CLF_MODVAL(cliptr);
+ break;
+ case CLI_FAIL:
+ printf("Incorrect format: variable '%s' not set\n",
+ cliptr->varname);
+ break;
+ case CLI_EXIT:
+ return (CLI_EXIT);
+ case CLI_CONT:
+ if (!assign) {
+ printf("\n");
+ }
+ break;
+ }
+ }
+
+ return (CLI_CONT);
+}
+
+static void
+cli_interpret(int wanted)
+{
+ printf("\n");
+ do {
+ printf(PROMPT);
+ (void) editline(cmdbuf, sizeof (cmdbuf));
+ printf("\n");
+
+ } while (cli_eval_buf(cmdbuf, wanted) != CLI_EXIT);
+}
+
+#if defined(__sparcv9)
+/*
+ * This routine queries the PROM to see what encryption keys exist.
+ */
+static void
+get_prom_encr_keys()
+{
+ cli_ent_t *cliptr;
+ char encr_key[WANBOOT_MAXKEYLEN];
+ int keylen;
+ int status;
+ int ret;
+
+ /*
+ * At the top of the priority list, we have AES.
+ */
+ ret = prom_get_security_key(WANBOOT_AES_128_KEY_NAME, encr_key,
+ WANBOOT_MAXKEYLEN, &keylen, &status);
+ if ((ret == 0) && (status == 0) && (keylen == AES_128_KEY_SIZE)) {
+ cliptr = find_cli_ent(BI_AES_KEY);
+ bcopy(encr_key, cliptr->varptr, AES_128_KEY_SIZE);
+ cliptr->varlen = AES_128_KEY_SIZE;
+ CLF_MODVAL(cliptr);
+ }
+
+ /*
+ * Next, 3DES.
+ */
+ ret = prom_get_security_key(WANBOOT_DES3_KEY_NAME, encr_key,
+ WANBOOT_MAXKEYLEN, &keylen, &status);
+ if ((ret == 0) && (status == 0) && (keylen == DES3_KEY_SIZE)) {
+ cliptr = find_cli_ent(BI_3DES_KEY);
+ bcopy(encr_key, cliptr->varptr, DES3_KEY_SIZE);
+ cliptr->varlen = DES3_KEY_SIZE;
+ CLF_MODVAL(cliptr);
+ }
+}
+
+/*
+ * This routine queries the PROM to see what hashing keys exist.
+ */
+static void
+get_prom_hash_keys()
+{
+ cli_ent_t *cliptr;
+ char hash_key[WANBOOT_HMAC_KEY_SIZE];
+ int keylen;
+ int status;
+ int ret;
+
+ /*
+ * The only supported key thus far is SHA1.
+ */
+ ret = prom_get_security_key(WANBOOT_HMAC_SHA1_KEY_NAME, hash_key,
+ WANBOOT_HMAC_KEY_SIZE, &keylen, &status);
+ if ((ret == 0) && (status == 0) && (keylen == WANBOOT_HMAC_KEY_SIZE)) {
+ cliptr = find_cli_ent(BI_SHA1_KEY);
+ bcopy(hash_key, cliptr->varptr, WANBOOT_HMAC_KEY_SIZE);
+ cliptr->varlen = WANBOOT_HMAC_KEY_SIZE;
+ CLF_MODVAL(cliptr);
+ }
+}
+#endif /* defined(__sparcv9) */
+
+/*
+ * For the given parameter type(s), get values from bootinfo and cache in
+ * the local variables used by the "boot>" interpreter.
+ */
+static void
+bootinfo_defaults(int which)
+{
+ cli_ent_t *cliptr;
+
+ for (cliptr = cli_list; cliptr < &cli_list[num_cli_ent]; ++cliptr) {
+ if ((cliptr->flags & which) != 0 && !CLF_ISSET(cliptr)) {
+ size_t len = cliptr->varmax;
+
+ if (bootinfo_get(cliptr->varname, cliptr->varptr,
+ &len, NULL) == BI_E_SUCCESS) {
+ cliptr->varlen = len;
+ CLF_SETVAL(cliptr);
+ }
+ }
+ }
+}
+
+/*
+ * For the given parameter type(s), store values entered at the "boot>"
+ * interpreter back into bootinfo.
+ */
+static void
+update_bootinfo(int which)
+{
+ cli_ent_t *cliptr;
+
+ for (cliptr = cli_list; cliptr < &cli_list[num_cli_ent]; ++cliptr) {
+ if ((cliptr->flags & which) != 0 && CLF_ISMOD(cliptr)) {
+ (void) bootinfo_put(cliptr->varname,
+ cliptr->varptr, cliptr->varlen, 0);
+ }
+ }
+}
+
+/*
+ * Return the net-config-strategy: "dhcp", "manual" or "rarp"
+ */
+static char *
+net_config_strategy(void)
+{
+ static char ncs[8]; /* "dhcp" or "manual" */
+ size_t len = sizeof (ncs);
+
+ if (ncs[0] == '\0' &&
+ bootinfo_get(BI_NET_CONFIG_STRATEGY, ncs, &len, NULL) !=
+ BI_E_SUCCESS) {
+ /*
+ * Support for old PROMs: create the net-config-strategy
+ * property under /chosen with an appropriate value. If we
+ * have a bootp-response (not interested in its value, just
+ * its presence) then we did DHCP; otherwise configuration
+ * is manual.
+ */
+ if (bootinfo_get(BI_BOOTP_RESPONSE, NULL, NULL,
+ NULL) == BI_E_BUF2SMALL) {
+ (void) strcpy(ncs, "dhcp");
+ } else {
+ (void) strcpy(ncs, "manual");
+ }
+ (void) bootinfo_put(BI_NET_CONFIG_STRATEGY, ncs, strlen(ncs),
+ BI_R_CHOSEN);
+
+ bootlog("wanboot", BOOTLOG_INFO,
+ "Default net-config-strategy: %s", ncs);
+ }
+
+ return (ncs);
+}
+
+/*
+ * If there is no client-id property published in /chosen (by the PROM or the
+ * boot interpreter) provide a default client-id based on the MAC address of
+ * the client.
+ * As specified in RFC2132 (section 9.14), this is prefixed with a byte
+ * which specifies the ARP hardware type defined in RFC1700 (for Ethernet,
+ * this should be 1).
+ */
+static void
+generate_default_clientid(void)
+{
+ char clid[WB_MAX_CID_LEN];
+ size_t len = sizeof (clid);
+
+ if (bootinfo_get(BI_CLIENT_ID, clid, &len, NULL) != BI_E_SUCCESS) {
+ len = mac_get_addr_len() + 1; /* include hwtype */
+
+ if (len > sizeof (clid)) {
+ return;
+ }
+
+ clid[0] = mac_arp_type(mac_get_type());
+ bcopy(mac_get_addr_buf(), &clid[1], len - 1);
+
+ (void) bootinfo_put(BI_CLIENT_ID, clid, len, 0);
+ }
+}
+
+/*
+ * Determine the URL of the boot server from the 'file' parameter to OBP,
+ * the SbootURI or BootFile DHCP options, or the 'bootserver' value entered
+ * either as a "-o" argument or at the interpreter.
+ */
+static void
+determine_bootserver_url(void)
+{
+ char bs[URL_MAX_STRLEN + 1];
+ size_t len;
+ url_t url;
+
+ if (bootinfo_get(BI_BOOTSERVER, bs, &len, NULL) != BI_E_SUCCESS) {
+ /*
+ * If OBP has published a network-boot-file property in
+ * /chosen (or there is a DHCP BootFile or SbootURI vendor
+ * option) and it's a URL, construct the bootserver URL
+ * from it.
+ */
+ len = URL_MAX_STRLEN;
+ if (bootinfo_get(BI_NETWORK_BOOT_FILE, bs, &len, NULL) !=
+ BI_E_SUCCESS) {
+ len = URL_MAX_STRLEN;
+ if (bootinfo_get(BI_BOOTFILE, bs, &len, NULL) !=
+ BI_E_SUCCESS) {
+ return;
+ }
+ }
+ if (url_parse(bs, &url) == URL_PARSE_SUCCESS) {
+ (void) bootinfo_put(BI_BOOTSERVER, bs, len, 0);
+ }
+ }
+}
+
+/*
+ * Provide a classful subnet mask based on the client's IP address.
+ */
+static in_addr_t
+generate_classful_subnet(in_addr_t client_ipaddr)
+{
+ struct in_addr subnetmask;
+ char *netstr;
+
+ if (IN_CLASSA(client_ipaddr)) {
+ subnetmask.s_addr = IN_CLASSA_NET;
+ } else if (IN_CLASSB(client_ipaddr)) {
+ subnetmask.s_addr = IN_CLASSB_NET;
+ } else {
+ subnetmask.s_addr = IN_CLASSC_NET;
+ }
+
+ netstr = inet_ntoa(subnetmask);
+ (void) bootinfo_put(BI_SUBNET_MASK, netstr, strlen(netstr) + 1, 0);
+
+ return (subnetmask.s_addr);
+}
+
+/*
+ * Informational output to the user (if interactive) or the bootlogger.
+ */
+static void
+info(const char *msg, boolean_t interactive)
+{
+ if (interactive) {
+ printf("%s\n", msg);
+ } else {
+ bootlog("wanboot", BOOTLOG_INFO, "%s", msg);
+ }
+}
+
+/*
+ * Determine whether we have sufficient information to proceed with booting,
+ * either for configuring the interface and downloading the bootconf file,
+ * or for downloading the miniroot.
+ */
+static int
+config_incomplete(int why, boolean_t interactive)
+{
+ boolean_t error = B_FALSE;
+ char buf[URL_MAX_STRLEN + 1];
+ size_t len;
+ char *urlstr;
+ url_t u;
+ struct hostent *hp;
+ in_addr_t client_ipaddr, ipaddr, bsnet, pxnet;
+ static in_addr_t subnetmask, clnet;
+ static boolean_t have_router = B_FALSE;
+ static boolean_t have_proxy = B_FALSE;
+ boolean_t have_root_server = B_FALSE;
+ boolean_t have_boot_logger = B_FALSE;
+ in_addr_t rsnet, blnet;
+
+ /*
+ * Note that 'have_router', 'have_proxy', 'subnetmask', and 'clnet'
+ * are static, so that their values (gathered when checking the
+ * interface configuration) may be used again when checking the boot
+ * configuration.
+ */
+ if (why == CLF_IF) {
+ /*
+ * A valid host IP address is an absolute requirement.
+ */
+ len = sizeof (buf);
+ if (bootinfo_get(BI_HOST_IP, buf, &len, NULL) == BI_E_SUCCESS) {
+ if ((client_ipaddr = inet_addr(buf)) == (in_addr_t)-1) {
+ info("host-ip invalid!", interactive);
+ error = B_TRUE;
+ }
+ } else {
+ info("host-ip not set!", interactive);
+ error = B_TRUE;
+ }
+
+ /*
+ * If a subnet mask was provided, use it; otherwise infer it.
+ */
+ len = sizeof (buf);
+ if (bootinfo_get(BI_SUBNET_MASK, buf, &len, NULL) ==
+ BI_E_SUCCESS) {
+ if ((subnetmask = inet_addr(buf)) == (in_addr_t)-1) {
+ info("subnet-mask invalid!", interactive);
+ error = B_TRUE;
+ }
+ } else {
+ info("Defaulting to classful subnetting", interactive);
+
+ subnetmask = generate_classful_subnet(client_ipaddr);
+ }
+ clnet = client_ipaddr & subnetmask;
+
+ /*
+ * A legal bootserver URL is also an absolute requirement.
+ */
+ len = sizeof (buf);
+ if (bootinfo_get(BI_BOOTSERVER, buf, &len, NULL) ==
+ BI_E_SUCCESS) {
+ if (url_parse(buf, &u) != URL_PARSE_SUCCESS ||
+ u.https ||
+ (ipaddr = inet_addr(u.hport.hostname)) ==
+ (in_addr_t)-1) {
+ info("bootserver not legal URL!", interactive);
+ error = B_TRUE;
+ } else {
+ bsnet = ipaddr & subnetmask;
+ }
+ } else {
+ info("bootserver not specified!", interactive);
+ error = B_TRUE;
+ }
+
+ /*
+ * Is there a correctly-defined router?
+ */
+ len = sizeof (buf);
+ if (bootinfo_get(BI_ROUTER_IP, buf, &len, NULL) ==
+ BI_E_SUCCESS) {
+ if ((ipaddr = inet_addr(buf)) == (in_addr_t)-1) {
+ info("router-ip invalid!", interactive);
+ error = B_TRUE;
+ } else if (clnet != (ipaddr & subnetmask)) {
+ info("router not on local subnet!",
+ interactive);
+ error = B_TRUE;
+ } else {
+ have_router = B_TRUE;
+ }
+ }
+
+ /*
+ * Is there a correctly-defined proxy?
+ */
+ len = sizeof (buf);
+ if (bootinfo_get(BI_HTTP_PROXY, buf, &len, NULL) ==
+ BI_E_SUCCESS) {
+ url_hport_t u;
+
+ if (url_parse_hostport(buf, &u, URL_DFLT_PROXY_PORT) !=
+ URL_PARSE_SUCCESS ||
+ (ipaddr = inet_addr(u.hostname)) == (in_addr_t)-1) {
+ info("http-proxy port invalid!", interactive);
+ error = B_TRUE;
+ } else {
+ /*
+ * The proxy is only of use to us if it's on
+ * our local subnet, or if a router has been
+ * specified (which should hopefully allow us
+ * to access the proxy).
+ */
+ pxnet = ipaddr & subnetmask;
+ have_proxy = (have_router || pxnet == clnet);
+ }
+ }
+
+ /*
+ * If there is no router and no proxy (either on the local
+ * subnet or reachable via a router), then the bootserver
+ * URL must be on the local net.
+ */
+ if (!error && !have_router && !have_proxy && bsnet != clnet) {
+ info("bootserver URL not on local subnet",
+ interactive);
+ error = B_TRUE;
+ }
+ } else {
+ /*
+ * There must be a correctly-defined root_server URL.
+ */
+ if ((urlstr = bootconf_get(&bc_handle,
+ BC_ROOT_SERVER)) == NULL) {
+ info("no root_server URL!", interactive);
+ error = B_TRUE;
+ } else if (url_parse(urlstr, &u) != URL_PARSE_SUCCESS) {
+ info("root_server not legal URL!", interactive);
+ error = B_TRUE;
+ } else if ((hp = gethostbyname(u.hport.hostname)) == NULL) {
+ info("cannot resolve root_server hostname!",
+ interactive);
+ error = B_TRUE;
+ } else {
+ rsnet = *(in_addr_t *)hp->h_addr & subnetmask;
+ have_root_server = B_TRUE;
+ }
+
+ /*
+ * Is there a correctly-defined (non-empty) boot_logger URL?
+ */
+ if ((urlstr = bootconf_get(&bc_handle,
+ BC_BOOT_LOGGER)) != NULL) {
+ if (url_parse(urlstr, &u) != URL_PARSE_SUCCESS) {
+ info("boot_logger not legal URL!", interactive);
+ error = B_TRUE;
+ } else if ((hp = gethostbyname(u.hport.hostname)) ==
+ NULL) {
+ info("cannot resolve boot_logger hostname!",
+ interactive);
+ error = B_TRUE;
+ } else {
+ blnet = *(in_addr_t *)hp->h_addr & subnetmask;
+ have_boot_logger = B_TRUE;
+ }
+ }
+
+ /*
+ * If there is no router and no proxy (either on the local
+ * subnet or reachable via a router), then the root_server
+ * URL (and the boot_logger URL if specified) must be on the
+ * local net.
+ */
+ if (!error && !have_router && !have_proxy) {
+ if (have_root_server && rsnet != clnet) {
+ info("root_server URL not on local subnet",
+ interactive);
+ error = B_TRUE;
+ }
+ if (have_boot_logger && blnet != clnet) {
+ info("boot_logger URL not on local subnet",
+ interactive);
+ error = B_TRUE;
+ }
+ }
+ }
+
+ return (error);
+}
+
+/*
+ * Actually setup our network interface with the values derived from the
+ * PROM, DHCP or interactively from the user.
+ */
+static void
+setup_interface()
+{
+ char str[MAXHOSTNAMELEN]; /* will accomodate an IP too */
+ size_t len;
+ struct in_addr in_addr;
+
+ len = sizeof (str);
+ if (bootinfo_get(BI_HOST_IP, str, &len, NULL) == BI_E_SUCCESS &&
+ (in_addr.s_addr = inet_addr(str)) != (in_addr_t)-1) {
+ in_addr.s_addr = htonl(in_addr.s_addr);
+ ipv4_setipaddr(&in_addr);
+ }
+
+ len = sizeof (str);
+ if (bootinfo_get(BI_SUBNET_MASK, str, &len, NULL) == BI_E_SUCCESS &&
+ (in_addr.s_addr = inet_addr(str)) != (in_addr_t)-1) {
+ in_addr.s_addr = htonl(in_addr.s_addr);
+ ipv4_setnetmask(&in_addr);
+ }
+
+ len = sizeof (str);
+ if (bootinfo_get(BI_ROUTER_IP, str, &len, NULL) == BI_E_SUCCESS &&
+ (in_addr.s_addr = inet_addr(str)) != (in_addr_t)-1) {
+ in_addr.s_addr = htonl(in_addr.s_addr);
+ ipv4_setdefaultrouter(&in_addr);
+ (void) ipv4_route(IPV4_ADD_ROUTE, RT_DEFAULT, NULL, &in_addr);
+ }
+
+ len = sizeof (str);
+ if (bootinfo_get(BI_HOSTNAME, str, &len, NULL) == BI_E_SUCCESS) {
+ (void) sethostname(str, len);
+ }
+}
+
+/* EXPORT DELETE END */
+boolean_t
+wanboot_init_interface(char *boot_arguments)
+{
+/* EXPORT DELETE START */
+ boolean_t interactive;
+ int which;
+
+#if defined(__sparcv9)
+ /*
+ * Get the keys from PROM before we allow the user
+ * to override them from the CLI.
+ */
+ get_prom_encr_keys();
+ get_prom_hash_keys();
+#endif /* defined(__sparcv9) */
+
+ /*
+ * If there is already a bootp-response property under
+ * /chosen then the PROM must have done DHCP for us;
+ * invoke dhcp() to 'bind' the interface.
+ */
+ if (bootinfo_get(BI_BOOTP_RESPONSE, NULL, NULL, NULL) ==
+ BI_E_BUF2SMALL) {
+ (void) cldhcp(NULL, NULL, 0);
+ }
+
+ /*
+ * Obtain default interface values from bootinfo.
+ */
+ bootinfo_defaults(CLF_IF);
+
+ /*
+ * Process the boot arguments (following the "-o" option).
+ */
+ if (boot_arguments != NULL) {
+ (void) cli_eval_buf(boot_arguments,
+ (CLF_ARG | CLF_IF | CLF_BM));
+ }
+
+ /*
+ * Stash away any interface/bootmisc parameter values we got
+ * from either the PROM or the boot arguments.
+ */
+ update_bootinfo(CLF_IF | CLF_BM);
+
+ /*
+ * If we don't already have a value for bootserver, try to
+ * deduce one. Refresh wbcli's idea of these values.
+ */
+ determine_bootserver_url();
+ bootinfo_defaults(CLF_BM);
+
+ /*
+ * Check that the information we have collected thus far is sufficient.
+ */
+ interactive = args_specified_prompt;
+
+ if (interactive) {
+ /*
+ * Drop into the boot interpreter to allow the input
+ * of keys, bootserver and bootmisc, and in the case
+ * that net-config-strategy == "manual" the interface
+ * parameters.
+ */
+ which = CLF_BM | CLF_CMD;
+ if (strcmp(net_config_strategy(), "manual") == 0)
+ which |= CLF_IF;
+
+ do {
+ cli_interpret(which);
+ update_bootinfo(CLF_IF | CLF_BM);
+ } while (config_incomplete(CLF_IF, interactive));
+ } else {
+ /*
+ * The user is not to be given the opportunity to
+ * enter further values; fail.
+ */
+ if (config_incomplete(CLF_IF, interactive)) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "interface incorrectly configured");
+ return (B_FALSE);
+ }
+ }
+
+ /*
+ * If a wanboot-enabled PROM hasn't processed client-id in
+ * network-boot-arguments, or no value for client-id has been
+ * specified to the boot interpreter, then provide a default
+ * client-id based on our MAC address.
+ */
+ generate_default_clientid();
+
+ /*
+ * If net-config-strategy == "manual" then we must setup
+ * the interface now; if "dhcp" then it will already have
+ * been setup.
+ */
+ if (strcmp(net_config_strategy(), "manual") == 0)
+ setup_interface();
+/* EXPORT DELETE END */
+ return (B_TRUE);
+}
+
+boolean_t
+wanboot_verify_config(void)
+{
+/* EXPORT DELETE START */
+ /*
+ * Check that the wanboot.conf file defines a valid root_server
+ * URL, and check that, if given, the boot_logger URL is valid.
+ */
+ if (config_incomplete(0, B_FALSE)) {
+ bootlog("wanboot", BOOTLOG_CRIT,
+ "incomplete boot configuration");
+ return (B_FALSE);
+ }
+/* EXPORT DELETE END */
+ return (B_TRUE);
+}
diff --git a/usr/src/psm/stand/boot/sparc/common/wbcli.h b/usr/src/psm/stand/boot/sparc/common/wbcli.h
new file mode 100644
index 0000000000..ddec3db215
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/wbcli.h
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ *
+ * 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 2002-2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* wanboot booter specific definitions */
+
+#ifndef _WBCLI_H
+#define _WBCLI_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <sys/wanboot_impl.h>
+#include <dhcp_impl.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define WB_MAX_CID_LEN DHCP_MAX_CID_LEN
+
+extern boolean_t wanboot_init_interface(char *);
+extern boolean_t wanboot_verify_config(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _WBCLI_H */
diff --git a/usr/src/psm/stand/boot/sparc/common/wbfsconf.c b/usr/src/psm/stand/boot/sparc/common/wbfsconf.c
new file mode 100644
index 0000000000..fe558b5bc2
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparc/common/wbfsconf.c
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/param.h>
+#include <sys/boothsfs.h>
+#include <sys/bootufs.h>
+#include <sys/bootvfs.h>
+
+struct boot_fs_ops *boot_fsw[] = {
+ &boot_ufs_ops,
+ &boot_hsfs_ops
+};
+
+int boot_nfsw = sizeof (boot_fsw) / sizeof (boot_fsw[0]);
+
+char *systype;
+
+static char *ufsname = "ufs";
+static char *hsfsname = "hsfs";
+
+int
+determine_fstype_and_mountroot(char *path)
+{
+ set_default_fs(ufsname);
+ if (mountroot(path) == VFS_SUCCESS) {
+ systype = ufsname;
+ return (VFS_SUCCESS);
+ }
+
+ set_default_fs(hsfsname);
+ if (mountroot(path) == VFS_SUCCESS) {
+ systype = hsfsname;
+ return (VFS_SUCCESS);
+ }
+ clr_default_fs();
+
+ return (VFS_FAILURE);
+}
diff --git a/usr/src/psm/stand/boot/sparcv9/Makefile b/usr/src/psm/stand/boot/sparcv9/Makefile
new file mode 100644
index 0000000000..3f3cb6915b
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparcv9/Makefile
@@ -0,0 +1,62 @@
+#
+# 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.
+#
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../../../../Makefile.master
+
+# firmware libraries, platform-group, and platform-specific
+# subdirectories to visit.
+
+SUBDIRS = sun4u sun4v
+
+all := TARGET = all
+install := TARGET = install
+clean := TARGET = clean
+clobber := TARGET = clobber
+lint := TARGET = lint
+
+all install clean clobber lint: $(SUBDIRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(MFLAGS) $(TARGET)
+
+#
+# Cross-reference customization: include all boot-related source files.
+#
+UTSDIR= ../../../../uts
+STANDLIBDIR= ../../../../stand/lib
+STANDSYSDIR= ../../../../stand/sys
+PROMDIRS= ../../../promif/ieee1275
+NAMESDIRS= ../../lib/names/sparcv9 ../../lib/names/sparc/common
+XRDIRS += ../common ../sparc/common $(NAMESDIRS) $(PROMDIRS) \
+ $(STANDSYSDIR) $(STANDLIBDIR)/sparcv9 $(STANDLIBDIR)/common \
+ $(STANDLIBDIR)/fs
+
+cscope.out tags: FRC
+ $(XREF) -x $@
+
+FRC:
diff --git a/usr/src/psm/stand/boot/sparcv9/Makefile.com b/usr/src/psm/stand/boot/sparcv9/Makefile.com
new file mode 100644
index 0000000000..e9967456f0
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparcv9/Makefile.com
@@ -0,0 +1,360 @@
+#
+# 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.
+#
+# 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 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# psm/stand/boot/sparcv9/Makefile.com
+
+
+include $(TOPDIR)/psm/stand/boot/Makefile.boot
+
+TARG_MACH = sparcv9
+
+BOOTSRCDIR = ../..
+
+TOP_CMN_DIR = $(SRC)/common
+CMN_DIR = $(BOOTSRCDIR)/common
+MACH_DIR = ../../sparc/common
+PLAT_DIR = .
+
+BOOT_SRC = boot.c wanboot.c
+
+CONF_SRC = ufsconf.c nfsconf.c hsfsconf.c wbfsconf.c wbcli.c
+
+TOP_CMN_C_SRC = getoptstr.c
+
+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 += get.c
+
+BOOT_OBJS = $(BOOT_SRC:%.c=%.o)
+BOOT_L_OBJS = $(BOOT_OBJS:%.o=%.ln)
+
+CONF_OBJS = $(CONF_SRC:%.c=%.o)
+CONF_L_OBJS = $(CONF_OBJS:%.o=%.ln)
+
+MISC_OBJS = $(MISC_SRC:%.c=%.o)
+MISC_L_OBJS = $(MISC_OBJS:%.o=%.ln)
+
+SRT0_OBJ = $(SRT0_S:%.s=%.o)
+SRT0_L_OBJ = $(SRT0_OBJ:%.o=%.ln)
+
+C_SRC = $(TOP_CMN_C_SRC) $(CMN_C_SRC) $(MACH_C_SRC) $(ARCH_C_SRC)
+C_SRC += $(PLAT_C_SRC)
+S_SRC = $(MACH_S_SRC) $(ARCH_S_SRC) $(PLAT_S_SRC)
+
+OBJS = $(C_SRC:%.c=%.o) $(S_SRC:%.s=%.o)
+L_OBJS = $(OBJS:%.o=%.ln)
+
+CPPDEFS = $(ARCHOPTS) -D$(PLATFORM) -D_BOOT -D_KERNEL -D_MACHDEP
+CPPDEFS += -D_ELF64_SUPPORT
+CPPINCS += -I$(TOP_CMN_DIR)
+CPPINCS += -I$(SRC)/uts/common
+CPPINCS += -I$(SRC)/uts/sun
+CPPINCS += -I$(SRC)/uts/sun4
+CPPINCS += -I$(SRC)/uts/$(PLATFORM)
+CPPINCS += -I$(SRC)/uts/sparc/$(ARCHVERS)
+CPPINCS += -I$(SRC)/uts/sparc
+CPPINCS += -I$(SRC)/uts/$(ARCHMMU)
+CPPINCS += -I$(SRC)/common/net/wanboot
+CPPINCS += -I$(SRC)/common/net/wanboot/crypt
+CPPINCS += -I$(ROOT)/usr/platform/$(PLATFORM)/include
+CPPINCS += -I$(ROOT)/usr/include/$(ARCHVERS)
+CPPINCS += -I$(PSMSYSHDRDIR)
+CPPINCS += -I$(STANDDIR)
+CPPINCS += -I$(STANDDIR)/lib
+CPPINCS += -I$(STANDDIR)/lib/sa
+CPPINCS += -I$(SRC)/common/net/dhcp
+CPPFLAGS = $(CPPDEFS) $(CPPINCS)
+CPPFLAGS += $(CCYFLAG)$(STANDDIR)
+ASFLAGS += $(CPPDEFS) -P -D_ASM $(CPPINCS)
+CFLAGS64 += ../../sparc/common/sparc.il
+
+#
+# Until we are building on a MACH=sparcv9 machine, we have to override
+# where to look for libraries.
+#
+PSMNAMELIBDIR = $(PSMSTANDDIR)/lib/names/$(TARG_MACH)
+PSMPROMLIBDIR = $(PSMSTANDDIR)/lib/promif/$(TARG_MACH)
+
+#
+# The following libraries are built in LIBNAME_DIR
+#
+LIBNAME_DIR += $(PSMNAMELIBDIR)/$(PLATFORM)
+LIBNAME_LIBS += libnames.a
+
+#
+# The following libraries are built in LIBPROM_DIR
+#
+LIBPROM_DIR += $(PSMPROMLIBDIR)/$(PROMVERS)/common
+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
+#
+STRIPALIGN = stripalign
+
+#
+# Program used to post-process the ELF executables
+#
+ELFCONV = ./$(STRIPALIGN) # Default value
+
+.KEEP_STATE:
+
+.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)
+
+all: $(ELFCONV) $(UFSBOOT) $(HSFSBOOT) $(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
+# libraries have been built and placed in $ROOT/stand/lib.
+#
+LIBDEPS= $(LIBPROM_DIR)/libprom.a $(LIBPLAT_DEP) \
+ $(LIBNAME_DIR)/libnames.a
+
+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
+#
+# EXPORT DELETE START
+LIBWANBOOT = libwanboot.a
+LIBSCRYPT = libscrypt.a
+LIBSSL = libssl.a
+LIBCRYPTO = libcrypto.a
+# EXPORT DELETE END
+
+LIBWAN_LIBS = \
+ $(LIBWANBOOT) \
+ libnvpair.a libufs.a libhsfs.a libnfs.a \
+ libxdr.a libnames.a libsock.a libinet.a libtcp.a \
+ $(LIBSCRYPT) $(LIBSSL) $(LIBCRYPTO) \
+ libmd5.a libsa.a libprom.a \
+ $(LIBSSL) \
+ $(LIBPLAT_LIBS)
+WAN_LIBS = $(LIBWAN_LIBS:lib%.a=-l%)
+WAN_DIRS = $(LIBNAME_DIR:%=-L%) $(LIBSYS_DIR:%=-L%)
+WAN_DIRS += $(LIBPLAT_DIR:%=-L%) $(LIBPROM_DIR:%=-L%)
+
+#
+# Loader flags used to build wanboot
+#
+WAN_MAPFILE = $(MACH_DIR)/mapfile
+WAN_LDFLAGS = -dn -M $(WAN_MAPFILE) -e _start $(WAN_DIRS)
+WAN_L_LDFLAGS = $(WAN_DIRS)
+
+#
+# Object files used to build wanboot
+#
+WAN_SRT0 = $(SRT0_OBJ)
+WAN_OBJS = $(OBJS) wbfsconf.o wbcli.o wanboot.o ramdisk.o
+WAN_L_OBJS = $(WAN_SRT0:%.o=%.ln) $(WAN_OBJS:%.o=%.ln)
+
+#
+# Build rules to build wanboot
+#
+
+$(WANBOOT).elf: $(WAN_MAPFILE) $(WAN_SRT0) $(WAN_OBJS) $(LIBDEPS)
+ $(LD) $(WAN_LDFLAGS) -o $@ $(WAN_SRT0) $(WAN_OBJS) $(WAN_LIBS)
+ $(MCS) -d $@
+ $(POST_PROCESS)
+ $(POST_PROCESS)
+ $(MCS) -c $@
+
+$(WANBOOT): $(WANBOOT).elf
+ $(RM) $@; cp $@.elf $@
+ $(STRIP) $@
+
+$(WANBOOT)_lint: $(L_LIBDEPS) $(WAN_L_OBJS)
+ @echo ""
+ @echo wanboot lint: global crosschecks:
+ $(LINT.c) $(WAN_L_LDFLAGS) $(WAN_L_OBJS) $(WAN_LIBS)
+
+# 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
+
+#
+# Libraries used to build nfsboot
+#
+LIBNFS_LIBS = libnfs.a libxdr.a libnames.a \
+ libsock.a libinet.a libtcp.a libsa.a libprom.a \
+ $(LIBPLAT_LIBS)
+NFS_LIBS = $(LIBNFS_LIBS:lib%.a=-l%)
+NFS_DIRS = $(LIBNAME_DIR:%=-L%) $(LIBSYS_DIR:%=-L%)
+NFS_DIRS += $(LIBPLAT_DIR:%=-L%) $(LIBPROM_DIR:%=-L%)
+
+#
+# Loader flags used to build inetboot
+#
+NFS_MAPFILE = $(MACH_DIR)/mapfile
+NFS_LDFLAGS = -dn -M $(NFS_MAPFILE) -e _start $(NFS_DIRS)
+NFS_L_LDFLAGS = $(NFS_DIRS)
+
+#
+# Object files used to build inetboot
+#
+NFS_SRT0 = $(SRT0_OBJ)
+NFS_OBJS = $(OBJS) nfsconf.o boot.o
+NFS_L_OBJS = $(NFS_SRT0:%.o=%.ln) $(NFS_OBJS:%.o=%.ln)
+
+$(NFSBOOT).elf: $(ELFCONV) $(NFS_MAPFILE) $(NFS_SRT0) $(NFS_OBJS) $(LIBDEPS)
+ $(LD) $(NFS_LDFLAGS) -o $@ $(NFS_SRT0) $(NFS_OBJS) $(NFS_LIBS)
+ $(MCS) -d $@
+ $(POST_PROCESS)
+ $(POST_PROCESS)
+ $(MCS) -c $@
+
+#
+# This is a bit strange because some platforms boot elf and some don't.
+# So this rule strips the file no matter which ELFCONV is used.
+#
+$(NFSBOOT): $(NFSBOOT).elf
+ $(RM) $@.tmp; cp $@.elf $@.tmp; $(STRIP) $@.tmp
+ $(RM) $@; $(ELFCONV) $@.tmp $@; $(RM) $@.tmp
+
+$(NFSBOOT)_lint: $(NFS_L_OBJS) $(L_LIBDEPS)
+ @echo ""
+ @echo inetboot lint: global crosschecks:
+ $(LINT.c) $(NFS_L_LDFLAGS) $(NFS_L_OBJS) $(NFS_LIBS)
+
+include $(BOOTSRCDIR)/Makefile.rules
+
+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) $(L_OBJS) $(CONF_L_OBJS) $(MISC_L_OBJS) $(BOOT_L_OBJS) \
+ $(SRT0_L_OBJ)
+
+clobber: clean
+ $(RM) $(UFSBOOT) $(HSFSBOOT) $(NFSBOOT) $(WANBOOT) $(STRIPALIGN)
+
+lint: $(UFSBOOT)_lint $(NFSBOOT)_lint $(WANBOOT)_lint
+
+include $(BOOTSRCDIR)/Makefile.targ
diff --git a/usr/src/psm/stand/boot/sparcv9/sun4u/Makefile b/usr/src/psm/stand/boot/sparcv9/sun4u/Makefile
new file mode 100644
index 0000000000..b81cbc1c07
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparcv9/sun4u/Makefile
@@ -0,0 +1,144 @@
+#
+# 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.
+#
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+
+TOPDIR = ../../../../..
+
+include $(TOPDIR)/uts/Makefile.uts
+
+MODULE = fs
+
+PLATLINKS = SUNW,Ultra-2
+PLATLINKS += SUNW,Ultra-250
+PLATLINKS += SUNW,Ultra-4
+PLATLINKS += SUNW,Ultra-Enterprise
+PLATLINKS += SUNW,Ultra-Enterprise-10000
+PLATLINKS += SUNW,UltraSPARC-IIi-Netract
+PLATLINKS += SUNW,UltraSPARC-IIe-NetraCT-40
+PLATLINKS += SUNW,UltraSPARC-IIe-NetraCT-60
+PLATLINKS += SUNW,Sun-Blade-100
+PLATLINKS += SUNW,Sun-Blade-1000
+PLATLINKS += SUNW,Sun-Blade-1500
+PLATLINKS += SUNW,Sun-Blade-2500
+PLATLINKS += SUNW,A70
+PLATLINKS += SUNW,Sun-Fire
+PLATLINKS += SUNW,Sun-Fire-V240
+PLATLINKS += SUNW,Sun-Fire-V250
+PLATLINKS += SUNW,Sun-Fire-V440
+PLATLINKS += SUNW,Sun-Fire-280R
+PLATLINKS += SUNW,Sun-Fire-15000
+PLATLINKS += SUNW,Sun-Fire-880
+PLATLINKS += SUNW,Sun-Fire-480R
+PLATLINKS += SUNW,Sun-Fire-V890
+PLATLINKS += SUNW,Sun-Fire-V490
+PLATLINKS += SUNW,Serverblade1
+PLATLINKS += SUNW,Netra-T12
+PLATLINKS += SUNW,Netra-T4
+PLATLINKS += SUNW,Netra-CP2300
+
+LINKED_DIRS = $(PLATLINKS:%=$(USR_PLAT_DIR)/%)
+LINKED_LIB_DIRS = $(PLATLINKS:%=$(USR_PLAT_DIR)/%/lib)
+LINKED_LIB_FS_DIRS = $(PLATLINKS:%=$(USR_PLAT_DIR)/%/lib/fs)
+
+all := TARGET = all
+install := TARGET = install
+clean := TARGET = clean
+
+TARG_MACH = sparcv9
+TARG_MACH_DIR = sparcv9
+ARCHVERS = v9
+PLATFORM = sun4u
+ARCHMMU = sfmmu
+PROMVERS = ieee1275
+ASFLAGS += $(sparcv9_XARCH)
+
+PLAT_C_SRC = machdep.c
+ARCH_C_SRC = sun4u_memlist.c sun4x_standalloc.c sun4dep.c
+ARCH_S_SRC = sparcv9_subr.s
+SRT0_S = sun4u_srt0.s
+INLINES =
+
+LDFLAGS += -L$(TOPDIR)/psm/stand/lib/promif/$(TARG_MACH)/$(PROMVERS)/common
+
+#
+# The following libraries are build in LIBPLAT_DIR
+#
+LIBPLAT_DIR = $(TOPDIR)/psm/stand/lib/promif/$(TARG_MACH)/$(PROMVERS)/$(PLATFORM)
+LIBPLAT_LIBS = libplat.a
+LIBPLAT_L_LIBS= $(LIBPLAT_LIBS:lib%.a=llib-l%.ln)
+LIBPLAT_DEP = $(LIBPLAT_DIR)/$(LIBPLAT_LIBS)
+LIBPLAT_DEP_L = $(LIBPLAT_DIR)/$(LIBPLAT_L_LIBS)
+
+#
+# Platform specific libraries
+#
+PSMLIBS += $(LIBPLAT_LIBS:lib%.a=-l%)
+PSMLIB_DIRS += $(LIBPLAT_DIR)
+
+
+# MPSAS support
+MPSAS_BUILD:sh= echo \\043
+$(MPSAS_BUILD)ARCHOPTS += -DMPSAS
+
+include ../Makefile.com
+
+# re-define ELFCONV for 4u--- sun4u can boot ELF directly
+ELFCONV = /usr/bin/cp
+
+# Don't need mapfile.inet for 4u inetboot
+NFS_MAPFILE = $(MACH_DIR)/mapfile
+
+#
+# Set the choice of compiler.
+
+include $(TOPDIR)/psm/Makefile.psm.64
+
+CFLAGS64 += -xchip=ultra $(CCABS32)
+
+#
+# XXX this totally sucks since it effectively turns off -errchk=longptr64,
+# which we really should be using.
+#
+LINTFLAGS64 = $(LINTFLAGS) -Xarch=v9
+
+#
+# Cross-reference customization: include all boot-related source files.
+#
+UTSDIR= ../../../../../uts
+STANDLIBDIR= ../../../../../stand/lib
+STANDSYSDIR= ../../../../../stand/sys
+PROMDIRS= ../../../../promif
+NAMESDIRS= ../../../lib/names/sparcv9 ../../../lib/names/sparc/common
+XRDIRS += ../../sparc/common ../../common $(STANDLIBDIR) \
+ $(STANDSYSDIR) $(PROMDIRS) $(NAMESDIRS)
+XRDEL = sun4x_srt0* sun4x_memlist*
+XRPRUNE = i86pc i386
+
+cscope.out tags: FRC
+ $(XREF) -x $@
+
+FRC:
diff --git a/usr/src/psm/stand/boot/sparcv9/sun4u/machdep.c b/usr/src/psm/stand/boot/sparcv9/sun4u/machdep.c
new file mode 100644
index 0000000000..48b1bcadf8
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparcv9/sun4u/machdep.c
@@ -0,0 +1,173 @@
+/*
+ * 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.
+ *
+ * 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 2005 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/promif.h>
+#include <sys/prom_plat.h>
+#include <sys/salib.h>
+
+int vac = 1;
+
+/*
+ * Check if the CPU should default to 64-bit or not.
+ * UltraSPARC-1's default to 32-bit mode.
+ * Everything else defaults to 64-bit mode.
+ */
+
+/*
+ * Manufacturer codes for the CPUs we're interested in
+ */
+#define TI_JEDEC 0x17
+#define SUNW_JEDEC 0x22
+
+/*
+ * Implementation codes for the CPUs we're interested in
+ */
+#define IMPL_US_I 0x10
+
+static dnode_t
+visit(dnode_t node)
+{
+ int impl, manu;
+ char name[32];
+ static char ultrasparc[] = "SUNW,UltraSPARC";
+ static char implementation[] = "implementation#";
+ static char manufacturer[] = "manufacturer#";
+
+ /*
+ * if name isn't 'SUNW,UltraSPARC', continue.
+ */
+ if (prom_getproplen(node, "name") != sizeof (ultrasparc))
+ return ((dnode_t)0);
+ (void) prom_getprop(node, "name", name);
+ if (strncmp(name, ultrasparc, sizeof (ultrasparc)) != 0)
+ return ((dnode_t)0);
+
+ if (prom_getproplen(node, manufacturer) != sizeof (int))
+ return ((dnode_t)0);
+ (void) prom_getprop(node, manufacturer, (caddr_t)&manu);
+
+ if ((manu != SUNW_JEDEC) && (manu != TI_JEDEC))
+ return ((dnode_t)0);
+
+ if (prom_getproplen(node, implementation) != sizeof (int))
+ return ((dnode_t)0);
+ (void) prom_getprop(node, implementation, (caddr_t)&impl);
+
+ if (impl != IMPL_US_I)
+ return ((dnode_t)0);
+
+ return (node);
+}
+
+/*
+ * visit each node in the device tree, until we get a non-null answer
+ */
+static dnode_t
+walk(dnode_t node)
+{
+ dnode_t id;
+
+ if (visit(node))
+ return (node);
+
+ for (node = prom_childnode(node); node; node = prom_nextnode(node))
+ if ((id = walk(node)) != (dnode_t)0)
+ return (id);
+
+ return ((dnode_t)0);
+}
+
+/*
+ * Check if the CPU is an UltraSPARC-1 or not.
+ */
+int
+cpu_is_ultrasparc_1(void)
+{
+ static int cpu_checked;
+ static int cpu_default;
+
+ /*
+ * If we already checked, we already know the answer.
+ */
+ if (cpu_checked == 0) {
+ if (walk(prom_rootnode()))
+ cpu_default = 1;
+ cpu_checked = 1;
+ }
+
+ return (cpu_default);
+}
+
+/*
+ * Retain a page or reclaim a previously retained page of physical
+ * memory for use by the prom upgrade. If successful, leave
+ * an indication that a page was retained by creating a boolean
+ * property in the root node.
+ *
+ * XXX: SUNW,retain doesn't work as expected on server systems,
+ * so we don't try to retain any memory on those systems.
+ *
+ * XXX: do a '0 to my-self' as a workaround for 4160914
+ */
+
+int dont_retain_memory;
+
+void
+retain_nvram_page(void)
+{
+ unsigned long long phys = 0;
+ int len;
+ char name[32];
+ static char create_prop[] =
+ "0 to my-self dev / 0 0 \" boot-retained-page\" property";
+ static char ue10000[] = "SUNW,Ultra-Enterprise-10000";
+ static char ue[] = "SUNW,Ultra-Enterprise";
+ extern int verbosemode;
+
+ if (dont_retain_memory)
+ return;
+
+ len = prom_getproplen(prom_rootnode(), "name");
+ if ((len != -1) && (len <= sizeof (name))) {
+ (void) prom_getprop(prom_rootnode(), "name", name);
+ if ((strcmp(name, ue) == 0) || (strcmp(name, ue10000) == 0))
+ return;
+ }
+
+ if (prom_retain("OBPnvram", PAGESIZE, PAGESIZE, &phys) != 0) {
+ printf("prom_retain failed\n");
+ return;
+ }
+ if (verbosemode)
+ printf("retained OBPnvram page at 0x%llx\n", phys);
+
+ prom_interpret(create_prop, 0, 0, 0, 0, 0);
+}
diff --git a/usr/src/psm/stand/boot/sparcv9/sun4v/Makefile b/usr/src/psm/stand/boot/sparcv9/sun4v/Makefile
new file mode 100644
index 0000000000..8005ea80df
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparcv9/sun4v/Makefile
@@ -0,0 +1,121 @@
+#
+# 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.
+#
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+
+TOPDIR = ../../../../..
+
+include $(TOPDIR)/uts/Makefile.uts
+
+MODULE = fs
+
+PLATLINKS = SUNW,Sun-Fire-T200
+
+LINKED_DIRS = $(PLATLINKS:%=$(USR_PLAT_DIR)/%)
+LINKED_LIB_DIRS = $(PLATLINKS:%=$(USR_PLAT_DIR)/%/lib)
+LINKED_LIB_FS_DIRS = $(PLATLINKS:%=$(USR_PLAT_DIR)/%/lib/fs)
+
+all := TARGET = all
+install := TARGET = install
+clean := TARGET = clean
+
+TARG_MACH = sparcv9
+TARG_MACH_DIR = sparcv9
+ARCHVERS = v9
+PLATFORM = sun4v
+ARCHMMU = sfmmu
+PROMVERS = ieee1275
+ASFLAGS += $(sparcv9_XARCH)
+
+PLAT_C_SRC = machdep.c
+ARCH_C_SRC = sun4u_memlist.c sun4x_standalloc.c sun4dep.c
+ARCH_S_SRC = sparcv9_subr.s
+SRT0_S = sun4u_srt0.s
+INLINES =
+
+LDFLAGS += -L$(TOPDIR)/psm/stand/lib/promif/$(TARG_MACH)/$(PROMVERS)/common
+
+#
+# The following libraries are build in LIBPLAT_DIR
+#
+LIBPLAT_DIR = $(TOPDIR)/psm/stand/lib/promif/$(TARG_MACH)/$(PROMVERS)/$(PLATFORM)
+LIBPLAT_LIBS = libplat.a
+LIBPLAT_L_LIBS= $(LIBPLAT_LIBS:lib%.a=llib-l%.ln)
+LIBPLAT_DEP = $(LIBPLAT_DIR)/$(LIBPLAT_LIBS)
+LIBPLAT_DEP_L = $(LIBPLAT_DIR)/$(LIBPLAT_L_LIBS)
+
+#
+# Platform specific libraries
+#
+PSMLIBS += $(LIBPLAT_LIBS:lib%.a=-l%)
+PSMLIB_DIRS += $(LIBPLAT_DIR)
+
+
+# MPSAS support
+MPSAS_BUILD:sh= echo \\043
+$(MPSAS_BUILD)ARCHOPTS += -DMPSAS
+
+include ../Makefile.com
+
+CPPINCS += -I$(SRC)/uts/sun4u
+CPPINCS += -I$(ROOT)/usr/platform/sun4u/include
+
+# re-define ELFCONV for 4v--- sun4v can boot ELF directly
+ELFCONV = /usr/bin/cp
+
+# Don't need mapfile.inet for 4v inetboot
+NFS_MAPFILE = $(MACH_DIR)/mapfile
+
+#
+# Set the choice of compiler.
+
+include $(TOPDIR)/psm/Makefile.psm.64
+
+CFLAGS64 += -xchip=ultra $(CCABS32)
+
+#
+# XXX this totally sucks since it effectively turns off -errchk=longptr64,
+# which we really should be using.
+#
+LINTFLAGS64 = $(LINTFLAGS) -Xarch=v9
+
+#
+# Cross-reference customization: include all boot-related source files.
+#
+UTSDIR= ../../../../../uts
+STANDLIBDIR= ../../../../../stand/lib
+STANDSYSDIR= ../../../../../stand/sys
+PROMDIRS= ../../../../promif
+NAMESDIRS= ../../../lib/names/sparcv9 ../../../lib/names/sparc/common
+XRDIRS += ../../sparc/common ../../common $(STANDLIBDIR) \
+ $(STANDSYSDIR) $(PROMDIRS) $(NAMESDIRS)
+XRDEL = sun4x_srt0* sun4x_memlist*
+XRPRUNE = i86pc i386
+
+cscope.out tags: FRC
+ $(XREF) -x $@
+
+FRC:
diff --git a/usr/src/psm/stand/boot/sparcv9/sun4v/machdep.c b/usr/src/psm/stand/boot/sparcv9/sun4v/machdep.c
new file mode 100644
index 0000000000..cada0384e2
--- /dev/null
+++ b/usr/src/psm/stand/boot/sparcv9/sun4v/machdep.c
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ *
+ * 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 2005 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/promif.h>
+#include <sys/prom_plat.h>
+#include <sys/salib.h>
+
+int vac = 0;
+
+/*
+ * Check if the CPU is an UltraSPARC-1 or not.
+ */
+int
+cpu_is_ultrasparc_1(void)
+{
+ return (0);
+}
+
+/*
+ * Retain a page or reclaim a previously retained page of physical
+ * memory for use by the prom upgrade. If successful, leave
+ * an indication that a page was retained by creating a boolean
+ * property in the root node.
+ *
+ * XXX: SUNW,retain doesn't work as expected on server systems,
+ * so we don't try to retain any memory on those systems.
+ *
+ * XXX: do a '0 to my-self' as a workaround for 4160914
+ */
+
+int dont_retain_memory;
+
+void
+retain_nvram_page(void)
+{
+ unsigned long long phys = 0;
+ static char create_prop[] =
+ "0 to my-self dev / 0 0 \" boot-retained-page\" property";
+ extern int verbosemode;
+
+ if (dont_retain_memory)
+ return;
+
+ if (prom_retain("OBPnvram", PAGESIZE, PAGESIZE, &phys) != 0) {
+ printf("prom_retain failed\n");
+ return;
+ }
+ if (verbosemode)
+ printf("retained OBPnvram page at 0x%llx\n", phys);
+
+ prom_interpret(create_prop, 0, 0, 0, 0, 0);
+}
diff --git a/usr/src/psm/stand/bootblks/Makefile b/usr/src/psm/stand/bootblks/Makefile
new file mode 100644
index 0000000000..81530b7c2b
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/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, Version 1.0 only
+# (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 (c) 1994 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# psm/stand/bootblks/Makefile
+#
+include ../../../Makefile.master
+
+SUBDIRS = ufs hsfs
+
+all install clean clobber lint: $(SUBDIRS)
+
+all := TARGET = all
+clean := TARGET = clean
+clobber := TARGET = clobber
+lint := TARGET = lint
+install := TARGET = install
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(MFLAGS) $(TARGET)
+
+FRC:
diff --git a/usr/src/psm/stand/bootblks/Makefile.1275 b/usr/src/psm/stand/bootblks/Makefile.1275
new file mode 100644
index 0000000000..1066fef16c
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/Makefile.1275
@@ -0,0 +1,55 @@
+#
+# 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.
+#
+# 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 (c) 1994, by Sun Microsystems, Inc.
+#
+# psm/stand/bootblks/Makefile.1275
+#
+
+#
+# Sources and objects used to build the Forth-based bootblock
+# for all Sun OpenFirmware machines (IEEE Std. 1275)
+#
+# Same names for both filesystems.
+#
+FORTH_SRC = boot_1275.fth
+FORTH_FCODE = $(FORTH_SRC:%.fth=%.fcode)
+
+#
+# Targets
+#
+$(PROG): $(FORTH_FCODE)
+ @-$(RM) $@
+ cp -p $(FORTH_FCODE) $@
+
+clean:
+ -$(RM) $(FORTH_FCODE)
+
+clobber: clean
+ -$(RM) $(PROG)
+
+lint: FRC
+
+FRC:
+
diff --git a/usr/src/psm/stand/bootblks/Makefile.com b/usr/src/psm/stand/bootblks/Makefile.com
new file mode 100644
index 0000000000..9d4ddab575
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/Makefile.com
@@ -0,0 +1,94 @@
+#
+# 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.
+#
+# 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 1994-2003 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# psm/stand/bootblks/Makefile.com
+#
+TOPDIR = ../../../$(BASEDIR)
+
+#
+# Hack until stand makefiles are fixed
+#
+CLASS = 32
+
+include $(TOPDIR)/Makefile.master
+include $(TOPDIR)/Makefile.psm
+
+STANDDIR = $(TOPDIR)/stand
+PSMSTANDDIR = $(TOPDIR)/psm/stand
+
+SYSHDRDIR = $(STANDDIR)
+SYSLIBDIR = $(ROOT)/stand/lib
+
+PSMSYSHDRDIR = $(PSMSTANDDIR)
+PSMNAMELIBDIR = $(PSMSTANDDIR)/lib/names/$(MACH)
+PSMPROMLIBDIR = $(PSMSTANDDIR)/lib/promif/$(MACH)
+
+#
+# 'bootblk' is the basic target we build - in many flavours
+#
+PROG = bootblk
+
+#
+# Used to convert Forth source to isa-independent FCode.
+#
+TOKENIZE = tokenize
+
+#
+# Common install modes and owners
+#
+FILEMODE = 444
+DIRMODE = 755
+OWNER = root
+GROUP = sys
+
+#
+# Lint rules (adapted from Makefile.uts)
+#
+LHEAD = ( $(ECHO) "\n$@";
+LGREP = grep -v "pointer cast may result in improper alignment"
+LTAIL = ) 2>&1 | $(LGREP)
+LINT_DEFS += -Dlint
+
+#
+# For building lint objects
+#
+LINTFLAGS.c = -nsxum
+LINT.c = $(LINT) $(LINTFLAGS.c) $(LINT_DEFS) $(CPPFLAGS) -c
+LINT.s = $(LINT) $(LINTFLAGS.s) $(LINT_DEFS) $(CPPFLAGS) -c
+
+#
+# For building lint libraries
+#
+LINTFLAGS.lib = -nsxum
+LINT.lib = $(LINT) $(LINTFLAGS.lib) $(LINT_DEFS) $(CPPFLAGS)
+
+#
+# For complete pass 2 cross-checks
+# XXX: lint flags should exclude -u, but the standalone libs confuse lint.
+#
+LINTFLAGS.2 = -nsxum
+LINT.2 = $(LINT) $(LINTFLAGS.2) $(LINT_DEFS) $(CPPFLAGS)
diff --git a/usr/src/psm/stand/bootblks/Makefile.obp b/usr/src/psm/stand/bootblks/Makefile.obp
new file mode 100644
index 0000000000..4572164d4b
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/Makefile.obp
@@ -0,0 +1,55 @@
+#
+# 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.
+#
+# 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 (c) 1994, by Sun Microsystems, Inc.
+#
+# psm/stand/bootblks/Makefile.obp
+#
+
+#
+# Sources and objects used to build the Forth-based bootblock
+# for Sun OBP V2 and V3 machines (using the romvec client interface)
+#
+# Same names for both filesystem versions.
+#
+FORTH_SRC = boot_obp.fth
+FORTH_FCODE = $(FORTH_SRC:%.fth=%.fcode)
+
+#
+# Targets
+#
+$(PROG): $(FORTH_FCODE)
+ @-$(RM) $@
+ cp -p $(FORTH_FCODE) $@
+
+clean:
+ -$(RM) $(FORTH_FCODE)
+
+clobber: clean
+ -$(RM) $(PROG)
+
+lint: FRC
+
+FRC:
+
diff --git a/usr/src/psm/stand/bootblks/Makefile.targ b/usr/src/psm/stand/bootblks/Makefile.targ
new file mode 100644
index 0000000000..94257fc963
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/Makefile.targ
@@ -0,0 +1,39 @@
+#
+# 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.
+#
+# 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 (c) 1994, by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# psm/stand/bootblks/Makefile.targ
+#
+
+#
+# Targets common to all versions.
+#
+install: all $(USR_PSM_BOOTBLOCK) $(USR_PSM_UFS_DIR_LINKS)
+
+#
+# Install rules
+#
+include $(TOPDIR)/Makefile.psm.targ
diff --git a/usr/src/psm/stand/bootblks/hsfs/Makefile b/usr/src/psm/stand/bootblks/hsfs/Makefile
new file mode 100644
index 0000000000..cfae7b9a31
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/hsfs/Makefile
@@ -0,0 +1,51 @@
+#
+# 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.
+#
+# 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 (c) 1989-1994, by Sun Microsystems, Inc.
+#
+# psm/stand/bootblks/hsfs/Makefile
+#
+SUBDIRS = $(MACH)
+
+all := TARGET= all
+install := TARGET= install
+clean := TARGET= clean
+clobber := TARGET= clobber
+lint := TARGET= lint
+
+.KEEP_STATE:
+
+all 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
new file mode 100644
index 0000000000..72ee6d8fd1
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/hsfs/Makefile.hsfs
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+# 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 (c) 1994, by Sun Microsystems, Inc.
+#
+# psm/stand/bootblks/hsfs/Makefile.hsfs
+#
+include $(BASEDIR)/Makefile.com
+include $(BASEDIR)/hsfs/common/Makefile.com
+
+#
+# Where stuff gets installed
+#
+USR_PSM_BOOTBLOCK = $(USR_PSM_LIB_HSFS_DIR)/$(PROG)
diff --git a/usr/src/psm/stand/bootblks/hsfs/common/Makefile.com b/usr/src/psm/stand/bootblks/hsfs/common/Makefile.com
new file mode 100644
index 0000000000..26b9823359
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/hsfs/common/Makefile.com
@@ -0,0 +1,56 @@
+#
+# 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.
+#
+# 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 (c) 1994, by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# psm/stand/bootblks/hsfs/common/Makefile.com
+#
+
+THISDIR = $(BASEDIR)/hsfs/common
+
+#
+# Files that define the fs-reading capabilities of the C-based boot block
+#
+# uncomment following line if want to build big bootblk
+# FS_C_SRCS = hsfs.c
+# uncomment following line if want to build small bootblk
+FS_C_SRCS = hsfs_small.c
+
+#
+# Allow hsfs-specific files to find hsfs-specific include files
+#
+$(FS_C_SRCS:%.c=%.o) := CPPINCS += -I$(THISDIR)
+
+#
+# Pattern-matching rules for source in this directory
+#
+%.o: $(THISDIR)/%.c
+ $(COMPILE.c) -o $@ $<
+
+%.ln: $(THISDIR)/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+
+%.fcode: $(THISDIR)/%.fth
+ $(TOKENIZE) $<
diff --git a/usr/src/psm/stand/bootblks/hsfs/common/boot_obp.fth b/usr/src/psm/stand/bootblks/hsfs/common/boot_obp.fth
new file mode 100644
index 0000000000..3ab085f7ba
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/hsfs/common/boot_obp.fth
@@ -0,0 +1,598 @@
+\ ident "%Z%%M% %I% %E% SMI"
+\ purpose: Rock Ridge Boot Block
+\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+\ copyright: Use is subject to license terms.
+\ copyright:
+\ copyright: CDDL HEADER START
+\ copyright:
+\ copyright: The contents of this file are subject to the terms of the
+\ copyright: Common Development and Distribution License, Version 1.0 only
+\ copyright: (the "License"). You may not use this file except in compliance
+\ copyright: with the License.
+\ copyright:
+\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+\ copyright: or http://www.opensolaris.org/os/licensing.
+\ copyright: See the License for the specific language governing permissions
+\ copyright: and limitations under the License.
+\ copyright:
+\ copyright: When distributing Covered Code, include this CDDL HEADER in each
+\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+\ copyright: If applicable, add the following below this CDDL HEADER, with the
+\ copyright: fields enclosed by brackets "[]" replaced with your own identifying
+\ copyright: information: Portions Copyright [yyyy] [name of copyright owner]
+\ copyright:
+\ copyright: CDDL HEADER END
+\ copyright:
+
+\ High Sierra, Rock Ridge (CD-ROM) file system reader and boot block
+\ Original HSFS code from Mitch Bradley, RR extensions by Sam Cramer
+
+\ There's some code in there that would be a shame to throw out,
+\ but which currently doesn't fit in the boot block. This code is commented
+\ out, with #ifdef style comment lines. The "options" are:
+\ HSFSNAMES -- look at hsfs names if you can't find Rock Ridge names
+\ PROCESS_CE -- process continuation (CE) signatures; this is
+\ potentially useful, but it looks like the RR disks
+\ we're dealing with don't use them, and it is a bit
+\ of work to implement continuations.
+\ PATHLOOKUP -- handle pathnames, not just filenames which are in
+\ the root directory
+
+\ FIXME need some way of returning exceptions cleanly
+\ The culprit is the "abort" in read-blocks
+
+\ Fcode-version1
+decimal
+headerless
+
+\
+\ Forth utility routines
+\
+\ : $find 2dup type cr $find ;
+
+: boot-eval ( adr len -- )
+ $find if
+ execute
+ else
+ type ." ?" cr exit
+ then
+;
+
+\ " romvec" boot-eval constant romvec
+variable boot-romvec
+
+: find-romvec
+ " romvec" $find if
+ execute
+ else
+ 2drop h# ffe8.0010
+ then
+ boot-romvec !
+;
+
+find-romvec
+
+: roment ( offset -- adr ) boot-romvec @ + l@ ;
+
+" load-base" $find drop constant 'loadbase
+\ " (is" $find drop constant '(is
+\ " $=" $find drop constant '$=
+" call" $find drop constant 'call
+
+: loadbase ( -- adr ) 'loadbase execute ;
+\ : (is ( val acf -- ) '(is execute ;
+\ : $= ( str1 str2 -- [ -1 | 0 | 1 ] ) '$= execute ;
+: call ( ... addr -- ??? ) 'call execute ;
+: loadbase! ( value -- ) 'loadbase " (is" boot-eval ;
+
+
+\ defer open-disk ( -- )
+\ defer read-dev-bytes ( adr len byte# -- error? )
+\ defer close-disk ( -- )
+
+
+: devname ( -- cstr )
+ h# 88 roment @ \ bootpath
+;
+
+\ Debug V2 or later PROMs
+\ : devname " /sbus/esp/sd@3,0:b" drop ;
+
+
+\ Debug V0 PROMS
+\ : devname " sd(0,0,0)" drop ;
+
+variable devid
+: open-disk ( -- error? )
+ devname
+ " op-open"
+ boot-eval dup if
+ dup devid !
+ then
+ 0= ( invert sense of error flag )
+;
+
+: close-disk ( -- )
+ devid @ " op-close" boot-eval drop
+;
+
+: read-blks ( adr len -- error? )
+ ( len adr devid -- #bytes_read )
+ tuck swap devid @ " op-read" boot-eval <>
+;
+
+: seek ( low high -- error? )
+ ( low high devid -- ? )
+ devid @ " op-seek" boot-eval 0<
+;
+
+: read-dev-bytes ( adr len byte# -- error? )
+ 0 seek ?dup if exit then
+ ( adr len ) read-blks
+;
+
+\ : xl@ ( adr -- l ) la1+ unaligned-l@ ; \ For big-endian machines
+\ unaligned-l@ is not define in OBP...
+: xl@ ( adr -- l ) \ For big-endian machines
+ dup c@ swap ( c1 adr )
+ 1+ dup c@ swap ( c0 c1 adr+1 )
+ 1+ dup c@ swap ( c0 c1 c2 adr+2 )
+ 1+ c@ ( c0 c1 c2 c3 )
+ 8 << + 8 << + 8 << +
+;
+
+\ : xl@ ( adr -- l ) unaligned-l@ ; \ For little-endian machines
+: xw@ ( adr -- w ) dup c@ swap 1+ c@ 8 << + ;
+
+\ compare two strings for equality
+: $= ( adr1 len1 adr2 len2 -- same? )
+ rot over = if ( adr1 adr2 len2 )
+ comp 0=
+ else
+ 2drop drop false
+ then
+;
+
+0 value dir-buf \ buffer for current directory block
+0 value sua-buf \ buffer for current sua block
+0 value vol-desc \ volume descriptor
+
+2048 constant /sector
+
+16 constant vol-desc-sector# ( -- n )
+
+\ logical block size (from volume descriptor)
+: /block ( -- n ) vol-desc 128 + xw@ ;
+
+\ root directory entry (in volume descriptor)
+: root-dirent ( -- adr ) vol-desc 156 + ;
+
+: release ( -- )
+ dir-buf /block free-mem
+ sua-buf /block free-mem
+ vol-desc /sector free-mem
+ close-disk
+;
+
+: read-abort ( adr len byte# -- error? )
+\ read-dev-bytes if release ." Disk read failed" abort then
+ 0 seek ?dup if exit then
+ read-blks drop \ Ignore error code !!
+;
+
+: get-vol-desc ( -- )
+ vol-desc /sector vol-desc-sector# /sector * read-abort
+;
+
+\ **** Allocate memory for necessary data structures
+: allocate-hsfs-buffers ( -- )
+ /sector alloc-mem is vol-desc
+ get-vol-desc
+ /block alloc-mem is dir-buf
+ /block alloc-mem is sua-buf
+;
+
+\ File handles
+
+\ #ifdef HSFSNAMES
+\ \ Remove any version number ( ;nnn ) from the name.
+\ : -version ( adr len -- adr len' )
+\ 2dup
+\ bounds ?do ( adr len )
+\ \ If a ; is located, set len to the length before the ;
+\ i c@ ascii ; =
+\ if drop i over - leave then ( adr len' )
+\ loop
+\ ;
+\ #endif HSFSNAMES
+
+0 value file-desc \ points to current dir entry
+0 value sua-desc \ points to current SUA entry
+
+: select-file ( adr -- ) is file-desc ;
+: +fd ( n -- adr ) file-desc + ;
+: file-extent ( -- n ) 2 +fd xl@ ;
+: filesize ( -- n ) 10 +fd xl@ ;
+
+: hsfs-file-name ( -- adr len ) 33 +fd 32 +fd c@ ;
+: dir? ( -- flag ) 25 +fd c@ h# 02 and 0<> ;
+: dir-len ( -- len ) file-desc c@ ;
+
+\ Directories
+
+variable dir-block0 \ First block number in the directory file
+variable dir-size \ Number of bytes in the directory file
+
+variable dir-block# \ Next block number in the directory file
+variable dir-last-block# \ Last block number in the directory file
+variable diroff \ Offset into the current directory block
+variable totoff \ Total offset into the directory
+
+\ RR fields
+
+\ SUAs
+variable sua-off \ Offset into the current sua entry
+: select-sua ( adr -- ) is sua-desc ;
+: +suad ( n -- adr ) sua-desc + ;
+
+\ return address of SUA, = addr of filename + len(filename) + 0/1 byte pad
+: file-sua ( -- adr )
+ hsfs-file-name dup ( addr len len )
+ \ add in pad: 1 if len is even, 0 if odd
+ 2 mod 0= if 1 else 0 then + ( addr len' )
+ +
+;
+
+: suf-sig ( -- adr len ) sua-desc 2 ; \ signature bytes
+: suf-len ( -- len ) 2 +suad c@ ; \ suf length
+
+\ #ifdef PROCESS_CE
+\ \ location of continuation area, if parsed CE signature
+\ variable ce-lbn
+\ variable ce-offset
+\ variable ce-len
+\
+\ \ CE signature, continuation block
+\ : suf-parse-ce-lbn ( -- loc ) 4 +suad xl@ ; \ location of cont
+\ : suf-parse-ce-offset ( -- n ) 12 +suad xl@ ; \ offset of cont
+\ : suf-parse-ce-len ( -- n ) 20 +suad xl@ ; \ len of cont
+\
+\ : clear-cont-flags ( -- ) 0 ce-lbn ! 0 ce-len ! 0 ce-offset ! ;
+\
+\ \ read the continuation area specified by CE signature
+\ : read-cont ( -- ) sua-buf /block ce-lbn /sector * read-abort ;
+\ #endif /* PROCESS_CE */
+
+\ NM signature, alternate name
+: suf-parse-nm ( -- addr len )
+ 5 +suad
+ suf-len 5 -
+;
+
+\ current suf is at or past end of the sua?
+: end-sua ( -- end? )
+ \ if (sua-off >= block size) then return (true);
+ \ if (sua-desc[0] == 0 || sua-desc[1] == 0) then return (true);
+ \ return (len(sua entry) == 0)
+ sua-off @ /block >= if true exit then
+ sua-desc c@ 0= if true exit then
+ 1 +suad c@ 0= if true exit then
+ suf-len 0=
+;
+
+\ select the next system use field
+: next-suf ( -- )
+ \ sua-off += len(suf); sua-desc += len(suf);
+ suf-len dup sua-off +! +suad select-sua
+;
+
+\ return the rock ridge file name associated with the current
+\ dir-ent; returns 0 0 if can't find name.
+\ ignores continuations
+: rr-file-name ( -- adr len )
+ \ select start of sua, record sua offset
+ file-sua select-sua
+ diroff @ sua-off !
+ \ while (1) do
+ \ if (end of sua) {
+ \ break
+ \ }
+ \ if parse(sua) == 'NM' return suf-parse-nm;
+ \ next-suf;
+ \ done
+ begin
+ end-sua if 0 0 exit then
+ suf-sig
+ " NM" $= if suf-parse-nm exit then
+ next-suf
+ false
+ until
+;
+
+\ #ifdef PROCESS_CE
+\ \ Alternate verson of rr-file-name which chases continuations
+\ \
+\ \ return the rock ridge file name associated with the current
+\ \ dir-ent; returns 0 0 if can't find name.
+\ \ chases continuations
+\ : rr-file-name ( -- adr len )
+\ clear-cont-flags
+\ \ select start of sua, record sua offset
+\ file-sua select-sua
+\ diroff @ sua-off !
+\ \ while (1) do
+\ \ if (end of sua) {
+\ \ if (ce-lbn)
+\ \ read-continuation;
+\ \ clear-continuation-info;
+\ \ fiddle sua pointers;
+\ \ else
+\ \ break;
+\ \ }
+\ \ if parse(sua) == 'NM' return suf-parse-nm;
+\ \ if parse(sua) == 'CE'
+\ \ ce-lbn = suf-parse-ce-lbn();
+\ \ ce-len = suf-parse-ce-len();
+\ \ ce-offset = suf-parse-ce-offset();
+\ \ next-suf;
+\ \ done
+\ begin
+\ end-sua if
+\ ce-lbn @ if
+\ read-cont
+\ clear-cont-flags
+\ sua-buf select-sua
+\ 0 sua-off !
+\ end-sua if 0 0 exit then
+\ else
+\ 0 0 exit
+\ then
+\ then
+\ suf-sig
+\ 2dup " NM" $= if \ NM
+\ 2drop suf-parse-nm exit
+\ then
+\ 2dup " CE" $= if \ CE
+\ suf-parse-ce-lbn ce-lbn !
+\ suf-parse-ce-offset ce-offset !
+\ suf-parse-ce-len ce-len !
+\ \ XXX debug " had CE" type cr
+\ then
+\ 2drop
+\ next-suf
+\ false
+\ until
+\ ;
+\ #endif /* PROCESS_CE */
+
+
+\ file name of dir entry
+: file-name ( -- adr len )
+ rr-file-name
+\ #ifdef HSFSNAMES
+\ \ if no rr name, use hsfs name minus version
+\ dup 0= if 2drop hsfs-file-name -version then
+\ #endif /* HSFSNAMES */
+;
+
+\ Read the next directory block, updating diroff and dir-block#
+: get-dirblk ( -- )
+ dir-buf /block dir-block# @ /block * read-abort
+ 0 diroff !
+ 1 dir-block# +!
+;
+
+\ **** Select the next directory entry
+: next-file ( -- end? )
+ \ diroff += len(dir entry); totoff += len(dir entry);
+ \ if (totoff >= dir-size) then return (true)
+ \ if (diroff = block size) then get-dirblk
+ \ if (len (next dir entry) == 0 && totoff < dir-size) then get-dirblk
+ \ file-desc = dir-buf + diroff
+ \ return (len(dir entry) == 0)
+ file-desc c@ dup diroff +! totoff +!
+ totoff @ dir-size @ >= if true exit then
+ diroff @ /block = if get-dirblk then
+ dir-buf diroff @ + c@ 0=
+ dir-block# @ dir-last-block# @ <
+ and if get-dirblk then
+ dir-buf diroff @ + select-file
+ file-desc c@ 0=
+;
+
+\ **** Select the first file in the current directory
+: reset-dir ( -- )
+ dir-block0 @ dir-block# !
+ get-dirblk
+ 0 totoff !
+ dir-buf diroff @ + select-file
+ next-file drop next-file drop \ Skip the "parent" and "self" entries
+;
+
+\ **** "cd" to the current file (read directory pointed to by dirent)
+: set-dir ( -- )
+ file-extent dir-block0 !
+ filesize dir-size !
+ filesize /block / dir-block0 @ + dir-last-block# !
+ reset-dir
+;
+
+\ **** Select the root directory
+: froot ( -- ) root-dirent select-file set-dir ;
+
+: dir ( -- ) begin file-name type cr next-file until ;
+
+
+\ search directory block for file name
+: lookup ( adr len -- not-found? )
+ \ #ifndef PATHLOOKUP
+ froot
+ \ #endif /* PATHLOOKUP */
+ begin
+ 2dup file-name $= if 2drop false exit then
+ next-file
+ until
+ 2drop true
+;
+
+\ #ifdef PATHLOOKUP
+\ : /string ( adr len size -- adr+size len-size ) tuck - >r + r> ;
+\
+\ \ Splits a string around a delimiter. If the delimiter is found,
+\ \ two strings are returned under true, otherwise one string under false.
+\ : $split ( adr len char -- remaining-adr,len [ initial-adr,len ] found? )
+\ 2 pick 2 pick bounds ?do
+\ dup i c@ = if i nip -1 then
+\ loop ( adr len adr' -1 | char )
+\ -1 = if ( adr len adr' )
+\ swap >r ( adr adr' ) ( r: len )
+\ 2dup swap - swap ( adr [adr'-adr] adr' ) ( r: len )
+\ 1+ r> ( adr [adr'-adr] adr'+1 len )
+\ 2 pick - 1- ( adr [adr'-adr] adr'+1 len-[adr'-adr-1] )
+\ 2swap true ( rem-adr,len initial-adr,len true )
+\ else
+\ false
+\ then
+\ ;
+\
+\ : path-lookup ( adr len -- not-found? )
+\ dup 0= if 2drop true exit then
+\ over c@ ascii / = if 1 /string then
+\ froot
+\ begin
+\ ascii / $split ( rem-adr,len [ adr,len ] delim-found? )
+\ while
+\ lookup if ." Bad path" cr 2drop true exit then
+\ dir? 0= if ." Bad path" cr 2drop true exit then
+\ set-dir
+\ repeat ( rem-adr,len )
+\
+\ \ Now we have found the directory containing the file
+\ lookup if
+\ ." File not found among: " cr
+\ reset-dir dir
+\ true
+\ else
+\ false \ File is already selected
+\ then ( flag )
+\ ;
+\ #endif /* PATHLOOKUP */
+
+\ File reading
+: read-file ( adr -- error? )
+ filesize file-extent /block * read-dev-bytes ( error? )
+;
+
+
+\
+\ ELF support
+\
+
+0 constant elfhdr
+0 constant phdr
+
+: +w_elfhdr ( index -- value ) elfhdr swap ca+ w@ ;
+: +l_elfhdr ( index -- value ) elfhdr swap ca+ l@ ;
+: e_entry ( -- n ) 24 +l_elfhdr ;
+: e_phoff ( -- n ) 28 +l_elfhdr ;
+: e_phentsize ( -- n ) 42 +w_elfhdr ;
+: e_phnum ( -- n ) 44 +w_elfhdr ;
+
+1 constant pt_load
+: +phdr ( index -- value ) phdr swap la+ l@ ;
+: p_type ( -- n ) 0 +phdr ;
+: p_offset ( -- n ) 1 +phdr ;
+: p_vaddr ( -- n ) 2 +phdr ;
+: p_filesz ( -- n ) 4 +phdr ;
+: p_memsz ( -- n ) 5 +phdr ;
+\ : p_flags ( -- n ) 6 +phdr ;
+\ : p_align ( -- n ) 7 +phdr ;
+
+: check-elf ( filebase -- is-elf? )
+ l@ h# 7f454c46 ( \x7fELF ) =
+;
+
+: get-phdr ( filebase index -- )
+ e_phentsize * e_phoff + +
+ phdr e_phentsize move
+;
+
+: load-elf ( filebase -- entry-point )
+ dup is elfhdr
+ e_phentsize alloc-mem is phdr
+ e_phnum 0 ?do
+ dup i get-phdr
+ p_type pt_load = if
+ ( read it )
+ dup p_offset + p_vaddr p_filesz move
+ p_memsz p_filesz > if
+ ( zero the bss )
+ p_vaddr p_filesz + p_memsz p_filesz - 0 fill
+ then
+ then
+ loop drop
+ phdr e_phentsize free-mem
+ e_entry
+;
+
+\ Installation
+
+: initialize ( -- )
+ open-disk ?dup if exit then
+ allocate-hsfs-buffers
+;
+
+hex
+headers
+( external )
+
+: get-file ( load-adr name-adr name-len -- error? )
+ initialize
+ \ #ifndef PATHLOOKUP
+ lookup if ." lookup failed" cr drop release true exit then
+ \ #else /* PATHLOOKUP */
+ \ path-lookup if drop release true exit then
+ \ #endif /* PATHLOOKUP */
+ dir? if
+ ." Requested file is a directory" cr drop release true exit
+ then
+ read-file ?dup if ." File read failed." cr exit then
+ filesize " file-size" boot-eval !
+ release
+ false
+;
+
+: reloc&go ( -- )
+ loadbase
+ \ Is it ELF?
+ dup check-elf if ( base-adr )
+ load-elf ( entry-point )
+ loadbase!
+ " init-program" boot-eval
+ else ( base-adr )
+\ Let FORTH handle anything else
+ " adjust-header" boot-eval if
+ " init-program" boot-eval
+ then ( entry-point )
+ loadbase!
+ then
+ 4000 loadbase!
+ " ?go" boot-eval
+;
+
+\
+\ The boot stuff itself
+\
+: do-boot
+ 4000 loadbase!
+ \ #ifndef PATHLOOKUP
+ loadbase " hsfsboot" get-file if
+ \ #else /* PATHLOOKUP */
+ \ loadbase " /hsfsboot" get-file if
+ \ #endif /* PATHLOOKUP */
+ ." Boot load failed." cr exit
+ then
+ reloc&go
+;
+
+do-boot
diff --git a/usr/src/psm/stand/bootblks/hsfs/common/hsfs.c b/usr/src/psm/stand/bootblks/hsfs/common/hsfs.c
new file mode 100644
index 0000000000..2ff62f6c24
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/hsfs/common/hsfs.c
@@ -0,0 +1,683 @@
+/*
+ * 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.
+ *
+ * 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 1991, 2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * The routines in this file are called only after the PROM
+ * version has been determined to be sunMON.
+ *
+ * Basic file system reading code for standalone I/O system.
+ * Simulates a primitive UNIX I/O system (read(), write(), open(), etc).
+ * Does not support writes.
+ */
+
+#include <sys/param.h>
+#include <sys/saio.h>
+#include <sys/sysmacros.h>
+#include <sys/vnode.h>
+#include <sys/fs/ufs_fsdir.h>
+#include <sys/fs/ufs_fs.h>
+#include <sys/fs/ufs_inode.h>
+
+#include <sys/fs/hsfs_spec.h>
+#include <sys/fs/hsfs_isospec.h>
+#include <sys/fs/hsfs_node.h>
+#include <sys/fs/hsfs_susp.h>
+#include <sys/fs/hsfs_rrip.h>
+
+#include <iob.h>
+#include "hsfs_sig.h"
+
+#define hdbtodb(n) ((ISO_SECTOR_SIZE / DEV_BSIZE) * (n))
+
+#define NULL 0
+
+#define TRUE 1
+#define FALSE 0
+
+char *bootname = "/hsfsboot";
+
+extern int (*printf_p)();
+
+struct dirstuff {
+ int loc;
+ struct iob *io;
+};
+
+struct hs_direct {
+ struct direct hs_ufs_dir;
+ struct hs_direntry hs_dir;
+};
+
+/* These are the pools of buffers, iob's, etc. */
+struct iob iob[1];
+
+/* This is the fd for the file(s) */
+static i_fd = 1;
+
+/* May not need this... */
+static uint_t root_ino = 0;
+
+/*
+ * Non-local prototypes
+ */
+extern int devread(struct saioreq *s);
+extern int devopen(struct saioreq *s);
+extern int devclose(struct saioreq *s);
+
+/*
+ * Local prototypes
+ */
+static struct hs_direct *readdir(struct dirstuff *);
+static ino_t dlook(char *, struct iob *);
+static ino_t find(char *, struct iob *);
+static uint_t parse_dir(struct iob *, int, struct hs_direct *);
+static uint_t parse_susp(char *, uint_t *, struct hs_direct *);
+static int opendir(ino_t, struct iob *);
+static int mountroot(void);
+
+extern int prom_type; /* Determined in main() */
+/*
+ * Exported functions
+ */
+extern int open(char *str, int flags);
+extern int close(int fd);
+extern int read(int fdesc, char *buf, int count);
+extern int lseek(int fdesc, off_t addr);
+
+static int
+opendir(ino_t inode, struct iob *io)
+{
+ struct hs_direct hsdep;
+ uint_t i;
+ int retval;
+
+ /* Set up the saio request */
+ io->i_offset = 0;
+ io->i_bn = hdbtodb(inode);
+ io->i_cc = ISO_SECTOR_SIZE;
+
+ if ((retval = devread(&io->i_si)) != ISO_SECTOR_SIZE)
+ return (0);
+
+ io->i_offset = 0;
+ io->i_bn = hdbtodb(inode);
+
+ if (inode != root_ino)
+ return (0);
+
+ if (parse_dir(io, 0, &hsdep) > 0) {
+ register struct inode *ip = &io->i_ino;
+
+ bzero(io->i_ino, sizeof (struct inode));
+ ip->i_size = hsdep.hs_dir.ext_size;
+ ip->i_smode = hsdep.hs_dir.mode;
+ ip->i_number = inode;
+ return (0);
+ }
+ return (1);
+}
+
+static ino_t
+find(char *path, struct iob *file)
+{
+ char *q;
+ char c;
+ ino_t n;
+
+ if (path == NULL || *path == '\0')
+ return (0);
+
+ if (opendir(root_ino, file))
+ return (0);
+
+ while (*path) {
+ while (*path == '/')
+ path++;
+ q = path;
+ while (*q != '/' && *q != '\0')
+ q++;
+ c = *q;
+ *q = '\0';
+
+ if ((n = dlook(path, file)) != 0) {
+ if (c == '\0')
+ break;
+ if (opendir(n, file))
+ return (0);
+ *q = c;
+ path = q;
+ continue;
+ } else {
+ return (0);
+ }
+ }
+ return ((ino_t)n);
+}
+
+static ino_t
+dlook(char *s, struct iob *io)
+{
+ register struct hs_direct *hsdep;
+ register struct direct *udp;
+ register struct inode *ip;
+ struct dirstuff dirp;
+ register int len;
+
+ ip = &io->i_ino;
+ if (s == NULL || *s == '\0')
+ return (0);
+ if ((ip->i_smode & IFMT) != IFDIR) {
+ return (0);
+ }
+ if (ip->i_size == 0) {
+ return (0);
+ }
+ len = strlen(s);
+ dirp.loc = 0;
+ dirp.io = io;
+ for (hsdep = readdir(&dirp); hsdep != NULL; hsdep = readdir(&dirp)) {
+ udp = &hsdep->hs_ufs_dir;
+ if (udp->d_namlen == 1 &&
+ udp->d_name[0] == '.' &&
+ udp->d_name[1] == '\0')
+ continue;
+ if (udp->d_namlen == 2 &&
+ udp->d_name[0] == '.' &&
+ udp->d_name[1] == '.' &&
+ udp->d_name[2] == '\0')
+ continue;
+ if (udp->d_namlen == len && (strcmp(s, udp->d_name)) == 0) {
+ register struct inode *ip = &io->i_ino;
+
+ io->i_offset = 0;
+ io->i_bn = hdbtodb(udp->d_ino);
+
+ bzero(io->i_ino, sizeof (struct inode));
+ ip->i_size = hsdep->hs_dir.ext_size;
+ ip->i_smode = hsdep->hs_dir.mode;
+ ip->i_number = udp->d_ino;
+ return (udp->d_ino);
+ }
+ }
+ return (0);
+}
+
+/*
+ * get next entry in a directory.
+ */
+static struct hs_direct *
+readdir(struct dirstuff *dirp)
+{
+ static struct hs_direct hsdep;
+ register struct direct *udp = &hsdep.hs_ufs_dir;
+ struct inode *ip;
+ struct iob *io;
+ daddr_t lbn, d;
+ int off;
+
+ io = dirp->io;
+ ip = &io->i_ino;
+ for (;;) {
+ if (dirp->loc >= ip->i_size) {
+ return (NULL);
+ }
+ off = dirp->loc & ((1 << ISO_SECTOR_SHIFT) - 1);
+ if (off == 0) {
+ lbn = hdbtodb(dirp->loc >> ISO_SECTOR_SHIFT);
+ io->i_bn = lbn + hdbtodb(ip->i_number);
+ io->i_ma = io->i_buf;
+ io->i_cc = ISO_SECTOR_SIZE;
+ if (devread(&io->i_si) != io->i_cc) {
+ return (NULL);
+ }
+ }
+ dirp->loc += parse_dir(io, off, &hsdep);
+ if (udp->d_reclen == 0 && dirp->loc <= ip->i_size) {
+ dirp->loc = roundup(dirp->loc, ISO_SECTOR_SIZE);
+ continue;
+ }
+ return (&hsdep);
+ }
+}
+
+static int
+getblock(struct iob *io)
+{
+ register struct hs_volume *fsp;
+ register struct inode *ip = &io->i_ino;
+ register int off, size, diff;
+ register daddr_t lbn;
+#ifdef SPIN_IND
+ static int pos;
+ static char ind[] = "|/-\\";
+ static int blks_read;
+#endif /* SPIN_IND */
+
+ diff = ip->i_size - io->i_offset;
+ if (diff <= 0)
+ return (-1);
+
+ fsp = &io->ui_hsfs;
+
+ /* which block (or frag) in the file do we read? */
+ lbn = hdbtodb(io->i_offset >> ISO_SECTOR_SHIFT);
+ io->i_bn = lbn + hdbtodb(ip->i_number);
+
+ off = io->i_offset & ((1 << ISO_SECTOR_SHIFT) - 1);
+ size = sizeof (io->i_buf);
+ io->i_ma = io->i_buf;
+ io->i_cc = size;
+
+ if (devread(&io->i_si) != size) /* Trap errors */
+ return (-1);
+
+#ifdef SPIN_IND
+ /*
+ * round and round she goes (though not on every block..
+ * - Even SunMON proms take some time to actually print stuff)
+ */
+ if ((blks_read++ & 0x3) == 0)
+ (*printf_p)("%c\b", ind[pos++ & 3]);
+#endif /* SPIN_IND */
+
+ if (io->i_offset - off + size >= ip->i_size)
+ io->i_cc = diff + off;
+ io->i_cc -= off;
+
+ io->i_ma = &io->i_buf[off];
+ return (0);
+}
+
+int
+read(int fd, caddr_t buf, int count)
+{
+ register i, j;
+ register struct iob *io = &iob[fd];
+ register struct inode *ip = &io->i_ino;
+ caddr_t n;
+
+ n = buf;
+
+ if (io->i_offset + count > ip->i_size)
+ count = ip->i_size - io->i_offset;
+
+ if ((i = count) <= 0)
+ return (0);
+
+ while (i > 0) {
+ if (io->i_cc <= 0) {
+ if (getblock(io) == -1)
+ return (0);
+ }
+ j = MIN(i, io->i_cc);
+ bcopy(io->i_ma, buf, (unsigned)j);
+ buf += j;
+ io->i_ma += j;
+ io->i_offset += j;
+ io->i_cc -= j;
+ i -= j;
+ }
+ return (buf - n);
+}
+
+/*
+ * We use the token iob for reading the "super block".
+ */
+static int
+mountroot()
+{
+ struct bootparam *bp;
+ struct hs_volume *fsp;
+ char *bufp;
+ int err;
+ int i;
+
+ /* This really has to be done only once. */
+ if (root_ino == 0) {
+
+ bp = *(romp->sunmon.v_bootparam);
+
+ fsp = &iob->ui_hsfs;
+ bufp = iob->i_buf;
+
+ iob->i_boottab = bp->bp_boottab;
+ iob->i_ino.i_dev = 0;
+ iob->i_ctlr = bp->bp_ctlr;
+ iob->i_unit = bp->bp_unit;
+ iob->i_boff = bp->bp_part;
+
+ /* make the prom open the device */
+ if (err = devopen(&iob->i_si))
+ return (-1); /* if devopen fails, open fails */
+
+ /* now opening file system; read the superblock. */
+ iob->i_ma = iob->i_buf;
+ iob->i_cc = ISO_SECTOR_SIZE;
+ iob->i_bn = hdbtodb(ISO_VOLDESC_SEC);
+ iob->i_offset = 0;
+ if ((err = devread(&iob->i_si)) != ISO_SECTOR_SIZE)
+ return (-1);
+
+ bufp = iob->i_buf;
+ fsp = &iob->ui_hsfs;
+
+ /* Since RRIP is based on ISO9660, that's where we start */
+
+ if (ISO_DESC_TYPE(bufp) != ISO_VD_PVD)
+ return (-1);
+ if (strncmp(ISO_std_id(bufp), ISO_ID_STRING, ISO_ID_STRLEN) != 0)
+ return (-1);
+ if (ISO_STD_VER(bufp) != ISO_ID_VER)
+ return (-1);
+
+ /* Now we fill in the volume descriptor */
+ fsp->vol_size = ISO_VOL_SIZE(bufp);
+ fsp->lbn_size = ISO_BLK_SIZE(bufp);
+ fsp->lbn_shift = ISO_SECTOR_SHIFT;
+ fsp->lbn_secshift = ISO_SECTOR_SHIFT;
+ fsp->vol_set_size = (ushort_t)ISO_SET_SIZE(bufp);
+ fsp->vol_set_seq = (ushort_t)ISO_SET_SEQ(bufp);
+
+ /* Make sure we have a valid logical block size */
+ if (fsp->lbn_size & ~(1 << fsp->lbn_shift)) {
+ (*printf_p)("%d invalid logical block size\n",
+ fsp->lbn_size);
+ return (-1);
+ }
+
+ /* Since an HSFS root could be located anywhere on the media! */
+ root_ino = IDE_EXT_LBN(ISO_root_dir(bufp));
+ }
+}
+
+/*
+ * Open a file. For the bootblock, we assume one file can be opened
+ * on a ufs filesystem. The underlying device is the one we rode in on.
+ */
+int
+open(char *str, int flags)
+{
+ register struct iob *ior;
+ register struct bootparam *bp;
+ register struct hs_volume *fsp;
+ register struct hs_direntry *dirp;
+ register char *bufp;
+ ino_t ino;
+ int err;
+
+ /* Make sure we are set up */
+ mountroot();
+
+ bp = *(romp->sunmon.v_bootparam);
+
+ ior = iob;
+ fsp = &ior->ui_hsfs;
+ dirp = &fsp->root_dir;
+ bufp = ior->i_buf;
+
+ ior->i_boottab = bp->bp_boottab;
+ ior->i_ino.i_dev = 0;
+ ior->i_ctlr = bp->bp_ctlr;
+ ior->i_unit = bp->bp_unit;
+ ior->i_boff = bp->bp_part;
+
+ if ((ino = find(str, ior)) == 0) {
+ (*printf_p)("%s not found\n", str);
+ return (-1);
+ }
+
+ ior->i_bn = hdbtodb(ino);
+ ior->i_offset = 0;
+ ior->i_cc = 0;
+
+ return (0);
+}
+
+int
+close(int fd)
+{
+ struct iob *file = &iob[fd];
+
+ return (devclose(&file->i_si));
+}
+
+/*
+ * This version of seek() only performs absolute seeks (whence == 0).
+ */
+int
+seek(int fd, off_t addr)
+{
+ struct iob *io = &iob[fd];
+
+ io->i_offset = addr;
+ io->i_bn = addr / DEV_BSIZE;
+ io->i_cc = 0;
+ return (0);
+}
+
+/*
+ * Parse a directory entry.
+ *
+ */
+static uint_t
+parse_dir(
+ struct iob *io, /* current dir block */
+ int offset, /* offset into dir blk for dir entry */
+ struct hs_direct *hsdep) /* return value: parsed entry */
+{
+ char *bufp = (char *)(io->i_ma + offset);
+ struct hs_volume *fsp = &io->ui_hsfs;
+ struct direct *udp = &hsdep->hs_ufs_dir; /* ufs-style dir info */
+ struct hs_direntry *hdp = &hsdep->hs_dir; /* hsfs-style dir info */
+ int ce_buf[ISO_SECTOR_SIZE/sizeof (int)]; /* continuation area buffer */
+ uint_t ce_lbn;
+ uint_t ce_len;
+ uint_t nmlen;
+ uint_t i;
+ uchar_t c;
+ int ret_code;
+
+ /* a zero length dir entry terminates the dir block */
+ if (!(udp->d_reclen = IDE_DIR_LEN(bufp)))
+ return (0);
+
+ /* fill in some basic hsfs info */
+ hdp->ext_lbn = IDE_EXT_LBN(bufp);
+ hdp->ext_size = IDE_EXT_SIZE(bufp);
+ hdp->xar_len = IDE_XAR_LEN(bufp);
+ hdp->intlf_sz = IDE_INTRLV_SIZE(bufp);
+ hdp->intlf_sk = IDE_INTRLV_SKIP(bufp);
+ hdp->sym_link = NULL;
+
+ /* we use lbn of data extent as an inode # equivalent */
+ udp->d_ino = hdp->ext_lbn;
+
+ c = IDE_FLAGS(bufp);
+ if (IDE_REGULAR_FILE(c)) {
+ hdp->type = VREG;
+ hdp->mode = IFREG;
+ hdp->nlink = 1;
+ } else if (IDE_REGULAR_DIR(c)) {
+ hdp->type = VDIR;
+ hdp->mode = IFDIR;
+ hdp->nlink = 2;
+ } else {
+ (*printf_p)("pd(): file type=0x%x unknown.\n", c);
+ return (-1);
+ }
+
+ /*
+ * Massage hsfs name, recognizing special entries for . and ..
+ * else lopping off version junk.
+ */
+
+ /* Some initial conditions */
+ nmlen = IDE_NAME_LEN(bufp);
+ c = *IDE_NAME(bufp);
+ /* Special Case: Current Directory */
+ if (nmlen == 1 && c == '\0') {
+ udp->d_name[0] = '.';
+ udp->d_name[1] = '\0';
+ udp->d_namlen = 1;
+ /* Special Case: Parent Directory */
+ } else if (nmlen == 1 && c == '\001') {
+ udp->d_name[0] = '.';
+ udp->d_name[1] = '.';
+ udp->d_name[2] = '\0';
+ udp->d_namlen = 2;
+ /* Other file name */
+ } else {
+ udp->d_namlen = 0;
+ for (i = 0; i < nmlen; i++) {
+ c = *(IDE_name(bufp)+i);
+ if (c == ';')
+ break;
+ else if (c == ' ')
+ continue;
+ else
+ udp->d_name[udp->d_namlen++] = c;
+ }
+ udp->d_name[udp->d_namlen] = '\0';
+ }
+
+ /* System Use Fields */
+ ce_len = IDE_SUA_LEN(bufp);
+
+ if (ce_len > 0) {
+ /* there is an SUA for this dir entry; go parse it */
+ ce_lbn = parse_susp((char *)IDE_sys_use_area(bufp),
+ &ce_len, hsdep);
+
+ if (ce_lbn) {
+ /*
+ * store away current position in dir,
+ * as we will be using the iobuf to reading SUA.
+ */
+ daddr_t save_bn = io->i_bn;
+ daddr_t save_offset = io->i_offset;
+ caddr_t save_ma = io->i_ma;
+ int save_cc = io->i_cc;
+ do {
+ io->i_cc = ISO_SECTOR_SIZE;
+ io->i_offset = 0;
+ io->i_bn = hdbtodb(ce_lbn);
+ io->i_ma = (char *)ce_buf;
+ ret_code = devread(&io->i_si);
+ if (ret_code != ISO_SECTOR_SIZE) {
+ ce_len = 0;
+ ce_lbn = 0;
+ break;
+ }
+ ce_lbn = parse_susp(io->i_ma, &ce_len, hsdep);
+ } while (ce_lbn);
+ io->i_bn = save_bn;
+ io->i_offset = save_offset;
+ io->i_ma = save_ma;
+ io->i_cc = save_cc;
+ }
+ }
+ return (udp->d_reclen);
+}
+
+/*
+ * Parse the System Use Fields in this System Use Area.
+ * Return blk number of continuation/SUA, or 0 if no continuation/not a SUA.
+ */
+static uint_t
+parse_susp(char *bufp, uint_t *len, struct hs_direct *hsdep)
+{
+ register struct direct *udp = &hsdep->hs_ufs_dir; /* ufs-style info */
+ char *susp;
+ uint_t cur_off = 0;
+ uint_t blk_len = *len;
+ uint_t susp_len = 0;
+ uint_t ce_lbn = 0;
+ uint_t i;
+
+ while (cur_off < blk_len) {
+ susp = (char *)(bufp + cur_off);
+
+ /*
+ * A null entry, or an entry with zero length
+ * terminates the SUSP.
+ */
+ if (susp[0] == '\0' || susp[1] == '\0' ||
+ (susp_len = SUF_LEN(susp)) == 0)
+ break;
+
+ /*
+ * Compare current entry to all known signatures.
+ */
+ for (i = 0; i < hsfs_num_sig; i++)
+ if (strncmp(hsfs_sig_tab[i], susp, SUF_SIG_LEN) == 0)
+ break;
+ switch (i) {
+ case SUSP_SP_IX:
+ /* SP signature: field tells us where SUA is */
+ if (CHECK_BYTES_OK(susp)) {
+ cur_off = SP_SUA_OFFSET(susp);
+ }
+ break;
+ case SUSP_CE_IX:
+ /*
+ * CE signature: continuation of SUSP.
+ * will want to return new lbn, len.
+ */
+ ce_lbn = CE_BLK_LOC(susp);
+ *len = CE_CONT_LEN(susp);
+ cur_off += susp_len;
+ break;
+ case SUSP_ST_IX:
+ /* ST signature: terminates SUSP */
+ return (ce_lbn);
+ case RRIP_RR_IX:
+ /* XXX do we want to break when we see a RR? */
+ cur_off += susp_len;
+ break;
+ case RRIP_NM_IX:
+ /* NM signature: POSIX-style file name */
+ if (!RRIP_NAME_FLAGS(susp)) {
+ udp->d_namlen = RRIP_NAME_LEN(susp);
+ bcopy((char *)RRIP_name(susp),
+ udp->d_name, udp->d_namlen);
+ udp->d_name[udp->d_namlen] = '\0';
+ }
+ break;
+
+ case HSFS_NUM_SIG:
+ /* couldn't find a legit susp, terminate loop */
+ (*printf_p)("parse_susp(): Bad SUSP\n");
+ cur_off = blk_len;
+ break;
+
+ default:
+ cur_off += susp_len;
+ }
+ }
+ return (ce_lbn);
+}
diff --git a/usr/src/psm/stand/bootblks/hsfs/common/hsfs_sig.h b/usr/src/psm/stand/bootblks/hsfs/common/hsfs_sig.h
new file mode 100644
index 0000000000..2b18abe8e7
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/hsfs/common/hsfs_sig.h
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ *
+ * 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, 1991-1994, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef HANDLE_CONTINUATION
+static char *hsfs_sig_tab[] = {
+ SUSP_SP,
+ SUSP_CE,
+ SUSP_PD,
+ SUSP_ST,
+ SUSP_ER,
+ RRIP_PX,
+ RRIP_PN,
+ RRIP_SL,
+ RRIP_CL,
+ RRIP_PL,
+ RRIP_RE,
+ RRIP_TF,
+ RRIP_RR,
+ RRIP_NM
+};
+
+static int hsfs_num_sig = sizeof (hsfs_sig_tab) / sizeof (hsfs_sig_tab[0]);
+#endif /* HANDLE_CONTINUATION */
+
+#define HSFS_NUM_SIG 14
+
+#define SUSP_SP_IX 0
+#define SUSP_CE_IX 1
+#define SUSP_PD_IX 2
+#define SUSP_ST_IX 3
+#define SUSP_ER_IX 4
+
+#define RRIP_PX_IX 5
+#define RRIP_PN_IX 6
+#define RRIP_SL_IX 7
+#define RRIP_CL_IX 8
+#define RRIP_PL_IX 9
+#define RRIP_RE_IX 10
+#define RRIP_RF_IX 11
+#define RRIP_RR_IX 12
+#define RRIP_NM_IX 13
diff --git a/usr/src/psm/stand/bootblks/hsfs/common/hsfs_small.c b/usr/src/psm/stand/bootblks/hsfs/common/hsfs_small.c
new file mode 100644
index 0000000000..b89892eafd
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/hsfs/common/hsfs_small.c
@@ -0,0 +1,674 @@
+/*
+ * 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.
+ *
+ * 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 (c) 1991-1994, Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* from "@(#)boot/ufssys.c 1.1 90/03/28 SMI" */
+
+/*
+ * Basic file system reading code for standalone I/O system.
+ */
+
+/*
+ * This code must be kept very small. If space allows, you can
+ * turn on the ability to handle continuations (and other signatures)
+ * by #defining HANDLE_CONTINUATION.
+ */
+
+#include <sys/param.h>
+#include <sys/vnode.h>
+#include <sys/fs/ufs_fsdir.h>
+#include <sys/fs/ufs_fs.h>
+#include <sys/fs/ufs_inode.h>
+
+#include <sys/fs/hsfs_spec.h>
+#include <sys/fs/hsfs_isospec.h>
+#include <sys/fs/hsfs_node.h>
+#include <sys/fs/hsfs_susp.h>
+#include <sys/fs/hsfs_rrip.h>
+
+#include "iob.h"
+#include "cbootblk.h"
+
+#include "hsfs_sig.h"
+
+#define NULL 0
+
+#define TRUE 1
+#define FALSE 0
+
+#define hdbtodb(n) ((ISO_SECTOR_SIZE / DEV_BSIZE) * (n))
+
+#ifdef DEBUG
+/* debugging printfs */
+#define DEBUG_PRINTF0(s) \
+ fprintf(stderr, s)
+#define DEBUG_PRINTF1(s, a1) \
+ fprintf(stderr, s, (a1))
+#define DEBUG_PRINTF2(s, a1, a2) \
+ fprintf(stderr, s, (a1), (a2))
+#define DEBUG_PRINTF3(s, a1, a2, a3) \
+ fprintf(stderr, s, (a1), (a2), (a3))
+#define DEBUG_PRINTF4(s, a1, a2, a3, a4) \
+ fprintf(stderr, s, (a1), (a2), (a3), (a4))
+#define DEBUG_PRINTF5(s, a1, a2, a3, a4, a5) \
+ fprintf(stderr, s, (a1), (a2), (a3), (a4), (a5))
+#else
+#define DEBUG_PRINTF0(s)
+#define DEBUG_PRINTF1(s, a1)
+#define DEBUG_PRINTF2(s, a1, a2)
+#define DEBUG_PRINTF3(s, a1, a2, a3)
+#define DEBUG_PRINTF4(s, a1, a2, a3, a4)
+#define DEBUG_PRINTF5(s, a1, a2, a3, a4, a5)
+#endif
+
+char fscompname[] = "hsfsboot";
+
+static struct iob iob[1]; /* only one open file! */
+
+static u_int dlook(char *, register struct iob *);
+static int parse_dir(struct iob *, int, u_char *, u_int *, u_int *);
+static u_int parse_susp(u_char *, u_int *, u_char *, u_int *, u_int *);
+static int read_sector(struct iob *, u_int, char *, u_char);
+
+static int
+read_sector(struct iob *io, u_int iso_secno, char *buf, u_char next)
+{
+#ifdef DEBUG
+ static char *msg = "rs:[%c] o=%d b=%d c=%d n=%d\n";
+#endif
+ DEBUG_PRINTF5(msg, 'I', io->i_offset, io->i_bn, io->i_cc, next);
+
+ io->i_cc = ISO_SECTOR_SIZE;
+ io->i_ma = buf;
+
+ if (next == TRUE) {
+ io->i_bn += (ISO_SECTOR_SIZE / DEV_BSIZE);
+ } else {
+ io->i_offset = 0;
+ io->i_bn = hdbtodb(iso_secno);
+ }
+
+ if (devbread(&io->i_si, io->i_ma,
+ io->i_bn, io->i_cc) != ISO_SECTOR_SIZE) {
+ DEBUG_PRINTF5(msg, '0', io->i_offset,
+ io->i_bn, io->i_cc, next);
+ return (0);
+ }
+
+ DEBUG_PRINTF5(msg, '1', io->i_offset, io->i_bn, io->i_cc, next);
+ return (1);
+}
+
+/*
+ * Look up a file, pathname component by pathname component.
+ * Return lbn of file if found, 0 otherwise.
+ */
+static u_int
+find(char *path, struct iob *file)
+{
+ char *q;
+ char c;
+ u_int n;
+
+ if (path == NULL || *path == '\0')
+ return (0);
+
+ while (*path) {
+ while (*path == '/')
+ path++;
+ q = path;
+ while (*q != '/' && *q != '\0')
+ q++;
+ c = *q;
+ *q = '\0';
+
+ if ((n = dlook(path, file)) != 0) {
+ DEBUG_PRINTF1("fnd: n=%d\n", n);
+ if (c == '\0')
+ break;
+ if (!read_sector(file, n, file->i_buf, FALSE))
+ return (0);
+ *q = c;
+ path = q;
+ continue;
+ } else {
+ return (0);
+ }
+ }
+ return (n);
+}
+
+/*
+ * Look up the file in the directory.
+ * Return lbn of file extent on success, 0 on failure.
+ */
+static u_int
+dlook(char *s, struct iob *io)
+{
+ struct hs_volume *fsp = &io->ui_hsfs;
+ struct hs_direntry *dirp = &fsp->root_dir;
+ int dirsz = dirp->ext_size;
+ u_char nameb[MAXPATHLEN];
+ u_int nml;
+ u_int blkloc = 0;
+ u_int dirloc;
+ u_int reclen;
+ u_int len;
+ u_int altnm;
+
+ if (s == NULL || *s == '\0')
+ return (0);
+
+ if (dirp->type != VDIR)
+ return (0);
+
+ len = strlen(s);
+
+ while (blkloc < dirsz) {
+ dirloc = 0;
+ while (dirloc < ISO_SECTOR_SIZE) {
+ altnm = 0;
+ nml = sizeof (nameb);
+ reclen = parse_dir(io, dirloc, nameb, &nml, &altnm);
+ dirloc += reclen;
+ if (!reclen)
+ break;
+ if (altnm) {
+ if (len != nml ||
+ strncmp(s, (char *)nameb, len) != 0)
+ continue;
+ } else {
+ if (strncmp(s, (char *)nameb, len) != 0)
+ continue;
+ }
+ DEBUG_PRINTF1("dl: ret lb=%d\n", dirp->ext_lbn);
+ return ((u_int) dirp->ext_lbn);
+ }
+ if (blkloc + ISO_SECTOR_SIZE < dirsz) {
+ if (!read_sector(io, 0, io->i_buf, TRUE))
+ return (0);
+ }
+ blkloc += ISO_SECTOR_SIZE;
+ }
+ return (0);
+}
+
+static int
+getblock(register struct iob *io)
+{
+ u_int lbn;
+ int off, size, diff;
+ struct hs_volume *fsp = &io->ui_hsfs;
+ struct hs_direntry *dirp = &fsp->root_dir;
+
+ diff = dirp->ext_size - io->i_offset;
+ if (diff <= 0)
+ return (-1);
+ lbn = hdbtodb(io->i_offset >> ISO_SECTOR_SHIFT);
+ io->i_bn = lbn + hdbtodb(dirp->ext_lbn);
+ off = io->i_offset % ISO_SECTOR_SIZE;
+ size = sizeof (io->i_buf);
+ io->i_cc = size;
+ io->i_ma = io->i_buf;
+
+ if (devbread(&io->i_si, io->i_ma,
+ io->i_bn, io->i_cc) != io->i_cc) /* Trap errors */
+ return (-1);
+
+ if (io->i_offset - off + size >= dirp->ext_size)
+ io->i_cc = diff + off;
+ io->i_cc -= off;
+
+ io->i_ma = &io->i_buf[off];
+ return (0);
+}
+
+int
+readfile(int fd, char *buf, int count)
+{
+ int i, j;
+ struct iob *io = &iob[fd];
+ struct iob *file = io;
+ struct hs_volume *fsp = &file->ui_hsfs;
+ struct hs_direntry *dirp = &fsp->root_dir;
+
+ if (file->i_offset + count > dirp->ext_size)
+ count = dirp->ext_size - file->i_offset;
+ if ((i = count) <= 0)
+ return (0);
+ while (i > 0) {
+ if (file->i_cc <= 0) {
+ if (getblock(file) == -1)
+ return (0);
+ }
+ j = (i < file->i_cc) ? i : file->i_cc;
+ bcopy(file->i_ma, buf, (unsigned)j);
+ buf += j;
+ file->i_ma += j;
+ file->i_offset += j;
+ file->i_cc -= j;
+ i -= j;
+ }
+ return (count);
+}
+
+/*
+ * Open a file. For the bootblock, we assume one file can be opened
+ * on a hsfs filesystem. The underlying device is the one we rode in on.
+ */
+int
+openfile(char *device, char *pathname)
+{
+ struct iob *io = &iob[0]; /* only one open file! */
+ register struct hs_volume *fsp;
+ register char *bufp;
+ u_int lbn;
+
+ DEBUG_PRINTF0("open\n");
+
+ fsp = &io->ui_hsfs;
+ bufp = io->i_buf;
+
+ if ((io->i_si = devopen(device)) == NULL)
+ return (-1); /* if devopen fails, open fails */
+ /*
+ * Pseudo-mount a file system; read the superblock.
+ */
+ if (!read_sector(io, ISO_VOLDESC_SEC, bufp, FALSE))
+ goto failed;
+
+ /* Make sure we start with a clean slate. */
+ (void) bzero((char *)fsp, sizeof (io->ui_hsfs));
+
+ /* Since RRIP is based on ISO9660, that's where we start */
+
+ if (ISO_DESC_TYPE(bufp) != ISO_VD_PVD ||
+ strncmp((char *)ISO_std_id(bufp), ISO_ID_STRING,
+ ISO_ID_STRLEN) != 0 ||
+ ISO_STD_VER(bufp) != ISO_ID_VER) {
+ puts("bootblk: not an ISO9660 file system.\n");
+ goto failed;
+ }
+
+ /* Now we fill in the volume descriptor */
+ fsp->vol_size = ISO_VOL_SIZE(bufp);
+ fsp->lbn_size = ISO_BLK_SIZE(bufp);
+ fsp->lbn_shift = ISO_SECTOR_SHIFT;
+ fsp->lbn_secshift = ISO_SECTOR_SHIFT;
+ fsp->vol_set_size = (u_short) ISO_SET_SIZE(bufp);
+ fsp->vol_set_seq = (u_short) ISO_SET_SEQ(bufp);
+
+ /* Make sure we have a valid logical block size */
+ if (fsp->lbn_size & ~(1 << fsp->lbn_shift)) {
+ DEBUG_PRINTF1("%d byte logical block size invalid.",
+ fsp->lbn_size);
+ goto failed;
+ }
+
+ /* Read the ROOT directory */
+ if (!read_sector(io, IDE_EXT_LBN(ISO_root_dir(bufp)), bufp, FALSE))
+ goto failed;
+
+ /* Extract the ROOT directory information from the directory block */
+ (void) parse_dir(io, 0, NULL, (u_int *) 0, (u_int *) 0);
+
+ if (!(lbn = find(pathname, io)))
+ goto failed;
+
+ DEBUG_PRINTF1("lb=%d\n", lbn);
+
+ io->i_bn = hdbtodb(lbn);
+ io->i_offset = 0;
+ io->i_cc = 0;
+
+ return (0); /* only one open file! */
+failed:
+ (void) devclose(io->i_si);
+ return (-1);
+}
+
+int
+closefile(int fd)
+{
+ struct iob *io = &iob[fd];
+
+ return (devclose(io->i_si));
+}
+
+/*
+ * This version of seek() only performs absolute seeks (whence == 0).
+ */
+void
+seekfile(int fd, off_t addr)
+{
+ struct iob *io = &iob[fd];
+
+ io->i_offset = addr;
+ io->i_bn = addr >> DEV_BSHIFT;
+ io->i_cc = 0;
+}
+
+/*
+ * Return the next directory entry.
+ * Return 0 if no next entry, length of directory entry otherwise.
+ */
+static int
+parse_dir(
+ struct iob *io, /* current dir block */
+ int offset, /* dir entry offset into dir blk */
+ u_char *namep, /* output: name found */
+ u_int *namelen, /* output: length of name found */
+ u_int *anm) /* output: found RR (altrnt) nm flg */
+{
+ u_char *bufp = (u_char *)(io->i_buf + offset);
+ struct hs_direntry *dirp = &(io->ui_hsfs.root_dir);
+ static u_char ce_buf[ISO_SECTOR_SIZE];
+ u_int ce_len;
+ static u_char nmbuf[MAXPATHLEN];
+ u_int nmlen;
+ u_int altnm = 0; /* found RR name flag */
+ u_char c;
+ u_int dir_len = IDE_DIR_LEN(bufp);
+
+ DEBUG_PRINTF1("pd %d\n", dir_len);
+
+ if (!dir_len)
+ /* zero length directory, done */
+ return (0);
+
+ dirp->ext_lbn = IDE_EXT_LBN(bufp);
+ dirp->ext_size = IDE_EXT_SIZE(bufp);
+ dirp->xar_len = IDE_XAR_LEN(bufp);
+ dirp->intlf_sz = IDE_INTRLV_SIZE(bufp);
+ dirp->intlf_sk = IDE_INTRLV_SKIP(bufp);
+ dirp->sym_link = NULL;
+
+ c = IDE_FLAGS(bufp);
+ if (IDE_REGULAR_FILE(c)) {
+ dirp->type = VREG;
+ dirp->mode = IFREG;
+ dirp->nlink = 1;
+ } else if (IDE_REGULAR_DIR(c)) {
+ dirp->type = VDIR;
+ dirp->mode = IFDIR;
+ dirp->nlink = 2;
+ } else {
+ DEBUG_PRINTF1("pd: ftype=0x%x unknown.\n", c);
+ return (-1);
+ }
+
+ /*
+ * Massage hsfs name, recognizing special entries for . and ..
+ * else lopping off version junk.
+ */
+
+ /* Some initial conditions */
+ nmlen = IDE_NAME_LEN(bufp);
+ c = *IDE_NAME(bufp);
+ /* Special Case: Current Directory */
+ if (nmlen == 1 && c == '\0') {
+ nmbuf[0] = '.';
+ nmbuf[1] = '\0';
+ nmlen = 1;
+ /* Special Case: Parent Directory */
+ } else if (nmlen == 1 && c == '\001') {
+ nmbuf[0] = '.';
+ nmbuf[1] = '.';
+ nmbuf[2] = '\0';
+ nmlen = 2;
+ /* Other file name */
+ } else {
+ register int l = nmlen;
+ register int i;
+
+ nmlen = 0;
+ for (i = 0; i < l; i++) {
+ c = *(IDE_name(bufp)+i);
+ if (c == ';')
+ break;
+ else if (c == ' ')
+ continue;
+ else
+ nmbuf[nmlen++] = c;
+ }
+ nmbuf[nmlen] = '\0';
+ }
+
+ DEBUG_PRINTF0("pd bf sua");
+
+#ifdef HANDLE_CONTINUATION
+ /* System Use Fields */
+ ce_len = IDE_SUA_LEN(bufp);
+ if (ce_len) {
+ /* there is an SUA for this dir entry; go parse it */
+ u_int ce_lbn;
+ u_int nmbsz = sizeof (nmbuf);
+
+ bcopy((char *)IDE_sys_use_area(bufp), (char *)ce_buf, ce_len);
+ ce_lbn = parse_susp(ce_buf, &ce_len, nmbuf, &nmbsz, &altnm);
+
+ while (ce_lbn) {
+ /*
+ * Process continuation of SUA,
+ * saving current position in dir,
+ * as will be using iobuf to read SUA continuation.
+ */
+ daddr_t save_bn = io->i_bn;
+ daddr_t save_offset = io->i_offset;
+ int save_cc = io->i_cc;
+ int rd_ok;
+
+ rd_ok = read_sector(io, ce_lbn, (char *)ce_buf, FALSE);
+
+ io->i_bn = save_bn;
+ io->i_offset = save_offset;
+ io->i_cc = save_cc;
+
+ if (!rd_ok)
+ return (0);
+
+ ce_lbn = parse_susp(ce_buf, &ce_len, nmbuf, &nmbsz,
+ &altnm);
+ }
+ if (altnm)
+ nmlen = nmbsz;
+ }
+#else /* HANDLE_CONTINUATION */
+ /* System Use Fields */
+ ce_len = IDE_SUA_LEN(bufp);
+ if (ce_len) {
+ /* there is an SUA for this dir entry; go parse it */
+
+ u_int nmbsz = sizeof (nmbuf);
+
+ bcopy((char *)IDE_sys_use_area(bufp), (char *)ce_buf, ce_len);
+ (void) parse_susp(ce_buf, &ce_len, nmbuf, &nmbsz, &altnm);
+
+ if (altnm)
+ nmlen = nmbsz;
+ }
+#endif /* HANDLE_CONTINUATION */
+
+ DEBUG_PRINTF0("pd af sua");
+
+ if (anm != NULL)
+ *anm = altnm;
+
+ if (namep != NULL && namelen != NULL && *namelen) {
+ /* assert(namelen >= nmlen) */
+ bcopy((char *)nmbuf, (char *)namep, nmlen);
+ *namelen = nmlen;
+ }
+
+#ifdef DEBUG
+ if (altnm)
+ nmbuf[nmlen] = '\0';
+#endif /* DEBUG */
+
+ DEBUG_PRINTF2("Nm(%d)=%s\n", nmlen, nmbuf);
+ DEBUG_PRINTF2(" lbn/len = %d/%d\n", dirp->ext_lbn, dirp->ext_size);
+ DEBUG_PRINTF0("pd end\n");
+
+ return (dir_len);
+}
+
+#ifdef HANDLE_CONTINUATION
+/*
+ * Parse the System Use Fields in the System Use Area.
+ * Return block number of continuation (if any),
+ * or 0 if no continuation.
+ */
+static u_int
+parse_susp(
+ u_char *bufp,
+ u_int *len,
+ u_char *nmp,
+ u_int *nmlen,
+ u_int *altnm) /* found RR name */
+{
+ u_char *susp;
+ u_int cur_off = 0;
+ u_int blk_len = *len;
+ u_int susp_len = 0;
+ u_int ce_lbn = 0;
+ u_int i;
+
+ DEBUG_PRINTF1("ps: l=%d\n", *len);
+
+ while (cur_off < blk_len) {
+ susp = (u_char *)(bufp + cur_off);
+ /*
+ * A null entry, or an entry with zero length
+ * terminates the SUSP.
+ */
+ if (susp[0] == '\0' || susp[1] == '\0' ||
+ (susp_len = SUF_LEN(susp)) == 0)
+ break;
+
+ /* Compare current entry to all known signatures */
+ for (i = 0; i < HSFS_NUM_SIG; i++) {
+ if (strncmp(hsfs_sig_tab[i], susp, SUF_SIG_LEN) == 0) {
+ DEBUG_PRINTF3("SUSP_%c%c %d\n", susp[0],
+ susp[1], susp_len);
+ break;
+ }
+ }
+
+ switch (i) {
+ case SUSP_CE_IX:
+ /*
+ * CE signature: continuation of SUSP.
+ * will want to return new lbn, len.
+ */
+ ce_lbn = CE_BLK_LOC(susp);
+ *len = CE_CONT_LEN(susp);
+ break;
+ case SUSP_ST_IX:
+ /* ST signature: terminates SUSP */
+ return (ce_lbn);
+ case RRIP_RR_IX:
+ /* XXX do we want to break when we see a RR? */
+ break;
+ case RRIP_NM_IX:
+ /* NM signature: POSIX-style file name */
+ DEBUG_PRINTF0(" NM\n");
+ if (!RRIP_NAME_FLAGS(susp)) {
+ /* copy out new name if requested */
+ if (*nmlen) {
+ *nmlen = RRIP_NAME_LEN(susp);
+ /* assert(old(nmlen) >= new(nmlen)) */
+ bcopy((char *)RRIP_name(susp),
+ (char *)nmp, *nmlen);
+ *altnm = 1;
+ }
+ }
+ break;
+ case HSFS_NUM_SIG:
+ /* couldn't find a legit susp, complain and continue */
+ (*printf_p)("parse_susp(): Bad SUSP\n");
+ break;
+ default:
+ break;
+ }
+
+ cur_off += susp_len;
+ DEBUG_PRINTF1("ps: o=%d\n", cur_off);
+ }
+ return (ce_lbn);
+}
+
+#else /* HANDLE_CONTINUATION */
+/*
+ * Parse the System Use Fields in the System Use Area.
+ * Return block number of continuation (if any),
+ * or 0 if no continuation.
+ */
+static u_int
+parse_susp(
+ u_char *bufp,
+ u_int *len,
+ u_char *nmp,
+ u_int *nmlen,
+ u_int *altnm) /* found RR name */
+{
+ u_char *susp;
+ u_int cur_off = 0;
+ u_int blk_len = *len;
+ u_int susp_len = 0;
+
+ DEBUG_PRINTF1("ps: l=%d\n", *len);
+
+ while (cur_off < blk_len) {
+ susp = (u_char *)(bufp + cur_off);
+
+ /*
+ * A null entry, or an entry with zero length
+ * terminates the SUSP.
+ */
+ if (susp[0] == '\0' || susp[1] == '\0' ||
+ (susp_len = SUF_LEN(susp)) == 0)
+ break;
+
+ /* Compare current entry to all known signatures */
+ if ((susp[0] == 'N' && susp[1] == 'M') &&
+ !RRIP_NAME_FLAGS(susp)) {
+ /* copy out new name if requested */
+ if (*nmlen) {
+ *nmlen = RRIP_NAME_LEN(susp);
+ /* assert(old(nmlen) >= new(nmlen)) */
+ bcopy((char *)RRIP_name(susp), (char *)nmp,
+ *nmlen);
+ *altnm = 1;
+ }
+ return (0);
+ }
+ cur_off += susp_len;
+ DEBUG_PRINTF1("ps: o=%d\n", cur_off);
+ }
+ return (0);
+}
+#endif /* HANDLE_CONTINUATION */
diff --git a/usr/src/psm/stand/bootblks/hsfs/common/iob.h b/usr/src/psm/stand/bootblks/hsfs/common/iob.h
new file mode 100644
index 0000000000..844f1152fb
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/hsfs/common/iob.h
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ *
+ * 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 (c) 1990-1994, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * This struct keeps track of an open file in the standalone I/O system.
+ *
+ * It includes an IOB for device addess, a buffer for reading directory blocks
+ * and a structure for volume.
+ */
+struct iob {
+ void *i_si; /* I/O handle for this file */
+ struct {
+ off_t si_offset; /* byte offset */
+ char *si_ma; /* memory address to r/w */
+ int si_cc; /* character count to r/w */
+ int si_bn; /* block number to r/w */
+ } i_saio;
+ struct inode i_ino; /* Buffer for inode information */
+ struct hs_volume ui_hsfs; /* Superblock for file system */
+ char i_buf[MAXBSIZE]; /* Buffer for reading dirs */
+};
+
+#define i_offset i_saio.si_offset
+#define i_bn i_saio.si_bn
+#define i_ma i_saio.si_ma
+#define i_cc i_saio.si_cc
diff --git a/usr/src/psm/stand/bootblks/hsfs/i386/Makefile b/usr/src/psm/stand/bootblks/hsfs/i386/Makefile
new file mode 100644
index 0000000000..7f3dd6b25c
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/hsfs/i386/Makefile
@@ -0,0 +1,44 @@
+#
+# 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.
+#
+# 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 (c) 1994, by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# psm/stand/bootblks/hsfs/i386/Makefile
+#
+BASEDIR = ../..
+
+include $(BASEDIR)/hsfs/Makefile.hsfs
+
+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/hsfs/sparc/Makefile b/usr/src/psm/stand/bootblks/hsfs/sparc/Makefile
new file mode 100644
index 0000000000..00d81e23f9
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/hsfs/sparc/Makefile
@@ -0,0 +1,49 @@
+#
+# 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.
+#
+# 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 1994, 2001-2002 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# psm/stand/bootblks/hsfs/sparc/Makefile
+#
+BASEDIR = ../..
+
+include $(BASEDIR)/hsfs/Makefile.hsfs
+
+SUBDIRS = unix
+
+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/hsfs/sparc/unix/Makefile b/usr/src/psm/stand/bootblks/hsfs/sparc/unix/Makefile
new file mode 100644
index 0000000000..8aa0b74787
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/hsfs/sparc/unix/Makefile
@@ -0,0 +1,71 @@
+#
+# 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.
+#
+# 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 (c) 1994, by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# psm/stand/bootblks/hsfs/sparc/unix/Makefile
+#
+
+#
+# Build the "Unix" version of the boot block.
+# Useful solely for testing. DO NOT INSTALL IT!
+#
+BASEDIR = ../../..
+PLATFORM = unix
+PLATFORM_INCS = ./
+PLATLINKS =
+
+include $(BASEDIR)/hsfs/Makefile.hsfs
+include $(BASEDIR)/obp-c/Makefile.rules
+
+CPPINCS += -I$(SRC)/head
+CPPINCS += -I$(SRC)/uts/common
+CPPINCS += -I$(SRC)/uts/sun
+CPPINCS += -I$(SRC)/uts/sparc
+CPPINCS += -I$(PLATFORM_INCS)
+
+UNIX_OBJS = hsfs_small.o unix_devio.o
+
+$(UNIX_OBJS) := CFLAGS += -g
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+$(PROG): $(UNIX_OBJS)
+ $(CC) $(CFLAGS) $(CPPFLAGS) -g -o $@ $(UNIX_OBJS)
+
+lint: FRC
+
+clean:
+ $(RM) $(UNIX_OBJS)
+
+clobber: clean
+ $(RM) $(PROG)
+
+install: FRC
+
+FRC:
+
diff --git a/usr/src/psm/stand/bootblks/obp-c/Makefile.rules b/usr/src/psm/stand/bootblks/obp-c/Makefile.rules
new file mode 100644
index 0000000000..b320f564ac
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/obp-c/Makefile.rules
@@ -0,0 +1,105 @@
+#
+# 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.
+#
+# 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 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# psm/stand/bootblks/obp-c/Makefile.rules
+#
+
+OBPSRCDIR = $(BASEDIR)/obp-c
+OBPCMNDIR = $(OBPSRCDIR)/common
+OBPMACHDIR = $(OBPSRCDIR)/$(MACH)/common
+OBPPLATDIR = $(OBPSRCDIR)/$(MACH)/$(PLATFORM)
+
+#
+# Sources and objects used to build the C-based bootblock for
+# deprecated OBP V0 and V2 platforms.
+#
+OBPDEP_C_SRCS = stub.c
+OBPDEP_S_SRCS =
+OBPDEP_SRCS = $(OBPDEP_C_SRCS) $(OBPDEP_S_SRCS)
+OBPDEP_SRT = obp_srt0.o
+OBPDEP_OBJS = $(OBPDEP_C_SRCS:%.c=%.o) $(OBPDEP_S_SRCS:%.s=%.o) bbvers.o
+OBPDEP_L_OBJS = $(OBPDEP_SRT:%.o=%.ln) $(OBPDEP_OBJS:%.o=%.ln)
+OBPDEP_LD_LIBS =
+
+#
+# Rules used to build boot blocks. PROM_TYPE is defined in the platform
+# specific Makefile in ../<fs>/<mach>/<platform>/Makefile and is set to one
+# of OBP or IEEE1275.
+#
+BOOT_OBJS = $($(PROM_TYPE)_OBJS)
+BOOT_SRT = $($(PROM_TYPE)_SRT)
+BOOT_L_OBJS = $($(PROM_TYPE)_L_OBJS)
+BOOT_LD_LIBS = $($(PROM_TYPE)_LD_LIBS)
+
+MAPFILE = $(OBPMACHDIR)/mapfile
+
+CPPINCS += -I$(OBPCMNDIR) -I$(PSMSYSHDRDIR)
+CPPFLAGS += -D_BOOT -D_KERNEL
+CPPFLAGS += $(CPPINCS) $(CCYFLAG)$(PSMSYSHDRDIR)
+ASFLAGS += -D_BOOT -D_ASM -P $(CPPINCS)
+LDFLAGS = -dn -e start -M $(MAPFILE)
+LDLIBS = $(BOOT_LD_LIBS)
+
+#
+# lint pass1 enforcement
+#
+CFLAGS += $(CCVERBOSE)
+
+MKBOOT = mkboot
+MKVERS = makevers
+
+#
+# Pattern matching rules to compile the source in this directory
+#
+%.o: $(OBPCMNDIR)/%.c
+ $(COMPILE.c) -o $@ $<
+
+%.o: $(OBPMACHDIR)/%.s
+ $(COMPILE.s) -o $@ $<
+
+%.o: $(OBPMACHDIR)/%.c
+ $(COMPILE.c) -o $@ $<
+
+%.o: $(OBPPLATDIR)/%.s
+ $(COMPILE.s) -o $@ $<
+
+%.ln: $(OBPCMNDIR)/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+
+%.ln: $(OBPMACHDIR)/%.s
+ @($(LHEAD) $(LINT.s) $< $(LTAIL))
+
+%.ln: $(OBPMACHDIR)/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+
+%.ln: $(OBPPLATHDIR)/%.s
+ @($(LHEAD) $(LINT.s) $< $(LTAIL))
+
+%: $(OBPCMNDIR)/%.sh
+ $(RM) $@
+ cat $< > $@
+ chmod +x $@
diff --git a/usr/src/psm/stand/bootblks/obp-c/Makefile.targ b/usr/src/psm/stand/bootblks/obp-c/Makefile.targ
new file mode 100644
index 0000000000..1b9e6bf55d
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/obp-c/Makefile.targ
@@ -0,0 +1,61 @@
+#
+# 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.
+#
+# 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 1994-2002 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# psm/stand/bootblks/obp-c/Makefile.targ
+#
+
+#
+# Targets for the C-only bootblock
+#
+.PARALLEL: $(BOOT_SRT) $(BOOT_OBJS) $(BOOT_L_OBJS)
+
+$(PROG).elf: $(BOOT_SRT) $(BOOT_OBJS) $(MAPFILE)
+ $(LD) $(LDFLAGS) -o $@ $(BOOT_SRT) $(BOOT_OBJS) $(LDLIBS)
+
+$(MKBOOT): $(OBPCMNDIR)/$$(@).c
+ $(NATIVECC) -o $@ $(OBPCMNDIR)/$@.c
+
+$(PROG): $(PROG).elf
+
+bbvers.c: $(MKVERS)
+ @-$(RM) $@
+ ./$(MKVERS) ${ECHO} $(PROG) $@
+
+clean:
+ -$(RM) $(BOOT_SRT) $(BOOT_OBJS)
+ -$(RM) $(BOOT_L_OBJS)
+ -$(RM) bbvers.c a.out core
+
+clobber: clean
+ -$(RM) $(PROG) $(PROG).elf bootblk.version
+ -$(RM) $(MKVERS) $(MKBOOT)
+
+lint: $(BOOT_L_OBJS)
+ @echo "Global Cross-checks:"
+ $(LINT.2) $(BOOT_L_OBJS) $(LDLIBS)
+
+FRC:
diff --git a/usr/src/psm/stand/bootblks/obp-c/common/cbootblk.h b/usr/src/psm/stand/bootblks/obp-c/common/cbootblk.h
new file mode 100644
index 0000000000..7a0565e88c
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/obp-c/common/cbootblk.h
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ *
+ * 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 (c) 1994, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _CBOOTBLK_H
+#define _CBOOTBLK_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int openfile(char *, char *);
+extern int closefile(int);
+extern int readfile(int, char *, int);
+extern void seekfile(int, off_t);
+
+extern void exit(void);
+extern void puts(char *);
+extern int utox(char *p, u_int n);
+
+extern void fw_init(void *);
+
+extern char *getbootdevice(char *);
+
+extern int devbread(void *, void *, int, int);
+extern void *devopen(char *);
+extern int devclose(void *);
+extern void get_rootfs_start(char *device);
+extern u_int fdisk2rootfs(u_int offset);
+
+extern void bcopy(const void *, void *, size_t);
+extern void bzero(void *, size_t);
+extern int strcmp(const char *, const char *);
+extern int strncmp(const char *, const char *, size_t);
+extern size_t strlen(const char *);
+extern char *strcpy(char *, const char *);
+
+extern void main(void *);
+extern void exitto(void *, void *);
+
+extern char ident[];
+extern char fscompname[];
+extern unsigned long read_elf_file(int, char *);
+void sync_instruction_memory(caddr_t, u_int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CBOOTBLK_H */
diff --git a/usr/src/psm/stand/bootblks/obp-c/common/makevers.sh b/usr/src/psm/stand/bootblks/obp-c/common/makevers.sh
new file mode 100644
index 0000000000..4665376d29
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/obp-c/common/makevers.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+#
+# 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.
+#
+# 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 1991-2000, 2003 Sun Microsystems, Inc.
+# All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+ECHO=$1
+BOOTER=$2
+FILENAME=$3
+
+BANNER="${BOOTER} 1.0 #"
+
+test -f ${BOOTER}.version || echo 0 > ${BOOTER}.version
+read OLDVERS < ${BOOTER}.version; export OLDVERS
+VERS=`expr ${OLDVERS} + 1`
+echo $VERS > ${BOOTER}.version
+
+(
+ SCCSSTRING="@(#)${FILENAME}\tDERIVED\t%E% SMI"
+ ${ECHO} "/*" ; \
+ ${ECHO} " * This file is derived by makevers.sh" ; \
+ ${ECHO} " */\n" ; \
+ ${ECHO} "#pragma\tident\t\"${SCCSSTRING}\"\n" ; \
+ ${ECHO} "char ident[] = \"@(#)${BANNER}${VERS} %G%\\\n\";"
+) > ${FILENAME}
diff --git a/usr/src/psm/stand/bootblks/obp-c/common/mkboot.c b/usr/src/psm/stand/bootblks/obp-c/common/mkboot.c
new file mode 100644
index 0000000000..5f2f058723
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/obp-c/common/mkboot.c
@@ -0,0 +1,172 @@
+/*
+ * 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.
+ *
+ * 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 1992-1994, 2002-2003 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/exechdr.h>
+#include <sys/elf.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#define BBSIZE (15 * 512)
+
+static Elf32_Ehdr elfhdr;
+static Elf32_Phdr phdr, dphdr;
+static char buf[4096];
+
+int
+main(int argc, char **argv)
+{
+ struct exec exec;
+ int ifd, ofd;
+ int count;
+ int text_written = 0;
+ int data_written = 0;
+
+ if (argc < 3) {
+ (void) printf("usage: %s elf_file a.outfile\n", argv[0]);
+ exit(1);
+ }
+ if ((ifd = open(argv[1], O_RDONLY)) == -1) {
+ perror("open input");
+ exit(1);
+ }
+ if (read(ifd, &elfhdr, sizeof (elfhdr)) < sizeof (elfhdr)) {
+ perror("read elfhdr");
+ exit(1);
+ }
+ if ((ofd = open(argv[2], O_RDWR | O_TRUNC | O_CREAT, 0777)) == -1) {
+ perror("open aout");
+ exit(1);
+ }
+
+ if (elfhdr.e_ident[EI_MAG0] != ELFMAG0 ||
+ elfhdr.e_ident[EI_MAG1] != ELFMAG1 ||
+ elfhdr.e_ident[EI_MAG2] != ELFMAG2 ||
+ elfhdr.e_ident[EI_MAG3] != ELFMAG3) {
+ perror("elfmagic");
+ exit(1);
+ }
+ if (lseek(ifd, elfhdr.e_phoff, 0) == -1) {
+ perror("lseek");
+ exit(1);
+ }
+ if (read(ifd, &phdr, sizeof (phdr)) < sizeof (phdr)) {
+ perror("read phdr");
+ exit(1);
+ }
+ if (read(ifd, &dphdr, sizeof (dphdr)) < sizeof (dphdr)) {
+ perror("read dphdr");
+ exit(1);
+ }
+
+ /*
+ * Create an a.out header that will fool the PROM
+ */
+ bzero(&exec, sizeof (exec));
+ exec.a_toolversion = 1;
+#ifdef sparc
+ exec.a_machtype = M_SPARC;
+#else
+#error "unknown machine type!"
+#endif
+ exec.a_magic = OMAGIC;
+ exec.a_text = dphdr.p_vaddr - phdr.p_vaddr;
+ exec.a_data = dphdr.p_filesz;
+ exec.a_bss = dphdr.p_memsz - dphdr.p_filesz;
+ exec.a_entry = elfhdr.e_entry;
+
+#define text exec.a_text
+#define data exec.a_data
+#define bss exec.a_bss
+
+ if (write(ofd, &exec, sizeof (exec)) != sizeof (exec)) {
+ perror("write exec");
+ exit(1);
+ }
+
+ /*
+ * Text section
+ */
+ (void) printf("%d", text);
+ if (lseek(ifd, phdr.p_offset, 0) == -1) {
+ perror("lseek text");
+ exit(1);
+ }
+ while (text_written < text &&
+ (count = read(ifd, buf, sizeof (buf))) > 0) {
+ if (count > exec.a_text - text_written)
+ count = (exec.a_text - text_written);
+ if (write(ofd, buf, count) < count) {
+ perror("write text file");
+ exit(1);
+ }
+ text_written += count;
+ }
+ /* Include a.out header in the accounting */
+ text_written += sizeof (exec);
+
+ /*
+ * Data section
+ */
+ if (lseek(ifd, dphdr.p_offset, 0) == -1) {
+ perror("lseek data");
+ exit(1);
+ }
+ (void) printf(" + %d (%d/0x%x)", data, text+data, text+data);
+ while (data_written < data &&
+ (count = read(ifd, buf, sizeof (buf))) > 0) {
+ if (count > data - data_written)
+ count = (data - data_written);
+ if (write(ofd, buf, count) < count) {
+ perror("write data file");
+ exit(1);
+ }
+ data_written += count;
+ }
+ (void) printf(" + %d (%d/0x%x)\n", bss, text+data+bss, text+data+bss);
+ (void) close(ofd);
+ (void) close(ifd);
+
+ if (text_written + data_written > BBSIZE) {
+ (void) printf("*** WARNING! ***\n"
+ "Do not install this bootblock!\n");
+ (void) printf("bootblock image is %d bytes too big.\n",
+ (text_written + data_written) - BBSIZE);
+ exit(1);
+ }
+
+ (void) printf("bootblock %d%% full - %d bytes to spare.\n",
+ (text_written + data_written) * 100 / BBSIZE,
+ BBSIZE - (text_written + data_written));
+ return (0);
+}
diff --git a/usr/src/psm/stand/bootblks/obp-c/common/romp.h b/usr/src/psm/stand/bootblks/obp-c/common/romp.h
new file mode 100644
index 0000000000..faa6ceca4a
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/obp-c/common/romp.h
@@ -0,0 +1,226 @@
+/*
+ * 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.
+ *
+ * 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 2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_ROMP_H
+#define _SYS_ROMP_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Autoconfig operations
+ */
+
+struct config_ops {
+#ifdef _KERNEL
+ dnode_t (*devr_next)(/* dnode_t nodeid */);
+ dnode_t (*devr_child)(/* dnode_t nodeid */);
+#else /* _KERNEL */
+ int (*devr_next)(/* dnode_t nodeid */);
+ int (*devr_child)(/* dnode_t nodeid */);
+#endif /* _KERNEL */
+ int (*devr_getproplen)(/* dnode_t nodeid, char *name */);
+ int (*devr_getprop)(/* dnode_t nodeid, char *name, caddr_t buf */);
+ int (*devr_setprop)(/* dnode_t nodeid, char *name, caddr_t value,
+ uint_t size */);
+ caddr_t (*devr_nextprop)(/* dnode_t nodeid, char *previous */);
+};
+
+struct romvec_obp {
+ uint_t op_magic; /* magic mushroom */
+ uint_t op_romvec_version; /* Version number of "romvec" */
+ uint_t op_plugin_version; /* Plugin Architecture version */
+ uint_t op_mon_id; /* version # of monitor firmware */
+
+ struct memlist **v_physmemory; /* total physical memory list */
+ struct memlist **v_virtmemory; /* taken virtual memory list */
+ struct memlist **v_availmemory; /* available physical memory */
+ struct config_ops *op_config_ops; /* dev_info configuration access */
+
+ /*
+ * storage device access facilities
+ */
+ char **v_bootcmd; /* expanded with PROM defaults */
+ uint_t (*v_open)(/* char *name */);
+ uint_t (*v_close)(/* ihandle_t fileid */);
+
+ /*
+ * block-oriented device access
+ */
+ uint_t (*v_read_blocks)();
+ uint_t (*v_write_blocks)();
+
+ /*
+ * network device access
+ */
+ uint_t (*v_xmit_packet)();
+ uint_t (*v_poll_packet)();
+
+ /*
+ * byte-oriented device access
+ */
+ uint_t (*v_read_bytes)();
+ uint_t (*v_write_bytes)();
+
+ /*
+ * 'File' access - i.e., Tapes for byte devices.
+ * TFTP for network devices
+ */
+ uint_t (*v_seek)();
+
+ /*
+ * single character I/O
+ */
+ uchar_t *v_insource; /* Current source of input */
+ uchar_t *v_outsink; /* Currrent output sink */
+ uchar_t (*v_getchar)(); /* Get a character from input */
+ void (*v_putchar)(); /* Put a character to output sink. */
+ int (*v_mayget)(); /* Maybe get a character, or "-1". */
+ int (*v_mayput)(); /* Maybe put a character, or "-1". */
+
+ /*
+ * Frame buffer
+ */
+ void (*v_fwritestr)(); /* write a string to framebuffer */
+
+ /*
+ * Miscellaneous Goodies
+ */
+ void (*op_boot)(/* char *bootspec */); /* reboot machine */
+ int (*v_printf)(); /* handles fmt string plus 5 args */
+ void (*op_enter)(); /* Entry for keyboard abort. */
+ int *op_milliseconds; /* Counts in milliseconds. */
+ void (*op_exit)(); /* Exit from user program. */
+
+ /*
+ * Note: Different semantics for V0 versus other op_vector_cmd:
+ */
+ void (**op_vector_cmd)(); /* Handler for the vector */
+ void (*op_interpret)(/* char *string, ... */);
+ /* interpret forth string */
+
+ /* boot parameters and 'old' style device access */
+ struct bootparam **v_bootparam;
+
+ uint_t (*v_mac_address)(/* int fd, caddr_t buf */);
+ /* Copyout ether address */
+
+ /*
+ * new V2 openprom stuff
+ */
+
+ char **op2_bootpath; /* Full path name of boot device */
+ char **op2_bootargs; /* Boot command line after dev spec */
+
+#ifdef _KERNEL
+ ihandle_t *op2_stdin; /* Console input device */
+ ihandle_t *op2_stdout; /* Console output device */
+
+ phandle_t (*op2_phandle)(/* ihandle_t */);
+ /* Convert ihandle to phandle */
+#else /* _KERNEL */
+ int *op2_stdin; /* Console input device */
+ int *op2_stdout; /* Console output device */
+
+ int (*op2_phandle)(/* ihandle_t */);
+ /* Convert ihandle to phandle */
+#endif /* _KERNEL */
+
+ caddr_t (*op2_alloc)(/* caddr_t virthint, uint_t size */);
+ /* Allocate physical memory */
+
+ void (*op2_free)(/* caddr_t virthint, uint_t size */);
+ /* Deallocate physical memory */
+
+ caddr_t (*op2_map)(/* caddr_t virthint, uint_t space, uint_t phys,
+ uint_t size */); /* Create device mapping */
+
+ void (*op2_unmap)(/* caddr_t virt, uint_t size */);
+ /* Destroy device mapping */
+
+#ifdef _KERNEL
+ ihandle_t (*op2_open)(/* char *name */);
+#else /* _KERNEL */
+ int (*op2_open)(/* char *name */);
+#endif /* _KERNEL */
+ uint_t (*op2_close)(/* int ihandle */);
+
+ int (*op2_read)(/* int ihandle, caddr_t buf, uint_t len */);
+ int (*op2_write)(/* int ihandle, caddr_t buf, uint_t len */);
+ int (*op2_seek)(/* int ihandle, uint_t offsh, uint_t offsl */);
+
+ void (*op2_chain)(/* caddr_t virt, uint_t size, caddr_t entry,
+ caddr_t argaddr, uint_t arglen */);
+
+ void (*op2_release)(/* caddr_t virt, uint_t size */);
+
+ /*
+ * End V2 stuff
+ */
+
+ caddr_t (*op3_alloc)(/* caddr_t virthint, uint_t size, int align */);
+ /* Allocate mem and align */
+
+ int *v_reserved[14];
+
+ /*
+ * Sun4c specific romvec routines (From sys/sun4c/machine/romvec.h)
+ * Common to all PROM versions.
+ */
+
+ void (*op_setcxsegmap)(/* int ctx, caddr_t v, int pmgno */);
+ /* Set segment in any context. */
+
+ /*
+ * V3 MP only functions: It's a fatal error to call these from a UP.
+ */
+
+ int (*op3_startcpu)(/* dnode_t moduleid, dev_reg_t contextable,
+ int whichcontext, caddr_t pc */);
+
+ int (*op3_stopcpu)(/* dnode_t */);
+
+ int (*op3_idlecpu)(/* dnode_t */);
+ int (*op3_resumecpu)(/* dnode_t */);
+};
+
+union sunromvec {
+ struct romvec_obp obp;
+};
+
+extern union sunromvec *romp;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_ROMP_H */
diff --git a/usr/src/psm/stand/bootblks/obp-c/common/stub.c b/usr/src/psm/stand/bootblks/obp-c/common/stub.c
new file mode 100644
index 0000000000..13b204597b
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/obp-c/common/stub.c
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ *
+ * 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 1999, 2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Stub for deprecated OBP V0 and V2 systems (sun4c).
+ */
+
+#include <sys/param.h>
+#include <sys/promif.h>
+#include "romp.h"
+
+/*
+ * XXX Should be 'static'; 'extern' definition in header files prevent this
+ */
+union sunromvec *romp;
+
+#define OBP_V0_ROMVEC_VERSION 0
+#define OBP_ROMVEC_VERSION (romp->obp.op_romvec_version)
+#define OBP_V0_PRINTF (*romp->obp.v_printf)
+#define OBP_V2_WRITE (*romp->obp.op2_write)
+#define OBP_V2_STDOUT (*romp->obp.op2_stdout)
+#define OBP_EXIT_TO_MON (*romp->obp.op_exit)
+
+static void
+fw_init(void *ptr)
+{
+ romp = ptr;
+}
+
+void
+exit()
+{
+ OBP_EXIT_TO_MON();
+}
+
+static void
+putchar(char c)
+{
+ while (OBP_V2_WRITE(OBP_V2_STDOUT, &c, 1) != 1)
+ ;
+}
+
+static void
+puts(char *msg)
+{
+ char c;
+
+ if (OBP_ROMVEC_VERSION == OBP_V0_ROMVEC_VERSION)
+ OBP_V0_PRINTF(msg);
+ else {
+ /* prepend carriage return to linefeed */
+ while ((c = *msg++) != '\0') {
+ if (c == '\n')
+ putchar('\r');
+ putchar(c);
+ }
+ }
+}
+
+void
+main(void *ptr)
+{
+ fw_init(ptr);
+ puts("This hardware platform is not supported by this "
+ "release of Solaris.\n");
+}
+
+void
+bzero(void *p, size_t n)
+{
+ char zeero = 0;
+ char *cp = p;
+
+ while (n != 0)
+ *cp++ = zeero, n--; /* Avoid clr for 68000, still... */
+}
diff --git a/usr/src/psm/stand/bootblks/obp-c/common/unix_devio.c b/usr/src/psm/stand/bootblks/obp-c/common/unix_devio.c
new file mode 100644
index 0000000000..b1399b9ccd
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/obp-c/common/unix_devio.c
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ *
+ * 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 (c) 1991-1994, Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Emulate the firmware on Unix
+ * Only useful for testing the boot block code.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/param.h>
+
+int
+devbread(void *handle, void *buf, int blkno, int size)
+{
+ int fd = (int)handle;
+
+ if (lseek(fd, (off_t) blkno * DEV_BSIZE, SEEK_SET) == -1)
+ perror("lseek"), exit(1);
+ return (read(fd, buf, size));
+}
+
+void *
+devopen(char *devname)
+{
+ int fd;
+
+ if ((fd = open(devname, O_RDONLY)) == -1) {
+ perror(devname);
+ return (NULL);
+ }
+ return ((void *)fd);
+}
+
+int
+devclose(void *handle)
+{
+ int fd = (int)handle;
+
+ return (close(fd));
+}
+
+#define SZBUF 511 /* or 513? */
+
+static void
+usage(void)
+{
+ char mess[] = "Usage:\ta.out raw-device pathname\n";
+
+ write(2, mess, strlen(mess) + 1);
+ exit(1);
+}
+
+static void
+openfail(void)
+{
+ char mess[] = "openfile failed\n";
+
+ write(2, mess, strlen(mess) + 1);
+ exit(2);
+}
+
+extern int openfile(char *, char *);
+extern int readfile(int, char *, size_t);
+extern int closefile(int);
+
+int
+main(int argc, char *argv[])
+{
+ char buf[SZBUF];
+ int fd, count;
+
+ if (argc != 3)
+ usage();
+ if ((fd = openfile(argv[1], argv[2])) == -1)
+ openfail();
+ while ((count = readfile(fd, buf, SZBUF)) != 0)
+ write(1, buf, count);
+ (void) closefile(fd);
+ return (0);
+}
+
+/*
+ * Sigh. These shouldn't be needed.
+ */
+void
+bcopy(void *from, void *to, size_t howmany)
+{
+ (void) memcpy(to, from, howmany);
+}
+
+void
+bzero(void *addr, size_t howmany)
+{
+ (void) memset(addr, 0, howmany);
+}
diff --git a/usr/src/psm/stand/bootblks/obp-c/sparc/common/mapfile b/usr/src/psm/stand/bootblks/obp-c/sparc/common/mapfile
new file mode 100644
index 0000000000..5a96e9e689
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/obp-c/sparc/common/mapfile
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+# 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 1992 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+text = LOAD ?RX V0x4000;
+text : $PROGBITS ?A!W;
+
+data = LOAD ?RWX A0x1;
+data : $PROGBITS ?AW;
+data : $NOBITS ?AW;
+
+note = NOTE;
+note : $NOTE;
diff --git a/usr/src/psm/stand/bootblks/obp-c/sparc/common/obp_srt0.s b/usr/src/psm/stand/bootblks/obp-c/sparc/common/obp_srt0.s
new file mode 100644
index 0000000000..e2d36ca37a
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/obp-c/sparc/common/obp_srt0.s
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ *
+ * 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 (c) 1986-1994, by Sun Microsystems, Inc.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * simple standalone startup code
+ */
+
+#include <sys/asm_linkage.h>
+
+#if defined(lint)
+
+#include "cbootblk.h"
+
+/*ARGSUSED*/
+void
+start(void *romp)
+{}
+
+#else /* lint */
+
+ ENTRY(start)
+ .global end
+ .global edata
+ .global main
+ !
+ ! OBP gives us control right here ..
+ !
+ ! On entry, %o0 contains the romp.
+ !
+ sethi %hi(start), %o1 ! Top of stack
+ or %o1, %lo(start), %o1
+ save %o1, -SA(MINFRAME), %sp
+ !
+ ! zero the bss
+ !
+ sethi %hi(edata), %o0 ! Beginning of bss
+ or %o0, %lo(edata), %o0
+ sethi %hi(end), %o2 ! End of the whole wad
+ or %o2, %lo(end), %o2
+ call bzero
+ sub %o2, %o0, %o1 ! end - edata = size of bss
+ call main
+ mov %i0, %o0 ! romvec pointer
+ call exit
+ mov 0, %o0
+ ret ! ret to prom
+ restore
+ SET_SIZE(start)
+
+#endif /* lint */
diff --git a/usr/src/psm/stand/bootblks/ufs/Makefile b/usr/src/psm/stand/bootblks/ufs/Makefile
new file mode 100644
index 0000000000..bf5167906d
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/ufs/Makefile
@@ -0,0 +1,55 @@
+#
+# 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.
+#
+# 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 (c) 1989-1994,1998 by by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# psm/stand/bootblks/ufs/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:
+
+#
+# install targets
+#
+$(USR_SBIN): $(USR)
+ -$(INS.dir.root.bin)
+
+$(USR_SBIN)/%: % $(USR_SBIN)
+ $(INS.file)
diff --git a/usr/src/psm/stand/bootblks/ufs/Makefile.ufs b/usr/src/psm/stand/bootblks/ufs/Makefile.ufs
new file mode 100644
index 0000000000..31c97a8635
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/ufs/Makefile.ufs
@@ -0,0 +1,58 @@
+#
+# 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.
+#
+# 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 (c) 1994, by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# psm/stand/bootblks/ufs/Makefile.ufs
+#
+
+include $(BASEDIR)/Makefile.com
+include $(BASEDIR)/ufs/common/Makefile.com
+
+#
+# This program is used to install the boot block
+#
+INSTALLBOOT = installboot
+
+#
+# Where and how stuff gets installed
+#
+USR_PSM_BOOTBLOCK = $(USR_PSM_LIB_UFS_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) $<
+
+#
+# install rules
+#
+$(USR_SBIN)/%: % $(USR_SBIN)
+ $(INS.file.555)
diff --git a/usr/src/psm/stand/bootblks/ufs/common/Makefile.com b/usr/src/psm/stand/bootblks/ufs/common/Makefile.com
new file mode 100644
index 0000000000..b759d5cf8f
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/ufs/common/Makefile.com
@@ -0,0 +1,55 @@
+#
+# 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.
+#
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# psm/stand/bootblks/ufs/common/Makefile.com
+#
+
+THISDIR = $(BASEDIR)/ufs/common
+
+#
+# Files that define the fs-reading capabilities of the C-based boot block
+#
+FS_C_SRCS = ufs.c
+
+#
+# Allow ufs-specific files to find ufs-specific include files
+#
+$(FS_C_SRCS:%.c=%.o) := CPPINCS += -I$(THISDIR)
+
+#
+# Pattern-matching rules for source in this directory
+#
+%.o: $(THISDIR)/%.c
+ $(COMPILE.c) -o $@ $<
+
+%.ln: $(THISDIR)/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+
+%.fcode: $(THISDIR)/%.fth
+ sed 's/sun4u/$(PLATFORM)/g' $< >$(<F)
+ $(TOKENIZE) $(<F)
+ @$(RM) -f $(<F)
diff --git a/usr/src/psm/stand/bootblks/ufs/common/boot_1275.fth b/usr/src/psm/stand/bootblks/ufs/common/boot_1275.fth
new file mode 100644
index 0000000000..8d0fe85209
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/ufs/common/boot_1275.fth
@@ -0,0 +1,898 @@
+\ ident "%Z%%M% %I% %E% SMI"
+\ Copyright 2005 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.
+\
+\ 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: @(#)ufs.fth 1.4 95/08/04
+purpose: UFS file system support package
+copyright: Copyright 1995 Sun Microsystems, Inc. All Rights Reserved
+
+headers
+" /packages" find-package 0= if
+ ." Can't find /packages" abort
+then push-package
+new-device
+ diagnostic-mode? if ." Loading " then
+ " ufs-file-system" device-name
+ diagnostic-mode? if
+ ." package 1.4 04 Aug 1995 13:02:54. " cr
+ then
+
+ 0 0 " support" property
+
+ : 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 cmove ( adr,len1 adr,len2 )
+ rot + ca+ 0 swap c! drop ( )
+ ;
+
+ : $= ( str1$ str2$ -- same? )
+ rot tuck <> if
+ 3drop false exit
+ then comp 0=
+ ;
+
+ " /openprom/client-services" find-package 0= if
+ ." Can't find client-services" abort
+ then constant cif-phandle
+
+ instance defer cif-claim ( align size virt -- base )
+ instance defer cif-release ( size virt -- )
+
+ : find-cif-method ( adr,len -- acf )
+ cif-phandle find-method drop
+ ;
+
+ " claim" find-cif-method to cif-claim
+ " release" find-cif-method to cif-release
+
+ : ufs-alloc-mem ( size -- virt ) 1 swap 0 cif-claim ;
+ : ufs-free-mem ( virt size -- ) swap cif-release ;
+
+ \
+ \ UFS low-level block routines
+ \
+
+ d# 512 constant ublock
+ d# 512 constant /super-block
+ d# 8 constant ndaddr
+ d# 16 constant super-block# ( -- n )
+
+ 0 instance value temp-block
+ 0 instance value indirect-block
+ 0 instance value indirect1-block
+ 0 instance value inode
+ 0 instance value super-block
+
+
+ \ Deblocker needs following
+
+ \ read-blocks ( adr #blocks block# -- #blocks-read )
+ \ write-blocks ( adr #blocks block# -- #blocks-written )
+
+ : quad@ ( adr -- l )
+ \ For little-endian machines
+ \ l@
+ \ For big-endian machines
+ la1+ l@
+ ;
+
+ : +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 ;
+
+
+ : read-ublocks ( adr len dev-block# -- error? )
+ ublock * 0 " seek" $call-parent ?dup if exit then
+ ( adr len ) tuck " read" $call-parent <>
+ ;
+ : get-super-block ( -- error? )
+ super-block /super-block super-block# read-ublocks
+ ;
+
+ : cgstart ( cg -- block# )
+ dup cgmask invert and cgoffset * swap fpg * +
+ ;
+ : cgimin ( cg -- block# ) cgstart iblkno + ;
+
+ : blkstofrags ( #blocks -- #frags ) fragshift lshift ;
+
+ : fsbtodb ( fs-blk# -- dev-blk# ) fsbtodbc lshift ;
+
+ : read-fs-blocks ( adr len fs-blk# -- error? ) fsbtodb read-ublocks ;
+
+ \
+ \ UFS inode routines
+ \
+
+ h# 80 constant /inode
+
+ instance variable blkptr
+ instance variable blklim
+ instance variable indirptr
+ instance variable indir1ptr
+ 0 instance value lblk#
+
+ : itoo ( i# -- offset ) inopb mod ;
+ : itog ( i# -- group ) ipg / ;
+ : itod ( i# -- block# )
+ dup itog cgimin swap ipg mod inopb / blkstofrags +
+ ;
+
+ : +i ( n -- ) inode + ;
+
+ : 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 quad@ ;
+ : direct0 ( -- adr ) d# 40 +i ;
+ : indirect0 ( -- adr ) d# 88 +i ;
+ \ : indirect1 ( -- adr ) d# 92 +i ;
+
+ \ **** Select the indicated file for subsequent accesses
+ : rewind ( -- )
+ direct0 blkptr ! indirect0 blklim ! indirect0 indirptr !
+ 0 to lblk#
+ ;
+
+ 0 instance value current-file
+ : select-file ( i# -- error? )
+ dup to current-file
+ dup temp-block bsize rot itod
+ read-fs-blocks ?dup if exit then
+ itoo /inode * temp-block + inode /inode move
+ rewind
+ false
+ ;
+
+ : l@++ ( ptr -- value ) dup @ l@ /l rot +! ;
+
+ \ **** Locate the next block within the current file
+ : next-block# ( -- [ n ] error? )
+ blkptr @ blklim @ = if
+ indirptr @ indirect0 = if
+ indirect-block bsize indirptr l@++ ( adr,len )
+ read-fs-blocks if true exit then
+ indirect-block blkptr ! indirect-block bsize + blklim !
+
+ indirect1-block bsize indirptr l@++ ( adr,len )
+ read-fs-blocks if true exit then
+ indirect1-block indir1ptr !
+ else
+ indirect-block bsize indir1ptr l@++ ( adr,len )
+ read-fs-blocks if true exit then
+ indirect-block blkptr ! indirect-block bsize + blklim !
+ then
+ then
+ lblk# 1+ to lblk#
+ blkptr l@++ ( blk# ) ?dup 0=
+ ;
+
+ : block#>fs-block# ( lblk# -- [ n ] error? )
+ dup lblk# < if rewind then ( target-blk# )
+ begin dup lblk# <> while ( target-blk# )
+ next-block# if ( target-blk# )
+ drop true exit
+ else ( target-blk# blk# )
+ drop ( target-blk# )
+ then ( target-blk# )
+ repeat drop next-block# ( [ n ] error? )
+ ;
+
+ : read-one-block ( adr block# -- error? )
+ block#>fs-block# ?dup if drop exit then
+ bsize swap read-fs-blocks
+ ;
+
+ : get-dirblk ( -- error? )
+ temp-block bsize next-block# 0= if
+ read-fs-blocks
+ else
+ 2drop true
+ then
+ ;
+
+ \
+ \ UFS directory routines
+ \
+
+ instance variable diroff
+ instance variable totoff
+
+ 0 instance value current-dir
+
+ \ **** Select the directory file
+ : init-dir ( i# -- error? )
+ dup to current-dir
+ select-file ?dup if exit then
+ get-dirblk ?dup if exit then
+ 0 diroff ! 0 totoff !
+ false
+ ;
+
+ : root-dir? ( -- flag ) current-dir 2 = ;
+
+ \ **** Return the address of the current directory entry
+ : dirent ( -- adr ) temp-block diroff @ + ;
+
+ \ **** Select the next directory entry
+ : next-dirent ( -- end? )
+ dirent la1+ w@ dup diroff +! totoff +!
+ totoff @ file-size >= if true exit then
+ diroff @ bsize = if
+ get-dirblk ?dup if exit then
+ diroff off
+ then
+ false
+ ;
+
+ \ **** From directory, get handle of the file or subdir that it references
+ \ For Unix, file handle is the inode #
+ : file-handle ( -- i# ) dirent l@ ;
+
+ \ **** From directory, get name of file
+ : file-name ( -- adr len ) dirent la1+ wa1+ dup wa1+ swap w@ ;
+
+ \ **** Select the root directory
+ : froot ( -- error? ) 2 init-dir ;
+
+ \
+ \ UFS high-level routines
+ \
+ \ After this point, the code should be independent of the disk format!
+
+ : lookup ( adr len -- i# false | true )
+ begin
+ 2dup file-name $= if ( adr,len )
+ 2drop file-handle ( i# )
+ dup select-file ?dup if ( i# true )
+ nip ( true )
+ else ( i# )
+ false ( i# false )
+ then exit
+ then ( adr,len )
+ next-dirent ( adr,len end? )
+ until 2drop true ( true )
+ ;
+
+
+ h# 200 instance buffer: fpath-buf
+
+ : follow-symlink ( tail$ -- tail$" )
+ temp-block 0 read-one-block if 2drop exit then ( tail-$ )
+ temp-block cscount ( tail-$ head-$' )
+ fpath-buf 0 $append ( $tail-$ )
+ ?dup if ( $tail-$ )
+ " /" fpath-buf cscount $append ( $tail-$ )
+ fpath-buf cscount $append ( )
+ else drop then ( )
+ fpath-buf cscount ( tail-$' )
+ over c@ ascii / = if ( path$ )
+ froot if 2drop true exit then ( \path$ )
+ ascii / left-parse-string 2drop ( path$ )
+ else ( path$ )
+ current-dir init-dir if 2drop true exit then ( tail-$ )
+ then
+ ;
+
+ : ($chdir ( adr len -- error? ) \ Fail if path is file, not dir
+ ?dup 0= if drop true exit then
+ over c@ ascii / = if ( path$ )
+ froot if 2drop true exit then ( \path$ )
+ ascii / left-parse-string 2drop ( path$ )
+ else ( path$ )
+ current-dir init-dir drop ( path$ )
+ then ( path$ )
+ begin ( path-$ )
+ ascii / left-parse-string ( tail-$ head-$ )
+ dup
+ while ( tail-$ head-$ )
+ lookup if 2drop true exit then ( tail-$ i# )
+ symlink? if ( tail-$ i# )
+ drop follow-symlink ( tail-$' )
+ else ( tail-$ i# )
+ dir? 0= if 2drop drop true exit then ( tail-$ i# )
+ init-dir if 2drop true exit then ( tail$ )
+ then ( tail$ )
+ repeat ( tail-$ head-$ )
+ 2drop 2drop false
+ ;
+
+ : $chdir ( dirpath$ -- error? )
+ current-dir >r ($chdir if ( ) ( r: prev-dir )
+ r> init-dir drop true ( error )
+ else ( ) ( r: prev-dir )
+ r> drop false ( ok )
+ then ( error? )
+ ;
+
+ : .dirname ( inode# -- )
+ begin ( inode# )
+ file-handle over = if ( inode# )
+ ." /" ( inode# )
+ file-name type true ( inode# done )
+ else ( inode# )
+ false ( inode# done? )
+ then ( inode# done? )
+ next-dirent or ( inode# done? )
+ until drop ( )
+ ;
+
+ \
+ \ UFS installation routines
+ \
+
+ \ **** Allocate memory for necessary data structures
+ : allocate-ufs-buffers ( -- error? )
+ /super-block ufs-alloc-mem to super-block
+ get-super-block ?dup if
+ ." failed to read super block" cr
+ super-block /super-block ufs-free-mem true exit
+ then
+ bsize ufs-alloc-mem to temp-block
+ bsize ufs-alloc-mem to indirect-block
+ bsize ufs-alloc-mem to indirect1-block
+ /inode ufs-alloc-mem to inode
+ false
+ ;
+
+ : release ( -- )
+ inode /inode ufs-free-mem
+ indirect-block bsize ufs-free-mem
+ indirect1-block bsize ufs-free-mem
+ temp-block bsize ufs-free-mem
+ super-block /super-block ufs-free-mem
+ ;
+
+ false instance value file-open?
+
+ \ UFS file interface
+
+ 0 instance value deblocker
+ : init-deblocker ( -- okay? )
+ " " " deblocker" $open-package to deblocker
+ deblocker if
+ true
+ else
+ ." Can't open deblocker package" cr false
+ then
+ ;
+
+ \ Splits a string into two halves after the last occurrence of
+ \ a delimiter character.
+ \ adra,lena is the string after the delimiter
+ \ adrb,lenb is the string before and including the delimiter
+ \ lena = 0 if there was no delimiter
+
+ \ adra,lena is the string after the delimiter
+ \ adrb,lenb is the string before and including the delimiter
+ \ lena = 0 if there was no delimiter
+
+ : right-parse-string ( adr len char -- adra lena adrb lenb )
+ >r 2dup + 0 ( adrb lenb adra 0 )
+
+ \ Throughout the loop, we maintain both substrings.
+ \ Each time through, we add a character to the "after"
+ \ string and remove it from the "before".
+ \ The loop terminates when either the "before" string
+ \ is empty or the desired character is found
+
+ begin 2 pick while ( adrb lenb adra lena )
+ over 1- c@ r@ = if \ Found it ( adrb lenb adra lena )
+ r> drop 2swap exit ( adrb lenb adra lena )
+ then
+ 2swap 1- 2swap swap 1- swap 1+ ( adrb lenb adra lena )
+ repeat ( adrb lenb adr1 len1 )
+
+ dup if ( adrb lenb adr1 len1 )
+ 2swap dup if 1- then ( adr1 len1 adrb lenb' )
+ else ( adrb lenb adr1 len1 )
+ 2swap ( adr1 len1 adrb lenb )
+ then ( adra lena adrb lenb )
+
+ \ Character not found. lena is 0.
+ r> drop
+ ;
+
+ h# 200 instance buffer: fpath1-buf
+
+ : file-lookup ( fname$ -- i# false | true )
+ begin lookup 0= while ( i# )
+ dup select-file if drop true exit then ( i# )
+ symlink? if ( i# )
+ drop 0 0 follow-symlink ( path$/file$ )
+ fpath1-buf 0 $append fpath1-buf cscount ( path$/file$ )
+ ascii / right-parse-string ( file$ path$ )
+ ?dup if ( file$ path$ )
+ $chdir if 2drop true exit then else drop
+ then ( file$ )
+ else false exit then ( file$ )
+ current-dir init-dir if 2drop true exit then ( file$ )
+ repeat true ( true )
+ ;
+
+ : ufs-open ( adr len -- success? )
+ file-lookup if ( )
+ false ( fail )
+ else ( i# )
+ select-file if ( )
+ false ( fail )
+ else ( )
+ init-deblocker ( success? )
+ then ( success? )
+ then ( success? )
+ ;
+
+ : (cwd) ( -- ) tokenizer[ reveal ]tokenizer
+ root-dir? 0= if
+ current-dir " .." $chdir drop
+ (cwd) dup .dirname init-dir drop
+ then
+ ;
+
+ h# 100 instance buffer: ufs-args
+
+ : get-my-args ( -- adr,len )
+ my-args ?dup if ( arg$ )
+ ufs-args pack count bounds ?do
+ i c@ ascii | = if ascii / i c! then
+ i c@ ascii \ = if ascii / i c! then
+ loop
+ else
+ drop 0 ufs-args c!
+ then ufs-args count
+ ;
+ : ufs-args$ ( -- arg$ ) ufs-args count ;
+
+ 0 instance value file-offset
+
+ external
+ : block-size ( -- #bytes/block ) bsize ;
+ : max-transfer ( -- #bytes/block ) block-size 4 * ;
+
+ : dma-alloc ( size -- virt ) " dma-alloc" $call-parent ;
+ : dma-free ( virt size -- ) " dma-free" $call-parent ;
+
+ : read-blocks ( adr block# #blocks -- #read )
+ 0 -rot bounds ?do ( adr block-count )
+ over i read-one-block ?leave ( adr count )
+ 1+ swap bsize ca+ swap ( adr' count+1 )
+ loop nip
+ ;
+
+ \ UFS Write is not supported
+ : write-blocks ( adr #blocks block# -- #blocks-written ) 3drop 0 ;
+
+ : open ( -- okay? )
+ allocate-ufs-buffers if false exit then
+
+ \ Select the root directory
+ froot drop
+
+ get-my-args " <NoFile>" $= if true exit then
+
+ ufs-args$ ascii / right-parse-string ( file$ path$ )
+ $chdir if 2drop release false exit then ( file$ )
+
+ \ Filename ends in "/"; select the directory and exit with success
+ dup 0= if 2drop true exit then ( file$ )
+
+ ufs-open ?dup if exit then ( failed? )
+
+ release false
+ ;
+
+ : close ( -- )
+ deblocker ?dup if close-package then
+ release
+ ;
+
+ : read ( addr len -- actual-len )
+ " read" deblocker $call-method dup if ( #bytes-read )
+ dup file-offset + file-size > if ( #bytes-read )
+ drop file-size file-offset - ( #bytes-left )
+ then ( #bytes-read )
+ then ( #bytes-read )
+ dup file-offset + to file-offset ( actual-len )
+ ;
+
+ \ UFS Write is not supported
+ : write ( addr len -- actual-len ) 2drop 0 ;
+
+ : size ( -- d ) file-size 0 ;
+
+
+ : seek ( offset.low offset.high -- failed? )
+
+ \ Return error if offset.hi != 0
+ dup 0<> if 2drop true exit then ( offset.lo offset.hi )
+
+ \ Return error if offset.lo > file-size
+ over file-size > if 2drop true exit then ( offset.lo offset.hi )
+
+ \ Looks like a reasonable offset
+ over to file-offset ( offset.lo offset.hi )
+
+ \ Finally give the deblocker chance to adjust
+ " seek" deblocker $call-method ( offset.lo offset.hi failed? )
+ ;
+ : load ( adr -- size ) file-size read ;
+
+ headers
+ : restore-file ( i# -- )
+ ?dup if
+ select-file 0= if regular? if file-offset 0 seek drop then then
+ then
+ ;
+ external
+ : dir ( -- )
+ current-file
+ current-dir init-dir drop
+ begin file-name type cr next-dirent until
+ restore-file
+ ;
+ : cwd ( -- )
+ current-file
+ root-dir? if ." /" else (cwd) then
+ restore-file
+ ;
+
+ headers
+
+finish-device
+pop-package
+
+id: @(#)boot.fth 1.6 95/08/04
+purpose: UFS File System Boot Block
+copyright: Copyright 1995 Sun Microsystems, Inc. All Rights Reserved
+
+headers
+" /packages/disk-label" find-package 0= if
+ ." Can't find /packages/disk-label" abort
+then dup push-package ( phandle )
+
+\ Find the previous "open" definition.
+defer prev-open ( -- ok? )
+' false to prev-open
+" open" rot find-method if to prev-open then
+
+external
+: open ( -- okay? )
+ \ Arg string is <part>[,<filespec>]
+ \ Split off partition, and handle filename
+ my-args ascii , left-parse-string ( file$ part$ )
+ 2drop ?dup if ( file$ )
+ " ufs-file-system" find-package if ( file$ phandle )
+ interpose ( )
+ else ( file$ )
+ 2drop ( )
+ then ( )
+ else ( file )
+ drop ( )
+ then prev-open ( okay? )
+;
+headers
+
+pop-package
+
+headers
+" /chosen" find-package 0= if false then ( phandle )
+constant chosen-phandle
+
+" /openprom/client-services" find-package 0= if false then ( phandle )
+constant cif-phandle
+
+defer cif-claim ( align size virt -- base )
+defer cif-release ( size virt -- )
+defer cif-open ( cstr -- ihandle|0 )
+defer cif-close ( ihandle -- )
+defer cif-read ( len adr ihandle -- #read )
+defer cif-seek ( low high ihandle -- -1|0|1 )
+defer cif-peer ( phandle -- phandle )
+defer cif-getprop ( len adr cstr phandle -- )
+
+: find-cif-method ( adr,len -- acf )
+ cif-phandle find-method drop
+;
+
+" claim" find-cif-method to cif-claim
+" release" find-cif-method to cif-release
+" 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
+" peer" find-cif-method to cif-peer
+" getprop" find-cif-method to cif-getprop
+
+
+d# 256 constant /devname-buf
+/devname-buf buffer: devname
+: clear-devname-buf ( -- )
+ devname /devname-buf 0 fill
+;
+
+: devname$ ( -- adr,len ) devname cscount ;
+
+: chosen-property ( name$ -- value$ false -or- true )
+ chosen-phandle get-package-property if true
+ else
+ decode-string 2swap 2drop false
+ then
+;
+: get-devname ( -- )
+ clear-devname-buf
+ " bootpath" chosen-property if ( )
+ ." Can't find bootpath" abort ( )
+ then devname$ $append ( )
+;
+
+get-devname \ Initialize the device name buffer
+
+: bootargs ( -- adr,len )
+ " bootargs" chosen-property if
+ ." Can't find bootargs" abort
+ then
+;
+
+: 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
+;
+
+: -leading ( adr len -- adr' len' )
+ begin dup while ( adr' len' )
+ over c@ white-space? 0= if exit then
+ swap 1+ swap 1-
+ repeat
+;
+
+: -trailing (s adr len -- adr len' )
+ dup 0 ?do 2dup + 1- c@ white-space? 0= ?leave 1- loop
+;
+: strip-blanks ( adr,len -- adr,len' ) -trailing -leading ;
+
+: (option?) ( char -- rem$ true -or- false )
+ >r bootargs begin strip-blanks ?dup while ( $r )
+ bl left-parse-string r@ -rot ( $r char $l )
+ strip-blanks ?dup if ( $r char $l )
+ over dup c@ ascii - = if ( $r char $l adr )
+ 1+ c@ ascii - = if ( $r char $l )
+ 2drop r> 2drop 2drop false exit
+ then ( $r char $l )
+ bounds 0 -rot ?do ( $r char flag )
+ over i c@ = or ( $r char flag )
+ loop nip if r> drop true exit then
+ else ( $r char $l adr )
+ 2drop 2drop ( $r )
+ then ( $r )
+ else ( $r char adr )
+ 2drop ( $r )
+ then ( $r )
+ repeat r> 2drop false ( false )
+;
+: option? ( char -- flag )
+ (option?) if 2drop true else false then
+;
+
+\ : don't-boot? ( -- flag ) ascii L option? ;
+: halt? ( -- flag ) ascii H option? ;
+
+: alternate-booter? ( -- fname true -or- false )
+ ascii F (option?) if ( adr,len )
+ strip-blanks ( adr,len' )
+ bl left-parse-string 2swap 2drop ?dup if ( fname$ )
+ true exit
+ then drop ( )
+ then false ( false )
+;
+
+d# 256 constant /booter-name
+/booter-name buffer: booter-name
+: booter-name$ ( -- adr,len ) booter-name cscount ;
+: clear-booter-name ( -- ) booter-name /booter-name 0 fill ;
+: $cat-booter-name ( adr,len -- ) booter-name$ $append ;
+
+d# 256 constant /root-name
+/root-name buffer: root-name
+: root-name$ ( -- adr,len ) root-name cscount ;
+: clear-root-name ( -- ) root-name /root-name 0 fill ;
+
+: root$ ( -- adr,len )
+ clear-root-name ( )
+ /root-name root-name ( len,adr )
+ " name" drop ( len,adr cstr )
+ 0 cif-peer ( len,adr cstr root )
+ cif-getprop drop ( )
+ " /" root-name$ $append ( )
+ root-name$ ( rootname$ )
+;
+
+: plat-booter$ ( -- adr,len )
+ clear-booter-name ( )
+ alternate-booter? 0= if ( )
+ " ufsboot" ( filename$ )
+ then ( filename$ )
+ over c@ ascii / <> if ( filename$ )
+ " /platform/" $cat-booter-name ( filename$ )
+ root$ $cat-booter-name ( filename$ )
+ then $cat-booter-name booter-name$ ( booter$ )
+;
+
+: def-dirname$ ( -- dir$ ) " /platform/sun4u/" ;
+
+: def-booter$ ( -- adr,len )
+ clear-booter-name ( )
+ alternate-booter? 0= if ( )
+ " ufsboot" ( filename$ )
+ then ( filename$ )
+ over c@ ascii / <> if ( filename$ )
+ def-dirname$ $cat-booter-name ( filename$ )
+ then $cat-booter-name booter-name$ ( booter$ )
+;
+
+d# 256 constant /filename-buf
+/filename-buf buffer: filename-buf
+: filename-buf$ ( -- adr,len ) filename-buf cscount ;
+: clear-filename-buf ( -- ) filename-buf /filename-buf 0 fill ;
+: $cat-filename ( adr,len -- ) filename-buf$ $append ;
+
+h# 10.0000 constant 1meg
+
+: ufs-fopen ( adr,len -- ihandle|0 ) drop cif-open ;
+: ufs-fread ( buf,len ihandle -- #read ) >r swap r> cif-read ;
+: ufs-fclose ( ihandle -- ) cif-close ;
+
+: fname>devname$ ( fname$ -- dev$ )
+ clear-filename-buf ( fname$ )
+ devname$ tuck $cat-filename ( fname$ len )
+ " ," $cat-filename ( fname$ len )
+ >r $cat-filename r> ( len )
+ filename-buf$ rot ?do ( bufadr )
+ dup i ca+ c@ ascii / = if ( bufadr )
+ ascii | over i ca+ c! ( bufadr )
+ then ( bufadr )
+ loop drop filename-buf$ ( dev$ )
+;
+
+: set-file-size ( ihandle -- )
+ " size" rot $call-method ( size.lo size.hi )
+ drop " to file-size" evaluate
+;
+
+h# 6000 constant loader-base
+
+: get-file ( adr fname$ -- fail? )
+ fname>devname$ ufs-fopen ?dup if ( adr ihandle )
+ dup set-file-size ( adr ihandle )
+ over to loader-base ( adr ihandle )
+ >r begin ( adr )
+ dup 1meg r@ ufs-fread ( adr #read )
+ ?dup while ( adr #read )
+ ca+ ( adr" )
+ repeat drop r> ufs-fclose false ( ok )
+ else ( adr )
+ drop true ( failed )
+ then ( failed? )
+;
+
+: get-redirect-info ( -- partition true -or- false )
+ loader-base " /.SUNW-boot-redirect" get-file if ( )
+ false ( false )
+ else ( adr )
+ loader-base c@ ( part )
+ dup ascii 0 ascii 9 between if ( part )
+ diagnostic-mode? if ( part )
+ ." Redirected to slice: " dup emit cr
+ then ( part )
+ ascii 0 - ascii a + true ( part' true )
+ else ( part )
+ drop false ( false )
+ then ( part true | false )
+ then ( part true | false )
+;
+
+: update-devname ( part -- )
+ clear-devname-buf ( part )
+ get-devname devname$ ( part adr,len )
+
+ ca+ 1- dup 1- c@ ascii : = if ( part adr:x )
+ c! ( )
+ else ( part adr:x )
+ 2drop ( )
+ then ( )
+;
+
+: real-devname ( -- )
+ get-redirect-info if ( part )
+ update-devname ( )
+ then ( )
+;
+
+: allocate-memory ( size -- virtual ) 1 swap 0 cif-claim ;
+: free-memory ( virt size -- ) swap cif-release ;
+
+: sign-on ( -- )
+ diagnostic-mode? if
+ ." FCode UFS Reader %I% %E% %U%. " cr
+ then
+;
+
+: check-elf ( vadr -- flag ) l@ h# 7f454c46 ( \x7fELF ) = ;
+
+: force? ( -- flag ) ascii X option? ;
+
+: execit ( -- )
+ \ we rely on the prom to do the right thing with the executable, since
+ \ it understands ELF32 and ELF64
+ loader-base dup check-elf force? or if
+ " to load-base init-program" evaluate
+ else
+ drop ." Not a valid ELF file" cr exit
+ then
+;
+
+: do-boot ( -- )
+ sign-on real-devname
+\ don't-boot? if exit then
+ halt? if
+ ." Halted with -H flag. " cr
+ exit
+ then
+ loader-base plat-booter$ ( adr,len )
+ diagnostic-mode? if ." Loading: " 2dup type cr then
+ get-file if
+ loader-base def-booter$
+ diagnostic-mode? if ." Loading: " 2dup type cr then
+ get-file if
+ ." Boot load failed." cr exit
+ then
+ then
+ execit
+;
+
+do-boot
diff --git a/usr/src/psm/stand/bootblks/ufs/common/boot_obp.fth b/usr/src/psm/stand/bootblks/ufs/common/boot_obp.fth
new file mode 100644
index 0000000000..9714b61f56
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/ufs/common/boot_obp.fth
@@ -0,0 +1,463 @@
+\
+\ 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.
+\
+\ 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 2000 Sun Microsystems, Inc. All rights reserved.
+\ Use is subject to license terms.
+\
+\ ident "%Z%%M% %I% %E% SMI"
+\
+\ Unix 4.2 file system reader
+\
+
+\ When debugging, the sign on banner is on the stack
+\ #ifdef DEBUG_BOOTBLK
+\ type
+\ #endif /* DEBUG_BOOTBLK */
+
+decimal
+headerless
+
+\
+\ Forth utility routines
+\
+\ : $find 2dup type cr $find ;
+
+: boot-eval ( adr len -- )
+ $find if
+ execute
+ else
+ type ." ?" cr exit
+ then
+;
+
+\ " romvec" boot-eval constant romvec
+variable boot-romvec
+
+: find-romvec
+ " romvec" $find if
+ execute
+ else
+ 2drop h# ffe8.0010
+ then
+ boot-romvec !
+;
+
+find-romvec
+
+: roment ( offset -- adr ) boot-romvec @ + l@ ;
+
+" load-base" $find drop constant 'loadbase
+\ " (is" $find drop constant '(is
+\ " $=" $find drop constant '$=
+" call" $find drop constant 'call
+
+: loadbase ( -- adr ) 'loadbase execute ;
+\ : (is ( val acf -- ) '(is execute ;
+\ : $= ( str1 str2 -- [ -1 | 0 | 1 ] ) '$= execute ;
+: call ( ... addr -- ??? ) 'call execute ;
+: loadbase! ( value -- ) 'loadbase " (is" boot-eval ;
+
+: devr_next ( nodeid -- next-nodeid ) h# 1c roment l@ call nip ;
+: devr_getprop ( adr namecstr nodeid -- len|-1 ) h# 1c roment 3 la+ l@ call nip nip nip ;
+
+: boot-/string ( adr len size -- adr+size len-size ) tuck - >r + r> ;
+
+\ Splits a string around a delimiter. If the delimiter is found,
+\ two strings are returned under true, otherwise one string under false.
+: boot-$split ( adr len char -- remaining-adr len [ initial-adr len ] found? )
+ 2 pick 2 pick bounds ?do
+ dup i c@ = if i nip -1 then
+ loop ( adr len adr' -1 | char )
+ -1 = if ( adr len adr' )
+ swap >r ( adr adr' ) ( r: len )
+ 2dup swap - swap ( adr [adr'-adr] adr' ) ( r: len )
+ 1+ r> ( adr [adr'-adr] adr'+1 len )
+ 2 pick - 1- ( adr [adr'-adr] adr'+1 len-[adr'-adr-1] )
+ 2swap true ( rem-adr,len initial-adr,len true )
+ else
+ false
+ then
+;
+
+\
+\ Device and driver section
+\
+
+512 constant ublock
+
+variable devid
+variable nextblock \ holds seek target for V1 read-blocks
+
+: devname ( -- cstr )
+ h# 88 roment @ \ bootpath
+;
+
+\ Debug V2 or later PROMs
+\ : devname " disk" drop ;
+
+
+\ Debug V0 PROMS
+\ : devname " sd(0,0,0)" drop ;
+
+: open-disk ( -- error? )
+ devname
+ " op-open"
+ boot-eval dup if
+ dup devid !
+ then
+ 0= ( invert sense of error flag )
+;
+
+: close-disk ( -- )
+ devid @ " op-close" boot-eval drop
+;
+
+: read-blks ( adr len -- error? )
+ ( len adr devid -- #bytes_read )
+ tuck swap devid @ " op-read" boot-eval <>
+;
+
+: seek ( low high -- error? )
+ ( low high devid -- ? )
+ devid @ " op-seek" boot-eval 0<
+;
+
+\
+\ UFS low-level block routines
+\
+
+512 constant /super-block
+8 constant ndaddr
+16 constant super-block# ( -- n )
+
+0 constant temp-block
+0 constant indirect-block
+0 constant inode
+0 constant super-block
+
+: quad@ ( adr -- l )
+\ For little-endian machines
+\ l@
+\ For big-endian machines
+ la1+ l@
+;
+
+: +sb ( index -- value ) super-block swap la+ l@ ;
+: iblkno ( -- n ) 4 +sb ;
+: cgoffset ( -- n ) 6 +sb ;
+: cgmask ( -- n ) 7 +sb ;
+: bsize ( -- n ) 12 +sb ;
+: fragshift ( -- n ) 24 +sb ;
+: fsbtodbc ( -- n ) 25 +sb ;
+: inopb ( -- n ) 30 +sb ;
+: ipg ( -- n ) 46 +sb ;
+: fpg ( -- n ) 47 +sb ;
+
+: read-ublocks ( adr len dev-block# -- error? )
+ ublock * 0 seek ?dup if exit then
+ ( adr len ) read-blks
+;
+
+: get-super-block ( -- error? )
+ super-block /super-block super-block# read-ublocks
+;
+
+: cgstart ( cg -- block# )
+ dup cgmask not and cgoffset * swap fpg * +
+;
+: cgimin ( cg -- block# ) cgstart iblkno + ;
+
+: blkstofrags ( #blocks -- #frags ) fragshift << ;
+
+: fsbtodb ( fs-blk# -- dev-blk# ) fsbtodbc << ;
+
+: read-fs-blocks ( adr len fs-blk# -- error? ) fsbtodb read-ublocks ;
+
+\
+\ UFS inode routines
+\
+
+h# 80 constant /inode
+
+variable blkptr
+variable blklim
+variable indirptr
+
+: itoo ( n -- offset ) inopb mod ;
+: itog ( n -- group ) ipg / ;
+: itod ( n -- block# )
+ dup itog cgimin swap ipg mod inopb / blkstofrags +
+;
+
+: +i ( n -- ) inode + ;
+: dir? ( -- flag ) 0 +i w@ h# 4000 and 0<> ; \ ****
+: filesize ( -- n ) 8 +i quad@ ; \ ****
+: direct0 ( -- adr ) 40 +i ;
+: indirect0 ( -- adr ) 88 +i ;
+
+\ **** Select the indicated file for subsequent accesses
+: select-file ( file-handle -- error? )
+ dup temp-block bsize rot itod
+ read-fs-blocks ?dup if exit then
+ itoo /inode * temp-block + inode /inode move
+ direct0 blkptr ! indirect0 blklim ! indirect0 indirptr !
+ false
+;
+
+: l@++ ( ptr -- value ) dup @ l@ /l rot +! ;
+
+\ **** Locate the next block within the current file
+: next-block# ( -- n )
+ blkptr @ blklim @ = if
+ indirect-block bsize indirptr l@++
+ read-fs-blocks drop ( XXX - what about the error? )
+ indirect-block blkptr ! indirect-block bsize + blklim !
+ then
+ blkptr l@++ ( blk# )
+;
+: get-dirblk ( -- error? ) temp-block bsize next-block# read-fs-blocks ;
+
+\
+\ UFS directory routines
+\
+
+variable diroff
+variable totoff
+variable current-dir
+
+\ **** Select the directory file
+: init-dir ( file-handle -- error? )
+ dup current-dir !
+ select-file ?dup if exit then
+ get-dirblk ?dup if exit then
+ 0 diroff ! 0 totoff !
+ false
+;
+
+\ **** Return the address of the current directory entry
+: dirent ( -- adr ) temp-block diroff @ + ;
+
+\ **** Select the next directory entry
+: next-dirent ( -- end? )
+ dirent la1+ w@ dup diroff +! totoff +!
+ totoff @ filesize >= if true exit then
+ diroff @ bsize = if
+ get-dirblk ?dup if exit then
+ diroff off
+ then
+ false
+;
+
+\ **** From directory, get handle of the file or subdir that it references
+\ For Unix, file handle is the inode #
+: file-handle ( -- file-handle ) dirent l@ ;
+
+\ **** From directory, get name of file
+: file-name ( -- adr len ) dirent la1+ wa1+ dup wa1+ swap w@ ;
+
+\ **** Select the root directory
+: froot ( -- error? ) 2 init-dir ;
+
+\
+\ UFS high-level routines
+\
+\ After this point, the code should be independent of the disk format!
+
+: dir ( -- ) begin file-name type cr next-dirent until ;
+
+: lookup ( adr len -- not-found? )
+ begin
+ 2dup file-name " $=" boot-eval if 2drop false exit then
+ next-dirent
+ until
+ 2drop true
+;
+: path-lookup ( adr len -- not-found? )
+ dup 0= if 2drop true exit then
+ over c@ ascii / = if 1 boot-/string then
+ froot if 2drop true exit then
+ begin
+ ascii / boot-$split ( rem-adr len [ adr len ] delim-found? )
+ while
+ lookup if 2drop true exit then
+ dir? 0= if 2drop true exit then
+ file-handle init-dir if 2drop true exit then
+ repeat ( rem-adr len )
+
+ \ Now we have found the directory containing the file
+ lookup ?dup if exit then
+ file-handle select-file
+;
+
+\
+\ File reading, loading, etc.
+\ ELF-specific routines go here.
+\
+
+: read-file ( adr -- error? )
+ filesize begin ( adr remaining )
+ dup 0>
+ while
+ over bsize next-block#
+ read-fs-blocks ?dup if exit then
+ ( adr remaining ) bsize boot-/string
+ repeat
+ 2drop false
+;
+
+\
+\ ELF support
+\
+
+0 constant elfhdr
+0 constant phdr
+
+: +w_elfhdr ( index -- value ) elfhdr swap ca+ w@ ;
+: +l_elfhdr ( index -- value ) elfhdr swap ca+ l@ ;
+: e_entry ( -- n ) 24 +l_elfhdr ;
+: e_phoff ( -- n ) 28 +l_elfhdr ;
+: e_phentsize ( -- n ) 42 +w_elfhdr ;
+: e_phnum ( -- n ) 44 +w_elfhdr ;
+
+1 constant pt_load
+: +phdr ( index -- value ) phdr swap la+ l@ ;
+: p_type ( -- n ) 0 +phdr ;
+: p_offset ( -- n ) 1 +phdr ;
+: p_vaddr ( -- n ) 2 +phdr ;
+: p_filesz ( -- n ) 4 +phdr ;
+: p_memsz ( -- n ) 5 +phdr ;
+: p_flags ( -- n ) 6 +phdr ;
+: p_align ( -- n ) 7 +phdr ;
+
+: check-elf ( filebase -- is-elf? )
+ l@ h# 7f454c46 ( \x7fELF ) =
+;
+
+: get-phdr ( filebase index -- )
+ e_phentsize * e_phoff + +
+ phdr e_phentsize move
+;
+
+: load-elf ( filebase -- entry-point )
+ dup is elfhdr
+ e_phentsize alloc-mem is phdr
+ e_phnum 0 ?do
+ dup i get-phdr
+ p_type pt_load = if
+ ( read it )
+ dup p_offset + p_vaddr p_filesz move
+ p_memsz p_filesz > if
+ ( zero the bss )
+ p_vaddr p_filesz + p_memsz p_filesz - 0 fill
+ then
+ then
+ loop drop
+ phdr e_phentsize free-mem
+ e_entry
+;
+
+\
+\ UFS installation routines
+\
+
+\ **** Allocate memory for necessary data structures
+: allocate-ufs-buffers ( -- error? )
+ /super-block alloc-mem is super-block
+ get-super-block ?dup if
+ ." failed to read super block" cr
+ super-block /super-block free-mem close-disk exit
+ then
+ bsize alloc-mem is temp-block
+ bsize alloc-mem is indirect-block
+ /inode alloc-mem is inode
+ false
+;
+
+: release ( -- )
+ inode /inode free-mem
+ indirect-block bsize free-mem
+ temp-block bsize free-mem
+ super-block /super-block free-mem
+ close-disk
+;
+
+: initialize ( -- error? )
+ open-disk ?dup if exit then
+ allocate-ufs-buffers
+;
+
+hex
+headers
+( external )
+
+: get-file ( load-adr name-adr name-len -- error? )
+ initialize ?dup if nip nip nip exit then ( )
+ path-lookup ?dup if nip release exit then ( )
+ dir? ?dup if ( load-adr error? )
+ nip ." File is a directory." cr release exit
+ then ( load-adr )
+ read-file ?dup if ." File read failed." cr exit then ( )
+ \ Set FORTH file-size variable
+ filesize " file-size" boot-eval !
+ release false ( ok )
+;
+
+: reloc&go ( -- )
+ loadbase
+ \ Is it ELF?
+ dup check-elf if ( base-adr )
+ load-elf ( entry-point )
+ loadbase!
+ " init-program" boot-eval
+ else ( base-adr )
+\ Let FORTH handle anything else
+ " adjust-header" boot-eval if " init-program" boot-eval then ( entry-point )
+ loadbase!
+ then
+ 4000 loadbase!
+ " ?go" boot-eval
+;
+
+d# 128 buffer: boot-name
+
+: get-boot-name ( -- adr,len )
+ boot-name d# 128 erase
+ " /platform/" boot-name swap dup >r cmove r> ( len0 )
+ boot-name over + " name" drop ( len0 bufadr namestr )
+ 0 devr_next devr_getprop ( len0 len )
+ 1- + boot-name over + ( len1 adr )
+ " /ufsboot" ( len1 adr adr,len )
+ >r swap r@ cmove r> ( len1 len )
+ + boot-name swap
+;
+
+\
+\ The boot stuff itself
+\
+: do-boot
+ 4000 loadbase!
+ loadbase get-boot-name get-file if
+ ." Boot load failed." cr exit
+ then
+ reloc&go
+;
+
+do-boot
diff --git a/usr/src/psm/stand/bootblks/ufs/common/iob.h b/usr/src/psm/stand/bootblks/ufs/common/iob.h
new file mode 100644
index 0000000000..7797839b4a
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/ufs/common/iob.h
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ *
+ * 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 (c) 1990-1994, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI" /* from SunOS 4.1 */
+
+/*
+ * This stuff keeps track of an open file in the standalone I/O system.
+ *
+ * The definitions herein are *private* to ufs.c
+ *
+ * It includes an IOB for device addess, an inode, a buffer for reading
+ * indirect blocks and inodes, and a buffer for the superblock of the
+ * file system (if any).
+ *
+ * To make the boot block smaller, we're using a 'bnode' (for boot node)
+ * struct instead of an inode struct. This contains just the common
+ * data from the on-disk inode.
+ */
+
+struct saioreq {
+ off_t si_offset;
+ char *si_ma; /* memory address to r/w */
+ int si_cc; /* character count to r/w */
+};
+
+struct bnode
+{
+ dev_t i_dev; /* from inode struct */
+ struct icommon i_ic; /* disk inode struct */
+};
+
+
+struct iob {
+ void *i_si; /* I/O handle for this file */
+ struct {
+ off_t si_offset;
+ char *si_ma; /* memory address to r/w */
+ int si_cc; /* character count to r/w */
+ } i_saio; /* I/O request block */
+ struct bnode i_ino; /* Inode for this file */
+ char i_buf[MAXBSIZE]; /* Buffer for reading inodes & dirs */
+ union {
+ struct fs ui_fs; /* Superblock for file system */
+ char dummy[SBSIZE];
+ } i_un;
+};
+
+/*
+ * XXX: i_fs conflicts with a definition in ufs_inode.h...
+ */
+#define iob_fs i_un.ui_fs
diff --git a/usr/src/psm/stand/bootblks/ufs/common/ufs.c b/usr/src/psm/stand/bootblks/ufs/common/ufs.c
new file mode 100644
index 0000000000..0d1f0f0540
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/ufs/common/ufs.c
@@ -0,0 +1,375 @@
+/*
+ * 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.
+ *
+ * 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 1991-1994, 2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* from "@(#)boot/ufssys.c 1.1 90/03/28 SMI" */
+
+/*
+ * Basic file system reading code for standalone I/O system.
+ */
+
+#include <sys/param.h>
+#include <sys/vnode.h>
+#include <sys/fs/ufs_fsdir.h>
+#include <sys/fs/ufs_fs.h>
+#include <sys/fs/ufs_inode.h>
+
+#include "iob.h"
+#include "cbootblk.h"
+
+/*
+ * private definitions of ufs macros from sys/fs/ufs_fs.h
+ * due to boot block size problems, these macros are coded
+ * to use the older narrow file offset type (31 bit). This
+ * saves a lot of code space. Since we will never encounter
+ * a large file here, it is safe to cast offset_t to off_t.
+ */
+
+#define bb_fragroundup(fs, size) /* roundup(size, fs->fs_fsize) */ \
+ ((off_t)((size) + (fs)->fs_fsize - 1) & (off_t)(fs)->fs_fmask)
+
+#define bb_blksize(fs, ip, lbn) \
+ (((lbn) >= NDADDR || \
+ (off_t)(ip)->i_size >= (off_t)((lbn) + 1) << (fs)->fs_bshift) \
+ ? (fs)->fs_bsize \
+ : (bb_fragroundup(fs, blkoff(fs, (off_t)(ip)->i_size))))
+
+#define NULL 0
+
+static struct direct *readdir(struct iob *, int *);
+static ino_t dlook(char *, struct iob *);
+static int getblock(struct iob *io);
+
+char fscompname[] = "ufsboot";
+
+static struct iob iob[1]; /* only one open file! */
+
+static int
+openi(ino_t n, struct iob *io)
+{
+ struct dinode *dp;
+ struct fs *fs = &io->iob_fs;
+
+ io->i_saio.si_offset = 0;
+ if (devbread(io->i_si, io->i_buf,
+ fsbtodb(fs, itod(fs, n)), fs->fs_bsize) != fs->fs_bsize)
+ return (0);
+ dp = (struct dinode *)io->i_buf;
+ io->i_ino.i_ic = dp[itoo(fs, n)].di_ic;
+ return (1);
+}
+
+static ino_t
+find(char *nm, struct iob *file)
+{
+ char *q;
+ char c;
+ ino_t n;
+ char pathbuf[MAXPATHLEN], *path;
+ char *link;
+ size_t linklen;
+ int fmt = IFDIR;
+
+ if (nm == NULL || *nm == '\0')
+ return (0);
+ bcopy(nm, pathbuf, strlen(nm) + 1);
+root:
+ path = pathbuf;
+ if (openi((ino_t)UFSROOTINO, file) == 0)
+ return (0);
+ while (*path) {
+ while (*path == '/')
+ path++;
+ q = path;
+ while (*q != '/' && *q != '\0')
+ q++;
+ c = *q;
+ *q = '\0';
+
+ if ((n = dlook(path, file)) != 0) {
+
+ *q = c;
+ if (openi(n, file) == 0)
+ return (0);
+ switch (fmt = (file->i_ino.i_smode & IFMT)) {
+ case IFREG:
+ case IFDIR:
+ break;
+
+ case IFLNK:
+ if (getblock(file) != 0)
+ return (0);
+ link = (char *)file->i_saio.si_ma;
+ linklen = strlen(link);
+ if (*link == '/')
+ path = pathbuf;
+ /*
+ * Copy unprocessed pathname up & prepend link
+ * (Yes, this bcopy handles overlapping args)
+ */
+ bcopy(q, path + linklen, strlen(q) + 1);
+ bcopy(link, path, linklen);
+ path = pathbuf;
+ goto root;
+ /*NOTREACHED*/
+
+ default:
+ return (0);
+ }
+ if (c == '\0')
+ break;
+ path = q;
+ continue;
+ } else
+ return (0);
+ }
+
+ return (fmt == IFREG ? n : 0);
+}
+
+static daddr_t
+sbmap(struct iob *io, daddr_t bn)
+{
+ struct bnode *ip;
+ int i, j, sh;
+ daddr_t nb, *bap;
+
+ /* These are the pools of buffers, iob's, etc. */
+
+ static union {
+ char b[NIADDR+1][MAXBSIZE];
+ daddr_t *dummy; /* force alignment */
+ } b;
+ static daddr_t blknos[NIADDR+1];
+
+ ip = &io->i_ino;
+
+ /*
+ * blocks 0..NDADDR are direct blocks
+ */
+ if (bn < NDADDR)
+ return (ip->i_db[bn]);
+
+ /*
+ * addresses NIADDR have single and double indirect blocks.
+ * the first step is to determine how many levels of indirection.
+ */
+ sh = 1;
+ bn -= NDADDR;
+ for (j = NIADDR; j > 0; j--) {
+ sh *= NINDIR(&io->iob_fs);
+ if (bn < sh)
+ break;
+ bn -= sh;
+ }
+ if (j == 0)
+ return ((daddr_t)0);
+
+ /*
+ * fetch the first indirect block address from the inode
+ */
+ nb = ip->i_ib[NIADDR - j];
+ if (nb == 0)
+ return ((daddr_t)0);
+
+ /*
+ * fetch through the indirect blocks
+ */
+ for (; j <= NIADDR; j++) {
+ if (blknos[j] != nb) {
+ if (devbread(io->i_si, b.b[j],
+ fsbtodb(&io->iob_fs, nb),
+ io->iob_fs.fs_bsize) != io->iob_fs.fs_bsize)
+ return ((daddr_t)0);
+ blknos[j] = nb;
+ }
+ bap = (daddr_t *)b.b[j];
+ sh /= NINDIR(&io->iob_fs);
+ i = (bn / sh) % NINDIR(&io->iob_fs);
+ nb = bap[i];
+ if (nb == 0)
+ return ((daddr_t)0);
+ }
+ return (nb);
+}
+
+static ino_t
+dlook(char *s, struct iob *io)
+{
+ struct direct *dp;
+ struct bnode *ip;
+ int len, loc = 0;
+
+ ip = &io->i_ino;
+ if (s == NULL || *s == '\0')
+ return (0);
+ if ((ip->i_smode & IFMT) != IFDIR || ip->i_size == 0)
+ return (0);
+ len = strlen(s);
+ for (dp = readdir(io, &loc); dp != NULL; dp = readdir(io, &loc)) {
+ if (dp->d_ino == 0)
+ continue;
+ if (dp->d_namlen == len && strcmp(s, dp->d_name) == 0)
+ return (dp->d_ino);
+ }
+ return (0);
+}
+
+/*
+ * get next entry in a directory.
+ */
+static struct direct *
+readdir(struct iob *io, int *loc_p)
+{
+ struct direct *dp;
+ daddr_t lbn, d;
+ int off;
+ int loc = *loc_p;
+ int bsize;
+
+ for (;;) {
+ if (loc >= io->i_ino.i_size)
+ return (NULL);
+ off = blkoff(&io->iob_fs, loc);
+ if (off == 0) {
+ lbn = lblkno(&io->iob_fs, loc);
+ if ((d = sbmap(io, lbn)) == 0)
+ return (NULL);
+ bsize = bb_blksize(&io->iob_fs, &io->i_ino, lbn);
+ if (devbread(io->i_si, io->i_buf,
+ fsbtodb(&io->iob_fs, d), bsize) != bsize)
+ return (NULL);
+ }
+ dp = (struct direct *)(io->i_buf + off);
+ *loc_p = (loc += dp->d_reclen);
+ if (dp->d_ino == 0)
+ continue;
+ return (dp);
+ }
+}
+
+static int
+getblock(struct iob *io)
+{
+ struct fs *fs;
+ int off, size, diff;
+ daddr_t lbn;
+
+ diff = io->i_ino.i_size - io->i_saio.si_offset;
+ if (diff <= 0)
+ return (-1);
+ fs = &io->iob_fs;
+ lbn = lblkno(fs, io->i_saio.si_offset);
+ off = blkoff(fs, io->i_saio.si_offset);
+ size = bb_blksize(fs, &io->i_ino, lbn);
+ io->i_saio.si_cc = size;
+ if (devbread(io->i_si, io->i_buf,
+ fsbtodb(fs, sbmap(io, lbn)), size) != size)
+ return (-1);
+ if (io->i_saio.si_offset - off + size >= io->i_ino.i_size)
+ io->i_saio.si_cc = diff + off;
+ io->i_saio.si_cc -= off;
+
+ io->i_saio.si_ma = &io->i_buf[off];
+ return (0);
+}
+
+int
+readfile(int fd, char *buf, int count)
+{
+ struct iob *io = &iob[fd];
+ int i, j;
+
+ if (io->i_saio.si_offset + count > io->i_ino.i_size)
+ count = io->i_ino.i_size - io->i_saio.si_offset;
+ if ((i = count) <= 0)
+ return (0);
+ while (i > 0) {
+ if (io->i_saio.si_cc <= 0) {
+ if (getblock(io) == -1)
+ return (0);
+ }
+ j = (i < io->i_saio.si_cc) ? i : io->i_saio.si_cc;
+ bcopy(io->i_saio.si_ma, buf, (size_t)j);
+ buf += j;
+ io->i_saio.si_ma += j;
+ io->i_saio.si_offset += j;
+ io->i_saio.si_cc -= j;
+ i -= j;
+ }
+ return (count);
+}
+
+/*
+ * Open a file.
+ */
+int
+openfile(char *device, char *pathname)
+{
+ struct iob *io = &iob[0]; /* only one open file! */
+
+ io->i_ino.i_dev = 0;
+ if ((io->i_si = devopen(device)) == NULL)
+ return (-1); /* if devopen fails, open fails */
+
+ /* Pseudo-mount a file system; read the superblock. */
+
+ if (devbread(io->i_si, &io->iob_fs, SBLOCK, SBSIZE) != SBSIZE)
+ goto failed;
+ if (io->iob_fs.fs_magic != FS_MAGIC) {
+ puts("bootblk: not a UFS file system.\n");
+ goto failed;
+ }
+ if (find(pathname, io) == 0)
+ goto failed;
+ io->i_saio.si_offset = io->i_saio.si_cc = 0;
+
+ return (0); /* only one open file! */
+failed:
+ (void) devclose(io->i_si);
+ return (-1);
+}
+
+int
+closefile(int fd)
+{
+ struct iob *io = &iob[fd];
+
+ return (devclose(io->i_si));
+}
+
+/*
+ * This version of seek() only performs absolute seeks (whence == 0).
+ */
+void
+seekfile(int fd, off_t addr)
+{
+ struct iob *io = &iob[fd];
+
+ io->i_saio.si_offset = addr;
+ io->i_saio.si_cc = 0;
+}
diff --git a/usr/src/psm/stand/bootblks/ufs/i386/Makefile b/usr/src/psm/stand/bootblks/ufs/i386/Makefile
new file mode 100644
index 0000000000..b11205a287
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/ufs/i386/Makefile
@@ -0,0 +1,84 @@
+#
+# 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.
+#
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# psm/stand/bootblks/ufs/i386/Makefile
+#
+.KEEP_STATE:
+
+BASEDIR = ../..
+
+include $(BASEDIR)/ufs/Makefile.ufs
+
+
+CC = $(GNU_ROOT)/bin/gcc
+ASFLAGS = -B$(GNU_ROOT)/bin/ -fno-builtin -nostdinc
+CPPFLAGS =
+
+LD = $(GNU_ROOT)/bin/gld
+LDFLAGS = -nostdlib -N -Ttext 600
+
+OBJCOPY = $(GNU_ROOT)/bin/gobjcopy
+
+INSTALL_DIR = $(USR)/lib/fs/ufs
+INSTALL_TARGETS = $(PROGS:%=$(INSTALL_DIR)/%)
+
+$(INSTALL_TARGETS) := FILEMODE = 0444
+
+PROGS = mboot
+
+
+all: $(INSTALLBOOT) $(PROGS)
+
+$(PROGS): $$(@).exec
+ $(OBJCOPY) -O binary $@.exec $@
+
+%.exec: %.o
+ $(LD) $(LDFLAGS) -o $@ $(@:exec=o)
+
+
+install: all $(INSTALL_TARGETS) $(USR_SBIN_INSTALLBOOT)
+
+$(INSTALL_DIR)/%: $(INSTALL_DIR) %
+ $(INS.file)
+
+$(INSTALL_DIR):
+ $(INS.dir)
+
+
+clean:
+ $(RM) $(PROGS) *.exec *.o $(INSTALLBOOT)
+
+clobber: clean
+ $(RM) $(INSTALL_TARGETS) $(INSTALLBOOT)
+
+#
+# Pattern matching rules for source in this directory
+#
+%: %.sh
+ $(RM) $@
+ cat $< > $@
+ chmod +x $@
diff --git a/usr/src/psm/stand/bootblks/ufs/i386/installboot.sh b/usr/src/psm/stand/bootblks/ufs/i386/installboot.sh
new file mode 100644
index 0000000000..6a3c365a12
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/ufs/i386/installboot.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+#
+# 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.
+#
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+
+away() {
+ echo $2 1>&2
+ exit $1
+}
+
+Error="Error: `basename $0` is obsolete. Use installgrub(1M)"
+Usage="Usage: `basename $0` --force_realmode pboot bootblk raw-device"
+
+test $# -ne 4 && away 1 "$Error"
+test $1 != "--force_realmode" && away 1 "$Error"
+shift 1
+
+PBOOT=$1
+BOOTBLK=$2
+DEVICE=$3
+test ! -f $PBOOT && away 1 "$PBOOT: File not found"
+test ! -f $BOOTBLK && away 1 "$BOOTBLK: File not found"
+test ! -c $DEVICE && away 1 "$DEVICE: Not a character device"
+test ! -w $DEVICE && away 1 "$DEVICE: Not writeable"
+
+# pboot at block 0, label at blocks 1 and 2, bootblk from block 3 on
+stderr=`dd if=$PBOOT of=$DEVICE bs=1b count=1 conv=sync 2>&1`
+err=$? ; test $err -ne 0 && away $err "$stderr"
+stderr=`dd if=$BOOTBLK of=$DEVICE bs=1b oseek=3 conv=sync 2>&1`
+err=$? ; test $err -ne 0 && away $err "$stderr"
+exit 0
diff --git a/usr/src/psm/stand/bootblks/ufs/i386/mboot.S b/usr/src/psm/stand/bootblks/ufs/i386/mboot.S
new file mode 100644
index 0000000000..646f1ef554
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/ufs/i386/mboot.S
@@ -0,0 +1,394 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * ident "%Z%%M% %I% %E% SMI"
+ */
+
+/*
+ * SOLARIS MASTER BOOT:
+ *
+ * PURPOSE: loads the primary boot from the active fdisk partition.
+ * in effect, this routine mimics the functionality of INT 0x19.
+ *
+ * resides on the first physical sector of the hard drive media.
+ * loaded by INT 0x19 (ROM bootstrap loader) at address 0x7C00
+ * limited to 512 bytes total, including embedded fdisk table.
+ *
+ * for compatibility with the ROM BIOS, we contain standard DOS structures:
+ *
+ * the fdisk partition table (at offset 0x1BE-0x1FE)
+ * boot signature bytes (0x55, 0xAA at 0x1FE, 0x1FF)
+ *
+ * the above two entities are required in order to be compatible with
+ * the manner in which the DOS BIOS has always performed its boot operation.
+ * In the event that our master boot record is inadvertently replaced by
+ * a standard DOS boot sector, the booting operation will still succeed!
+ *
+ * This master boot record uses the relsect/numsect fields of the partition
+ * table entry, to compute the start of the active partition; therefore,
+ * it is geometry independent. This means that the drive could be "built"
+ * on a system with a disk controller that uses a given disk geometry, but
+ * would run on any other controller.
+ *
+ * SYNOPSIS:
+ * begins execution at 0:0x7C00
+ * relocates to 0:0x600 (to get out of the way!)
+ * reads fdisk table to locate bootable partition
+ * load boot record from the active fdisk partition at 0x7C00
+ * verify boot record signature bytes
+ * jump to/execute the SOLARIS PARTITION PRIMARY BOOT
+ * error handler - can either reboot, or invoke INT 0x18.
+ *
+ * interface from DOS INT 0x19: BootDev in DL
+ * (this fails sometimes, so we look for a signature to determine whether
+ * to rely on DL from the floppy boot, or if we should assume 0x80 from
+ * the BIOS)
+ *
+ * interface to partition boot: BootDev in DL
+ *
+ *=============================================================================
+ * Master boot record: resides on first physical sector of device
+ */
+
+/*
+ * This file is written in GNU as syntax using Intel assembler syntax. The
+ * startup label _start will be executed at address PBOOT_ADDR (0x7C00), but
+ * the text section must be set at address RELOC_ADDR (0x600). With GNU ld
+ * this can be done using the "-Ttext 600" option.
+ */
+
+
+#define PBOOT_ADDR 0x7C00
+#define RELOC_ADDR 0x600
+
+#define FDISK_START 0x1BE
+#define BOOT_SIG 0xAA55
+#define N_RETRIES 5
+
+#define FD_NUMPART 4
+#define FD_PTESIZE 0x10
+#define ACTIVE 0x80
+
+/*
+ * A convenience macro for declaring a message string (using .ascii directive--
+ * NOT nul-terminated) surrounded by two labels, which can then be used with
+ * the SIZEOF() macro to get its length.
+ */
+#define MSG(label, string) label: .ascii string; label##_end:
+
+/*
+ * Returns the length of some consecutive bytes. These bytes must be placed
+ * between two labels. The ending label must be the same as the starting label
+ * but with a suffix "_end".
+ */
+#define SIZEOF(label) (offset label##_end - offset label)
+
+
+ .title "Solaris_Master_Boot"
+
+ .intel_syntax noprefix /* use Intel syntax */
+ .code16 /* 16-bit mode (real mode) */
+
+ .text /* code segment begins here */
+
+ .global BootDev
+ .global _start
+
+_start: /* _start is loaded at PBOOT_ADDR */
+ jmp bootrun
+
+Version:
+ .ascii "M3.0" /* ident string */
+
+bootrun:
+ cli /* don't bother me now! */
+
+ /* prepare to relocate ourselves */
+ cld /* prepare for relocation */
+ mov si, PBOOT_ADDR
+ mov di, RELOC_ADDR
+
+ /* set up segment registers */
+ mov ax, cs /* initialize segment registers */
+ mov ss, ax
+ mov sp, si /* stack starts down from 7C00 */
+ mov es, ax
+ mov ds, ax
+
+ push cx /* save possible signature on stack */
+ mov cx, 0x100
+ rep movsw
+ pop cx /* restore saved cx */
+
+ /* running at PBOOT_ADDR, jump to RELOC_ADDR-rel addr */
+ jmp (new_home - PBOOT_ADDR + RELOC_ADDR)
+
+new_home:
+ sti /* re-enable interrupts */
+
+ /*
+ * assuming boot device number is in dl has caused problems in the past
+ * since we still don't absolutely have to rely on it, I've just
+ * removed the now-pointless code to check for the FACE-CAFE signature
+ * from mdexec, which doesn't do anything anymore, but left the
+ * assumption that BootDev is 0x80 and nothing but. If we ever need to
+ * have BIOS load us from a drive not numbered 0x80, we'll need to
+ * uncomment the following line; otherwise, the initialized value of
+ * BootDev, namely 0x80, will be used for disk accesses.
+ */
+ /* mov BootDev, dl */
+
+ /* set debug flag based on seeing "both shift down" */
+ mov ah, 2 /* get shift state */
+ int 0x16
+ and al, 3 /* isolate shift-key bits */
+ cmp al, 3
+ jne nodbg
+ mov byte ptr [debugmode], 1 /* set to 1 */
+
+nodbg:
+ /*
+ * Search the fdisk table sequentially to find a physical partition
+ * that is marked as "active" (bootable).
+ */
+ mov bx, RELOC_ADDR + FDISK_START
+ mov cx, FD_NUMPART
+
+nxtpart:
+ cmp byte ptr [bx], ACTIVE
+ je got_active_part
+ add bx, FD_PTESIZE
+ loop nxtpart
+
+noparts:
+ mov bp, offset NoActiveErrMsg
+ mov cx, SIZEOF(NoActiveErrMsg)
+ jmp fatal_err
+
+got_active_part:
+ mov ah, 0 /* reset disk */
+ int 0x13
+
+ push bx /* save partition pointer */
+
+ /* Check for LBA BIOS */
+ mov ah, 0x41 /* chkext function */
+ mov bx, 0x55AA /* signature to change */
+ mov cx, 0
+ int 0x13
+ jc noLBA /* carry == failure */
+ cmp bx, 0xAA55
+ jne noLBA /* bad signature in BX == failure */
+ test cx, 1 /* cx & 1 must be true, or... */
+ jz noLBA /* ...no LBA */
+
+ mov bp, offset lbastring
+ mov cx, SIZEOF(lbastring)
+ call debugout
+
+ /*
+ * LBA case: form a packet on the stack and call fn 0x42 to read
+ * packet, backwards (from hi to lo addresses):
+ * 8-byte LBA
+ * seg:ofs buffer address
+ * byte reserved
+ * byte nblocks
+ * byte reserved
+ * packet size in bytes (>= 0x10)
+ */
+
+ pop bx /* restore partition pointer */
+ push bx /* and save again */
+ mov cx, N_RETRIES /* retry count */
+retryLBA:
+ pushd 0 /* hi 32 bits of 64-bit sector number */
+ push dword ptr [bx+8] /* relsect (lo 32 of 64-bit number) */
+ push dword ptr [solaris_priboot] /* seg:ofs of buffer */
+ push 1 /* reserved, one block */
+ push 0x10 /* reserved, size (0x10) */
+ mov ah, 0x42 /* "read LBA" */
+ mov si, sp /* (ds already == ss) */
+ int 0x13
+ lahf /* save flags */
+ add sp, 16 /* restore stack */
+ sahf /* restore flags */
+ jnc readok /* got it */
+ mov ah, 0 /* reset disk */
+ int 0x13
+ loop retryLBA /* try again */
+ jmp readerr /* exhausted retries; give up */
+
+noLBA:
+ mov bp, offset chsstring
+ mov cx, SIZEOF(chsstring)
+ call debugout
+
+ pop bx /* restore partition pointer */
+ push bx /* and save again */
+
+ /* get BIOS disk parameters */
+ mov dl, byte ptr [BootDev]
+ mov ah, 0x8
+ int 0x13
+
+ jnc geomok
+
+ /* error reading geom; die */
+ mov bp, offset GeomErrMsg
+ mov cx, SIZEOF(GeomErrMsg)
+ jmp fatal_err
+
+geomok:
+ /* calculate sectors per track */
+ mov al, cl /* ah doesn't matter; mul dh will set it */
+ and al, 0x3F
+ mov byte ptr [secPerTrk], al
+
+ /* calculate sectors per cylinder */
+ inc dh
+ mul dh
+ mov word ptr [secPerCyl], ax
+
+ /* calculate cylinder # */
+ mov ax, [bx+8] /* ax = loword(relsect) */
+ mov dx, [bx+10] /* dx:ax = relsect */
+ div word ptr [secPerCyl] /* ax = cyl, */
+ /* dx = sect in cyl (0 - cylsize-1) */
+ mov bx, ax /* bx = cyl */
+
+ /* calculate head/sector # */
+ mov ax, dx /* ax = sect in cyl (0 - cylsize-1) */
+ div byte ptr [secPerTrk] /* al = head, */
+ /* ah = 0-rel sect in track */
+ inc ah /* ah = 1-rel sector */
+
+ xor cl,cl /* cl = 0 */
+ mov ch, bh /* ch = hi bits of cyl (if any) */
+ shr cx, 2 /* cl{7:6} = cyl{9:8} (if any) */
+ and cl, 0xC0 /* cl = cyl{9:8} to merge with sect (if any) */
+
+ or cl, ah /* cl{7:6} = cyl bits, cl{5:0} = sect */
+ mov ch, bl /* ch = lo cyl bits */
+ mov dh, al /* dh = head */
+ mov dl, byte ptr [BootDev] /* dl = drivenum */
+ les bx, solaris_priboot /* es:bx points to buffer */
+
+ mov si, N_RETRIES
+retry_noLBA:
+ mov ax, 0x201 /* 02=read, sector count = 1 */
+
+ int 0x13
+ jnc readok
+ mov ah, 0 /* reset disk */
+ int 0x13
+ dec si
+ cmp si, 0
+ jne retry_noLBA /* retry, or fall through to read error */
+
+readerr:
+ mov bp, offset ReadErrMsg
+ mov cx, SIZEOF(ReadErrMsg)
+ jmp fatal_err
+
+readok:
+ /* verify boot record signature */
+ mov bx, PBOOT_ADDR
+ cmp word ptr [bx+0x1FE], BOOT_SIG
+ je sigok
+
+ mov bp, offset SigErrMsg
+ mov cx, SIZEOF(SigErrMsg)
+ jmp fatal_err
+
+sigok:
+ mov dl, byte ptr [BootDev] /* pass BootDev to next boot phase */
+ pop si /* and pass partition pointer ds:si */
+ call dword ptr [solaris_priboot] /* call doesn't return! */
+
+ mov bp, offset ReturnErrMsg
+ mov cx, SIZEOF(ReturnErrMsg)
+
+fatal_err: /* land of no return....... */
+ /*
+ * bp contains pointer to error message string,
+ * cx contains string length
+ */
+ mov bx, 0x4F /* video page, attribute */
+ call msgout
+ int 0x18
+
+debugout:
+ /* call with string pointer in es:bp, len in cx */
+ cmp byte ptr [debugmode], 0
+ je debugout_ret /* skip if not in debug mode */
+
+ mov bx, 0x1F /* page, attr (white on blue) */
+
+ /* alternate entry for fatal_err */
+msgout:
+ pusha
+ mov ax, 0x1301
+ mov dx, 0x1700 /* row, col */
+ int 0x10
+
+ mov al, 7 /* BEL */
+ mov cx, 1
+ int 0x10
+
+ mov ah, 0 /* get key */
+ int 0x16
+ popa
+
+debugout_ret:
+ ret
+
+secPerTrk:
+ .byte 0
+secPerCyl:
+ .word 0
+solaris_priboot:
+ .long PBOOT_ADDR
+BootDev:
+ .byte 0x80 /* assumes drive 80 (see comment above) */
+debugmode:
+ .byte 0
+
+MSG(GeomErrMsg, "Can't read geometry")
+MSG(NoActiveErrMsg, "No active partition")
+MSG(ReadErrMsg, "Can't read PBR")
+MSG(SigErrMsg, "Bad PBR sig")
+MSG(ReturnErrMsg, "!!!")
+MSG(lbastring, "LBA")
+MSG(chsstring, "CHS")
+
+/*
+ * For debugging: Here's a representative FDISK table entry
+ *
+ * .org 0x1BE
+ * .byte 0x80,1,1,0,0x82,0xfe,0x7f,4,0x3f,0,0,0,0x86,0xfa,0x3f,0
+ */
+ .org 0x1FE
+
+ .word BOOT_SIG
diff --git a/usr/src/psm/stand/bootblks/ufs/sparc/Makefile b/usr/src/psm/stand/bootblks/ufs/sparc/Makefile
new file mode 100644
index 0000000000..69ec178a4e
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/ufs/sparc/Makefile
@@ -0,0 +1,65 @@
+#
+# 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.
+#
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# psm/stand/bootblks/ufs/sparc/Makefile
+#
+
+BASEDIR = ../..
+
+include $(BASEDIR)/ufs/Makefile.ufs
+
+SUBDIRS = unix sun4c sun4m sun4d sun4u sun4v
+
+all := TARGET= all
+install := TARGET= install
+clean := TARGET= clean
+clobber := TARGET= clobber
+lint := TARGET= lint
+
+.KEEP_STATE:
+
+all: $(INSTALLBOOT) $(SUBDIRS)
+
+install: $(USR_SBIN_INSTALLBOOT) $(SUBDIRS)
+
+lint clean: $(SUBDIRS)
+
+clobber: $(SUBDIRS)
+ -$(RM) $(INSTALLBOOT)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+#
+# Pattern matching rules for source in this directory
+#
+%: %.sh
+ $(RM) $@
+ cat $< > $@
+ chmod +x $@
diff --git a/usr/src/psm/stand/bootblks/ufs/sparc/installboot.sh b/usr/src/psm/stand/bootblks/ufs/sparc/installboot.sh
new file mode 100644
index 0000000000..cd463bef71
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/ufs/sparc/installboot.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+#
+# 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.
+#
+# 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 (c) 1994-1997, by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+
+away() {
+ echo $2 1>&2
+ exit $1
+}
+
+Usage="Usage: `basename $0` bootblk raw-device"
+
+test $# -ne 2 && away 1 "$Usage"
+
+BOOTBLK=$1
+DEVICE=$2
+test ! -f $BOOTBLK && away 1 "$BOOTBLK: File not found"
+test ! -c $DEVICE && away 1 "$DEVICE: Not a character device"
+test ! -w $DEVICE && away 1 "$DEVICE: Not writeable"
+
+# label at block 0, bootblk from block 1 through 15
+stderr=`dd if=$BOOTBLK of=$DEVICE bs=1b oseek=1 count=15 conv=sync 2>&1`
+err=$? ; test $err -ne 0 && away $err "$stderr"
+exit 0
diff --git a/usr/src/psm/stand/bootblks/ufs/sparc/sun4c/Makefile b/usr/src/psm/stand/bootblks/ufs/sparc/sun4c/Makefile
new file mode 100644
index 0000000000..e177bae10b
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/ufs/sparc/sun4c/Makefile
@@ -0,0 +1,59 @@
+#
+# 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.
+#
+# 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 (c) 1994, 1999, by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# psm/stand/bootblks/ufs/sparc/sun4c/Makefile
+#
+
+#
+# Platform specific Makefile for the boot block.
+#
+# PLATFORM is the target for the binary installation.
+#
+# PLATLINKS is a list of platforms which are to be linked to this binary
+# at the file level.
+#
+# PROM_TYPE is the type of prom OBP, IEEE1275, etc...
+#
+BASEDIR = ../../..
+PLATFORM = sun4c
+PLATLINKS =
+PROM_TYPE = OBPDEP
+
+include $(BASEDIR)/ufs/Makefile.ufs
+include $(BASEDIR)/obp-c/Makefile.rules
+
+CPPINCS += -I$(SRC)/uts/common
+CPPINCS += -I$(SRC)/uts/sun
+CPPINCS += -I$(SRC)/uts/sparc
+
+.KEEP_STATE:
+
+all: $(MKBOOT) $(PROG).elf
+ ./$(MKBOOT) $(PROG).elf $(PROG); chmod -x $(PROG)
+
+include $(BASEDIR)/obp-c/Makefile.targ
+include $(BASEDIR)/Makefile.targ
diff --git a/usr/src/psm/stand/bootblks/ufs/sparc/sun4d/Makefile b/usr/src/psm/stand/bootblks/ufs/sparc/sun4d/Makefile
new file mode 100644
index 0000000000..abb8f28aec
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/ufs/sparc/sun4d/Makefile
@@ -0,0 +1,62 @@
+#
+# 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.
+#
+# 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 (c) 1994, 2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# psm/stand/bootblks/ufs/sparc/sun4d/Makefile
+#
+
+#
+# Platform specific Makefile for the boot block.
+#
+# PLATFORM is the target for the binary installation.
+#
+# PLATFORM_INCS is a list of directories to look in for platform specific
+# header files to include
+#
+# PLATLINKS is a list of platforms which are to be linked to this binary
+# at the file level.
+#
+# PROM_TYPE is the type of prom OBP, IEEE1275, etc...
+#
+BASEDIR = ../../..
+PLATFORM = sun4d
+PLATLINKS =
+PROM_TYPE = OBPDEP
+
+include $(BASEDIR)/ufs/Makefile.ufs
+include $(BASEDIR)/obp-c/Makefile.rules
+
+CPPINCS += -I$(SRC)/uts/common
+CPPINCS += -I$(SRC)/uts/sun
+CPPINCS += -I$(SRC)/uts/sparc
+
+.KEEP_STATE:
+
+all: $(MKBOOT) $(PROG).elf
+ ./$(MKBOOT) $(PROG).elf $(PROG); chmod -x $(PROG)
+
+include $(BASEDIR)/obp-c/Makefile.targ
+include $(BASEDIR)/Makefile.targ
diff --git a/usr/src/psm/stand/bootblks/ufs/sparc/sun4m/Makefile b/usr/src/psm/stand/bootblks/ufs/sparc/sun4m/Makefile
new file mode 100644
index 0000000000..5177d46a29
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/ufs/sparc/sun4m/Makefile
@@ -0,0 +1,55 @@
+#
+# 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.
+#
+# 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 1994, 2002 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# psm/stand/bootblks/ufs/sparc/sun4m/Makefile
+#
+
+#
+# Platform specific Makefile for the boot block.
+#
+# PLATFORM is the target for the binary installation.
+#
+# PROM_TYPE is the type of prom OBP, IEEE1275, etc...
+#
+BASEDIR = ../../..
+PLATFORM = sun4m
+PROM_TYPE = OBPDEP
+
+include $(BASEDIR)/ufs/Makefile.ufs
+include $(BASEDIR)/obp-c/Makefile.rules
+
+CPPINCS += -I$(SRC)/uts/common
+CPPINCS += -I$(SRC)/uts/sun
+CPPINCS += -I$(SRC)/uts/sparc
+
+.KEEP_STATE:
+
+all: $(MKBOOT) $(PROG).elf
+ ./$(MKBOOT) $(PROG).elf $(PROG); chmod -x $(PROG)
+
+include $(BASEDIR)/obp-c/Makefile.targ
+include $(BASEDIR)/Makefile.targ
diff --git a/usr/src/psm/stand/bootblks/ufs/sparc/sun4u/Makefile b/usr/src/psm/stand/bootblks/ufs/sparc/sun4u/Makefile
new file mode 100644
index 0000000000..47061d5bba
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/ufs/sparc/sun4u/Makefile
@@ -0,0 +1,76 @@
+#
+# 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.
+#
+# 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 1994,2000-2003 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# psm/stand/bootblks/ufs/sparc/sun4u/Makefile
+#
+
+#
+# Platform specific Makefile for the boot block.
+#
+# PLATFORM is the target for the binary installation.
+#
+# PLATLINKS is a list of platforms which are to be linked to the ../fs
+# directory.
+#
+BASEDIR = ../../..
+PLATFORM = sun4u
+
+PLATLINKS = SUNW,Ultra-2
+PLATLINKS += SUNW,Ultra-250
+PLATLINKS += SUNW,Ultra-4
+PLATLINKS += SUNW,Ultra-Enterprise
+PLATLINKS += SUNW,Ultra-Enterprise-10000
+PLATLINKS += SUNW,Sun-Blade-100
+PLATLINKS += SUNW,Sun-Blade-1000
+PLATLINKS += SUNW,Sun-Blade-1500
+PLATLINKS += SUNW,Sun-Blade-2500
+PLATLINKS += SUNW,Sun-Fire
+PLATLINKS += SUNW,Sun-Fire-V240
+PLATLINKS += SUNW,Sun-Fire-V250
+PLATLINKS += SUNW,Sun-Fire-V440
+PLATLINKS += SUNW,Sun-Fire-280R
+PLATLINKS += SUNW,Sun-Fire-15000
+PLATLINKS += SUNW,Sun-Fire-880
+PLATLINKS += SUNW,Sun-Fire-480R
+PLATLINKS += SUNW,Sun-Fire-V890
+PLATLINKS += SUNW,Sun-Fire-V490
+PLATLINKS += SUNW,Serverblade1
+PLATLINKS += SUNW,Netra-T12
+PLATLINKS += SUNW,Netra-T4
+
+LINKED_DIRS = $(PLATLINKS:%=$(USR_PLAT_DIR)/%)
+LINKED_LIB_DIRS = $(PLATLINKS:%=$(USR_PLAT_DIR)/%/lib)
+LINKED_LIB_FS_DIRS = $(PLATLINKS:%=$(USR_PLAT_DIR)/%/lib/fs)
+
+include $(BASEDIR)/ufs/Makefile.ufs
+include $(BASEDIR)/Makefile.1275
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+include $(BASEDIR)/Makefile.targ
diff --git a/usr/src/psm/stand/bootblks/ufs/sparc/sun4v/Makefile b/usr/src/psm/stand/bootblks/ufs/sparc/sun4v/Makefile
new file mode 100644
index 0000000000..62a45edd98
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/ufs/sparc/sun4v/Makefile
@@ -0,0 +1,55 @@
+#
+# 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.
+#
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# psm/stand/bootblks/ufs/sparc/sun4v/Makefile
+#
+
+#
+# Platform specific Makefile for the boot block.
+#
+# PLATFORM is the target for the binary installation.
+#
+# PLATLINKS is a list of platforms which are to be linked to the ../fs
+# directory.
+#
+BASEDIR = ../../..
+PLATFORM = sun4v
+
+#PLATLINKS = SUNW,...
+
+#LINKED_DIRS = $(PLATLINKS:%=$(USR_PLAT_DIR)/%)
+#LINKED_LIB_DIRS = $(PLATLINKS:%=$(USR_PLAT_DIR)/%/lib)
+#LINKED_LIB_FS_DIRS = $(PLATLINKS:%=$(USR_PLAT_DIR)/%/lib/fs)
+
+include $(BASEDIR)/ufs/Makefile.ufs
+include $(BASEDIR)/Makefile.1275
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+include $(BASEDIR)/Makefile.targ
diff --git a/usr/src/psm/stand/bootblks/ufs/sparc/unix/Makefile b/usr/src/psm/stand/bootblks/ufs/sparc/unix/Makefile
new file mode 100644
index 0000000000..ae83da4aea
--- /dev/null
+++ b/usr/src/psm/stand/bootblks/ufs/sparc/unix/Makefile
@@ -0,0 +1,72 @@
+#
+# 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.
+#
+# 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 (c) 1994, by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# psm/stand/bootblks/ufs/sparc/unix/Makefile
+#
+
+#
+# Build the "Unix" version of the boot block.
+# Useful solely for testing. DO NOT INSTALL IT!
+#
+
+BASEDIR = ../../..
+PLATFORM = unix
+PLATFORM_INCS = ./
+PLATLINKS =
+
+include $(BASEDIR)/ufs/Makefile.ufs
+include $(BASEDIR)/obp-c/Makefile.rules
+
+CPPINCS += -I$(SRC)/head
+CPPINCS += -I$(SRC)/uts/common
+CPPINCS += -I$(SRC)/uts/sun
+CPPINCS += -I$(SRC)/uts/sparc
+CPPINCS += -I$(PLATFORM_INCS)
+
+UNIX_OBJS = ufs.o unix_devio.o
+
+$(UNIX_OBJS) := CFLAGS += -g
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+$(PROG): $(UNIX_OBJS)
+ $(CC) $(CFLAGS) $(CPPFLAGS) -g -o $@ $(UNIX_OBJS)
+
+lint: FRC
+
+clean:
+ $(RM) $(UNIX_OBJS)
+
+clobber: clean
+ $(RM) $(PROG)
+
+install: FRC
+
+FRC:
+
diff --git a/usr/src/psm/stand/cpr/Makefile b/usr/src/psm/stand/cpr/Makefile
new file mode 100644
index 0000000000..1c7ecca4ab
--- /dev/null
+++ b/usr/src/psm/stand/cpr/Makefile
@@ -0,0 +1,62 @@
+#
+# 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.
+#
+# 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 1994, 2002 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include $(SRC)/Makefile.master
+
+# All the real work gets done in kernel-architecture directories,
+# and that's where the targets wind up. This makefile just gets us there.
+
+sparcv9_ARCHITECTURES = sparcv9
+sparc_ARCHITECTURES = $(sparcv9_ARCHITECTURES)
+SUBDIRS = $($(MACH)_ARCHITECTURES)
+
+all := TARGET= all
+install := TARGET= install
+clean := TARGET= clean
+clobber := TARGET= clobber
+lint := TARGET= lint
+clean.lint := TARGET= clean.lint
+
+.KEEP_STATE:
+
+all install clean clobber lint clean.lint: $(SUBDIRS)
+
+TOPDIR= ../../..
+
+#
+# Cross-reference customization: include other relevant CPR-related code
+# in the cross-reference.
+#
+STANDDIR = $(TOPDIR)/stand
+XRDIRS += $(STANDDIR)/lib $(STANDDIR)/sys ../../promif \
+ $(TOPDIR)/uts/*/cpr $(TOPDIR)/uts/*/sys/cpr_*
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
diff --git a/usr/src/psm/stand/cpr/common/Makefile.com b/usr/src/psm/stand/cpr/common/Makefile.com
new file mode 100644
index 0000000000..aeeefbd7c0
--- /dev/null
+++ b/usr/src/psm/stand/cpr/common/Makefile.com
@@ -0,0 +1,147 @@
+#
+# 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.
+#
+# 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 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# psm/stand/cpr/common/Makefile.com
+#
+GREP = egrep
+WC = wc
+TOPDIR = ../../../../..
+
+include $(TOPDIR)/Makefile.master
+include $(TOPDIR)/Makefile.psm
+include $(TOPDIR)/psm/stand/lib/Makefile.lib
+
+SYSDIR = $(TOPDIR)/uts
+COMDIR = ../../common
+OSDIR = $(SYSDIR)/common/os
+ARCHDIR = $(SYSDIR)/$(ARCH)
+MACHDIR = $(SYSDIR)/$(MACH)
+MMUDIR = $(SYSDIR)/$(MMU)
+PROMLIBDIR= $(TOPDIR)/psm/stand/lib/promif/$(ARCH_PROMDIR)
+PROMLIB = $(PROMLIBDIR)/libprom.a
+
+SALIBS += $(PROMLIB)
+LDLIBS += -L$(PROMLIBDIR) -lprom
+LDFLAGS = -dn -M mapfile $(MAP_FLAG)
+
+LINTLIBS += $(PROMLIBDIR)/llib-lprom.ln
+LINTFLAGS.lib = -ysxmun
+
+CPRBOOTOBJ += support.o compress.o
+
+L_SRCS = $(COMDIR)/support.c $(OSDIR)/compress.c
+L_COBJ = $(CPRBOOTOBJ:%.o=%.ln)
+
+CPPDEFS = $(ARCHOPTS) -D$(ARCH) -D__$(ARCH) -D$(MACH) -D__$(MACH)
+CPPDEFS += -D_KERNEL -D_MACHDEP -D__ELF
+
+CPPINCS = -I. -I$(ARCHDIR) -I$(MMUDIR) -I$(MACHDIR)
+CPPINCS += -I$(MACHDIR)/$(ARCHVER) -I$(SYSDIR)/sun
+CPPINCS += -I$(SYSDIR)/sun4 -I$(SYSDIR)/common -I$(TOPDIR)/head
+
+CPPFLAGS = $(CPPDEFS) $(CPPINCS) $(CPPFLAGS.master)
+CPPFLAGS += $(CCYFLAG)$(SYSDIR)/common
+
+CFLAGS = $(CCVERBOSE) -O
+
+ASFLAGS = -P -D_ASM $(CPPDEFS) -DLOCORE -D_LOCORE -D__STDC__
+AS_CPPFLAGS = $(CPPINCS) $(CPPFLAGS.master)
+
+# install values
+CPRFILES= $(ALL:%=$(ROOT_PSM_DIR)/$(ARCH)/%)
+FILEMODE= 644
+OWNER= root
+GROUP= sys
+
+# lint stuff
+LINTFLAGS += -Dlint
+LOPTS = -hbxn
+
+# install rule
+$(ROOT_PSM_DIR)/$(ARCH)/%: %
+ $(INS.file)
+
+
+all: $(ALL)
+
+install: all $(CPRFILES)
+
+
+LINT.c= $(LINT) $(LINTFLAGS.c) $(LINT_DEFS) $(CPPFLAGS) -c
+LINT.s= $(LINT) $(LINTFLAGS.s) $(LINT_DEFS) $(CPPFLAGS) -c
+
+# build rule
+
+compress.o: $(OSDIR)/compress.c
+ $(COMPILE.c) $(OSDIR)/compress.c
+
+support.o: $(COMDIR)/support.c
+ $(COMPILE.c) $(COMDIR)/support.c
+
+compress.ln: $(OSDIR)/compress.c
+ @$(LHEAD) $(LINT.c) $(OSDIR)/compress.c $(LTAIL)
+
+support.ln: $(COMDIR)/support.c
+ @$(LHEAD) $(LINT.c) $(COMDIR)/support.c $(LTAIL)
+
+%.ln: %.c
+ @$(LHEAD) $(LINT.c) $< $(LTAIL)
+
+%.ln: %.s
+ @$(LHEAD) $(LINT.s) $< $(LTAIL)
+
+.KEEP_STATE:
+
+.PARALLEL: $(CPRBOOTOBJ) $(L_COBJ)
+
+cprboot: $(CPRBOOT_MAPFILE) $(CPRBOOTOBJ) $(SALIBS)
+ $(LD) $(LDFLAGS) -o $@ $(CPRBOOTOBJ) $(LDLIBS)
+ $(POST_PROCESS)
+
+$(SALIBS): FRC
+ @cd $(@D); $(MAKE) $(MFLAGS)
+
+$(LINTLIBS): FRC
+ @cd $(@D); $(MAKE) $(MFLAGS) $(@F)
+
+$(ROOTDIR):
+ $(INS.dir)
+
+lint: $(L_COBJ) $(LINTLIBS)
+ @$(ECHO) "\nperforming global crosschecks: $@"
+ @$(LINT.2) $(L_COBJ) $(LDLIBS)
+
+clean.lint:
+ $(RM) *.ln
+
+clean:
+ $(RM) *.o *.ln
+
+clobber:
+ $(RM) *.o *.ln $(ALL)
+
+FRC:
diff --git a/usr/src/psm/stand/cpr/common/support.c b/usr/src/psm/stand/cpr/common/support.c
new file mode 100644
index 0000000000..c0082cb770
--- /dev/null
+++ b/usr/src/psm/stand/cpr/common/support.c
@@ -0,0 +1,243 @@
+/*
+ * 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.
+ *
+ * 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 (c) 1987-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <sys/cpr.h>
+#include <sys/pte.h>
+#include <sys/promimpl.h>
+#include <sys/prom_plat.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;
+static int cpr_show_props = 0;
+
+
+/*
+ * Read the config file and pass back the file path, filesystem
+ * device path.
+ */
+int
+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) ||
+ cf.cf_magic != CPR_CONFIG_MAGIC)
+ return (-1);
+
+ (void) prom_strcpy(file_path, cf.cf_path);
+ (void) prom_strcpy(fs_path, cf.cf_dev_prom);
+
+ return (0);
+}
+
+
+/*
+ * Read the location of the state file from the root filesystem.
+ * Pass back to the caller the full device path of the filesystem
+ * and the filename relative to that fs.
+ */
+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) {
+ rc = cpr_read_cprinfo(fd, file_path, fs_path);
+ (void) cpr_ufs_close(fd);
+ } else
+ rc = -1;
+
+ return (rc);
+}
+
+
+/*
+ * Open the "defaults" file in the root fs and read the values of the
+ * properties saved during the checkpoint. Restore the values to nvram.
+ *
+ * Note: an invalid magic number in the "defaults" file means that the
+ * state file is bad or obsolete so our caller should not proceed with
+ * the resume.
+ */
+int
+cpr_reset_properties(void)
+{
+ char *str, *boot_path, *default_path;
+ int fd, len, rc, prop_errors;
+ cprop_t *prop, *tail;
+ cdef_t cdef;
+ dnode_t node;
+
+ 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);
+ return (-1);
+ }
+
+ rc = 0;
+ len = cpr_ufs_read(fd, (char *)&cdef, sizeof (cdef));
+ if (len != sizeof (cdef)) {
+ prom_printf("%s: error reading %s\n", str, default_path);
+ rc = -1;
+ } else if (cdef.mini.magic != CPR_DEFAULT_MAGIC) {
+ prom_printf("%s: bad magic number in %s\n", str, default_path);
+ rc = -1;
+ }
+
+ (void) cpr_ufs_close(fd);
+ if (rc)
+ return (rc);
+
+ node = prom_optionsnode();
+ if (node == OBP_NONODE || node == OBP_BADNODE) {
+ prom_printf("%s: cannot find \"options\" node\n");
+ return (-1);
+ }
+
+ /*
+ * reset nvram to the original property values
+ */
+ if (cpr_show_props)
+ prom_printf("\n\ncpr_show_props:\n");
+ for (prop_errors = 0, prop = cdef.props, tail = prop + CPR_MAXPROP;
+ prop < tail; prop++) {
+ if (cpr_show_props) {
+ prom_printf("mod=%c, name=\"%s\",\tvalue=\"%s\"\n",
+ prop->mod, prop->name, prop->value);
+ }
+ if (prop->mod != PROP_MOD)
+ continue;
+
+ len = prom_strlen(prop->value);
+ if (prom_setprop(node, prop->name, prop->value, len + 1) < 0 ||
+ prom_getproplen(node, prop->name) != len) {
+ prom_printf("%s: error setting \"%s\" to \"%s\"\n",
+ str, prop->name, prop->value);
+ prop_errors++;
+ }
+ }
+
+ return (prop_errors ? -1 : 0);
+}
+
+
+/*
+ * Read and verify cpr dump descriptor
+ */
+int
+cpr_read_cdump(int fd, cdd_t *cdp, ushort_t mach_type)
+{
+ char *str;
+ int nread;
+
+ str = "\ncpr_read_cdump:";
+ nread = cpr_read(fd, (caddr_t)cdp, sizeof (*cdp));
+ if (nread != sizeof (*cdp)) {
+ prom_printf("%s Error reading cpr dump descriptor\n", str);
+ return (-1);
+ }
+
+ if (cdp->cdd_magic != CPR_DUMP_MAGIC) {
+ prom_printf("%s bad dump magic 0x%x, expected 0x%x\n",
+ str, cdp->cdd_magic, CPR_DUMP_MAGIC);
+ return (-1);
+ }
+
+ if (cdp->cdd_version != CPR_VERSION) {
+ prom_printf("%s bad cpr version %d, expected %d\n",
+ str, cdp->cdd_version, CPR_VERSION);
+ return (-1);
+ }
+
+ if (cdp->cdd_machine != mach_type) {
+ prom_printf("%s bad machine type 0x%x, expected 0x%x\n",
+ str, cdp->cdd_machine, mach_type);
+ return (-1);
+ }
+
+ if (cdp->cdd_bitmaprec <= 0) {
+ prom_printf("%s bad bitmap %d\n", str, cdp->cdd_bitmaprec);
+ return (-1);
+ }
+
+ if (cdp->cdd_dumppgsize <= 0) {
+ prom_printf("%s Bad pg tot %d\n", str, cdp->cdd_dumppgsize);
+ return (-1);
+ }
+
+ cpr_debug = cdp->cdd_debug;
+
+ return (0);
+}
+
+
+/*
+ * update cpr dump terminator
+ */
+void
+cpr_update_terminator(ctrm_t *file_term, caddr_t mapva)
+{
+ ctrm_t *mem_term;
+
+ /*
+ * Add the offset to reach the terminator in the kernel so that we
+ * can directly change the restored kernel image.
+ */
+ mem_term = (ctrm_t *)(mapva + (file_term->va & MMU_PAGEOFFSET));
+
+ mem_term->real_statef_size = file_term->real_statef_size;
+ mem_term->tm_shutdown = file_term->tm_shutdown;
+ mem_term->tm_cprboot_start.tv_sec = file_term->tm_cprboot_start.tv_sec;
+ mem_term->tm_cprboot_end.tv_sec = prom_gettime() / 1000;
+}
+
+
+/*
+ * simple bcopy for cprboot
+ */
+void
+bcopy(const void *s, void *d, size_t count)
+{
+ const char *src = s;
+ char *dst = d;
+
+ while (count--)
+ *dst++ = *src++;
+}
diff --git a/usr/src/psm/stand/cpr/sparcv9/Makefile b/usr/src/psm/stand/cpr/sparcv9/Makefile
new file mode 100644
index 0000000000..b5030d3f65
--- /dev/null
+++ b/usr/src/psm/stand/cpr/sparcv9/Makefile
@@ -0,0 +1,47 @@
+#
+# 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.
+#
+# 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 (c) 1994-1997, by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# psm/stand/cpr/sparcv9/Makefile
+#
+
+SUBDIRS = sun4u
+
+all := TARGET= all
+install := TARGET= install
+clean := TARGET= clean
+clobber := TARGET= clobber
+lint := TARGET= lint
+clean.lint := TARGET= clean.lint
+
+.KEEP_STATE:
+
+all install clean clobber lint clean.lint: $(SUBDIRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
diff --git a/usr/src/psm/stand/cpr/sparcv9/sun4u/Makefile b/usr/src/psm/stand/cpr/sparcv9/sun4u/Makefile
new file mode 100644
index 0000000000..b687625d6d
--- /dev/null
+++ b/usr/src/psm/stand/cpr/sparcv9/sun4u/Makefile
@@ -0,0 +1,69 @@
+#
+# 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.
+#
+# 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 1995-1999,2002-2003 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+TOPDIR = ../../../../..
+
+# override global macros as necessary
+TARGET_ARCH = sun4u
+TARG_MACH = sparcv9
+ARCH = sun4u
+MACH = sparc
+MMU = sfmmu
+ARCHVER = v9
+PROMTYPE = ieee1275
+ARCH_PROMDIR = $(TARG_MACH)/$(PROMTYPE)/common
+PROMIFDIR = $(TOPDIR)/psm/stand/lib/promif
+PLATLIBDIR = $(PROMIFDIR)/$(TARG_MACH)/$(PROMTYPE)/$(TARGET_ARCH)
+PLATLIB = $(PLATLIBDIR)/libplat.a
+LDLIBS = -L$(PLATLIBDIR) -lplat
+SALIBS = $(PLATLIB)
+LINTLIBS = $(PLATLIBDIR)/llib-lplat.ln
+
+CPRBOOTOBJ = cb_srt0.o cprboot.o machdep.o pages.o bitmap.o util.o
+
+ALL = cprboot
+
+include ../../common/Makefile.com
+include $(TOPDIR)/psm/Makefile.psm.64
+CFLAGS64 += -xchip=ultra $(CCABS32)
+
+.KEEP_STATE:
+
+STANDDIR = $(TOPDIR)/stand
+CPPINCS += -I$(STANDDIR)
+
+#
+# Cross-reference customization: build a cross-reference over all of
+# the sun4u-related CPR source files.
+#
+XRDIRS += ../../common \
+ $(STANDDIR)/lib $(STANDDIR)/sys \
+ ../../../../promif/ieee1275 \
+ $(TOPDIR)/uts/common/os/compress.c \
+ $(TOPDIR)/uts/common/sys/cpr.h \
+ $(TOPDIR)/uts/sun4u/sys/cpr_impl.h
diff --git a/usr/src/psm/stand/cpr/sparcv9/sun4u/bitmap.c b/usr/src/psm/stand/cpr/sparcv9/sun4u/bitmap.c
new file mode 100644
index 0000000000..fd265db6d5
--- /dev/null
+++ b/usr/src/psm/stand/cpr/sparcv9/sun4u/bitmap.c
@@ -0,0 +1,599 @@
+/*
+ * 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.
+ *
+ * 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 1999-2002 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/cpr.h>
+#include <sys/fs/ufs_fs.h>
+#include <sys/prom_plat.h>
+#include "cprboot.h"
+
+
+/*
+ * max space for a copy of physavail data
+ * prop size is usually 80 to 128 bytes
+ */
+#define PA_BUFSIZE 1024
+
+#define CB_SETBIT 1
+#define CB_ISSET 2
+#define CB_ISCLR 3
+
+/*
+ * globals
+ */
+int cb_nbitmaps;
+
+/*
+ * file scope
+ */
+static arange_t *cb_physavail;
+static char pabuf[PA_BUFSIZE];
+static caddr_t high_virt;
+
+static cbd_t cb_bmda[CPR_MAX_BMDESC];
+static int tracking_init;
+
+
+static int
+cb_bitop(pfn_t ppn, int op)
+{
+ int rel, rval = 0;
+ char *bitmap;
+ cbd_t *dp;
+
+ for (dp = cb_bmda; dp->cbd_size; dp++) {
+ if (PPN_IN_RANGE(ppn, dp)) {
+ bitmap = (char *)dp->cbd_reg_bitmap;
+ rel = ppn - dp->cbd_spfn;
+ if (op == CB_SETBIT)
+ setbit(bitmap, rel);
+ else if (op == CB_ISSET)
+ rval = isset(bitmap, rel);
+ else if (op == CB_ISCLR)
+ rval = isclr(bitmap, rel);
+ break;
+ }
+ }
+
+ return (rval);
+}
+
+
+/*
+ * count pages that are isolated from the kernel
+ * within each available range
+ */
+static void
+count_free_pages(void)
+{
+ arange_t *arp;
+ pfn_t bitno;
+ int cnt;
+
+ for (arp = cb_physavail; arp->high; arp++) {
+ cnt = 0;
+ for (bitno = arp->low; bitno <= arp->high; bitno++) {
+ if (cb_bitop(bitno, CB_ISCLR))
+ cnt++;
+ }
+ arp->nfree = cnt;
+ }
+}
+
+
+/*
+ * scan the physavail list for a page
+ * that doesn't clash with the kernel
+ */
+static pfn_t
+search_phav_pages(void)
+{
+ static arange_t *arp;
+ static pfn_t bitno;
+ int rescan;
+
+ if (arp == NULL) {
+ count_free_pages();
+ arp = cb_physavail;
+ bitno = arp->low;
+ }
+
+ /*
+ * begin scanning from the previous position and if the scan
+ * reaches the end of the list, scan a second time from the top;
+ * nfree is checked to eliminate scanning overhead when most
+ * of the available space gets used up. when a page is found,
+ * set a bit so the page wont be found by another scan.
+ */
+ for (rescan = 0; rescan < 2; rescan++) {
+ for (; arp->high; bitno = (++arp)->low) {
+ if (arp->nfree == 0)
+ continue;
+ for (; bitno <= arp->high; bitno++) {
+ if (cb_bitop(bitno, CB_ISCLR)) {
+ (void) cb_bitop(bitno, CB_SETBIT);
+ arp->nfree--;
+ return (bitno++);
+ }
+ }
+ }
+ arp = cb_physavail;
+ bitno = arp->low;
+ }
+
+ return (PFN_INVALID);
+}
+
+
+/*
+ * scan statefile buffer pages for reusable tmp space
+ */
+static pfn_t
+search_buf_pages(void)
+{
+ size_t coff, src_base;
+ static size_t lboff;
+ pfn_t ppn;
+
+ if (tracking_init == 0)
+ return (PFN_INVALID);
+
+ /*
+ * when scanning the list of statefile buffer ppns, we know that
+ * all pages from lboff to the page boundary of buf_offset have
+ * already been restored; when the associated page bit is clear,
+ * that page is isolated from the kernel and we can reuse it for
+ * tmp space; otherwise, when SF_DIFF_PPN indicates a page had
+ * been moved, we know the page bit was previously clear and
+ * later set, and we can reuse the new page.
+ */
+ src_base = sfile.buf_offset & MMU_PAGEMASK;
+ while (lboff < src_base) {
+ coff = lboff;
+ lboff += MMU_PAGESIZE;
+ ppn = SF_ORIG_PPN(coff);
+ if (cb_bitop(ppn, CB_ISCLR)) {
+ (void) cb_bitop(ppn, CB_SETBIT);
+ SF_STAT_INC(recycle);
+ return (ppn);
+ } else if (SF_DIFF_PPN(coff)) {
+ SF_STAT_INC(recycle);
+ return (SF_BUF_PPN(coff));
+ }
+ }
+
+ return (PFN_INVALID);
+}
+
+
+/*
+ * scan physavail and statefile buffer page lists
+ * for a page that doesn't clash with the kernel
+ */
+pfn_t
+find_apage(void)
+{
+ pfn_t ppn;
+
+ ppn = search_phav_pages();
+ if (ppn != PFN_INVALID)
+ return (ppn);
+ ppn = search_buf_pages();
+ if (ppn != PFN_INVALID)
+ return (ppn);
+
+ prom_printf("\n%s: ran out of available/free pages!\n%s\n",
+ prog, rsvp);
+ cb_exit_to_mon();
+
+ /* NOTREACHED */
+ return (PFN_INVALID);
+}
+
+
+/*
+ * reserve virt range, find available phys pages,
+ * and map-in each phys starting at vaddr
+ */
+static caddr_t
+map_free_phys(caddr_t vaddr, size_t size, char *name)
+{
+ int pages, ppn, err;
+ physaddr_t phys;
+ caddr_t virt;
+ char *str;
+
+ str = "map_free_phys";
+ virt = prom_claim_virt(size, vaddr);
+ CB_VPRINTF(("\n%s: claim vaddr 0x%x, size 0x%x, ret 0x%x\n",
+ str, vaddr, size, virt));
+ if (virt != vaddr) {
+ prom_printf("\n%s: cant reserve (0x%p - 0x%p) for \"%s\"\n",
+ str, vaddr, vaddr + size, name);
+ return (virt);
+ }
+
+ for (pages = mmu_btop(size); pages--; virt += MMU_PAGESIZE) {
+ /*
+ * map virt page to free phys
+ */
+ ppn = find_apage();
+ phys = PN_TO_ADDR(ppn);
+
+ err = prom_map_phys(-1, MMU_PAGESIZE, virt, phys);
+ if (err || verbose) {
+ prom_printf(" map virt 0x%p, phys 0x%lx, "
+ "ppn 0x%lx, ret %d\n", virt, phys, ppn, err);
+ }
+ if (err)
+ return ((caddr_t)ERR);
+ }
+
+ return (vaddr);
+}
+
+
+/*
+ * check bitmap desc and relocate bitmap data
+ * to pages isolated from the kernel
+ *
+ * sets globals:
+ * high_virt
+ */
+int
+cb_set_bitmap(void)
+{
+ size_t bmda_size, all_bitmap_size, alloc_size;
+ caddr_t newvirt, src, dst, base;
+ cbd_t *dp;
+ char *str;
+
+ str = "cb_set_bitmap";
+ CB_VPRINTF((ent_fmt, str, entry));
+
+ /*
+ * max is checked in the cpr module;
+ * this condition should never occur
+ */
+ if (cb_nbitmaps > (CPR_MAX_BMDESC - 1)) {
+ prom_printf("%s: too many bitmap descriptors %d, max %d\n",
+ str, cb_nbitmaps, (CPR_MAX_BMDESC - 1));
+ return (ERR);
+ }
+
+ /*
+ * copy bitmap descriptors to aligned space, check magic numbers,
+ * and set the total size of all bitmaps
+ */
+ bmda_size = cb_nbitmaps * sizeof (cbd_t);
+ src = SF_DATA();
+ bcopy(src, cb_bmda, bmda_size);
+ base = src + bmda_size;
+ all_bitmap_size = 0;
+ for (dp = cb_bmda; dp < &cb_bmda[cb_nbitmaps]; dp++) {
+ if (dp->cbd_magic != CPR_BITMAP_MAGIC) {
+ prom_printf("%s: bad magic 0x%x, expect 0x%x\n",
+ str, dp->cbd_magic, CPR_BITMAP_MAGIC);
+ return (ERR);
+ }
+ all_bitmap_size += dp->cbd_size;
+ dp->cbd_reg_bitmap = (cpr_ptr)base;
+ base += dp->cbd_size;
+ }
+
+ /*
+ * reserve new space for bitmaps
+ */
+ alloc_size = PAGE_ROUNDUP(all_bitmap_size);
+ if (verbose || CPR_DBG(7)) {
+ prom_printf("%s: nbitmaps %d, bmda_size 0x%lx\n",
+ str, cb_nbitmaps);
+ prom_printf("%s: all_bitmap_size 0x%lx, alloc_size 0x%lx\n",
+ str, all_bitmap_size, alloc_size);
+ }
+ high_virt = (caddr_t)CB_HIGH_VIRT;
+ newvirt = map_free_phys(high_virt, alloc_size, "bitmaps");
+ if (newvirt != high_virt)
+ return (ERR);
+
+ /*
+ * copy the bitmaps, clear any unused space trailing them,
+ * and set references into the new space
+ */
+ base = src + bmda_size;
+ dst = newvirt;
+ bcopy(base, dst, all_bitmap_size);
+ if (alloc_size > all_bitmap_size)
+ bzero(dst + all_bitmap_size, alloc_size - all_bitmap_size);
+ for (dp = cb_bmda; dp->cbd_size; dp++) {
+ dp->cbd_reg_bitmap = (cpr_ptr)dst;
+ dst += dp->cbd_size;
+ }
+
+ /* advance past all the bitmap data */
+ SF_ADV(bmda_size + all_bitmap_size);
+ high_virt += alloc_size;
+
+ return (0);
+}
+
+
+/*
+ * create a new stack for cprboot;
+ * this stack is used to avoid clashes with kernel pages and
+ * to avoid exceptions while remapping cprboot virt pages
+ */
+int
+cb_get_newstack(void)
+{
+ caddr_t newstack;
+
+ CB_VENTRY(cb_get_newstack);
+ newstack = map_free_phys((caddr_t)CB_STACK_VIRT,
+ CB_STACK_SIZE, "new stack");
+ if (newstack != (caddr_t)CB_STACK_VIRT)
+ return (ERR);
+ return (0);
+}
+
+
+/*
+ * since kernel phys pages span most of the installed memory range,
+ * some statefile buffer pages will likely clash with the kernel
+ * and need to be moved before kernel pages are restored; a list
+ * of buf phys page numbers is created here and later updated as
+ * buf pages are moved
+ *
+ * sets globals:
+ * sfile.buf_map
+ * tracking_init
+ */
+int
+cb_tracking_setup(void)
+{
+ pfn_t ppn, lppn;
+ uint_t *imap;
+ caddr_t newvirt;
+ size_t size;
+ int pages;
+
+ CB_VENTRY(cb_tracking_setup);
+
+ pages = mmu_btop(sfile.size);
+ size = PAGE_ROUNDUP(pages * sizeof (*imap));
+ newvirt = map_free_phys(high_virt, size, "buf tracking");
+ if (newvirt != high_virt)
+ return (ERR);
+ sfile.buf_map = (uint_t *)newvirt;
+ high_virt += size;
+
+ /*
+ * create identity map of sfile.buf phys pages
+ */
+ imap = sfile.buf_map;
+ lppn = sfile.low_ppn + pages;
+ for (ppn = sfile.low_ppn; ppn < lppn; ppn++, imap++)
+ *imap = (uint_t)ppn;
+ tracking_init = 1;
+
+ return (0);
+}
+
+
+/*
+ * get "available" prop from /memory node
+ *
+ * sets globals:
+ * cb_physavail
+ */
+int
+cb_get_physavail(void)
+{
+ int len, glen, scnt, need, space;
+ char *str, *pdev, *mem_prop;
+ dnode_t mem_node;
+ physaddr_t phys;
+ pgcnt_t pages;
+ arange_t *arp;
+ pphav_t *pap;
+ size_t size;
+ pfn_t ppn;
+ int err;
+
+ str = "cb_get_physavail";
+ CB_VPRINTF((ent_fmt, str, entry));
+
+ /*
+ * first move cprboot pages off the physavail list
+ */
+ size = PAGE_ROUNDUP((uintptr_t)_end) - (uintptr_t)_start;
+ ppn = cpr_vatopfn((caddr_t)_start);
+ phys = PN_TO_ADDR(ppn);
+ err = prom_claim_phys(size, phys);
+ CB_VPRINTF((" text/data claim (0x%lx - 0x%lx) = %d\n",
+ ppn, ppn + mmu_btop(size) - 1, err));
+ if (err)
+ return (ERR);
+
+ pdev = "/memory";
+ mem_node = prom_finddevice(pdev);
+ if (mem_node == OBP_BADNODE) {
+ prom_printf("%s: cant find \"%s\" node\n", str, pdev);
+ return (ERR);
+ }
+ mem_prop = "available";
+
+ /*
+ * prop data is treated as a struct array;
+ * verify pabuf has enough room for the array
+ * in the original and converted forms
+ */
+ len = prom_getproplen(mem_node, mem_prop);
+ scnt = len / sizeof (*pap);
+ need = len + (sizeof (*arp) * (scnt + 1));
+ space = sizeof (pabuf);
+ CB_VPRINTF((" %s node 0x%x, len %d\n", pdev, mem_node, len));
+ if (len == -1 || need > space) {
+ prom_printf("\n%s: bad \"%s\" length %d, min %d, max %d\n",
+ str, mem_prop, len, need, space);
+ return (ERR);
+ }
+
+ /*
+ * read-in prop data and clear trailing space
+ */
+ glen = prom_getprop(mem_node, mem_prop, pabuf);
+ if (glen != len) {
+ prom_printf("\n%s: %s,%s: expected len %d, got %d\n",
+ str, mem_node, mem_prop, len, glen);
+ return (ERR);
+ }
+ bzero(&pabuf[len], space - len);
+
+ /*
+ * convert the physavail list in place
+ * from (phys_base, phys_size) to (low_ppn, high_ppn)
+ */
+ if (verbose)
+ prom_printf("\nphysavail list:\n");
+ cb_physavail = (arange_t *)pabuf;
+ arp = cb_physavail + scnt - 1;
+ pap = (pphav_t *)cb_physavail + scnt - 1;
+ for (; scnt--; pap--, arp--) {
+ pages = mmu_btop(pap->size);
+ arp->low = ADDR_TO_PN(pap->base);
+ arp->high = arp->low + pages - 1;
+ if (verbose) {
+ prom_printf(" %d: (0x%lx - 0x%lx),\tpages %d\n",
+ (int)(arp - cb_physavail),
+ arp->low, arp->high, (arp->high - arp->low + 1));
+ }
+ }
+
+ return (0);
+}
+
+
+/*
+ * search for an available phys page,
+ * copy the old phys page to the new one
+ * and remap the virt page to the new phys
+ */
+static int
+move_page(caddr_t vaddr, pfn_t oldppn)
+{
+ physaddr_t oldphys, newphys;
+ pfn_t newppn;
+ int err;
+
+ newppn = find_apage();
+ newphys = PN_TO_ADDR(newppn);
+ oldphys = PN_TO_ADDR(oldppn);
+ CB_VPRINTF((" remap vaddr 0x%p, old 0x%x/0x%x, new 0x%x/0x%x\n",
+ vaddr, oldppn, oldphys, newppn, newphys));
+ phys_xcopy(oldphys, newphys, MMU_PAGESIZE);
+ err = prom_remap(MMU_PAGESIZE, vaddr, newphys);
+ if (err)
+ prom_printf("\nmove_page: remap error\n");
+ return (err);
+}
+
+
+/*
+ * physically relocate any text/data pages that clash
+ * with the kernel; since we're already running on
+ * a new stack, the original stack area is skipped
+ */
+int
+cb_relocate(void)
+{
+ int is_ostk, is_clash, clash_cnt, ok_cnt;
+ char *str, *desc, *skip_fmt;
+ caddr_t ostk_low, ostk_high;
+ caddr_t virt, saddr, eaddr;
+ pfn_t ppn;
+
+ str = "cb_relocate";
+ CB_VPRINTF((ent_fmt, str, entry));
+
+ ostk_low = (caddr_t)&estack - CB_STACK_SIZE;
+ ostk_high = (caddr_t)&estack - MMU_PAGESIZE;
+ saddr = (caddr_t)_start;
+ eaddr = (caddr_t)PAGE_ROUNDUP((uintptr_t)_end);
+
+ install_remap();
+
+ skip_fmt = " skip vaddr 0x%p, clash=%d, %s\n";
+ clash_cnt = ok_cnt = 0;
+ ppn = cpr_vatopfn(saddr);
+
+ for (virt = saddr; virt < eaddr; virt += MMU_PAGESIZE, ppn++) {
+ is_clash = (cb_bitop(ppn, CB_ISSET) != 0);
+ if (is_clash)
+ clash_cnt++;
+ else
+ ok_cnt++;
+
+ is_ostk = (virt >= ostk_low && virt <= ostk_high);
+ if (is_ostk)
+ desc = "orig stack";
+ else
+ desc = "text/data";
+
+ /*
+ * page logic:
+ *
+ * if (original stack page)
+ * clash doesn't matter, just skip the page
+ * else (not original stack page)
+ * if (no clash)
+ * setbit to avoid later alloc and overwrite
+ * else (clash)
+ * relocate phys page
+ */
+ if (is_ostk) {
+ CB_VPRINTF((skip_fmt, virt, is_clash, desc));
+ } else if (is_clash == 0) {
+ CB_VPRINTF((skip_fmt, virt, is_clash, desc));
+ (void) cb_bitop(ppn, CB_SETBIT);
+ } else if (move_page(virt, ppn))
+ return (ERR);
+ }
+ CB_VPRINTF(("%s: total %d, clash %d, ok %d\n",
+ str, clash_cnt + ok_cnt, clash_cnt, ok_cnt));
+
+ /*
+ * free original stack area for reuse
+ */
+ ppn = cpr_vatopfn(ostk_low);
+ prom_free_phys(CB_STACK_SIZE, PN_TO_ADDR(ppn));
+ CB_VPRINTF(("%s: free old stack (0x%lx - 0x%lx)\n",
+ str, ppn, ppn + mmu_btop(CB_STACK_SIZE) - 1));
+
+ return (0);
+}
diff --git a/usr/src/psm/stand/cpr/sparcv9/sun4u/cb_srt0.s b/usr/src/psm/stand/cpr/sparcv9/sun4u/cb_srt0.s
new file mode 100644
index 0000000000..a75271d06c
--- /dev/null
+++ b/usr/src/psm/stand/cpr/sparcv9/sun4u/cb_srt0.s
@@ -0,0 +1,405 @@
+/*
+ * 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.
+ *
+ * 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 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * cb_srt0.s - cprboot startup code
+ */
+#include <sys/asm_linkage.h>
+#include <sys/machthread.h>
+#include <sys/privregs.h>
+#include <sys/cpr_impl.h>
+#include <sys/param.h>
+#include <sys/mmu.h>
+
+#if defined(lint)
+#include <sys/cpr.h>
+void *estack;
+caddr_t _end[1];
+#endif
+
+#include "cprboot.h"
+
+
+#if defined(lint)
+
+/* ARGSUSED */
+void
+_start(void *a, ...)
+{}
+
+#else /* !lint */
+
+ .seg ".bss"
+ .align MMU_PAGESIZE
+ .skip CB_SSS
+eslave_stack: ! top of slave cpu stack
+ .skip CB_MSS
+estack: ! top of cprboot stack
+ .global estack
+
+ .seg ".data"
+ .align 8
+local_cif:
+ .xword 0 ! space for prom cookie
+
+ .seg ".text"
+ .align 8
+
+ !
+ ! regs on entry:
+ ! %o4 = prom cookie
+ !
+ ENTRY(_start)
+ set estack - STACK_BIAS, %o5
+ save %o5, -SA(MINFRAME), %sp
+
+ !
+ ! clear the bss
+ !
+ set _edata, %o0
+ set _end, %g2
+ call bzero
+ sub %g2, %o0, %o1 ! bss size = (_end - _edata)
+
+ !
+ ! Set pstate to a known state:
+ ! enable fp, privilege, interrupt enable
+ !
+ wrpr %g0, PSTATE_PEF|PSTATE_PRIV|PSTATE_IE, %pstate
+
+ !
+ ! first stage
+ !
+ set local_cif, %g2
+ stx %i4, [%g2]
+ mov %i4, %o0 ! SPARCV9/CIF
+ call main ! Mcprboot [tag]
+ mov 1, %o1 ! first=true
+
+ !
+ ! switch to new stack
+ !
+ set CB_STACK_VIRT + CB_STACK_SIZE, %o5
+ sub %o5, STACK_BIAS + SA(MINFRAME), %sp
+
+ !
+ ! second stage
+ !
+ set local_cif, %g2
+ ldx [%g2], %o0 ! SPARCV9/CIF
+ call main ! Mcprboot [tag]
+ mov 0, %o1 ! first=false
+
+ call prom_exit_to_mon ! can't happen... :-)
+ nop
+ SET_SIZE(_start)
+
+#endif /* lint */
+
+
+#if defined(lint)
+
+/*
+ * args from cprboot main:
+ * %o0 prom cookie
+ * %o1 struct sun4u_machdep *mdp
+ *
+ * Any change to this register assignment requires
+ * changes to uts/sun4u/ml/cpr_resume_setup.s
+ */
+
+/* ARGSUSED */
+void
+exit_to_kernel(void *cookie, csu_md_t *mdp)
+{}
+
+#else /* lint */
+
+ ENTRY(exit_to_kernel)
+ !
+ ! setup temporary stack and adjust
+ ! by the saved kernel stack bias
+ !
+ set tmp_stack, %g1 ! g1 = &tmp_stack
+ ldx [%g1], %l2 ! l2 = tmp_stack
+ sub %l2, SA(MINFRAME), %l2
+ ld [%o1 + CPR_MD_KSB], %l4 ! mdp->ksb
+ sub %l2, %l4, %sp
+
+ !
+ ! set pstate and wstate from saved values
+ !
+ lduh [%o1 + CPR_MD_KPSTATE], %l4 ! l4 = mdp->kpstate
+ wrpr %g0, %l4, %pstate
+ lduh [%o1 + CPR_MD_KWSTATE], %l4 ! l4 = mdp->kwstate
+ wrpr %g0, %l4, %wstate
+
+ !
+ ! jump to kernel with %o0 and %o1 unchanged
+ !
+ ldx [%o1 + CPR_MD_FUNC], %l3 ! l3 = mdp->func
+ jmpl %l3, %g0
+ nop
+
+ /* there is no return from here */
+ unimp 0
+ SET_SIZE(exit_to_kernel)
+
+#endif /* lint */
+
+
+#if defined(lint)
+
+/* ARGSUSED */
+int
+client_handler(void *cif_handler, void *arg_array)
+{ return (0); }
+
+#else
+
+ !
+ ! 64/64 client interface for ieee1275 prom
+ !
+ ENTRY(client_handler)
+ mov %o7, %g1
+ mov %o0, %g5
+ mov %o1, %o0
+ jmp %g5
+ mov %g1, %o7
+ SET_SIZE(client_handler)
+
+#endif /* lint */
+
+
+#if defined(lint)
+
+/* ARGSUSED */
+void
+bzero(void *base, size_t len)
+{}
+
+#else
+
+ ENTRY(bzero)
+ brz,pn %o1, 2f
+ nop
+ mov %o0, %o2
+ mov %o1, %o3
+1:
+ stub %g0, [%o2]
+ dec %o3
+ brgz,pt %o3, 1b
+ inc %o2
+2:
+ retl
+ nop
+ SET_SIZE(bzero)
+
+#endif /* lint */
+
+
+#if defined(lint)
+
+/* ARGSUSED */
+void
+phys_xcopy(physaddr_t phys_src, physaddr_t phys_dst, size_t len)
+{}
+
+#else
+
+ !
+ ! copy len bytes from src to dst phys addrs;
+ ! requires src/dst/len 8-byte alignment;
+ ! used only for copying phys pages
+ !
+ ENTRY(phys_xcopy)
+ brz,pn %o2, 2f
+ mov %o0, %o3 ! %o3 = src
+ mov %o1, %o4 ! %o4 = dst
+1:
+ ldxa [%o3]ASI_MEM, %o5 ! %o5 = *src
+ stxa %o5, [%o4]ASI_MEM ! *dst = %o5
+ dec 8, %o2 ! len -= 8
+ inc 8, %o3 ! src += 8
+ brgz,pt %o2, 1b ! branch when (len > 0)
+ inc 8, %o4 ! dst += 8
+2:
+ retl
+ nop
+ SET_SIZE(phys_xcopy)
+
+#endif
+
+
+#if defined(lint)
+
+/* ARGSUSED */
+void
+get_dtlb_entry(int index, caddr_t *vaddrp, tte_t *tte)
+{}
+
+#else /* lint */
+
+ ENTRY(get_dtlb_entry)
+ sllx %o0, 3, %o0
+ ldxa [%o0]ASI_DTLB_ACCESS, %o3
+ stx %o3, [%o2]
+ ldxa [%o0]ASI_DTLB_TAGREAD, %o4
+ retl
+ stx %o4, [%o1]
+ SET_SIZE(get_dtlb_entry)
+
+#endif
+
+
+#if defined(lint)
+
+/* ARGSUSED */
+void
+set_itlb_entry(int index, caddr_t vaddr, tte_t *tte)
+{}
+
+/* ARGSUSED */
+void
+set_dtlb_entry(int index, caddr_t vaddr, tte_t *tte)
+{}
+
+#else /* lint */
+
+ ENTRY(set_dtlb_entry)
+ sllx %o0, 3, %o0
+ srlx %o1, MMU_PAGESHIFT, %o1
+ sllx %o1, MMU_PAGESHIFT, %o1
+ set MMU_TAG_ACCESS, %o4
+ ldx [%o2], %o3
+ stxa %o1, [%o4]ASI_DMMU
+ stxa %o3, [%o0]ASI_DTLB_ACCESS
+ membar #Sync
+ retl
+ nop
+ SET_SIZE(set_dtlb_entry)
+
+ ENTRY(set_itlb_entry)
+ sllx %o0, 3, %o0
+ srlx %o1, MMU_PAGESHIFT, %o1
+ sllx %o1, MMU_PAGESHIFT, %o1
+ set MMU_TAG_ACCESS, %o4
+ ldx [%o2], %o3
+ stxa %o1, [%o4]ASI_IMMU
+ stxa %o3, [%o0]ASI_ITLB_ACCESS
+ membar #Sync
+ retl
+ nop
+ SET_SIZE(set_itlb_entry)
+
+#endif
+
+
+#if defined(lint)
+
+uint_t
+getmid(void)
+{ return (0); }
+
+#else /* lint */
+
+ ENTRY(getmid)
+ CPU_INDEX(%o0, %o1)
+ retl
+ nop
+ SET_SIZE(getmid)
+
+#endif
+
+
+#if defined(lint)
+
+/* ARGSUSED */
+void
+cpu_launch(int cpuid)
+{
+ slave_init(cpuid);
+}
+
+#else /* lint */
+
+ ENTRY(cpu_launch)
+ set CB_STACK_VIRT + CB_SSS, %o5
+ sub %o5, STACK_BIAS + SA(MINFRAME), %sp
+ wrpr %g0, PSTATE_PEF|PSTATE_PRIV|PSTATE_IE, %pstate
+ call slave_init
+ nop
+ unimp 0
+ SET_SIZE(cpu_launch)
+
+#endif
+
+
+#if defined(lint)
+
+void
+membar_stld(void)
+{}
+
+#else /* lint */
+
+ ENTRY(membar_stld)
+ retl
+ membar #StoreLoad
+ SET_SIZE(membar_stld)
+
+#endif
+
+
+#if defined(lint)
+
+/* ARGSUSED */
+void
+cb_usec_wait(int usecs)
+{}
+
+#else
+
+ .align 32 ! cache alignment for next 8 instr
+ ENTRY(cb_usec_wait)
+
+ sethi %hi(cpu_delay), %o1
+ ld [%o1 + %lo(cpu_delay)], %o1
+ mov %o1, %o2
+1: brnz,pt %o2, 1b ! usec countdown loop
+ dec %o2 ! 2 instr in loop
+
+ dec %o0 ! for each usec:
+ brgz,pt %o0, 1b ! run the above loop
+ mov %o1, %o2
+
+ retl
+ nop
+ SET_SIZE(cb_usec_wait)
+
+#endif
diff --git a/usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.c b/usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.c
new file mode 100644
index 0000000000..d622b1e594
--- /dev/null
+++ b/usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.c
@@ -0,0 +1,577 @@
+/*
+ * 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.
+ *
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * cprboot - prom client that restores kadb/kernel pages
+ *
+ * simple cprboot overview:
+ * reset boot-file/boot-device to their original values
+ * open cpr statefile, usually "/.CPR"
+ * read in statefile
+ * close statefile
+ * restore kernel pages
+ * jump back into kernel text
+ *
+ *
+ * cprboot supports a restartable statefile for FAA/STARS,
+ * Federal Aviation Administration
+ * Standard Terminal Automation Replacement System
+ */
+
+#include <sys/types.h>
+#include <sys/cpr.h>
+#include <sys/promimpl.h>
+#include <sys/ddi.h>
+#include "cprboot.h"
+
+
+/*
+ * local defs
+ */
+#define CB_MAXPROP 256
+#define CB_MAXARGS 8
+
+
+/*
+ * globals
+ */
+struct statefile sfile;
+
+char cpr_statefile[OBP_MAXPATHLEN];
+char cpr_filesystem[OBP_MAXPATHLEN];
+
+int cpr_debug; /* cpr debug, set with uadmin 3 10x */
+uint_t cb_msec; /* cprboot start runtime */
+uint_t cb_dents; /* number of dtlb entries */
+
+int do_halt = 0; /* halt (enter mon) after load */
+int verbose = 0; /* verbose, traces cprboot ops */
+
+char rsvp[] = "please reboot";
+char prog[] = "cprboot";
+char entry[] = "ENTRY";
+char ent_fmt[] = "\n%s %s\n";
+
+
+/*
+ * file scope
+ */
+static char cb_argbuf[CB_MAXPROP];
+static char *cb_args[CB_MAXARGS];
+
+static int reusable;
+static char *specialstate;
+
+
+static int
+cb_intro(void)
+{
+ static char cstr[] = "\014" "\033[1P" "\033[18;21H";
+
+ CB_VENTRY(cb_intro);
+
+ /*
+ * build/debug aid; this condition should not occur
+ */
+ if ((uintptr_t)_end > CB_SRC_VIRT) {
+ prom_printf("\ndata collision:\n"
+ "(_end=0x%p > CB_LOW_VIRT=0x%p), recompile...\n",
+ _end, CB_SRC_VIRT);
+ return (ERR);
+ }
+
+ /* clear console */
+ prom_printf(cstr);
+
+ prom_printf("Restoring the System. Please Wait... ");
+ return (0);
+}
+
+
+/*
+ * read bootargs and convert to arg vector
+ *
+ * sets globals:
+ * cb_argbuf
+ * cb_args
+ */
+static void
+get_bootargs(void)
+{
+ char *cp, *tail, *argp, **argv;
+
+ CB_VENTRY(get_bootargs);
+
+ (void) prom_strcpy(cb_argbuf, prom_bootargs());
+ tail = cb_argbuf + prom_strlen(cb_argbuf);
+
+ /*
+ * scan to the trailing NULL so the last arg
+ * will be found without any special-case code
+ */
+ argv = cb_args;
+ for (cp = argp = cb_argbuf; cp <= tail; cp++) {
+ if (prom_strchr(" \t\n\r", *cp) == NULL)
+ continue;
+ *cp = '\0';
+ if (cp - argp) {
+ *argv++ = argp;
+ if ((argv - cb_args) == (CB_MAXARGS - 1))
+ break;
+ }
+ argp = cp + 1;
+ }
+ *argv = NULLP;
+
+ if (verbose) {
+ for (argv = cb_args; *argv; argv++) {
+ prom_printf(" %d: \"%s\"\n",
+ (argv - cb_args), *argv);
+ }
+ }
+}
+
+
+static void
+usage(char *expect, char *got)
+{
+ if (got == NULL)
+ got = "(NULL)";
+ prom_printf("\nbad OBP boot args: expect %s, got %s\n"
+ "Usage: boot -F %s [-R] [-S <diskpath>]\n%s\n\n",
+ expect, got, prog, rsvp);
+ prom_exit_to_mon();
+}
+
+
+/*
+ * bootargs should start with "-F cprboot"
+ *
+ * may set globals:
+ * specialstate
+ * reusable
+ * do_halt
+ * verbose
+ */
+static void
+check_bootargs(void)
+{
+ char **argv, *str, *cp;
+
+ argv = cb_args;
+
+ /* expect "-F" */
+ str = "-F";
+ if (*argv == NULL || prom_strcmp(*argv, str))
+ usage(str, *argv);
+ argv++;
+
+ /* expect "cprboot*" */
+ if (*argv == NULL || prom_strncmp(*argv, prog, sizeof (prog) - 1))
+ usage(prog, *argv);
+
+ /*
+ * optional args
+ */
+ str = "-[SR]";
+ for (argv++; *argv; argv++) {
+ cp = *argv;
+ if (*cp != '-')
+ usage(str, *argv);
+
+ switch (*++cp) {
+ case 'R':
+ case 'r':
+ reusable = 1;
+ break;
+ case 'S':
+ case 's':
+ if (*++argv)
+ specialstate = *argv;
+ else
+ usage("statefile-path", *argv);
+ break;
+ case 'h':
+ do_halt = 1;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ usage(str, *argv);
+ break;
+ }
+ }
+}
+
+
+/*
+ * reset prom props and get statefile info
+ *
+ * sets globals:
+ * cpr_filesystem
+ * cpr_statefile
+ */
+static int
+cb_startup(void)
+{
+ CB_VENTRY(cb_startup);
+
+ if (!reusable) {
+ /*
+ * Restore the original values of the nvram properties modified
+ * during suspend. Note: if we can't get this info from the
+ * defaults file, the state file may be obsolete or bad, so we
+ * abort. However, failure to restore one or more properties
+ * is NOT fatal (better to continue the resume).
+ */
+ if (cpr_reset_properties() == -1) {
+ prom_printf("\n%s: cannot read saved "
+ "nvram info, %s\n", prog, rsvp);
+ return (ERR);
+ }
+ }
+
+ /*
+ * simple copy if using specialstate,
+ * otherwise read in fs and statefile from a config file
+ */
+ if (specialstate)
+ (void) prom_strcpy(cpr_statefile, specialstate);
+ else if (cpr_locate_statefile(cpr_statefile, cpr_filesystem) == -1) {
+ prom_printf("\n%s: cannot find cpr statefile, %s\n",
+ prog, rsvp);
+ return (ERR);
+ }
+
+ return (0);
+}
+
+
+static int
+cb_open_sf(void)
+{
+ CB_VENTRY(cb_open_sf);
+
+ sfile.fd = cpr_statefile_open(cpr_statefile, cpr_filesystem);
+ if (sfile.fd == -1) {
+ prom_printf("\n%s: can't open %s", prog, cpr_statefile);
+ if (specialstate)
+ prom_printf(" on %s", cpr_filesystem);
+ prom_printf("\n%s\n", rsvp);
+ return (ERR);
+ }
+
+ /*
+ * for block devices, seek past the disk label and bootblock
+ */
+ if (specialstate)
+ (void) prom_seek(sfile.fd, CPR_SPEC_OFFSET);
+
+ return (0);
+}
+
+
+static int
+cb_close_sf(void)
+{
+ CB_VENTRY(cb_close_sf);
+
+ /*
+ * close the device so the prom will free up 20+ pages
+ */
+ (void) cpr_statefile_close(sfile.fd);
+ return (0);
+}
+
+
+/*
+ * to restore kernel pages, we have to open a prom device to read-in
+ * the statefile contents; a prom "open" request triggers the driver
+ * and various packages to allocate 20+ pages; unfortunately, some or
+ * all of those pages always clash with kernel pages, and we cant write
+ * to them without corrupting the prom.
+ *
+ * to solve that problem, the only real solution is to close the device
+ * to free up those pages; this means we need to open, read-in the entire
+ * statefile, and close; and to store the statefile, we need to allocate
+ * plenty of space, usually around 2 to 60 MB.
+ *
+ * the simplest alloc means is prom_alloc(), which will "claim" both
+ * virt and phys pages, and creates mappings with a "map" request;
+ * "map" also causes the prom to alloc pages, and again these clash
+ * with kernel pages...
+ *
+ * to solve the "map" problem, we just reserve virt and phys pages and
+ * manage the translations by creating our own tlb entries instead of
+ * relying on the prom.
+ *
+ * sets globals:
+ * cpr_test_mode
+ * sfile.kpages
+ * sfile.size
+ * sfile.buf
+ * sfile.low_ppn
+ * sfile.high_ppn
+ */
+static int
+cb_read_statefile(void)
+{
+ size_t alsize, len, resid;
+ physaddr_t phys, dst_phys;
+ char *str, *dst_virt;
+ int err, cnt, mmask;
+ uint_t dtlb_index;
+ ssize_t nread;
+ cdd_t cdump;
+
+ str = "cb_read_statefile";
+ CB_VPRINTF((ent_fmt, str, entry));
+
+ /*
+ * read-in and check cpr dump header
+ */
+ if (cpr_read_cdump(sfile.fd, &cdump, CPR_MACHTYPE_4U))
+ return (ERR);
+ if (cpr_debug)
+ prom_printf("\n");
+ cb_nbitmaps = cdump.cdd_bitmaprec;
+ cpr_test_mode = cdump.cdd_test_mode;
+ sfile.kpages = cdump.cdd_dumppgsize;
+ DEBUG4(prom_printf("%s: total kpages %d\n", prog, sfile.kpages));
+
+ /*
+ * alloc virt and phys space with 512K alignment;
+ * alloc size should be (n * tte size);
+ */
+ sfile.size = PAGE_ROUNDUP(cdump.cdd_filesize);
+ alsize = (cdump.cdd_filesize + MMU_PAGEOFFSET512K) &
+ MMU_PAGEMASK512K;
+ phys = 0;
+ err = cb_alloc(alsize, MMU_PAGESIZE512K, &sfile.buf, &phys);
+ CB_VPRINTF(("%s:\n alloc size 0x%lx, buf size 0x%lx\n"
+ " virt 0x%p, phys 0x%lx\n",
+ str, alsize, sfile.size, sfile.buf, phys));
+ if (err) {
+ prom_printf("%s: cant alloc statefile buf, size 0x%lx\n%s\n",
+ str, sfile.size, rsvp);
+ return (ERR);
+ }
+
+ /*
+ * record low and high phys page numbers for sfile.buf
+ */
+ sfile.low_ppn = ADDR_TO_PN(phys);
+ sfile.high_ppn = sfile.low_ppn + mmu_btop(sfile.size) - 1;
+
+ /*
+ * setup destination virt and phys addrs for reads;
+ * mapin-mask tells when to create a new tlb entry for the
+ * next set of reads; NB: the read and tlb method needs
+ * ((big-pagesize % read-size) == 0)
+ */
+ dst_phys = phys;
+ mmask = (MMU_PAGESIZE512K / PROM_MAX_READ) - 1;
+
+ cnt = 0;
+ dtlb_index = cb_dents - 1;
+ (void) prom_seek(sfile.fd, specialstate ? CPR_SPEC_OFFSET : 0);
+ DEBUG1(prom_printf("%s: reading statefile... ", prog));
+ for (resid = cdump.cdd_filesize; resid; resid -= len) {
+ /*
+ * do a full spin (4 spin chars)
+ * for every MB read (8 reads = 256K)
+ */
+ if ((cnt & 0x7) == 0)
+ cb_spin();
+
+ /*
+ * map-in statefile buf pages in 512K blocks;
+ * see MMU_PAGESIZE512K above
+ */
+ if ((cnt & mmask) == 0) {
+ dst_virt = sfile.buf;
+ cb_mapin(dst_virt, ADDR_TO_PN(dst_phys),
+ TTE512K, TTE_HWWR_INT, dtlb_index);
+ }
+
+ cnt++;
+
+ len = min(PROM_MAX_READ, resid);
+ nread = prom_read(sfile.fd, dst_virt, len, 0, 0);
+ if (nread != (ssize_t)len) {
+ prom_printf("\n%s: prom read error, "
+ "expect %ld, got %ld\n", str, len, nread);
+ return (ERR);
+ }
+ dst_virt += len;
+ dst_phys += len;
+ }
+ DEBUG1(prom_printf(" \b\n"));
+
+ /*
+ * free up any unused phys pages trailing the statefile buffer;
+ * these pages will later appear on the physavail list
+ */
+ if (alsize > sfile.size) {
+ len = alsize - sfile.size;
+ prom_free_phys(len, phys + sfile.size);
+ CB_VPRINTF(("%s: freed %ld phys pages (0x%lx - 0x%lx)\n",
+ str, mmu_btop(len), phys + sfile.size, phys + alsize));
+ }
+
+ /*
+ * start the statefile buffer offset at the base of
+ * the statefile buffer and skip past the dump header
+ */
+ sfile.buf_offset = 0;
+ SF_ADV(sizeof (cdump));
+
+ /*
+ * finish with the first block mapped-in to provide easy virt access
+ * to machdep structs and the bitmap; for 2.8, the combined size of
+ * (cdd_t + cmd_t + csu_md_t + prom_words + cbd_t) is about 1K,
+ * leaving room for a bitmap representing nearly 32GB
+ */
+ cb_mapin(sfile.buf, sfile.low_ppn,
+ TTE512K, TTE_HWWR_INT, dtlb_index);
+
+ return (0);
+}
+
+
+/*
+ * cprboot first stage worklist
+ */
+static int (*first_worklist[])(void) = {
+ cb_intro,
+ cb_startup,
+ cb_get_props,
+ cb_usb_setup,
+ cb_open_sf,
+ cb_read_statefile,
+ cb_close_sf,
+ cb_check_machdep,
+ cb_interpret,
+ cb_get_physavail,
+ cb_set_bitmap,
+ cb_get_newstack,
+ NULL
+};
+
+/*
+ * cprboot second stage worklist
+ */
+static int (*second_worklist[])(void) = {
+ cb_relocate,
+ cb_tracking_setup,
+ cb_restore_kpages,
+ cb_terminator,
+ cb_ksetup,
+ cb_mpsetup,
+ NULL
+};
+
+
+/*
+ * simple loop driving major cprboot operations;
+ * exits to prom if any error is returned
+ */
+static void
+cb_drive(int (**worklist)(void))
+{
+ int i;
+
+ for (i = 0; worklist[i] != NULL; i++) {
+ if (worklist[i]())
+ cb_exit_to_mon();
+ }
+}
+
+
+/*
+ * debugging support: drop to prom if do_halt is set
+ */
+static void
+check_halt(char *str)
+{
+ if (do_halt) {
+ prom_printf("\n%s halted by -h flag\n==> before %s\n\n",
+ prog, str);
+ cb_enter_mon();
+ }
+}
+
+
+/*
+ * main is called twice from "cb_srt0.s", args are:
+ * cookie ieee1275 cif handle
+ * first (true): first stage, (false): second stage
+ *
+ * first stage summary:
+ * various setup
+ * allocate a big statefile buffer
+ * read in the statefile
+ * setup the bitmap
+ * create a new stack
+ *
+ * return to "cb_srt0.s", switch to new stack
+ *
+ * second stage summary:
+ * relocate cprboot phys pages
+ * setup tracking for statefile buffer pages
+ * restore kernel pages
+ * various cleanup
+ * install tlb entries for the nucleus and cpr module
+ * restore registers and jump into cpr module
+ */
+int
+main(void *cookie, int first)
+{
+ if (first) {
+ prom_init(prog, cookie);
+ cb_msec = prom_gettime();
+ get_bootargs();
+ check_bootargs();
+ check_halt("first_worklist");
+ cb_drive(first_worklist);
+ return (0);
+ } else {
+ cb_drive(second_worklist);
+ if (verbose || CPR_DBG(1)) {
+ prom_printf("%s: milliseconds %d\n",
+ prog, prom_gettime() - cb_msec);
+ prom_printf("%s: resume pc 0x%p\n", prog, mdinfo.func);
+ prom_printf("%s: exit_to_kernel(0x%p, 0x%p)\n\n",
+ prog, cookie, &mdinfo);
+ }
+ check_halt("exit_to_kernel");
+ exit_to_kernel(cookie, &mdinfo);
+ return (ERR);
+ }
+}
diff --git a/usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.h b/usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.h
new file mode 100644
index 0000000000..52807b6616
--- /dev/null
+++ b/usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.h
@@ -0,0 +1,259 @@
+/*
+ * 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.
+ *
+ * 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 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _CPRBOOT_H
+#define _CPRBOOT_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * defs for sun4u cprboot
+ */
+
+/*
+ * select virt ranges well past _end;
+ * these ranges are used for tmp tlb entries
+ *
+ * CB_SRC_VIRT source statefile buffer pages
+ * CB_DST_VIRT destination kernel pages
+ * CB_STACK_VIRT new stack
+ * CB_HIGH_VIRT ...and above for the bitmap and co.
+ */
+
+#define CB_SRC_VIRT 0x200000
+#define CB_DST_VIRT 0x300000
+#define CB_STACK_VIRT 0x400000
+#define CB_HIGH_VIRT 0x500000
+
+/*
+ * master cpu and slave cpu stack sizes
+ * their sum should be (n * MMU_PAGESIZE)
+ */
+#define CB_MSS 0x009000
+#define CB_SSS 0x001000
+#define CB_STACK_SIZE (CB_MSS + CB_SSS)
+
+
+/*
+ * max number of tlb entries and tmp pages for
+ * src statefile buf pages and dst kernel pages
+ */
+#define CB_MAX_KPAGES mmu_btop(CPR_MAX_BLOCK)
+#define CB_MAX_BPAGES (CB_MAX_KPAGES + 1)
+
+#define ERR -1
+
+
+#ifndef _ASM
+
+#define CB_VPRINTF(args) \
+ if (verbose) prom_printf args
+
+#define CB_VENTRY(name) \
+ CB_VPRINTF((ent_fmt, #name, entry))
+
+#define NULLP (char *)0
+
+#define CPR_DBG(n) (cpr_debug & LEVEL##n)
+
+
+/*
+ * info for handling statefile data
+ */
+struct statefile {
+ int fd; /* prom file handle */
+ int kpages; /* total number of kernel pages */
+ size_t size; /* file size, rounded for alloc */
+ caddr_t buf; /* allocated file buffer */
+ size_t buf_offset; /* byte offset from buf */
+ uint_t *buf_map; /* map of buf phys page numbers */
+ pfn_t low_ppn; /* lowest buf ppn */
+ pfn_t high_ppn; /* highest buf ppn */
+ int npages; /* nubmer of pages restored */
+ int ngroups; /* number of page groups restored */
+ int outside; /* kpage is outside of buf range */
+ int precede; /* kpage preceeds buf offset */
+ int move; /* number of buf pages moved */
+ int recycle; /* free tmp page for reuse */
+};
+
+/*
+ * convert a statefile buffer byte-offset into a buffer ppn;
+ * buf_map starts out as an identity map, and gets updated as
+ * pages are moved; the original ppn can always be derived
+ * from the ORIG macro:
+ */
+#define SF_BUF_PPN(off) *(sfile.buf_map + mmu_btop(off))
+#define SF_ORIG_PPN(off) sfile.low_ppn + mmu_btop(off)
+#define SF_SAME_PPN(off) (SF_BUF_PPN(off) == SF_ORIG_PPN(off))
+#define SF_DIFF_PPN(off) (SF_BUF_PPN(off) != SF_ORIG_PPN(off))
+
+#define SF_STAT_INC(field) sfile.field++
+
+
+/*
+ * next data in statefile buffer
+ */
+#define SF_DATA() sfile.buf + sfile.buf_offset
+
+/*
+ * advance statefile buffer offset
+ */
+#define SF_ADV(len) sfile.buf_offset += len
+
+/*
+ * struct data is written to the statefile without any alignment
+ * handling; for easy access, struct data gets copied to aligned
+ * space and the buf data pointer is advanced
+ */
+#define SF_DCOPY(space) \
+ bcopy(SF_DATA(), &space, sizeof (space)); \
+ SF_ADV(sizeof (space))
+
+
+/*
+ * structure of "available" property from /memory node
+ */
+struct prom_physavail {
+ physaddr_t base; /* start of phys range */
+ size_t size; /* size of phys range */
+};
+
+struct avail_range {
+ pfn_t low;
+ pfn_t high;
+ pgcnt_t nfree;
+};
+
+typedef struct prom_physavail pphav_t;
+typedef struct avail_range arange_t;
+
+
+/*
+ * prom properties and data
+ */
+struct cb_props {
+ caddr_t prop;
+ uint_t *datap;
+};
+
+
+/*
+ * ../../common/support.c
+ */
+extern int cpr_reset_properties(void);
+extern int cpr_locate_statefile(char *, char *);
+extern void cpr_update_terminator(ctrm_t *, caddr_t);
+
+/*
+ * cprboot.c
+ */
+extern struct statefile sfile;
+extern char prog[];
+extern char rsvp[];
+extern char entry[];
+extern char ent_fmt[];
+extern int verbose;
+extern uint_t cb_dents;
+extern uint_t cb_msec;
+
+/*
+ * machdep.c
+ */
+extern int cpr_test_mode;
+extern csu_md_t mdinfo;
+extern uint_t cpu_delay;
+extern uint_t cb_mid;
+extern uint_t cb_clock_freq;
+extern int cb_check_machdep(void);
+extern int cb_interpret(void);
+extern int cb_ksetup(void);
+extern int cb_mpsetup(void);
+extern void slave_init(int);
+
+/*
+ * pages.c
+ */
+extern int cb_restore_kpages(void);
+extern int cb_terminator(void);
+
+/*
+ * bitmap.c
+ */
+extern int cb_nbitmaps;
+extern pfn_t find_apage(void);
+extern int cb_set_bitmap(void);
+extern int cb_get_newstack(void);
+extern int cb_tracking_setup(void);
+extern int cb_get_physavail(void);
+extern int cb_relocate(void);
+
+/*
+ * util.c
+ */
+extern int cpr_statefile_open(char *, char *);
+extern int cpr_statefile_close(int);
+extern int cpr_read(int, caddr_t, size_t);
+extern void cb_spin(void);
+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_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);
+
+/*
+ * cb_srt0.s
+ */
+extern caddr_t _end[];
+extern void *estack;
+extern void _start(void *, ...);
+extern void exit_to_kernel(void *, csu_md_t *);
+extern void bzero(void *, size_t);
+extern void phys_xcopy(physaddr_t, physaddr_t, size_t);
+extern void ptov_bcopy(physaddr_t, void *, size_t);
+extern void get_dtlb_entry(int, caddr_t *, tte_t *);
+extern void set_dtlb_entry(int, caddr_t, tte_t *);
+extern void set_itlb_entry(int, caddr_t, tte_t *);
+extern void cpu_launch(int);
+extern void cb_usec_wait(int);
+extern void membar_stld(void);
+extern uint_t getmid(void);
+
+#endif /* !_ASM */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CPRBOOT_H */
diff --git a/usr/src/psm/stand/cpr/sparcv9/sun4u/machdep.c b/usr/src/psm/stand/cpr/sparcv9/sun4u/machdep.c
new file mode 100644
index 0000000000..43ab650fd7
--- /dev/null
+++ b/usr/src/psm/stand/cpr/sparcv9/sun4u/machdep.c
@@ -0,0 +1,315 @@
+/*
+ * 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.
+ *
+ * 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 1999-2002 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/cpr.h>
+#include <sys/promimpl.h>
+#include <sys/privregs.h>
+#include <sys/stack.h>
+#include <sys/cpuvar.h>
+#include "cprboot.h"
+
+
+#define TIMEOUT_MSECS 1000
+
+
+/*
+ * globals
+ */
+int cpr_test_mode;
+csu_md_t mdinfo;
+caddr_t tmp_stack;
+uint_t cb_mid;
+uint_t cb_clock_freq;
+uint_t cpu_delay;
+
+
+/*
+ * file scope
+ */
+typedef void (*tlb_func_t)(int, caddr_t, tte_t *);
+static uint_t mdlen;
+static cpuset_t slave_set;
+static int has_scbc;
+
+
+/*
+ * check machdep desc and cpr_machdep info
+ *
+ * sets globals:
+ * mdinfo
+ * mdlen
+ */
+int
+cb_check_machdep(void)
+{
+ uint16_t wst32, wst64;
+ char *fmt, *str;
+ cmd_t cmach;
+
+ str = "cb_check_machdep";
+ CB_VPRINTF((ent_fmt, str, entry));
+
+ /*
+ * get machdep desc and set length of prom words
+ */
+ SF_DCOPY(cmach);
+ if (cmach.md_magic != CPR_MACHDEP_MAGIC) {
+ prom_printf("%s: bad machdep magic 0x%x, expect 0x%x\n",
+ str, cmach.md_magic, CPR_MACHDEP_MAGIC);
+ return (ERR);
+ }
+ mdlen = cmach.md_size - sizeof (csu_md_t);
+
+ /*
+ * get machep info, check for valid stack bias and wstate
+ */
+ SF_DCOPY(mdinfo);
+ fmt = "found bad statefile data: %s (0x%x), expect 0x%x or 0x%x\n";
+ if (mdinfo.ksb != 0x0 && mdinfo.ksb != V9BIAS64) {
+ prom_printf(fmt, "stack bias", mdinfo.ksb, 0, V9BIAS64);
+ return (ERR);
+ }
+ wst32 = WSTATE(WSTATE_U32, WSTATE_K32);
+ wst64 = WSTATE(WSTATE_U32, WSTATE_K64);
+ if (mdinfo.kwstate != wst32 && mdinfo.kwstate != wst64) {
+ prom_printf(fmt, "wstate", mdinfo.kwstate, wst32, wst64);
+ return (ERR);
+ }
+
+ return (0);
+}
+
+
+/*
+ * interpret saved prom words
+ */
+int
+cb_interpret(void)
+{
+ int bytes, wlen, s;
+ char minibuf[60];
+ char *words;
+
+ CB_VENTRY(cb_interpret);
+
+ /*
+ * The variable length machdep section for sun4u consists of
+ * a sequence of null-terminated strings stored contiguously.
+ *
+ * The first string defines Forth words which help the prom
+ * handle kernel translations.
+ *
+ * The second string defines Forth words required by kadb to
+ * interface with the prom when a trap is taken.
+ */
+ words = SF_DATA();
+ bytes = mdlen;
+ while (bytes) {
+ wlen = prom_strlen(words) + 1; /* include the null */
+ if (verbose) {
+ s = sizeof (minibuf) - 4;
+ (void) prom_strncpy(minibuf, words, s);
+ if (wlen > s)
+ (void) prom_strcpy(&minibuf[s], "...");
+ prom_printf(" interpret \"%s\"\n", minibuf);
+ }
+ prom_interpret(words, 0, 0, 0, 0, 0);
+ words += wlen;
+ bytes -= wlen;
+ }
+
+ /* advance past prom words */
+ SF_ADV(mdlen);
+
+ return (0);
+}
+
+
+/*
+ * write dtlb/itlb entries
+ */
+static void
+restore_tlb(struct sun4u_tlb *utp, int cpu_id)
+{
+ struct sun4u_tlb *tail;
+ tlb_func_t tfunc;
+ caddr_t virt;
+ char tname;
+
+ if (utp == mdinfo.dtte) {
+ tfunc = set_dtlb_entry;
+ tname = 'd';
+ } else if (utp == mdinfo.itte) {
+ tfunc = set_itlb_entry;
+ tname = 'i';
+ }
+
+ for (tail = utp + CPR_MAX_TLB; utp < tail; utp++) {
+ if (utp->va_tag == NULL)
+ continue;
+ virt = (caddr_t)utp->va_tag;
+ (*tfunc)(utp->index, virt, &utp->tte);
+ if (verbose || CPR_DBG(4)) {
+ prom_printf(" cpu_id %d: write %ctlb "
+ "(index %x, virt 0x%p, size 0x%x)\n",
+ cpu_id, tname, utp->index, utp->va_tag,
+ TTEBYTES(utp->tte.tte_size));
+ }
+ }
+}
+
+
+/*
+ * install locked tlb entries for the kernel and cpr module;
+ * also sets up the tmp stack
+ */
+int
+cb_ksetup(void)
+{
+ CB_VENTRY(cb_ksetup);
+
+ restore_tlb(mdinfo.dtte, cb_mid);
+ restore_tlb(mdinfo.itte, cb_mid);
+ tmp_stack = (caddr_t)(mdinfo.tmp_stack + mdinfo.tmp_stacksize);
+
+ return (0);
+}
+
+
+static void
+cb_park_err(int cpu_id)
+{
+ prom_printf("\ncpu_id %d did not stop!...\n", cpu_id);
+ cb_exit_to_mon();
+}
+
+
+/*
+ * local copy of an older interface for OBP revs < 4.6
+ */
+static int
+cb_prom_stop_self(void)
+{
+ cell_t ci[3];
+
+ ci[0] = p1275_ptr2cell("SUNW,stop-self"); /* Service name */
+ ci[1] = (cell_t)0; /* #argument cells */
+ ci[2] = (cell_t)0; /* #result cells */
+ (void) p1275_cif_handler(&ci); /* Do NOT lock */
+ return (0);
+}
+
+
+/*
+ * install locked tlb entries and spin or park in a prom idle-loop
+ */
+void
+slave_init(int cpu_id)
+{
+ restore_tlb(mdinfo.dtte, cpu_id);
+ restore_tlb(mdinfo.itte, cpu_id);
+ CPUSET_ADD(slave_set, cpu_id);
+ membar_stld();
+ if (has_scbc) {
+ /* just spin, master will park this cpu */
+ /* CONSTCOND */
+ while (1);
+ } else {
+ (void) cb_prom_stop_self();
+ cb_park_err(cpu_id);
+ }
+}
+
+
+/*
+ * when any cpu is started, they naturally rely on the prom for all
+ * text/data translations until switching to the kernel trap table.
+ * to jump back into the cpr module and to restart slave cpus, cprboot
+ * needs to reinstall translations for the nucleus and some cpr pages.
+ *
+ * the easy method is creating one set of global translations available
+ * to all cpus with prom_map(); unfortunately, a 4MB "map" request will
+ * allocate and overwrite a few pages, and these are often kernel pages
+ * that were just restored.
+ *
+ * to solve the "map" problem, all cpus install their own set of locked
+ * tlb entries to translate the nucleus and parts of the cpr module;
+ * after all cpus have switched to kernel traps, any of these locked
+ * tlb entries for pages outside the nucleus will be cleared.
+ */
+int
+cb_mpsetup(void)
+{
+ struct sun4u_cpu_info *scip, *tail;
+ int timeout, ncpu;
+ char *str, *intf;
+
+ intf = "SUNW,stop-cpu-by-cpuid";
+ has_scbc = (prom_test(intf) == 0);
+ CB_VPRINTF(("\n\"%s\" test %d\n", intf, has_scbc));
+
+ str = "cb_mp_setup";
+ CB_VPRINTF((ent_fmt, str, entry));
+
+ /*
+ * launch any slave cpus from the .sci array into cprboot text
+ * and wait about a second for them to checkin with slave_set
+ */
+ ncpu = 0;
+ CPUSET_ZERO(slave_set);
+ for (scip = mdinfo.sci, tail = scip + NCPU; scip < tail; scip++) {
+ if (scip->node == 0 || scip->cpu_id == cb_mid)
+ continue;
+ (void) prom_startcpu(scip->node,
+ (caddr_t)cpu_launch, scip->cpu_id);
+
+ for (timeout = TIMEOUT_MSECS; timeout; timeout--) {
+ if (CPU_IN_SET(slave_set, scip->cpu_id))
+ break;
+ cb_usec_wait(MILLISEC);
+ }
+
+ if (timeout == 0) {
+ prom_printf("\n%s: cpu did not start, "
+ "cpu_id %d, node 0x%x\n",
+ prog, scip->cpu_id, scip->node);
+ return (ERR);
+ }
+
+ if (has_scbc && prom_stopcpu_bycpuid(scip->cpu_id))
+ cb_park_err(scip->cpu_id);
+
+ ncpu++;
+ }
+
+ if (verbose && ncpu)
+ prom_printf("\n%s: slave cpu count: %d\n", str, ncpu);
+
+ return (0);
+}
diff --git a/usr/src/psm/stand/cpr/sparcv9/sun4u/mapfile b/usr/src/psm/stand/cpr/sparcv9/sun4u/mapfile
new file mode 100644
index 0000000000..51e01a8c7e
--- /dev/null
+++ b/usr/src/psm/stand/cpr/sparcv9/sun4u/mapfile
@@ -0,0 +1,35 @@
+#
+# Copyright 2005 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.
+#
+# 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
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+text = LOAD ?RX V0x100000;
+text : $PROGBITS ?A!W;
+
+data = LOAD ?RWX A0x8;
+data : $PROGBITS ?AW;
+data : $NOBITS ?AW;
+
+note = NOTE;
+note : $NOTE;
diff --git a/usr/src/psm/stand/cpr/sparcv9/sun4u/pages.c b/usr/src/psm/stand/cpr/sparcv9/sun4u/pages.c
new file mode 100644
index 0000000000..7b163a7aca
--- /dev/null
+++ b/usr/src/psm/stand/cpr/sparcv9/sun4u/pages.c
@@ -0,0 +1,364 @@
+/*
+ * 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.
+ *
+ * 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 1999-2002 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/cpr.h>
+#include <sys/ddi.h>
+#include "cprboot.h"
+
+
+/*
+ * check if any cpd_t pages clash with the statefile buffer and shuffle
+ * buf pages to free space; since kpages are saved in ascending order,
+ * any buf pages preceding the current statefile buffer offset can be
+ * written because those pages have already been read and restored
+ */
+static void
+shuffle_pages(cpd_t *descp)
+{
+ pfn_t low_src_ppn, dst_ppn, tail_ppn, new_ppn;
+ size_t dst_off;
+
+ /*
+ * set the lowest source buf ppn for the (precede) comparison
+ * below; the ORIG macro is used for the case where the src buf
+ * page had already been moved - and would confuse the compare
+ */
+ low_src_ppn = SF_ORIG_PPN(sfile.buf_offset);
+
+ tail_ppn = descp->cpd_pfn + descp->cpd_pages;
+ for (dst_ppn = descp->cpd_pfn; dst_ppn < tail_ppn; dst_ppn++) {
+ /*
+ * if the dst page is outside the range of statefile
+ * buffer phys pages, it's OK to write that page;
+ * buf pages may have been moved outside the range,
+ * but only to locations isolated from any dst page
+ */
+ if (dst_ppn < sfile.low_ppn || dst_ppn > sfile.high_ppn) {
+ SF_STAT_INC(outside);
+ continue;
+ }
+
+ /*
+ * the dst page is inside the range of buf ppns;
+ * dont need to move the buf page if the dst page
+ * precedes the lowest src buf page
+ */
+ if (dst_ppn < low_src_ppn) {
+ SF_STAT_INC(precede);
+ continue;
+ }
+
+ /*
+ * the dst page clashes with the statefile buffer;
+ * move the buf page to a free location and update
+ * the buffer map
+ */
+ new_ppn = find_apage();
+ phys_xcopy(PN_TO_ADDR(dst_ppn), PN_TO_ADDR(new_ppn),
+ MMU_PAGESIZE);
+ dst_off = mmu_ptob(dst_ppn - sfile.low_ppn);
+ SF_BUF_PPN(dst_off) = new_ppn;
+ SF_STAT_INC(move);
+ }
+}
+
+
+/*
+ * map-in source statefile buffer pages (read-only) at CB_SRC_VIRT;
+ * sets the starting source vaddr with correct page offset
+ */
+static void
+mapin_buf_pages(size_t datalen, caddr_t *srcp)
+{
+ int dtlb_index, pg_off;
+ caddr_t vaddr, tail;
+ size_t off, bytes;
+ pfn_t src_ppn;
+
+ dtlb_index = cb_dents - CB_MAX_KPAGES - 1;
+ off = sfile.buf_offset;
+ pg_off = off & MMU_PAGEOFFSET;
+ bytes = PAGE_ROUNDUP(pg_off + datalen);
+ vaddr = (caddr_t)CB_SRC_VIRT;
+ *srcp = vaddr + pg_off;
+
+ for (tail = vaddr + bytes; vaddr < tail; vaddr += MMU_PAGESIZE) {
+ src_ppn = SF_BUF_PPN(off);
+ cb_mapin(vaddr, src_ppn, TTE8K, 0, dtlb_index);
+ dtlb_index--;
+ off += MMU_PAGESIZE;
+ }
+}
+
+
+/*
+ * map-in destination kernel pages (read/write) at CB_DST_VIRT
+ */
+static void
+mapin_dst_pages(cpd_t *descp)
+{
+ int dtlb_index, pages;
+ caddr_t vaddr;
+ pfn_t dst_ppn;
+
+ dtlb_index = cb_dents - 1;
+ vaddr = (caddr_t)CB_DST_VIRT;
+ dst_ppn = descp->cpd_pfn;
+ for (pages = 0; pages < descp->cpd_pages; pages++) {
+ cb_mapin(vaddr, dst_ppn, TTE8K, TTE_HWWR_INT, dtlb_index);
+ dtlb_index--;
+ vaddr += MMU_PAGESIZE;
+ dst_ppn++;
+ }
+}
+
+
+/*
+ * run a checksum on un/compressed data when flag is set
+ */
+static int
+kdata_cksum(void *data, cpd_t *descp, uint_t flag)
+{
+ uint_t sum, expect;
+ size_t len;
+
+ if ((descp->cpd_flag & flag) == 0)
+ return (0);
+ else if (flag == CPD_CSUM) {
+ expect = descp->cpd_csum;
+ len = descp->cpd_length;
+ } else {
+ expect = descp->cpd_usum;
+ len = mmu_ptob(descp->cpd_pages);
+ }
+ sum = checksum32(data, len);
+ if (sum != expect) {
+ prom_printf("\n%scompressed data checksum error, "
+ "expect 0x%x, got 0x%x\n", (flag == CPD_USUM) ? "un" : "",
+ expect, sum);
+ return (ERR);
+ }
+
+ return (0);
+}
+
+
+/*
+ * primary kpage restoration routine
+ */
+static int
+restore_page_group(cpd_t *descp)
+{
+ caddr_t dst, datap;
+ size_t size, len;
+ caddr_t src;
+ int raw;
+
+#if defined(lint)
+ (void) compress(0, 0, 0);
+#endif
+
+ /*
+ * move any source buf pages that clash with dst kernel pages;
+ * create tlb entries for the orig/new source buf pages and
+ * the dst kpages
+ */
+ shuffle_pages(descp);
+ mapin_buf_pages(descp->cpd_length, &src);
+ mapin_dst_pages(descp);
+
+ /*
+ * for compressed pages, run a checksum at the src vaddr and
+ * decompress to the mapped-in dst kpages; for uncompressed pages,
+ * just copy direct; uncompressed checksums are used for either
+ * uncompressed src data or decompressed result data
+ */
+ dst = (caddr_t)CB_DST_VIRT;
+ if (descp->cpd_flag & CPD_COMPRESS) {
+ if (kdata_cksum(src, descp, CPD_CSUM))
+ return (ERR);
+ size = mmu_ptob(descp->cpd_pages);
+ len = decompress(src, dst, descp->cpd_length, size);
+ if (len != size) {
+ prom_printf("\nbad decompressed len %d, size %d\n",
+ len, size);
+ return (ERR);
+ }
+ raw = 0;
+ datap = dst;
+ } else {
+ raw = 1;
+ datap = src;
+ }
+ if (kdata_cksum(datap, descp, CPD_USUM))
+ return (ERR);
+ if (raw)
+ bcopy(src, dst, descp->cpd_length);
+
+ /*
+ * advance past the kdata for this cpd_t
+ */
+ SF_ADV(descp->cpd_length);
+
+ return (0);
+}
+
+
+/*
+ * mapin part of the statefile buffer, copy to the virt destination,
+ * and advance the statefile buffer offset. this is used primarily
+ * to copy thousands of tiny cpd_t into aligned struct space.
+ */
+static void
+get_phys_data(void *vdst, size_t size)
+{
+ caddr_t src;
+
+ mapin_buf_pages(size, &src);
+ bcopy(src, vdst, size);
+ SF_ADV(size);
+}
+
+
+/*
+ * clear leftover locked dtlb entries
+ */
+static void
+dtlb_cleanup(void)
+{
+ int dtlb_index;
+ caddr_t vaddr;
+ tte_t tte;
+
+ CB_VENTRY(dtlb_cleanup);
+
+ dtlb_index = cb_dents - CB_MAX_KPAGES - CB_MAX_BPAGES - 1;
+ for (; dtlb_index < cb_dents; dtlb_index++) {
+ get_dtlb_entry(dtlb_index, &vaddr, &tte);
+ if (TTE_IS_LOCKED(&tte)) {
+ tte.ll = 0;
+ set_dtlb_entry(dtlb_index, (caddr_t)0, &tte);
+ CB_VPRINTF((" cleared dtlb entry %x\n", dtlb_index));
+ }
+ }
+}
+
+
+/*
+ * before calling this routine, all cprboot phys pages
+ * are isolated from kernel pages; now we can restore
+ * kpages from the statefile buffer
+ */
+int
+cb_restore_kpages(void)
+{
+ int npages, compressed, regular;
+ cpd_t desc;
+ char *str;
+
+ str = "cb_restore_kpages";
+ CB_VPRINTF((ent_fmt, str, entry));
+
+ DEBUG1(prom_printf("%s: restoring kpages... ", prog));
+ npages = compressed = regular = 0;
+ while (npages < sfile.kpages) {
+ get_phys_data(&desc, sizeof (desc));
+ if (desc.cpd_magic != CPR_PAGE_MAGIC) {
+ prom_printf("\nbad page magic 0x%x, expect 0x%x\n",
+ desc.cpd_magic, CPR_PAGE_MAGIC);
+ return (ERR);
+ }
+ if (restore_page_group(&desc))
+ return (ERR);
+ npages += desc.cpd_pages;
+
+ if (desc.cpd_flag & CPD_COMPRESS)
+ compressed += desc.cpd_pages;
+ else
+ regular += desc.cpd_pages;
+
+ /*
+ * display a spin char for every 32 page groups
+ * (a full spin <= each MB restored)
+ */
+ if ((sfile.ngroups++ & 0x1f) == 0)
+ cb_spin();
+ }
+ DEBUG1(prom_printf(" \b\n"));
+
+ dtlb_cleanup();
+
+ if (verbose) {
+ prom_printf("\npage stats: total %d, outside %d, "
+ "move %d, precede %d\n", sfile.kpages, sfile.outside,
+ sfile.move, sfile.precede);
+ prom_printf("page stats: ngroups %d, recycle %d\n",
+ sfile.ngroups, sfile.recycle);
+ }
+
+ DEBUG4(prom_printf(
+ "%s: total=%d, npages=%d, compressed=%d, regular=%d\n",
+ str, sfile.kpages, npages, compressed, regular));
+
+ /*
+ * sanity check
+ */
+ if (npages != sfile.kpages) {
+ prom_printf("\n%s: page count mismatch, expect %d, got %d\n",
+ str, sfile.kpages, npages);
+ return (ERR);
+ }
+
+ return (0);
+}
+
+
+/*
+ * check and update the statefile terminator;
+ * on exit there will be a leftover tlb entry,
+ * but it will soon get replaced by restore_tlb()
+ */
+int
+cb_terminator(void)
+{
+ ctrm_t cterm;
+
+ CB_VENTRY(cb_terminator);
+ get_phys_data(&cterm, sizeof (cterm));
+ if (cterm.magic != CPR_TERM_MAGIC) {
+ prom_printf("\nbad term magic 0x%x, expect 0x%x\n",
+ cterm.magic, CPR_TERM_MAGIC);
+ return (ERR);
+ }
+ cterm.tm_cprboot_start.tv_sec = cb_msec / 1000;
+ cb_mapin((caddr_t)CB_DST_VIRT, cterm.pfn,
+ TTE8K, TTE_HWWR_INT, cb_dents - 1);
+ cpr_update_terminator(&cterm, (caddr_t)CB_DST_VIRT);
+ return (0);
+}
diff --git a/usr/src/psm/stand/cpr/sparcv9/sun4u/util.c b/usr/src/psm/stand/cpr/sparcv9/sun4u/util.c
new file mode 100644
index 0000000000..e2e6667929
--- /dev/null
+++ b/usr/src/psm/stand/cpr/sparcv9/sun4u/util.c
@@ -0,0 +1,495 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/cpr.h>
+#include <sys/promimpl.h>
+#include "cprboot.h"
+
+
+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
+ * 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.
+ */
+/* ARGSUSED */
+int
+cpr_statefile_open(char *path, char *fs)
+{
+ char full_path[OBP_MAXPATHLEN];
+ char *fp;
+ int handle;
+ int c;
+
+ /*
+ * instead of using specialstate, we use fs as the flag
+ */
+ if (*fs == '\0') { /* device open */
+ 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.
+ */
+ 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);
+ }
+
+ /*
+ * IEEE1275 prom_open returns 0 on failure; we return -1
+ */
+ return (handle ? handle : -1);
+}
+
+
+/*
+ * 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.
+ */
+/* ARGSUSED */
+int
+cpr_ufs_open(char *path, char *fs)
+{
+ 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);
+ return (ERR);
+ }
+ return (cpr_statefile_open(path, fs));
+}
+
+
+/*
+ * On sun4u there's no difference here, since prom groks ufs directly
+ */
+int
+cpr_read(int fd, caddr_t buf, size_t len)
+{
+ return (prom_read(fd, buf, len, 0, 0));
+}
+
+
+int
+cpr_ufs_read(int fd, caddr_t buf, int len)
+{
+ return (prom_read(fd, buf, len, 0, 0));
+}
+
+
+int
+cpr_ufs_close(int fd)
+{
+ CB_VPRINTF(("cpr_ufs_close 0x%x\n", fd));
+ return (prom_close(fd));
+}
+
+
+int
+cpr_statefile_close(int fd)
+{
+ return (prom_close(fd));
+}
+
+
+void
+cb_spin(void)
+{
+ static int spindex = 0;
+ static char *spin_pairs[] = { "|\b", "/\b", "-\b", "\\\b" };
+ const size_t nspin_pairs = sizeof (spin_pairs) / sizeof (spin_pairs[0]);
+
+ prom_printf(spin_pairs[spindex]);
+ spindex = (spindex + 1) % nspin_pairs;
+}
+
+
+/*
+ * translate vaddr to phys page number
+ */
+pfn_t
+cpr_vatopfn(caddr_t vaddr)
+{
+ physaddr_t paddr;
+ int valid, mode;
+
+ (void) prom_translate_virt(vaddr, &valid, &paddr, &mode);
+ if (valid != -1)
+ return (PFN_INVALID);
+ return (paddr >> MMU_PAGESHIFT);
+}
+
+
+/*
+ * unmap virt, then map virt to new phys;
+ * see remap definition below
+ */
+int
+prom_remap(size_t size, caddr_t virt, physaddr_t phys)
+{
+ ihandle_t immu;
+ cell_t ci[8];
+ int rv;
+
+ immu = prom_mmu_ihandle();
+ if (immu == (ihandle_t)-1)
+ return (ERR);
+
+ ci[0] = p1275_ptr2cell("call-method"); /* Service name */
+ ci[1] = (cell_t)5; /* #argument cells */
+ ci[2] = (cell_t)0; /* #result cells */
+ ci[3] = p1275_ptr2cell("remap"); /* Arg1: Method name */
+ ci[4] = p1275_ihandle2cell(immu); /* Arg2: memory ihandle */
+ ci[5] = p1275_size2cell(size); /* remap arg0 */
+ ci[6] = p1275_ptr2cell(virt); /* remap arg1 */
+ ci[7] = p1275_ull2cell_low(phys); /* remap arg2 */
+
+ promif_preprom();
+ rv = p1275_cif_handler(ci);
+ promif_postprom();
+
+ if (rv)
+ return (rv); /* Service "call-method" failed */
+ return (0);
+}
+
+
+/*
+ * install remap definition in /virtual-memory node;
+ * used for replacing a virt->phys mapping in one promif call;
+ * this needs to be atomic from the client's perspective to
+ * avoid faults while relocating client text.
+ */
+void
+install_remap(void)
+{
+ static char remap_def[] =
+ "\" /virtual-memory\" find-device "
+ ": remap ( phys.lo virt size -- )"
+ " 2dup unmap ( phys.lo virt size )"
+ " 0 -rot -1 map ( ) ; "
+ "device-end";
+
+ prom_interpret(remap_def, 0, 0, 0, 0, 0);
+}
+
+
+/*
+ * allocate virt and phys space without any mapping;
+ * stores virt and phys addrs at *vap and *pap
+ */
+int
+cb_alloc(size_t size, uint_t align, caddr_t *vap, physaddr_t *pap)
+{
+ physaddr_t phys;
+ caddr_t virt;
+
+ virt = prom_allocate_virt(align, (size_t)align);
+ if (virt == (caddr_t)-1)
+ return (ERR);
+ if (prom_allocate_phys(size, align, &phys) == -1) {
+ prom_free_virt(size, virt);
+ return (ERR);
+ }
+
+ *vap = virt;
+ *pap = phys;
+ return (0);
+}
+
+
+static int
+get_intprop(dnode_t node, caddr_t prop, void *dst)
+{
+ int len, glen;
+
+ len = sizeof (uint_t);
+ glen = prom_getprop(node, prop, dst);
+ if (glen != len)
+ return (ERR);
+
+ return (0);
+}
+
+
+/*
+ * find cpu node for the boot processor
+ *
+ * sets globals:
+ * cb_mid
+ */
+static dnode_t
+get_cpu_node(void)
+{
+ static char *props[] = { "upa-portid", "portid", NULL };
+ dnode_t node;
+ char *str, *name, **propp;
+ uint_t cpu_id;
+ int err;
+
+ str = "get_cpu_node";
+ name = "cpu";
+
+ cb_mid = getmid();
+ for (node = prom_rootnode(); ; node = prom_nextnode(node)) {
+ node = prom_findnode_bydevtype(node, name);
+ if (node == OBP_NONODE) {
+ prom_printf("\n%s: cant find node for devtype \"%s\"\n",
+ str, name);
+ break;
+ }
+
+ cpu_id = (uint_t)-1;
+ for (propp = props; *propp; propp++) {
+ err = get_intprop(node, *propp, &cpu_id);
+ CB_VPRINTF((" cpu node 0x%x, "
+ "prop \"%s\", cpu_id %d\n",
+ node, *propp, (int)cpu_id));
+ if (err == 0)
+ break;
+ }
+
+ if (cpu_id == cb_mid)
+ return (node);
+ }
+
+ return (OBP_NONODE);
+}
+
+
+/*
+ * lookup prom properties
+ *
+ * sets globals:
+ * cb_dents
+ * cb_clock_freq
+ * cpu_delay
+ */
+int
+cb_get_props(void)
+{
+ uint_t clock_mhz;
+ dnode_t node;
+ struct cb_props *cbp;
+ static struct cb_props cpu_data[] = {
+ "#dtlb-entries", &cb_dents,
+ "clock-frequency", &cb_clock_freq,
+ NULL, NULL,
+ };
+
+ CB_VENTRY(cb_get_props);
+
+ node = get_cpu_node();
+ if (node == OBP_NONODE)
+ return (ERR);
+ for (cbp = cpu_data; cbp->prop; cbp++) {
+ if (get_intprop(node, cbp->prop, cbp->datap)) {
+ prom_printf("\n%s: getprop error, "
+ "node 0x%x, prop \"%s\"\n",
+ prog, node, cbp->prop);
+ return (ERR);
+ }
+ CB_VPRINTF((" \"%s\" = 0x%x\n",
+ cbp->prop, *cbp->datap));
+ }
+
+ /*
+ * setup cpu_delay for cb_usec_wait
+ */
+ clock_mhz = (cb_clock_freq + 500000) / 1000000;
+ cpu_delay = clock_mhz - 7;
+ CB_VPRINTF((" clock_mhz %d, cpu_delay %d\n",
+ clock_mhz, cpu_delay));
+
+ return (0);
+}
+
+
+/*
+ * map-in data pages
+ * size should fit tte_bit.sz
+ * rw should be 0 or TTE_HWWR_INT
+ */
+void
+cb_mapin(caddr_t vaddr, pfn_t ppn, uint_t size, uint_t rw, uint_t dtlb_index)
+{
+ tte_t tte;
+
+ tte.tte_inthi = TTE_VALID_INT | TTE_SZ_INT(size) |
+ TTE_PFN_INTHI(ppn);
+ tte.tte_intlo = TTE_PFN_INTLO(ppn) | TTE_LCK_INT |
+ TTE_CP_INT | TTE_CV_INT | TTE_PRIV_INT | rw;
+ set_dtlb_entry(dtlb_index, vaddr, &tte);
+}
+
+
+static char *
+prom_strstr(char *string, char *substr)
+{
+ char *strp, *subp, *tmp, c;
+
+ if (substr == NULL || *substr == '\0')
+ return (string);
+
+ strp = string;
+ subp = substr;
+ c = *subp;
+
+ while (*strp) {
+ if (*strp++ == c) {
+ tmp = strp;
+ while ((c = *++subp) == *strp++ && c)
+ ;
+ if (c == '\0')
+ return (tmp - 1);
+ strp = tmp;
+ subp = substr;
+ c = *subp;
+ }
+ }
+
+ return (NULL);
+}
+
+
+static void
+cb_set_idev(char *istr)
+{
+ if (reset_input) {
+ prom_interpret(istr, 0, 0, 0, 0, 0);
+ CB_VPRINTF(("\ncb_set_idev: reset with [%s]\n", istr));
+ }
+}
+
+
+/*
+ * workaround for USB keyboard:
+ * USB DMA activity has been known to corrupt kernel pages while cprboot
+ * is restoring them. to quiesce the USB chip, we craft a "null" device
+ * and temporarily use that as the prom's input device. this effectively
+ * disables the USB keyboard until the cpr module restores the original
+ * prom and a kernel driver re-inits and takes-over control of USB.
+ *
+ * may set globals:
+ * reset_input
+ */
+int
+cb_usb_setup(void)
+{
+ char sp[OBP_MAXPATHLEN];
+ static char cb_nulldev[] = {
+ "\" /\" select-dev "
+ "new-device "
+ "\" nulldev\" device-name "
+ ": read 2drop -2 ; "
+ ": open true ; "
+ ": close ; "
+ ": install-abort ; "
+ ": remove-abort ; "
+ ": write 2drop 0 ; "
+ ": restore ; "
+ "finish-device "
+ "unselect-dev"
+ };
+
+ CB_VENTRY(cb_usb_setup);
+
+ bzero(sp, sizeof (sp));
+ prom_interpret("stdin @ ihandle>devname swap -rot move",
+ (uintptr_t)sp, 0, 0, 0, 0);
+ if (prom_strstr(sp, "usb") && prom_strstr(sp, "keyboard")) {
+ prom_interpret(cb_nulldev, 0, 0, 0, 0, 0);
+ reset_input = 1;
+ cb_set_idev(null_input);
+ }
+
+ return (0);
+}
+
+
+/*
+ * switch input to keyboard before entering the prom, and switch to the
+ * crafted nulldev after returning from the prom. this occurs only when
+ * stdinpath is a USB keyboard; entering the prom is usually done only
+ * for debugging purposes - see check_halt() and above DMA comment.
+ */
+void
+cb_enter_mon(void)
+{
+ cb_set_idev(kbd_input);
+ prom_enter_mon();
+ cb_set_idev(null_input);
+}
+
+
+/*
+ * similar to above before exiting to the prom
+ */
+void
+cb_exit_to_mon(void)
+{
+ cb_set_idev(kbd_input);
+ prom_exit_to_mon();
+}
diff --git a/usr/src/psm/stand/lib/Makefile b/usr/src/psm/stand/lib/Makefile
new file mode 100644
index 0000000000..eab3a61f2f
--- /dev/null
+++ b/usr/src/psm/stand/lib/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, Version 1.0 only
+# (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 (c) 1994 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# psm/stand/lib/Makefile
+
+include ../../../Makefile.master
+
+SUBDIRS = boot names promif
+
+all install clean clobber lint: $(SUBDIRS)
+
+all := TARGET = all
+clean := TARGET = clean
+clobber := TARGET = clobber
+lint := TARGET = lint
+install := TARGET = install
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(MFLAGS) $(TARGET)
+
+FRC:
diff --git a/usr/src/psm/stand/lib/Makefile.lib b/usr/src/psm/stand/lib/Makefile.lib
new file mode 100644
index 0000000000..3c55bdbc2d
--- /dev/null
+++ b/usr/src/psm/stand/lib/Makefile.lib
@@ -0,0 +1,88 @@
+#
+# 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.
+#
+# 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 1994, 2003 Sun Microsystems, Inc.
+# All rights reserved.
+# Use is subject to license terms.
+#
+# psm/stand/lib/Makefile.lib
+
+include $(TOPDIR)/Makefile.master
+include $(TOPDIR)/Makefile.psm
+
+STANDDIR = $(TOPDIR)/stand
+PSMSTANDDIR = $(TOPDIR)/psm/stand
+
+SYSHDRDIR = $(STANDDIR)
+SYSLIBDIR = $(STANDDIR)/lib/$(MACH)
+
+PSMSYSHDRDIR = $(PSMSTANDDIR)
+PSMBOOTLIBDIR = $(PSMSTANDDIR)/lib/boot/$(MACH)
+PSMNAMELIBDIR = $(PSMSTANDDIR)/lib/names/$(MACH)
+PSMPROMLIBDIR = $(PSMSTANDDIR)/lib/promif/$(MACH)
+
+#
+# Lint rules (adapted from Makefile.uts)
+#
+LHEAD = ( $(ECHO) "\n$@";
+LGREP = grep -v "pointer cast may result in improper alignment"
+LTAIL = ) 2>&1 | $(LGREP)
+LINT_DEFS += -Dlint
+
+#
+# For building lint objects
+#
+LINTFLAGS.c = -nsxum
+LINTFLAGS.c += $(ALWAYS_LINT_DEFS)
+LINTFLAGS64.c = -nsxum
+LINTFLAGS64.c += $(ALWAYS_LINT_DEFS)
+LINT64.c = $(LINT) $(LINTFLAGS64.c) $(LINT_DEFS) $(CPPFLAGS) -c
+LINT.c = $(LINT) $(LINTFLAGS.c) $(LINT_DEFS) $(CPPFLAGS) -c
+LINT.s = $(LINT) $(LINTFLAGS.s) $(LINT_DEFS) $(CPPFLAGS) -c
+
+#
+# For building lint libraries
+#
+LINTFLAGS.lib = -nsxumy
+LINTFLAGS.lib += $(ALWAYS_LINT_DEFS)
+LINT.lib = $(LINT) $(LINTFLAGS.lib) $(LINT_DEFS) $(CPPFLAGS)
+
+#
+# For complete pass 2 cross-checks
+#
+LINTFLAGS.2 = -nsxm
+LINT.2 = $(LINT) $(LINTFLAGS.2) $(LINT_DEFS) $(CPPFLAGS)
+
+#
+# Simple rule for making objs/%.ln from %.c and %.s
+#
+
+objs/%.ln: %.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+ @$(MV) $(@F) $@
+
+objs/%.ln: %.s
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+ @$(MV) $(@F) $@
+
diff --git a/usr/src/psm/stand/lib/Makefile.rules b/usr/src/psm/stand/lib/Makefile.rules
new file mode 100644
index 0000000000..10a1229837
--- /dev/null
+++ b/usr/src/psm/stand/lib/Makefile.rules
@@ -0,0 +1,50 @@
+#
+# 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.
+#
+# 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 (c) 1994, by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# psm/stand/lib/Makefile.rules
+
+#
+# Pattern matching rules to compile the source into the OBJSDIR directory
+#
+$(OBJSDIR)/%.o: $(SRCSDIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+$(OBJSDIR)/%.o: $(SRCSDIR)/%.s
+ $(COMPILE.s) -o $@ $<
+ $(POST_PROCESS_O)
+
+#
+# Pattern matching rules to lint the source into the OBJSDIR directory
+#
+$(OBJSDIR)/%.ln: $(SRCSDIR)/%.c
+ @($(LHEAD) $(LINT.c) -c $< $(LTAIL))
+ @$(MV) $(@F) $@
+
+$(OBJSDIR)/%.ln: $(SRCSDIR)/%.s
+ @($(LHEAD) $(LINT.s) -c $< $(LTAIL))
+ @$(MV) $(@F) $@
diff --git a/usr/src/psm/stand/lib/boot/Makefile b/usr/src/psm/stand/lib/boot/Makefile
new file mode 100644
index 0000000000..d9872f907f
--- /dev/null
+++ b/usr/src/psm/stand/lib/boot/Makefile
@@ -0,0 +1,49 @@
+#
+# 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.
+#
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# psm/stand/lib/boot/Makefile
+
+include ../../../../Makefile.master
+
+sparcv7_ARCHITECTURES = sparc
+sparcv9_ARCHITECTURES = sparcv9
+sparc_ARCHITECTURES = $(sparcv9_ARCHITECTURES) $(sparcv7_ARCHITECTURES)
+
+SUBDIRS = $($(MACH)_ARCHITECTURES)
+
+all install clean clobber lint: $(SUBDIRS)
+
+all := TARGET = all
+clean := TARGET = clean
+clobber := TARGET = clobber
+lint := TARGET = lint
+install := TARGET = install
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(MFLAGS) $(TARGET)
+
+FRC:
diff --git a/usr/src/psm/stand/lib/boot/inc.flg b/usr/src/psm/stand/lib/boot/inc.flg
new file mode 100644
index 0000000000..50d7ef0de3
--- /dev/null
+++ b/usr/src/psm/stand/lib/boot/inc.flg
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+# 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.
+#
+# 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
+#
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+#
+# Find all of the header files
+#
+
+echo_file usr/src/uts/sparc/os/bootops.c
diff --git a/usr/src/psm/stand/lib/boot/sparc/Makefile b/usr/src/psm/stand/lib/boot/sparc/Makefile
new file mode 100644
index 0000000000..554e9730c6
--- /dev/null
+++ b/usr/src/psm/stand/lib/boot/sparc/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, Version 1.0 only
+# (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 1997, 2001-2002 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# psm/stand/lib/boot/sparc/Makefile
+
+include ../../../../../Makefile.master
+
+SUBDIRS = sun4u
+
+all install clean clobber lint: $(SUBDIRS)
+
+all := TARGET = all
+clean := TARGET = clean
+clobber := TARGET = clobber
+lint := TARGET = lint
+install := TARGET = install
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(MFLAGS) $(TARGET)
+
+FRC:
diff --git a/usr/src/psm/stand/lib/boot/sparc/Makefile.com b/usr/src/psm/stand/lib/boot/sparc/Makefile.com
new file mode 100644
index 0000000000..495ca3d0ed
--- /dev/null
+++ b/usr/src/psm/stand/lib/boot/sparc/Makefile.com
@@ -0,0 +1,112 @@
+#
+# 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.
+#
+# 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 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# psm/stand/lib/boot/sparc/Makefile.com
+#
+# SPARC architecture Makefile for Standalone Library
+# Platform-specific, but shared between platforms.
+# Firmware dependent.
+#
+
+include $(TOPDIR)/Makefile.master
+include $(TOPDIR)/lib/Makefile.lib
+include $(TOPDIR)/psm/stand/lib/Makefile.lib
+
+PSMSYSHDRDIR = $(TOPDIR)/psm/stand
+
+LIBBOOT = libboot.a
+LINTLIBBOOT = llib-lboot.ln
+
+# ARCHCMNDIR - common code for several machines of a given isa
+# OBJSDIR - where the .o's go
+
+ARCHCMNDIR = $(TOPDIR)/uts/sparc/os
+OBJSDIR = objs
+
+CMNSRCS = bootops.c
+BOOTSRCS = $(PLATSRCS) $(CMNSRCS)
+BOOTOBJS = $(BOOTSRCS:%.c=%.o)
+
+OBJS = $(BOOTOBJS:%=$(OBJSDIR)/%)
+L_OBJS = $(OBJS:%.o=%.ln)
+L_SRCS = $(CMNSRCS:%=$(ARCHCMNDIR)/%) $(PLATSRCS)
+
+CPPINCS += -I$(SRC)/uts/common
+CPPINCS += -I$(SRC)/uts/sun
+CPPINCS += -I$(SRC)/uts/sparc
+CPPINCS += -I$(SRC)/uts/sparc/$(ARCHVERS)
+CPPINCS += -I$(SRC)/uts/$(PLATFORM)
+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
+ASFLAGS = -P -D__STDC__ -D_ASM $(CPPINCS)
+CFLAGS += $(CCVERBOSE)
+
+.KEEP_STATE:
+
+.PARALLEL: $(OBJS) $(L_OBJS)
+
+all install: $(LIBBOOT) .WAIT
+
+lint: $(LINTLIBBOOT)
+
+clean:
+ $(RM) $(OBJS) $(L_OBJS)
+
+clobber: clean
+ $(RM) $(LIBBOOT) $(LINTLIBBOOT) a.out core
+
+$(LIBBOOT): $(OBJSDIR) .WAIT $(OBJS)
+ $(BUILD.AR) $(OBJS)
+
+$(LINTLIBBOOT): $(OBJSDIR) .WAIT $(L_OBJS)
+ @$(ECHO) "\nlint library construction:" $@
+ @$(LINT.lib) -o boot $(L_SRCS)
+
+$(OBJSDIR):
+ -@[ -d $@ ] || mkdir $@
+
+#
+# build rules using standard library object subdirectory
+#
+$(OBJSDIR)/%.o: $(ARCHCMNDIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+$(OBJSDIR)/%.o: $(ARCHCMNDIR)/%.s
+ $(COMPILE.s) -o $@ $<
+ $(POST_PROCESS_O)
+
+$(OBJSDIR)/%.ln: $(ARCHCMNDIR)/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+ @$(MV) $(@F) $@
+
+$(OBJSDIR)/%.ln: $(ARCHCMNDIR)/%.s
+ @($(LHEAD) $(LINT.s) $< $(LTAIL))
+ @$(MV) $(@F) $@
diff --git a/usr/src/psm/stand/lib/boot/sparc/sun4u/Makefile b/usr/src/psm/stand/lib/boot/sparc/sun4u/Makefile
new file mode 100644
index 0000000000..51700d7fdc
--- /dev/null
+++ b/usr/src/psm/stand/lib/boot/sparc/sun4u/Makefile
@@ -0,0 +1,38 @@
+#
+# 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.
+#
+# 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 (c) 1997, by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# psm/stand/lib/boot/sparc/sun4u/Makefile
+#
+# Platform-specific, but shared between platforms.
+#
+
+PLATFORM = sun4u
+ARCHVERS = v9
+TOPDIR = ../../../../../..
+PLATSRCS =
+
+include ../Makefile.com
diff --git a/usr/src/psm/stand/lib/boot/sparcv9/Makefile b/usr/src/psm/stand/lib/boot/sparcv9/Makefile
new file mode 100644
index 0000000000..f0b2521715
--- /dev/null
+++ b/usr/src/psm/stand/lib/boot/sparcv9/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, Version 1.0 only
+# (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 (c) 1997 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# psm/stand/lib/boot/sparcv9/Makefile
+
+include ../../../../../Makefile.master
+
+SUBDIRS = sun4u
+
+all install clean clobber lint: $(SUBDIRS)
+
+all := TARGET = all
+clean := TARGET = clean
+clobber := TARGET = clobber
+lint := TARGET = lint
+install := TARGET = install
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(MFLAGS) $(TARGET)
+
+FRC:
diff --git a/usr/src/psm/stand/lib/boot/sparcv9/Makefile.com b/usr/src/psm/stand/lib/boot/sparcv9/Makefile.com
new file mode 100644
index 0000000000..f160c1405e
--- /dev/null
+++ b/usr/src/psm/stand/lib/boot/sparcv9/Makefile.com
@@ -0,0 +1,112 @@
+#
+# 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.
+#
+# 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 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# psm/stand/lib/boot/sparcv9/Makefile.com
+#
+# SPARC architecture Makefile for Standalone Library
+# Platform-specific, but shared between platforms.
+# Firmware dependent.
+#
+
+include $(TOPDIR)/Makefile.master
+include $(TOPDIR)/lib/Makefile.lib
+include $(TOPDIR)/psm/stand/lib/Makefile.lib
+
+PSMSYSHDRDIR = $(TOPDIR)/psm/stand
+
+LIBBOOT = libboot.a
+LINTLIBBOOT = llib-lboot.ln
+
+# ARCHCMNDIR - common code for several machines of a given isa
+# OBJSDIR - where the .o's go
+
+ARCHCMNDIR = $(TOPDIR)/uts/sparc/os
+OBJSDIR = objs
+
+CMNSRCS = bootops.c
+BOOTSRCS = $(PLATSRCS) $(CMNSRCS)
+BOOTOBJS = $(BOOTSRCS:%.c=%.o)
+
+OBJS = $(BOOTOBJS:%=$(OBJSDIR)/%)
+L_OBJS = $(OBJS:%.o=%.ln)
+L_SRCS = $(CMNSRCS:%=$(ARCHCMNDIR)/%) $(PLATSRCS)
+
+CPPINCS += -I$(SRC)/uts/common
+CPPINCS += -I$(SRC)/uts/sun
+CPPINCS += -I$(SRC)/uts/sparc
+CPPINCS += -I$(SRC)/uts/sparc/$(ARCHVERS)
+CPPINCS += -I$(SRC)/uts/$(PLATFORM)
+CPPINCS += -I$(ROOT)/usr/include/$(ARCHVERS)
+CPPINCS += -I$(ROOT)/usr/platform/$(PLATFORM)/include
+CPPINCS += -I$(PSMSYSHDRDIR)
+CPPFLAGS = $(CPPINCS) $(CCYFLAG)$(PSMSYSHDRDIR)
+CPPFLAGS += -D_KERNEL
+ASFLAGS = -P -D__STDC__ -D_ASM $(CPPINCS)
+CFLAGS += $(CCVERBOSE)
+
+.KEEP_STATE:
+
+.PARALLEL: $(OBJS) $(L_OBJS)
+
+all install: $(LIBBOOT) .WAIT
+
+lint: $(LINTLIBBOOT)
+
+clean:
+ $(RM) $(OBJS) $(L_OBJS)
+
+clobber: clean
+ $(RM) $(LIBBOOT) $(LINTLIBBOOT) a.out core
+
+$(LIBBOOT): $(OBJSDIR) .WAIT $(OBJS)
+ $(BUILD.AR) $(OBJS)
+
+$(LINTLIBBOOT): $(OBJSDIR) .WAIT $(L_OBJS)
+ @$(ECHO) "\nlint library construction:" $@
+ @$(LINT.lib) -o boot $(L_SRCS)
+
+$(OBJSDIR):
+ -@[ -d $@ ] || mkdir $@
+
+#
+# build rules using standard library object subdirectory
+#
+$(OBJSDIR)/%.o: $(ARCHCMNDIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+$(OBJSDIR)/%.o: $(ARCHCMNDIR)/%.s
+ $(COMPILE.s) -o $@ $<
+ $(POST_PROCESS_O)
+
+$(OBJSDIR)/%.ln: $(ARCHCMNDIR)/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+ @$(MV) $(@F) $@
+
+$(OBJSDIR)/%.ln: $(ARCHCMNDIR)/%.s
+ @($(LHEAD) $(LINT.s) $< $(LTAIL))
+ @$(MV) $(@F) $@
diff --git a/usr/src/psm/stand/lib/boot/sparcv9/sun4u/Makefile b/usr/src/psm/stand/lib/boot/sparcv9/sun4u/Makefile
new file mode 100644
index 0000000000..b14037da89
--- /dev/null
+++ b/usr/src/psm/stand/lib/boot/sparcv9/sun4u/Makefile
@@ -0,0 +1,42 @@
+#
+# 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.
+#
+# 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 (c) 1997, by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# psm/stand/lib/boot/sparcv9/sun4u/Makefile
+#
+# Platform-specific
+#
+
+PLATFORM = sun4u
+ARCHVERS = v9
+TOPDIR = ../../../../../..
+PLATSRCS =
+
+include ../Makefile.com
+
+include $(TOPDIR)/psm/Makefile.psm.64
+
+CFLAGS64 += -xchip=ultra $(CCABS32)
diff --git a/usr/src/psm/stand/lib/names/Makefile b/usr/src/psm/stand/lib/names/Makefile
new file mode 100644
index 0000000000..0f88fc896e
--- /dev/null
+++ b/usr/src/psm/stand/lib/names/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, Version 1.0 only
+# (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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# psm/stand/lib/names/Makefile
+
+include ../../../../Makefile.master
+
+sparcv9_ARCHITECTURES = sparcv9
+sparc_ARCHITECTURES = $(sparcv9_ARCHITECTURES)
+
+SUBDIRS = $($(MACH)_ARCHITECTURES)
+
+all install clean clobber lint: $(SUBDIRS)
+
+all := TARGET = all
+clean := TARGET = clean
+clobber := TARGET = clobber
+lint := TARGET = lint
+install := TARGET = install
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(MFLAGS) $(TARGET)
+
+FRC:
diff --git a/usr/src/psm/stand/lib/names/sparc/common/mfgname.c b/usr/src/psm/stand/lib/names/sparc/common/mfgname.c
new file mode 100644
index 0000000000..358c0ac38f
--- /dev/null
+++ b/usr/src/psm/stand/lib/names/sparc/common/mfgname.c
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/param.h>
+#include <sys/promif.h>
+
+#include <sys/platnames.h>
+
+#define MAXNMLEN 80 /* # of chars in an impl-arch name */
+
+/*
+ * Return the manufacturer name for this platform.
+ *
+ * This is exported (solely) as the rootnode name property in
+ * the kernel's devinfo tree via the 'mfg-name' boot property.
+ * So it's only used by boot, not the boot blocks.
+ */
+char *
+get_mfg_name(void)
+{
+ dnode_t n;
+ int len;
+
+ static char mfgname[MAXNMLEN];
+
+ if ((n = prom_rootnode()) != OBP_NONODE &&
+ (len = prom_getproplen(n, OBP_NAME)) > 0 && len < MAXNMLEN) {
+ (void) prom_getprop(n, OBP_NAME, mfgname);
+ mfgname[len] = '\0'; /* broken clones don't terminate name */
+ return (mfgname);
+ }
+
+ return ("Unknown");
+}
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
new file mode 100644
index 0000000000..42f8a90bd4
--- /dev/null
+++ b/usr/src/psm/stand/lib/names/sparc/common/uname-i.c
@@ -0,0 +1,213 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/param.h>
+#include <sys/idprom.h>
+#include <sys/promif.h>
+#include <sys/salib.h>
+
+#include <sys/platnames.h>
+
+/*
+ * This source is (and should be ;-) shared between the boot blocks
+ * and the boot programs. So if you change it, be sure to test them all!
+ */
+
+#define MAXNMLEN 1024 /* # of chars in a property */
+
+/*
+ * Supplied by modpath.c
+ *
+ * Making these externs here allows all sparc machines to share
+ * get_impl_arch_name().
+ */
+extern char *default_name;
+extern char *default_path;
+
+enum ia_state_mach {
+ STATE_NAME,
+ STATE_COMPAT_INIT,
+ STATE_COMPAT,
+ STATE_DEFAULT,
+ STATE_FINI
+};
+
+/*
+ * Return the implementation architecture name (uname -i) for this platform.
+ *
+ * Use the named rootnode property to determine the iarch.
+ */
+static char *
+get_impl_arch_name(enum ia_state_mach *state, int use_default)
+{
+ static char iarch[MAXNMLEN];
+ static int len;
+ static char *ia;
+
+ dnode_t n;
+ char *cp;
+ char *namename;
+
+newstate:
+ switch (*state) {
+ case STATE_NAME:
+ *state = STATE_COMPAT_INIT;
+ namename = OBP_NAME;
+ n = (dnode_t)prom_rootnode();
+ len = prom_getproplen(n, namename);
+ if (len <= 0 || len >= MAXNMLEN)
+ goto newstate;
+ (void) prom_getprop(n, namename, iarch);
+ iarch[len] = '\0'; /* fix broken clones */
+ ia = iarch;
+ break;
+
+ case STATE_COMPAT_INIT:
+ *state = STATE_COMPAT;
+ namename = OBP_COMPATIBLE;
+ n = (dnode_t)prom_rootnode();
+ len = prom_getproplen(n, namename);
+ if (len <= 0 || len >= MAXNMLEN) {
+ *state = STATE_DEFAULT;
+ goto newstate;
+ }
+ (void) prom_getprop(n, namename, iarch);
+ iarch[len] = '\0'; /* ensure null termination */
+ ia = iarch;
+ break;
+
+ case STATE_COMPAT:
+ /*
+ * Advance 'ia' to point to next string in
+ * compatible property array (if any).
+ */
+ while (*ia++)
+ ;
+ if ((ia - iarch) >= len) {
+ *state = STATE_DEFAULT;
+ goto newstate;
+ }
+ break;
+
+ case STATE_DEFAULT:
+ *state = STATE_FINI;
+ if (!use_default || default_name == NULL)
+ goto newstate;
+ (void) strcpy(iarch, default_name);
+ ia = iarch;
+ break;
+
+ case STATE_FINI:
+ return (NULL);
+ }
+
+ /*
+ * Crush filesystem-awkward characters. See PSARC/1992/170.
+ * (Convert the property to a sane directory name in UFS)
+ */
+ for (cp = ia; *cp; cp++)
+ if (*cp == '/' || *cp == ' ' || *cp == '\t')
+ *cp = '_';
+ return (ia);
+}
+
+static void
+make_platform_path(char *fullpath, char *iarch, char *filename)
+{
+ (void) strcpy(fullpath, "/platform/");
+ (void) strcat(fullpath, iarch);
+ if (filename != NULL) {
+ (void) strcat(fullpath, "/");
+ (void) strcat(fullpath, filename);
+ }
+}
+
+/*
+ * Generate impl_arch_name by searching the /platform hierarchy
+ * for a matching directory. We are not looking for any particular
+ * file here, but for a directory hierarchy for the module path.
+ */
+int
+find_platform_dir(int (*isdirfn)(char *), char *iarch, int use_default)
+{
+ char fullpath[MAXPATHLEN];
+ char *ia;
+ enum ia_state_mach state = STATE_NAME;
+
+ /*
+ * Hunt the filesystem looking for a directory hierarchy.
+ */
+ while ((ia = get_impl_arch_name(&state, use_default)) != NULL) {
+ make_platform_path(fullpath, ia, NULL);
+ if (((*isdirfn)(fullpath)) != 0) {
+ (void) strcpy(iarch, ia);
+ return (1);
+ }
+ }
+ return (0);
+}
+
+/*
+ * Search the /platform hierarchy looking for a particular file.
+ *
+ * impl_arch_name is given as an optional hint as to where the
+ * file might be found.
+ */
+int
+open_platform_file(
+ char *filename,
+ int (*openfn)(char *, void *),
+ void *arg,
+ char *fullpath,
+ char *given_iarch)
+{
+ 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) {
+ make_platform_path(fullpath, ia, filename);
+ if ((fd = (*openfn)(fullpath, arg)) != -1)
+ return (fd);
+ }
+
+ return (-1);
+}
diff --git a/usr/src/psm/stand/lib/names/sparc/common/uname-m.c b/usr/src/psm/stand/lib/names/sparc/common/uname-m.c
new file mode 100644
index 0000000000..780ef78443
--- /dev/null
+++ b/usr/src/psm/stand/lib/names/sparc/common/uname-m.c
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ *
+ * 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 (c) 1994-1995, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/param.h>
+#include <sys/modctl.h>
+#include <sys/salib.h>
+
+#include <sys/platnames.h>
+
+/*
+ * Supplied by modpath.c
+ *
+ * Making these externs here allows all sparc machines to share
+ * mod_path_uname_m().
+ */
+extern char *default_name;
+extern char *default_path;
+
+/*
+ * Is path "/platform/"dir"/" ?
+ */
+static int
+platcmp(char *path, char *dir)
+{
+ static char prefix[] = "/platform/";
+ static char suffix[] = "/kernel";
+ int len;
+
+ if (strncmp(path, prefix, sizeof (prefix) - 1) != 0)
+ return (0);
+ len = strlen(dir);
+ path += sizeof (prefix) - 1;
+ if (strncmp(path, dir, len) != 0)
+ return (0);
+ path += len;
+ if (strcmp(path, suffix) != 0)
+ return (0);
+ return (1);
+}
+
+/*
+ * This function provides a hook for enhancing the module_path.
+ */
+/*ARGSUSED*/
+void
+mod_path_uname_m(char *mod_path, char *ia_name)
+{
+
+ if (ia_name == NULL)
+ return;
+
+ /*
+ * If we found the kernel in the default dir, prepend the ia_name
+ * directory (e.g. /platform/SUNW,foo/kernel) to the mod_path unless
+ * ia_name is the same as the default dir. This can happen if we
+ * found the kernel via the "compatible" property.
+ *
+ * If we found the kernel in the ia_name dir, append the default
+ * directory to the modpath.
+ *
+ * If neither of the above are true, we were given a specific kernel
+ * to boot, so we leave things well enough alone.
+ */
+ if (platcmp(mod_path, default_name)) {
+ if (strcmp(ia_name, default_name) != 0) {
+ char tmp[MOD_MAXPATH];
+
+ (void) strcpy(tmp, mod_path);
+ (void) strcpy(mod_path, "/platform/");
+ (void) strcat(mod_path, ia_name);
+ (void) strcat(mod_path, "/kernel ");
+ (void) strcat(mod_path, tmp);
+ }
+ } else if (platcmp(mod_path, ia_name))
+ (void) strcat(mod_path, default_path);
+}
diff --git a/usr/src/psm/stand/lib/names/sparcv9/Makefile b/usr/src/psm/stand/lib/names/sparcv9/Makefile
new file mode 100644
index 0000000000..e5f119a296
--- /dev/null
+++ b/usr/src/psm/stand/lib/names/sparcv9/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, Version 1.0 only
+# (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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# psm/stand/lib/names/sparcv9/Makefile
+
+include ../../../../../Makefile.master
+
+SUBDIRS = sun4u sun4v
+
+all install clean clobber lint: $(SUBDIRS)
+
+all := TARGET = all
+clean := TARGET = clean
+clobber := TARGET = clobber
+lint := TARGET = lint
+install := TARGET = install
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(MFLAGS) $(TARGET)
+
+FRC:
diff --git a/usr/src/psm/stand/lib/names/sparcv9/Makefile.com b/usr/src/psm/stand/lib/names/sparcv9/Makefile.com
new file mode 100644
index 0000000000..ca39db2192
--- /dev/null
+++ b/usr/src/psm/stand/lib/names/sparcv9/Makefile.com
@@ -0,0 +1,116 @@
+#
+# 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.
+#
+# 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 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# psm/stand/lib/names/sparcv9/Makefile.com
+#
+# SPARCv9 architecture Makefile for Standalone Library
+# Platform-specific, but shared between platforms.
+# Firmware dependent.
+#
+
+include $(TOPDIR)/Makefile.master
+include $(TOPDIR)/lib/Makefile.lib
+include $(TOPDIR)/psm/stand/lib/Makefile.lib
+
+PSMSYSHDRDIR = $(TOPDIR)/psm/stand
+STANDDIR = $(TOPDIR)/stand
+
+LIBNAMES = libnames.a
+LINTLIBNAMES = llib-lnames.ln
+
+# ARCHCMNDIR - common code for several machines of a given isa
+# OBJSDIR - where the .o's go
+
+ARCHCMNDIR = ../../sparc/common
+OBJSDIR = objs
+
+CMNSRCS = uname-i.c uname-m.c mfgname.c
+NAMESRCS = $(PLATSRCS) $(CMNSRCS)
+NAMEOBJS = $(NAMESRCS:%.c=%.o)
+
+OBJS = $(NAMEOBJS:%=$(OBJSDIR)/%)
+L_OBJS = $(OBJS:%.o=%.ln)
+L_SRCS = $(CMNSRCS:%=$(ARCHCMNDIR)/%) $(PLATSRCS)
+
+CPPINCS += -I$(SRC)/uts/common
+CPPINCS += -I$(SRC)/uts/sun
+CPPINCS += -I$(SRC)/uts/sparc
+CPPINCS += -I$(SRC)/uts/sparc/$(ARCHVERS)
+CPPINCS += -I$(SRC)/uts/sun4
+CPPINCS += -I$(SRC)/uts/$(PLATFORM)
+CPPINCS += -I$(ROOT)/usr/include/$(ARCHVERS)
+CPPINCS += -I$(ROOT)/usr/platform/$(PLATFORM)/include
+CPPINCS += -I$(PSMSYSHDRDIR)
+CPPINCS += -I$(STANDDIR)
+CPPINCS += -I$(STANDDIR)/lib/sa
+CPPFLAGS = $(CPPINCS) $(CCYFLAG)$(PSMSYSHDRDIR)
+CPPFLAGS += -D_KERNEL
+ASFLAGS = -P -D__STDC__ -D_ASM $(CPPINCS)
+CFLAGS += $(CCVERBOSE)
+
+.KEEP_STATE:
+
+.PARALLEL: $(OBJS) $(L_OBJS)
+
+all install: $(LIBNAMES) .WAIT
+
+lint: $(LINTLIBNAMES)
+
+clean:
+ $(RM) $(OBJS) $(L_OBJS)
+
+clobber: clean
+ $(RM) $(LIBNAMES) $(LINTLIBNAMES) a.out core
+
+$(LIBNAMES): $(OBJSDIR) .WAIT $(OBJS)
+ $(BUILD.AR) $(OBJS)
+
+$(LINTLIBNAMES): $(OBJSDIR) .WAIT $(L_OBJS)
+ @$(ECHO) "\nlint library construction:" $@
+ @$(LINT.lib) -o names $(L_SRCS)
+
+$(OBJSDIR):
+ -@[ -d $@ ] || mkdir $@
+
+#
+# build rules using standard library object subdirectory
+#
+$(OBJSDIR)/%.o: $(ARCHCMNDIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+$(OBJSDIR)/%.o: $(ARCHCMNDIR)/%.s
+ $(COMPILE.s) -o $@ $<
+ $(POST_PROCESS_O)
+
+$(OBJSDIR)/%.ln: $(ARCHCMNDIR)/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+ @$(MV) $(@F) $@
+
+$(OBJSDIR)/%.ln: $(ARCHCMNDIR)/%.s
+ @($(LHEAD) $(LINT.s) $< $(LTAIL))
+ @$(MV) $(@F) $@
diff --git a/usr/src/psm/stand/lib/names/sparcv9/sun4u/Makefile b/usr/src/psm/stand/lib/names/sparcv9/sun4u/Makefile
new file mode 100644
index 0000000000..288b990d54
--- /dev/null
+++ b/usr/src/psm/stand/lib/names/sparcv9/sun4u/Makefile
@@ -0,0 +1,41 @@
+#
+# 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.
+#
+# 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 (c) 1997, by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# psm/stand/lib/names/sparcv9/sun4u/Makefile
+#
+# Platform-specific
+#
+
+PLATFORM = sun4u
+ARCHVERS = v9
+TOPDIR = ../../../../../..
+PLATSRCS = modpath.c
+
+include ../Makefile.com
+include $(TOPDIR)/psm/Makefile.psm.64
+
+CFLAGS64 += -xchip=ultra $(CCABS32)
diff --git a/usr/src/psm/stand/lib/names/sparcv9/sun4u/modpath.c b/usr/src/psm/stand/lib/names/sparcv9/sun4u/modpath.c
new file mode 100644
index 0000000000..5637eba938
--- /dev/null
+++ b/usr/src/psm/stand/lib/names/sparcv9/sun4u/modpath.c
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ *
+ * 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 (c) 1997, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Platform specific vars used by uname-i.c
+ */
+
+char *default_name = "sun4u";
+char *default_path = " /platform/sun4u/kernel";
diff --git a/usr/src/psm/stand/lib/names/sparcv9/sun4v/Makefile b/usr/src/psm/stand/lib/names/sparcv9/sun4v/Makefile
new file mode 100644
index 0000000000..0b776f972b
--- /dev/null
+++ b/usr/src/psm/stand/lib/names/sparcv9/sun4v/Makefile
@@ -0,0 +1,41 @@
+#
+# 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.
+#
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# psm/stand/lib/names/sparcv9/sun4v/Makefile
+#
+# Platform-specific
+#
+
+PLATFORM = sun4v
+ARCHVERS = v9
+TOPDIR = ../../../../../..
+PLATSRCS = modpath.c
+
+include ../Makefile.com
+include $(TOPDIR)/psm/Makefile.psm.64
+
+CFLAGS64 += -xchip=ultra $(CCABS32)
diff --git a/usr/src/psm/stand/lib/names/sparcv9/sun4v/modpath.c b/usr/src/psm/stand/lib/names/sparcv9/sun4v/modpath.c
new file mode 100644
index 0000000000..21f7689804
--- /dev/null
+++ b/usr/src/psm/stand/lib/names/sparcv9/sun4v/modpath.c
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ *
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Platform specific vars used by uname-i.c
+ */
+
+char *default_name = "sun4v";
+char *default_path = " /platform/sun4v/kernel";
diff --git a/usr/src/psm/stand/lib/promif/Makefile b/usr/src/psm/stand/lib/promif/Makefile
new file mode 100644
index 0000000000..1123c4259c
--- /dev/null
+++ b/usr/src/psm/stand/lib/promif/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, Version 1.0 only
+# (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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# psm/stand/lib/promif/Makefile
+#
+
+include ../../../../Makefile.master
+
+sparc_ARCHITECTURES = sparcv9
+
+SUBDIRS = $($(MACH)_ARCHITECTURES)
+
+all := TARGET = all
+install := TARGET = install
+clean := TARGET = clean
+clobber := TARGET = clobber
+lint := TARGET = lint
+
+all install clean clobber lint: $(SUBDIRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(MFLAGS) $(TARGET)
+
+FRC:
diff --git a/usr/src/psm/stand/lib/promif/sparcv9/Makefile b/usr/src/psm/stand/lib/promif/sparcv9/Makefile
new file mode 100644
index 0000000000..6fd7361218
--- /dev/null
+++ b/usr/src/psm/stand/lib/promif/sparcv9/Makefile
@@ -0,0 +1,47 @@
+#
+# 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.
+#
+# 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
+#
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+#
+# Copyright (c) 1997, by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# psm/stand/lib/promif/sparcv9/Makefile
+#
+
+include ../../../../../Makefile.master
+
+SUBDIRS = ieee1275
+
+all := TARGET = all
+install := TARGET = install
+clean := TARGET = clean
+clobber := TARGET = clobber
+lint := TARGET = lint
+
+all install clean clobber lint: $(SUBDIRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(MFLAGS) $(TARGET)
+
+FRC:
diff --git a/usr/src/psm/stand/lib/promif/sparcv9/ieee1275/Makefile b/usr/src/psm/stand/lib/promif/sparcv9/ieee1275/Makefile
new file mode 100644
index 0000000000..7817f55bf9
--- /dev/null
+++ b/usr/src/psm/stand/lib/promif/sparcv9/ieee1275/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, Version 1.0 only
+# (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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# psm/stand/boot/sparcv9/ieee1275/Makefile
+#
+
+# shared and platform-specific firmware libraries
+
+SUBDIRS = common sun4u sun4v
+
+all := TARGET = all
+install := TARGET = install
+clean := TARGET = clean
+clobber := TARGET = clobber
+lint := TARGET = lint
+
+all install clean clobber lint: $(SUBDIRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(MFLAGS) $(TARGET)
+
+FRC:
diff --git a/usr/src/psm/stand/lib/promif/sparcv9/ieee1275/common/Makefile b/usr/src/psm/stand/lib/promif/sparcv9/ieee1275/common/Makefile
new file mode 100644
index 0000000000..e24b92b763
--- /dev/null
+++ b/usr/src/psm/stand/lib/promif/sparcv9/ieee1275/common/Makefile
@@ -0,0 +1,146 @@
+#
+# 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.
+#
+# 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 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# psm/stand/lib/promif/sparcv9/ieee1275/common/Makefile
+#
+
+# usr/src
+TOPDIR = ../../../../../../..
+
+include $(TOPDIR)/Makefile.master
+include $(TOPDIR)/lib/Makefile.lib
+include $(TOPDIR)/psm/stand/lib/Makefile.lib
+include $(TOPDIR)/psm/Makefile.psm.64
+
+CFLAGS64 += -xchip=ultra $(CCABS32)
+
+PROMDIR = $(TOPDIR)/psm/promif/ieee1275/common
+SYSDIR = $(TOPDIR)/uts
+
+LIBPROM = libprom.a
+LINTLIBPROM = llib-lprom.ln
+
+PROM_CFILES = \
+ prom_2path.c \
+ prom_boot.c \
+ prom_devname.c \
+ prom_devtype.c \
+ prom_enter.c \
+ prom_env.c \
+ prom_exit.c \
+ prom_fb.c \
+ prom_getchar.c \
+ prom_gettime.c \
+ prom_handler.c \
+ prom_inpath.c \
+ prom_interp.c \
+ prom_io.c \
+ prom_kbd.c \
+ prom_key.c \
+ prom_node.c \
+ prom_outpath.c \
+ prom_panic.c \
+ prom_path.c \
+ prom_phandle.c \
+ prom_printf.c \
+ prom_prop.c \
+ prom_putchar.c \
+ prom_reboot.c \
+ prom_stdin.c \
+ prom_stdout.c \
+ prom_string.c \
+ prom_test.c \
+ prom_trap.c \
+ prom_version.c \
+ prom_wrtestr.c
+
+PROM_SFILES =
+
+PROM_FILES = $(PROM_CFILES) $(PROM_SFILES)
+
+KARCH = sun4u
+MMU = sfmmu
+
+OBJSDIR = objs
+
+PROM_COBJ = $(PROM_CFILES:%.c=$(OBJSDIR)/%.o)
+PROM_SOBJ = $(PROM_SFILES:%.s=$(OBJSDIR)/%.o)
+OBJS = $(PROM_COBJ) $(PROM_SOBJ)
+L_OBJS = $(OBJS:%.o=%.ln)
+L_SRCS = $(PROM_FILES:%=$(PROMDIR)/%)
+
+ARCHOPTS = -DSTACK_64BIT -Dsun4u
+ASFLAGS = -P -D__STDC__ -D_BOOT -D_ASM
+CPPDEFS = $(ARCHOPTS) -D$(KARCH) -D_BOOT -D_KERNEL -D_MACHDEP
+CPPINCS = -I. -I$(SYSDIR)/sun4 -I$(SYSDIR)/$(KARCH) -I$(SYSDIR)/$(MMU) \
+ -I$(SYSDIR)/sparc/v9 -I$(SYSDIR)/sparc \
+ -I$(SYSDIR)/sun -I$(SYSDIR)/common
+CPPFLAGS = $(CPPDEFS) $(CPPINCS) $(CPPFLAGS.master)
+CFLAGS += $(CCVERBOSE)
+
+.KEEP_STATE:
+
+.PARALLEL: $(OBJS) $(L_OBJS)
+
+all install: $(LIBPROM)
+
+lint: $(LINTLIBPROM)
+
+clean:
+ $(RM) $(OBJS) $(L_OBJS)
+
+clobber: clean
+ $(RM) $(LIBPROM) $(LINTLIBPROM) a.out core
+
+$(LIBPROM): $(OBJSDIR) .WAIT $(OBJS)
+ $(BUILD.AR) $(OBJS)
+
+$(LINTLIBPROM): $(OBJSDIR) .WAIT $(L_OBJS)
+ @$(ECHO) "\nlint library construction:" $@
+ @$(LINT.lib) -o prom $(L_SRCS)
+
+$(OBJSDIR):
+ -@[ -d $@ ] || mkdir $@
+
+#
+# build rules using standard library object subdirectory
+#
+$(OBJSDIR)/%.o: $(PROMDIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+$(OBJSDIR)/%.o: $(PROMDIR)/%.s
+ $(COMPILE.s) -o $@ $<
+ $(POST_PROCESS_O)
+
+$(OBJSDIR)/%.ln: $(PROMDIR)/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+ @$(MV) $(@F) $@
+
+$(OBJSDIR)/%.ln: $(PROMDIR)/%.s
+ @($(LHEAD) $(LINT.s) $< $(LTAIL))
+ @$(MV) $(@F) $@
diff --git a/usr/src/psm/stand/lib/promif/sparcv9/ieee1275/sun4u/Makefile b/usr/src/psm/stand/lib/promif/sparcv9/ieee1275/sun4u/Makefile
new file mode 100644
index 0000000000..0d47a6ef89
--- /dev/null
+++ b/usr/src/psm/stand/lib/promif/sparcv9/ieee1275/sun4u/Makefile
@@ -0,0 +1,144 @@
+#
+# 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.
+#
+# 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 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# psm/stand/boot/sparcv9/ieee1275/sun4u/Makefile
+#
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+TOPDIR = ../../../../../../..
+
+include $(TOPDIR)/Makefile.master
+include $(TOPDIR)/lib/Makefile.lib
+include $(TOPDIR)/psm/stand/lib/Makefile.lib
+include $(TOPDIR)/psm/Makefile.psm.64
+
+CFLAGS64 += -xchip=ultra $(CCABS32)
+
+PLATDIR = $(TOPDIR)/psm/promif/ieee1275/sun4u
+PLATSUN4DIR = $(TOPDIR)/psm/promif/ieee1275/sun4
+SYSDIR = $(TOPDIR)/uts
+
+LIBPLAT = libplat.a
+LINTLIBPLAT = llib-lplat.ln
+
+PLAT_PFILES = \
+ prom_heartbeat.c \
+ prom_mmu.c \
+ prom_serengeti.c \
+ prom_sunfire.c \
+ prom_vercheck.c
+
+PLAT_PSUN4FILES = \
+ prom_alloc.c \
+ prom_cpuctl.c \
+ prom_getunum.c \
+ prom_idprom.c \
+ prom_init.c \
+ prom_macaddr.c \
+ prom_map.c \
+ prom_mem.c \
+ prom_retain.c \
+ prom_sparc.c
+
+KARCH = sun4u
+MMU = sfmmu
+
+OBJSDIR = objs
+
+PLAT_POBJ = $(PLAT_PFILES:%.c=$(OBJSDIR)/%.o)
+PLAT_PSUN4OBJ = $(PLAT_PSUN4FILES:%.c=$(OBJSDIR)/%.o)
+OBJS = $(PLAT_POBJ) $(PLAT_PSUN4OBJ)
+L_OBJS = $(OBJS:%.o=%.ln)
+L_SRCS = $(PLAT_PFILES:%=$(PLATDIR)/%)
+L_SRCS += $(PLAT_PSUN4FILES:%=$(PLATSUN4DIR)/%)
+
+ARCHOPTS= -Dsun4u
+ASFLAGS = -P -D__STDC__ -D_BOOT -D_ASM
+CPPDEFS = $(ARCHOPTS) -D$(KARCH) -D_BOOT -D_KERNEL -D_MACHDEP
+CPPINCS = -I. -I$(SYSDIR)/sun4 -I$(SYSDIR)/$(KARCH) -I$(SYSDIR)/$(MMU) \
+ -I$(SYSDIR)/sparc/v9 -I$(SYSDIR)/sparc \
+ -I$(SYSDIR)/sun -I$(SYSDIR)/common
+CPPFLAGS= $(CPPDEFS) $(CPPINCS) $(CPPFLAGS.master)
+CFLAGS += $(CCVERBOSE)
+
+.KEEP_STATE:
+
+.PARALLEL: $(OBJS) $(L_OBJS)
+
+all install: $(LIBPLAT)
+
+lint: $(LINTLIBPLAT)
+
+clean:
+ $(RM) $(OBJS) $(L_OBJS)
+
+clobber: clean
+ $(RM) $(LIBPLAT) $(LINTLIBPLAT) a.out core
+
+$(LIBPLAT): $(OBJSDIR) .WAIT $(OBJS)
+ $(BUILD.AR) $(OBJS)
+
+$(LINTLIBPLAT): $(OBJSDIR) .WAIT $(L_OBJS)
+ @$(ECHO) "\nlint library construction:" $@
+ @$(LINT.lib) -o plat $(L_SRCS)
+
+$(OBJSDIR):
+ -@[ -d $@ ] || mkdir $@
+
+#
+# build rules using standard library object subdirectory
+#
+$(OBJSDIR)/%.o: $(PLATDIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+$(OBJSDIR)/%.o: $(PLATDIR)/%.s
+ $(COMPILE.s) -o $@ $<
+ $(POST_PROCESS_O)
+
+$(OBJSDIR)/%.o: $(PLATSUN4DIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+$(OBJSDIR)/%.o: $(PLATSUN4DIR)/%.s
+ $(COMPILE.s) -o $@ $<
+ $(POST_PROCESS_O)
+
+$(OBJSDIR)/%.ln: $(PLATDIR)/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+ @$(MV) $(@F) $@
+
+$(OBJSDIR)/%.ln: $(PLATDIR)/%.s
+ @($(LHEAD) $(LINT.s) $< $(LTAIL))
+ @$(MV) $(@F) $@
+
+$(OBJSDIR)/%.ln: $(PLATSUN4DIR)/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+ @$(MV) $(@F) $@
+
+$(OBJSDIR)/%.ln: $(PLATSUN4DIR)/%.s
+ @($(LHEAD) $(LINT.s) $< $(LTAIL))
+ @$(MV) $(@F) $@
diff --git a/usr/src/psm/stand/lib/promif/sparcv9/ieee1275/sun4v/Makefile b/usr/src/psm/stand/lib/promif/sparcv9/ieee1275/sun4v/Makefile
new file mode 100644
index 0000000000..c02f97839c
--- /dev/null
+++ b/usr/src/psm/stand/lib/promif/sparcv9/ieee1275/sun4v/Makefile
@@ -0,0 +1,143 @@
+#
+# 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.
+#
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# psm/stand/boot/sparcv9/ieee1275/sun4v/Makefile
+#
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+TOPDIR = ../../../../../../..
+
+include $(TOPDIR)/Makefile.master
+include $(TOPDIR)/lib/Makefile.lib
+include $(TOPDIR)/psm/stand/lib/Makefile.lib
+include $(TOPDIR)/psm/Makefile.psm.64
+
+CFLAGS64 += -xchip=ultra $(CCABS32)
+
+PLATDIR = $(TOPDIR)/psm/promif/ieee1275/sun4u
+PLATSUN4DIR = $(TOPDIR)/psm/promif/ieee1275/sun4
+SYSDIR = $(TOPDIR)/uts
+
+LIBPLAT = libplat.a
+LINTLIBPLAT = llib-lplat.ln
+
+PLAT_PFILES = \
+ prom_heartbeat.c \
+ prom_mmu.c \
+ prom_vercheck.c
+
+PLAT_PSUN4FILES = \
+ prom_alloc.c \
+ prom_cpuctl.c \
+ prom_getunum.c \
+ prom_idprom.c \
+ prom_init.c \
+ prom_macaddr.c \
+ prom_map.c \
+ prom_mem.c \
+ prom_retain.c \
+ prom_sparc.c
+
+KARCH = sun4v
+MMU = sfmmu
+
+OBJSDIR = objs
+
+PLAT_POBJ = $(PLAT_PFILES:%.c=$(OBJSDIR)/%.o)
+PLAT_PSUN4OBJ = $(PLAT_PSUN4FILES:%.c=$(OBJSDIR)/%.o)
+OBJS = $(PLAT_POBJ) $(PLAT_PSUN4OBJ)
+L_OBJS = $(OBJS:%.o=%.ln)
+L_SRCS = $(PLAT_PFILES:%=$(PLATDIR)/%)
+L_SRCS += $(PLAT_PSUN4FILES:%=$(PLATSUN4DIR)/%)
+
+ARCHOPTS= -Dsun4v
+ASFLAGS = -P -D__STDC__ -D_BOOT -D_ASM
+CPPDEFS = $(ARCHOPTS) -D$(KARCH) -D_BOOT -D_KERNEL -D_MACHDEP
+CPPINCS = -I. -I$(SYSDIR)/sun4 -I$(SYSDIR)/$(KARCH) -I$(SYSDIR)/$(MMU) \
+ -I$(SYSDIR)/sun4u \
+ -I$(SYSDIR)/sparc/v9 -I$(SYSDIR)/sparc \
+ -I$(SYSDIR)/sun -I$(SYSDIR)/common
+CPPFLAGS= $(CPPDEFS) $(CPPINCS) $(CPPFLAGS.master)
+CFLAGS += $(CCVERBOSE)
+
+.KEEP_STATE:
+
+.PARALLEL: $(OBJS) $(L_OBJS)
+
+all install: $(LIBPLAT)
+
+lint: $(LINTLIBPLAT)
+
+clean:
+ $(RM) $(OBJS) $(L_OBJS)
+
+clobber: clean
+ $(RM) $(LIBPLAT) $(LINTLIBPLAT) a.out core
+
+$(LIBPLAT): $(OBJSDIR) .WAIT $(OBJS)
+ $(BUILD.AR) $(OBJS)
+
+$(LINTLIBPLAT): $(OBJSDIR) .WAIT $(L_OBJS)
+ @$(ECHO) "\nlint library construction:" $@
+ @$(LINT.lib) -o plat $(L_SRCS)
+
+$(OBJSDIR):
+ -@[ -d $@ ] || mkdir $@
+
+#
+# build rules using standard library object subdirectory
+#
+$(OBJSDIR)/%.o: $(PLATDIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+$(OBJSDIR)/%.o: $(PLATDIR)/%.s
+ $(COMPILE.s) -o $@ $<
+ $(POST_PROCESS_O)
+
+$(OBJSDIR)/%.o: $(PLATSUN4DIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+$(OBJSDIR)/%.o: $(PLATSUN4DIR)/%.s
+ $(COMPILE.s) -o $@ $<
+ $(POST_PROCESS_O)
+
+$(OBJSDIR)/%.ln: $(PLATDIR)/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+ @$(MV) $(@F) $@
+
+$(OBJSDIR)/%.ln: $(PLATDIR)/%.s
+ @($(LHEAD) $(LINT.s) $< $(LTAIL))
+ @$(MV) $(@F) $@
+
+$(OBJSDIR)/%.ln: $(PLATSUN4DIR)/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+ @$(MV) $(@F) $@
+
+$(OBJSDIR)/%.ln: $(PLATSUN4DIR)/%.s
+ @($(LHEAD) $(LINT.s) $< $(LTAIL))
+ @$(MV) $(@F) $@
diff --git a/usr/src/psm/stand/old/bootblks/common/goforth.s b/usr/src/psm/stand/old/bootblks/common/goforth.s
new file mode 100644
index 0000000000..5d424a7ebe
--- /dev/null
+++ b/usr/src/psm/stand/old/bootblks/common/goforth.s
@@ -0,0 +1,60 @@
+!
+! 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.
+!
+! 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 2000 Sun Microsystems, Inc. All rights reserved.
+! Use is subject to license terms.
+!
+! #ident "%Z%%M% %I% %E% SMI"
+!
+
+#include <sys/asm_linkage.h>
+
+#if defined(lint)
+void
+goforth(struct sunromvec *romp, caddr_t start, caddr_t end)
+{ return; }
+#endif
+
+ .text
+!
+! goforth(struct sunromvec *romp,
+! char *start, char *end)
+!
+ ENTRY(goforth)
+ save %sp, -SA(MINFRAME), %sp
+ ld [%i0 + 0x7c], %l2 ! Address of romp->v_interpret
+ set byteload, %i1
+ sethi %hi(forthblock), %i2
+ or %i2, %lo(forthblock), %i2
+v2:
+ !
+ ! op_interpret(cmd, 1, forthblock);
+ !
+ mov %i1, %o0
+ mov %i2, %o2
+
+ call %l2
+ mov 1, %o1
+/*NOTREACHED*/
+
+byteload:
+ .asciz "byte-load"
+ .align 4
diff --git a/usr/src/psm/stand/old/bootblks/common/process.c b/usr/src/psm/stand/old/bootblks/common/process.c
new file mode 100644
index 0000000000..d8e96bc778
--- /dev/null
+++ b/usr/src/psm/stand/old/bootblks/common/process.c
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ *
+ * 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 (c) 1991 Sun Microsystems, Inc.
+ *
+ * Produce a big hunk o' data from an Fcode input file.
+ * Usage: process <infile.fcode >outfile
+ */
+
+#include <stdio.h>
+
+main()
+{
+ int c, count = 0;
+
+ (void) printf("const unsigned char forthblock[] = {\n");
+ while ((c = getchar()) != EOF)
+ (void) printf("0x%02x,%c", c & 0xff,
+ (count = ++count % 8) ? ' ' : '\n');
+ (void) printf("\n};\n");
+ return (0);
+}
diff --git a/usr/src/psm/stand/sys/boot.h b/usr/src/psm/stand/sys/boot.h
new file mode 100644
index 0000000000..8138fa0121
--- /dev/null
+++ b/usr/src/psm/stand/sys/boot.h
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ *
+ * 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 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _BOOT_H
+#define _BOOT_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Platform-independent declarations for the secondary bootloader
+ * (in psm/stand/boot).
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include <sys/link.h>
+
+
+
+/*
+ * Common variable declarations.
+ */
+extern int boothowto;
+extern int verbosemode;
+extern char *systype;
+
+extern struct memlist *pfreelistp, *vfreelistp, *pinstalledp;
+
+
+
+/*
+ * Global variables from readfile.c
+ */
+extern int (*readfile(int fd, int print))();
+
+#ifdef _ELF64_SUPPORT
+extern Elf32_Boot *elfbootvecELF32_64; /* Bootstrap vector ELF32 LP64 client */
+extern Elf64_Boot *elfbootvecELF64; /* Bootstrap vector for Elf64 LP64 */
+#endif
+
+
+
+/*
+ * Prototypes from heap_kmem.c
+ */
+extern void kmem_init(void);
+extern void *kmem_alloc(size_t, int);
+extern void kmem_free(void *, size_t);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _BOOT_H */
diff --git a/usr/src/psm/stand/sys/boot_policy.h b/usr/src/psm/stand/sys/boot_policy.h
new file mode 100644
index 0000000000..141cd1f4cb
--- /dev/null
+++ b/usr/src/psm/stand/sys/boot_policy.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ *
+ * 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 (c) 1998 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _SYS_POLICY_H
+#define _SYS_POLICY_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * External interfaces
+ */
+extern void policy_open(void);
+extern void policy_close(void);
+extern char *policy_lookup(char *pattern, int ignore_case);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_POLICY_H */
diff --git a/usr/src/psm/stand/sys/boot_redirect.h b/usr/src/psm/stand/sys/boot_redirect.h
new file mode 100644
index 0000000000..a444049658
--- /dev/null
+++ b/usr/src/psm/stand/sys/boot_redirect.h
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ *
+ * 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 (c) 1994, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _SYS_BOOT_REDIRECT_H
+#define _SYS_BOOT_REDIRECT_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The name of the redirection file used on the install CD-ROM
+ */
+#define BOOT_REDIRECT ".SUNW-boot-redirect"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_BOOT_REDIRECT_H */
diff --git a/usr/src/psm/stand/sys/platnames.h b/usr/src/psm/stand/sys/platnames.h
new file mode 100644
index 0000000000..e63b357104
--- /dev/null
+++ b/usr/src/psm/stand/sys/platnames.h
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ *
+ * 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 (c) 1994-1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _SYS_PLATNAMES_H
+#define _SYS_PLATNAMES_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * External interfaces
+ */
+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 *);
+extern void mod_path_uname_m(char *, char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_PLATNAMES_H */