Remove sparc64 support from the boot loader.

Remove all the sparc64 specific bits, both files and ifdefs.
This commit is contained in:
Warner Losh 2020-02-03 17:34:57 +00:00
parent c68c82324f
commit eb24e1491f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=357454
18 changed files with 2 additions and 2580 deletions

View file

@ -49,55 +49,6 @@ __FBSDID("$FreeBSD$");
#include "geliboot.h"
#endif
#if defined(__sparc64__)
#include <openfirm.h>
extern struct tlb_entry *dtlb_store;
extern struct tlb_entry *itlb_store;
extern int dtlb_slot;
extern int itlb_slot;
static int
md_bootserial(void)
{
char buf[64];
ihandle_t inst;
phandle_t input;
phandle_t node;
phandle_t output;
if ((node = OF_finddevice("/options")) == -1)
return(-1);
if (OF_getprop(node, "input-device", buf, sizeof(buf)) == -1)
return(-1);
input = OF_finddevice(buf);
if (OF_getprop(node, "output-device", buf, sizeof(buf)) == -1)
return(-1);
output = OF_finddevice(buf);
if (input == -1 || output == -1 ||
OF_getproplen(input, "keyboard") >= 0) {
if ((node = OF_finddevice("/chosen")) == -1)
return(-1);
if (OF_getprop(node, "stdin", &inst, sizeof(inst)) == -1)
return(-1);
if ((input = OF_instance_to_package(inst)) == -1)
return(-1);
if (OF_getprop(node, "stdout", &inst, sizeof(inst)) == -1)
return(-1);
if ((output = OF_instance_to_package(inst)) == -1)
return(-1);
}
if (input != output)
return(-1);
if (OF_getprop(input, "device_type", buf, sizeof(buf)) == -1)
return(-1);
if (strcmp(buf, "serial") != 0)
return(-1);
return(0);
}
#endif
static int
md_getboothowto(char *kargs)
{
@ -106,15 +57,10 @@ md_getboothowto(char *kargs)
/* Parse kargs */
howto = boot_parse_cmdline(kargs);
howto |= boot_env_to_howto();
#if defined(__sparc64__)
if (md_bootserial() != -1)
howto |= RB_SERIAL;
#else
if (!strcmp(getenv("console"), "comconsole"))
howto |= RB_SERIAL;
if (!strcmp(getenv("console"), "nullconsole"))
howto |= RB_MUTE;
#endif
return(howto);
}
@ -362,16 +308,6 @@ md_load_dual(char *args, vm_offset_t *modulep, vm_offset_t *dtb, int kern64)
#ifdef LOADER_GELI_SUPPORT
geli_export_key_metadata(kfp);
#endif
#if defined(__sparc64__)
file_addmetadata(kfp, MODINFOMD_DTLB_SLOTS,
sizeof dtlb_slot, &dtlb_slot);
file_addmetadata(kfp, MODINFOMD_ITLB_SLOTS,
sizeof itlb_slot, &itlb_slot);
file_addmetadata(kfp, MODINFOMD_DTLB,
dtlb_slot * sizeof(*dtlb_store), dtlb_store);
file_addmetadata(kfp, MODINFOMD_ITLB,
itlb_slot * sizeof(*itlb_store), itlb_store);
#endif
*modulep = addr;
size = md_copymodules(0, kern64);
@ -411,15 +347,13 @@ md_load_dual(char *args, vm_offset_t *modulep, vm_offset_t *dtb, int kern64)
return(0);
}
#if !defined(__sparc64__)
int
md_load(char *args, vm_offset_t *modulep, vm_offset_t *dtb)
{
return (md_load_dual(args, modulep, dtb, 0));
}
#endif
#if defined(__mips__) || defined(__powerpc__) || defined(__sparc64__)
#if defined(__mips__) || defined(__powerpc__)
int
md_load64(char *args, vm_offset_t *modulep, vm_offset_t *dtb)
{

View file

@ -1,99 +0,0 @@
/*******************************************************************
** s y s d e p . c
** Forth Inspired Command Language
** Author: John Sadler (john_sadler@alum.mit.edu)
** Created: 16 Oct 1997
** Implementations of FICL external interface functions...
**
*******************************************************************/
/* $FreeBSD$ */
#ifdef TESTMAIN
#include <stdio.h>
#include <stdlib.h>
#else
#include <stand.h>
#endif
#include "ficl.h"
/*
******************* FreeBSD P O R T B E G I N S H E R E ******************** Michael Smith
*/
#if PORTABLE_LONGMULDIV == 0
DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y)
{
DPUNS q;
uint64_t qx;
qx = (uint64_t)x * (uint64_t) y;
q.hi = (uint32_t)( qx >> 32 );
q.lo = (uint32_t)( qx & 0xFFFFFFFFL);
return q;
}
UNSQR ficlLongDiv(DPUNS q, FICL_UNS y)
{
UNSQR result;
uint64_t qx, qh;
qh = q.hi;
qx = (qh << 32) | q.lo;
result.quot = qx / y;
result.rem = qx % y;
return result;
}
#endif
void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline)
{
IGNORE(pVM);
while(*msg != 0)
putchar(*(msg++));
if (fNewline)
putchar('\n');
return;
}
void *ficlMalloc (size_t size)
{
return malloc(size);
}
void *ficlRealloc (void *p, size_t size)
{
return realloc(p, size);
}
void ficlFree (void *p)
{
free(p);
}
/*
** Stub function for dictionary access control - does nothing
** by default, user can redefine to guarantee exclusive dict
** access to a single thread for updates. All dict update code
** is guaranteed to be bracketed as follows:
** ficlLockDictionary(TRUE);
** <code that updates dictionary>
** ficlLockDictionary(FALSE);
**
** Returns zero if successful, nonzero if unable to acquire lock
** befor timeout (optional - could also block forever)
*/
#if FICL_MULTITHREAD
int ficlLockDictionary(short fLock)
{
IGNORE(fLock);
return 0;
}
#endif /* FICL_MULTITHREAD */

View file

@ -1,412 +0,0 @@
/*******************************************************************
s y s d e p . h
** Forth Inspired Command Language
** Author: John Sadler (john_sadler@alum.mit.edu)
** Created: 16 Oct 1997
** Ficl system dependent types and prototypes...
**
** Note: Ficl also depends on the use of "assert" when
** FICL_ROBUST is enabled. This may require some consideration
** in firmware systems since assert often
** assumes stderr/stdout.
** $Id: sysdep.h,v 1.6 2001-04-26 21:41:55-07 jsadler Exp jsadler $
*******************************************************************/
/*
** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
** All rights reserved.
**
** Get the latest Ficl release at http://ficl.sourceforge.net
**
** L I C E N S E and D I S C L A I M E R
**
** 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.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
**
** I am interested in hearing from anyone who uses ficl. If you have
** a problem, a success story, a defect, an enhancement request, or
** if you would like to contribute to the ficl release, please send
** contact me by email at the address above.
**
** $Id: sysdep.h,v 1.6 2001-04-26 21:41:55-07 jsadler Exp jsadler $
*/
/* $FreeBSD$ */
#if !defined (__SYSDEP_H__)
#define __SYSDEP_H__
#include <sys/types.h>
#include <stddef.h> /* size_t, NULL */
#include <setjmp.h>
#include <assert.h>
#if !defined IGNORE /* Macro to silence unused param warnings */
#define IGNORE(x) &x
#endif
/*
** TRUE and FALSE for C boolean operations, and
** portable 32 bit types for CELLs
**
*/
#if !defined TRUE
#define TRUE 1
#endif
#if !defined FALSE
#define FALSE 0
#endif
/*
** System dependent data type declarations...
*/
#if !defined INT32
#define INT32 int
#endif
#if !defined UNS32
#define UNS32 unsigned int
#endif
#if !defined UNS16
#define UNS16 unsigned short
#endif
#if !defined UNS8
#define UNS8 unsigned char
#endif
#if !defined NULL
#define NULL ((void *)0)
#endif
/*
** FICL_UNS and FICL_INT must have the same size as a void* on
** the target system. A CELL is a union of void*, FICL_UNS, and
** FICL_INT.
** (11/2000: same for FICL_FLOAT)
*/
#if !defined FICL_INT
#define FICL_INT long
#endif
#if !defined FICL_UNS
#define FICL_UNS unsigned long
#endif
#if !defined FICL_FLOAT
#define FICL_FLOAT float
#endif
/*
** Ficl presently supports values of 32 and 64 for BITS_PER_CELL
*/
#if !defined BITS_PER_CELL
#define BITS_PER_CELL 64
#endif
#if ((BITS_PER_CELL != 32) && (BITS_PER_CELL != 64))
Error!
#endif
typedef struct
{
FICL_UNS hi;
FICL_UNS lo;
} DPUNS;
typedef struct
{
FICL_UNS quot;
FICL_UNS rem;
} UNSQR;
typedef struct
{
FICL_INT hi;
FICL_INT lo;
} DPINT;
typedef struct
{
FICL_INT quot;
FICL_INT rem;
} INTQR;
/*
** B U I L D C O N T R O L S
*/
#if !defined (FICL_MINIMAL)
#define FICL_MINIMAL 0
#endif
#if (FICL_MINIMAL)
#define FICL_WANT_SOFTWORDS 0
#define FICL_WANT_FLOAT 0
#define FICL_WANT_USER 0
#define FICL_WANT_LOCALS 0
#define FICL_WANT_DEBUGGER 0
#define FICL_WANT_OOP 0
#define FICL_PLATFORM_EXTEND 0
#define FICL_MULTITHREAD 0
#define FICL_ROBUST 0
#define FICL_EXTENDED_PREFIX 0
#endif
/*
** FICL_PLATFORM_EXTEND
** Includes words defined in ficlCompilePlatform
*/
#if !defined (FICL_PLATFORM_EXTEND)
#define FICL_PLATFORM_EXTEND 1
#endif
/*
** FICL_WANT_FLOAT
** Includes a floating point stack for the VM, and words to do float operations.
** Contributed by Guy Carver
*/
#if !defined (FICL_WANT_FLOAT)
#define FICL_WANT_FLOAT 0
#endif
/*
** FICL_WANT_DEBUGGER
** Inludes a simple source level debugger
*/
#if !defined (FICL_WANT_DEBUGGER)
#define FICL_WANT_DEBUGGER 1
#endif
/*
** User variables: per-instance variables bound to the VM.
** Kinda like thread-local storage. Could be implemented in a
** VM private dictionary, but I've chosen the lower overhead
** approach of an array of CELLs instead.
*/
#if !defined FICL_WANT_USER
#define FICL_WANT_USER 1
#endif
#if !defined FICL_USER_CELLS
#define FICL_USER_CELLS 16
#endif
/*
** FICL_WANT_LOCALS controls the creation of the LOCALS wordset and
** a private dictionary for local variable compilation.
*/
#if !defined FICL_WANT_LOCALS
#define FICL_WANT_LOCALS 1
#endif
/* Max number of local variables per definition */
#if !defined FICL_MAX_LOCALS
#define FICL_MAX_LOCALS 16
#endif
/*
** FICL_WANT_OOP
** Inludes object oriented programming support (in softwords)
** OOP support requires locals and user variables!
*/
#if !(FICL_WANT_LOCALS) || !(FICL_WANT_USER)
#if !defined (FICL_WANT_OOP)
#define FICL_WANT_OOP 0
#endif
#endif
#if !defined (FICL_WANT_OOP)
#define FICL_WANT_OOP 1
#endif
/*
** FICL_WANT_SOFTWORDS
** Controls inclusion of all softwords in softcore.c
*/
#if !defined (FICL_WANT_SOFTWORDS)
#define FICL_WANT_SOFTWORDS 1
#endif
/*
** FICL_MULTITHREAD enables dictionary mutual exclusion
** wia the ficlLockDictionary system dependent function.
** Note: this implementation is experimental and poorly
** tested. Further, it's unnecessary unless you really
** intend to have multiple SESSIONS (poor choice of name
** on my part) - that is, threads that modify the dictionary
** at the same time.
*/
#if !defined FICL_MULTITHREAD
#define FICL_MULTITHREAD 0
#endif
/*
** PORTABLE_LONGMULDIV causes ficlLongMul and ficlLongDiv to be
** defined in C in sysdep.c. Use this if you cannot easily
** generate an inline asm definition
*/
#if !defined (PORTABLE_LONGMULDIV)
#define PORTABLE_LONGMULDIV 0
#endif
/*
** INLINE_INNER_LOOP causes the inner interpreter to be inline code
** instead of a function call. This is mainly because MS VC++ 5
** chokes with an internal compiler error on the function version.
** in release mode. Sheesh.
*/
#if !defined INLINE_INNER_LOOP
#if defined _DEBUG
#define INLINE_INNER_LOOP 0
#else
#define INLINE_INNER_LOOP 1
#endif
#endif
/*
** FICL_ROBUST enables bounds checking of stacks and the dictionary.
** This will detect stack over and underflows and dictionary overflows.
** Any exceptional condition will result in an assertion failure.
** (As generated by the ANSI assert macro)
** FICL_ROBUST == 1 --> stack checking in the outer interpreter
** FICL_ROBUST == 2 also enables checking in many primitives
*/
#if !defined FICL_ROBUST
#define FICL_ROBUST 2
#endif
/*
** FICL_DEFAULT_STACK Specifies the default size (in CELLs) of
** a new virtual machine's stacks, unless overridden at
** create time.
*/
#if !defined FICL_DEFAULT_STACK
#define FICL_DEFAULT_STACK 128
#endif
/*
** FICL_DEFAULT_DICT specifies the number of CELLs to allocate
** for the system dictionary by default. The value
** can be overridden at startup time as well.
** FICL_DEFAULT_ENV specifies the number of cells to allot
** for the environment-query dictionary.
*/
#if !defined FICL_DEFAULT_DICT
#define FICL_DEFAULT_DICT 12288
#endif
#if !defined FICL_DEFAULT_ENV
#define FICL_DEFAULT_ENV 260
#endif
/*
** FICL_DEFAULT_VOCS specifies the maximum number of wordlists in
** the dictionary search order. See Forth DPANS sec 16.3.3
** (file://dpans16.htm#16.3.3)
*/
#if !defined FICL_DEFAULT_VOCS
#define FICL_DEFAULT_VOCS 16
#endif
/*
** FICL_MAX_PARSE_STEPS controls the size of an array in the FICL_SYSTEM structure
** that stores pointers to parser extension functions. I would never expect to have
** more than 8 of these, so that's the default limit. Too many of these functions
** will probably exact a nasty performance penalty.
*/
#if !defined FICL_MAX_PARSE_STEPS
#define FICL_MAX_PARSE_STEPS 8
#endif
/*
** FICL_EXTENDED_PREFIX enables a bunch of extra prefixes in prefix.c and prefix.fr (if
** included as part of softcore.c)
*/
#if !defined FICL_EXTENDED_PREFIX
#define FICL_EXTENDED_PREFIX 0
#endif
/*
** FICL_ALIGN is the power of two to which the dictionary
** pointer address must be aligned. This value is usually
** either 1 or 2, depending on the memory architecture
** of the target system; 2 is safe on any 16 or 32 bit
** machine. 3 would be appropriate for a 64 bit machine.
*/
#if !defined FICL_ALIGN
#define FICL_ALIGN 3
#define FICL_ALIGN_ADD ((1 << FICL_ALIGN) - 1)
#endif
/*
** System dependent routines --
** edit the implementations in sysdep.c to be compatible
** with your runtime environment...
** ficlTextOut sends a NULL terminated string to the
** default output device - used for system error messages
** ficlMalloc and ficlFree have the same semantics as malloc and free
** in standard C
** ficlLongMul multiplies two UNS32s and returns a 64 bit unsigned
** product
** ficlLongDiv divides an UNS64 by an UNS32 and returns UNS32 quotient
** and remainder
*/
struct vm;
void ficlTextOut(struct vm *pVM, char *msg, int fNewline);
void *ficlMalloc (size_t size);
void ficlFree (void *p);
void *ficlRealloc(void *p, size_t size);
/*
** Stub function for dictionary access control - does nothing
** by default, user can redefine to guarantee exclusive dict
** access to a single thread for updates. All dict update code
** must be bracketed as follows:
** ficlLockDictionary(TRUE);
** <code that updates dictionary>
** ficlLockDictionary(FALSE);
**
** Returns zero if successful, nonzero if unable to acquire lock
** before timeout (optional - could also block forever)
**
** NOTE: this function must be implemented with lock counting
** semantics: nested calls must behave properly.
*/
#if FICL_MULTITHREAD
int ficlLockDictionary(short fLock);
#else
#define ficlLockDictionary(x) 0 /* ignore */
#endif
/*
** 64 bit integer math support routines: multiply two UNS32s
** to get a 64 bit product, & divide the product by an UNS32
** to get an UNS32 quotient and remainder. Much easier in asm
** on a 32 bit CPU than in C, which usually doesn't support
** the double length result (but it should).
*/
DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y);
UNSQR ficlLongDiv(DPUNS q, FICL_UNS y);
#endif /*__SYSDEP_H__*/

View file

@ -62,9 +62,7 @@ struct preloaded_file;
struct file_format;
/* MD code implementing MI interfaces */
#if !defined(__sparc64__)
vm_offset_t md_load(char *args, vm_offset_t *modulep, vm_offset_t *dtb);
#endif
vm_offset_t md_load64(char *args, vm_offset_t *modulep, vm_offset_t *dtb);
extern void reboot(void);

View file

@ -1,94 +0,0 @@
/*
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* 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. 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.
*
* $Header: _setjmp.s,v 1.1 91/07/06 16:45:53 torek Exp
*/
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
.asciz "@(#)_setjmp.s 8.1 (Berkeley) 6/4/93"
#else
RCSID("$NetBSD: _setjmp.S,v 1.4 1998/10/08 02:27:59 eeh Exp $")
#endif
#endif /* LIBC_SCCS and not lint */
#include <machine/asm.h>
__FBSDID("$FreeBSD$");
#define _JB_FP 0x0
#define _JB_PC 0x8
#define _JB_SP 0x10
.register %g2,#ignore
.register %g3,#ignore
/*
* C library -- setjmp, longjmp
*
* longjmp(a,v)
* will generate a "return(v?v:1)" from
* the last call to
* setjmp(a)
* by restoring the previous context.
*/
ENTRY(_setjmp)
stx %sp, [%o0 + _JB_SP]
stx %o7, [%o0 + _JB_PC]
stx %fp, [%o0 + _JB_FP]
retl
clr %o0
END(_setjmp)
ENTRY(_longjmp)
mov 1, %g1
movrnz %o1, %o1, %g1
mov %o0, %g2
ldx [%g2 + _JB_FP], %g3
1: cmp %fp, %g3
bl,a 1b
restore
be,a 2f
ldx [%g2 + _JB_SP], %o0
.Lbotch:
illtrap
2: cmp %o0, %sp
bge,a 3f
mov %o0, %sp
b,a .Lbotch
nop
3: ldx [%g2 + _JB_PC], %o7
retl
mov %g1, %o0
END(_longjmp)

View file

@ -19,9 +19,6 @@ SRCS+= load_elf32.c reloc_elf32.c
SRCS+= load_elf32.c reloc_elf32.c
SRCS+= load_elf64.c reloc_elf64.c
SRCS+= metadata.c
.elif ${MACHINE_CPUARCH} == "sparc64"
SRCS+= load_elf64.c reloc_elf64.c
SRCS+= metadata.c
.elif ${MACHINE_ARCH:Mmips64*} != ""
SRCS+= load_elf64.c reloc_elf64.c
SRCS+= metadata.c

View file

@ -632,7 +632,7 @@ Modifies kernel option
Limits the amount of KVM reserved for use by the
buffer cache, specified in bytes.
The default maximum is 200MB on i386,
and 400MB on amd64 and sparc64.
and 400MB on amd64.
This parameter is used to
prevent the buffer cache from eating too much
KVM in large-memory machine configurations.

View file

@ -1,10 +0,0 @@
# $FreeBSD$
NO_OBJ=t
.include <bsd.init.mk>
SUBDIR.yes= boot1 loader
SUBDIR.${MK_LOADER_ZFS}+=zfsboot
.include <bsd.subdir.mk>

View file

@ -1,5 +0,0 @@
# $FreeBSD$
LDFLAGS+= -nostdlib
.include "../Makefile.inc"

View file

@ -1,29 +0,0 @@
# $FreeBSD$
.include <bsd.init.mk>
PROG= boot1.elf
INTERNALPROG=
FILES?= boot1
SRCS= _start.s boot1.c
CLEANFILES+=${FILES} boot1.aout
BOOTBLOCKBASE= 0x4000
CFLAGS.clang+=-mcmodel=small
CFLAGS.gcc+=-mcmodel=medlow
CFLAGS+=-Os -I${LDRSRC}
LDFLAGS+=-Ttext ${BOOTBLOCKBASE} -Wl,-N
# Construct boot1. sunlabel expects it to contain zeroed-out space for the
# label, and to be of the correct size.
${FILES}: boot1.aout
@set -- `ls -l ${.ALLSRC}`; x=$$((7680-$$5)); \
echo "$$x bytes available"; test $$x -ge 0
${DD} if=/dev/zero of=${.TARGET} bs=512 count=16
${DD} if=${.ALLSRC} of=${.TARGET} bs=512 oseek=1 conv=notrunc
boot1.aout: boot1.elf
elf2aout -o ${.TARGET} ${.ALLSRC}
.include <bsd.prog.mk>

View file

@ -1,8 +0,0 @@
/* $FreeBSD$ */
.text
.globl _start
_start:
call ofw_init
nop
sir

View file

@ -1,751 +0,0 @@
/*-
* Copyright (c) 1998 Robert Nordier
* All rights reserved.
* Copyright (c) 2001 Robert Drehmel
* All rights reserved.
*
* Redistribution and use in source and binary forms are freely
* permitted provided that the above copyright notice and this
* paragraph and the following disclaimer are duplicated in all
* such forms.
*
* This software is provided "AS IS" and without any express or
* implied warranties, including, without limitation, the implied
* warranties of merchantability and fitness for a particular
* purpose.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/dirent.h>
#include <machine/elf.h>
#include <machine/stdarg.h>
#include "paths.h"
#define READ_BUF_SIZE 8192
typedef int putc_func_t(char c, void *arg);
typedef int32_t ofwh_t;
struct sp_data {
char *sp_buf;
u_int sp_len;
u_int sp_size;
};
static const char digits[] = "0123456789abcdef";
static char bootpath[128];
static char bootargs[128];
static ofwh_t bootdev;
static uint32_t fs_off;
int main(int ac, char **av);
static void exit(int) __dead2;
static void usage(void);
#ifdef ZFSBOOT
static void loadzfs(void);
static int zbread(char *buf, off_t off, size_t bytes);
#else
static void load(const char *);
#endif
static void bcopy(const void *src, void *dst, size_t len);
static void bzero(void *b, size_t len);
static int domount(const char *device);
static int dskread(void *buf, uint64_t lba, int nblk);
static void panic(const char *fmt, ...) __dead2;
static int printf(const char *fmt, ...);
static int putchar(char c, void *arg);
static int vprintf(const char *fmt, va_list ap);
static int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap);
static int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap);
static int __puts(const char *s, putc_func_t *putc, void *arg);
static int __sputc(char c, void *arg);
static char *__uitoa(char *buf, u_int val, int base);
static char *__ultoa(char *buf, u_long val, int base);
/*
* Open Firmware interface functions
*/
typedef uint64_t ofwcell_t;
typedef uint32_t u_ofwh_t;
typedef int (*ofwfp_t)(ofwcell_t []);
static ofwfp_t ofw; /* the PROM Open Firmware entry */
void ofw_init(int, int, int, int, ofwfp_t);
static ofwh_t ofw_finddevice(const char *);
static ofwh_t ofw_open(const char *);
static int ofw_getprop(ofwh_t, const char *, void *, size_t);
static int ofw_read(ofwh_t, void *, size_t);
static int ofw_write(ofwh_t, const void *, size_t);
static int ofw_seek(ofwh_t, uint64_t);
static void ofw_exit(void) __dead2;
static ofwh_t stdinh, stdouth;
/*
* This has to stay here, as the PROM seems to ignore the
* entry point specified in the a.out header. (or elftoaout is broken)
*/
void
ofw_init(int d, int d1, int d2, int d3, ofwfp_t ofwaddr)
{
ofwh_t chosenh;
char *av[16];
char *p;
int ac;
ofw = ofwaddr;
chosenh = ofw_finddevice("/chosen");
ofw_getprop(chosenh, "stdin", &stdinh, sizeof(stdinh));
ofw_getprop(chosenh, "stdout", &stdouth, sizeof(stdouth));
ofw_getprop(chosenh, "bootargs", bootargs, sizeof(bootargs));
ofw_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath));
bootargs[sizeof(bootargs) - 1] = '\0';
bootpath[sizeof(bootpath) - 1] = '\0';
ac = 0;
p = bootargs;
for (;;) {
while (*p == ' ' && *p != '\0')
p++;
if (*p == '\0' || ac >= 16)
break;
av[ac++] = p;
while (*p != ' ' && *p != '\0')
p++;
if (*p != '\0')
*p++ = '\0';
}
exit(main(ac, av));
}
static ofwh_t
ofw_finddevice(const char *name)
{
ofwcell_t args[] = {
(ofwcell_t)"finddevice",
1,
1,
(ofwcell_t)name,
0
};
if ((*ofw)(args)) {
printf("ofw_finddevice: name=\"%s\"\n", name);
return (1);
}
return (args[4]);
}
static int
ofw_getprop(ofwh_t ofwh, const char *name, void *buf, size_t len)
{
ofwcell_t args[] = {
(ofwcell_t)"getprop",
4,
1,
(u_ofwh_t)ofwh,
(ofwcell_t)name,
(ofwcell_t)buf,
len,
0
};
if ((*ofw)(args)) {
printf("ofw_getprop: ofwh=0x%x buf=%p len=%u\n",
ofwh, buf, len);
return (1);
}
return (0);
}
static ofwh_t
ofw_open(const char *path)
{
ofwcell_t args[] = {
(ofwcell_t)"open",
1,
1,
(ofwcell_t)path,
0
};
if ((*ofw)(args)) {
printf("ofw_open: path=\"%s\"\n", path);
return (-1);
}
return (args[4]);
}
static int
ofw_close(ofwh_t devh)
{
ofwcell_t args[] = {
(ofwcell_t)"close",
1,
0,
(u_ofwh_t)devh
};
if ((*ofw)(args)) {
printf("ofw_close: devh=0x%x\n", devh);
return (1);
}
return (0);
}
static int
ofw_read(ofwh_t devh, void *buf, size_t len)
{
ofwcell_t args[] = {
(ofwcell_t)"read",
3,
1,
(u_ofwh_t)devh,
(ofwcell_t)buf,
len,
0
};
if ((*ofw)(args)) {
printf("ofw_read: devh=0x%x buf=%p len=%u\n", devh, buf, len);
return (1);
}
return (0);
}
static int
ofw_write(ofwh_t devh, const void *buf, size_t len)
{
ofwcell_t args[] = {
(ofwcell_t)"write",
3,
1,
(u_ofwh_t)devh,
(ofwcell_t)buf,
len,
0
};
if ((*ofw)(args)) {
printf("ofw_write: devh=0x%x buf=%p len=%u\n", devh, buf, len);
return (1);
}
return (0);
}
static int
ofw_seek(ofwh_t devh, uint64_t off)
{
ofwcell_t args[] = {
(ofwcell_t)"seek",
3,
1,
(u_ofwh_t)devh,
off >> 32,
off,
0
};
if ((*ofw)(args)) {
printf("ofw_seek: devh=0x%x off=0x%lx\n", devh, off);
return (1);
}
return (0);
}
static void
ofw_exit(void)
{
ofwcell_t args[3];
args[0] = (ofwcell_t)"exit";
args[1] = 0;
args[2] = 0;
for (;;)
(*ofw)(args);
}
static void
bcopy(const void *src, void *dst, size_t len)
{
const char *s = src;
char *d = dst;
while (len-- != 0)
*d++ = *s++;
}
static void
memcpy(void *dst, const void *src, size_t len)
{
bcopy(src, dst, len);
}
static void
bzero(void *b, size_t len)
{
char *p = b;
while (len-- != 0)
*p++ = 0;
}
static int
strcmp(const char *s1, const char *s2)
{
for (; *s1 == *s2 && *s1; s1++, s2++)
;
return ((u_char)*s1 - (u_char)*s2);
}
int
main(int ac, char **av)
{
const char *path;
int i;
path = PATH_LOADER;
for (i = 0; i < ac; i++) {
switch (av[i][0]) {
case '-':
switch (av[i][1]) {
default:
usage();
}
break;
default:
path = av[i];
break;
}
}
#ifdef ZFSBOOT
printf(" \n>> FreeBSD/sparc64 ZFS boot block\n Boot path: %s\n",
bootpath);
#else
printf(" \n>> FreeBSD/sparc64 boot block\n Boot path: %s\n"
" Boot loader: %s\n", bootpath, path);
#endif
if (domount(bootpath) == -1)
panic("domount");
#ifdef ZFSBOOT
loadzfs();
#else
load(path);
#endif
return (1);
}
static void
usage(void)
{
printf("usage: boot device [/path/to/loader]\n");
exit(1);
}
static void
exit(int code)
{
ofw_exit();
}
#ifdef ZFSBOOT
#define VDEV_BOOT_OFFSET (2 * 256 * 1024)
static char zbuf[READ_BUF_SIZE];
static int
zbread(char *buf, off_t off, size_t bytes)
{
size_t len;
off_t poff;
off_t soff;
char *p;
unsigned int nb;
unsigned int lb;
p = buf;
soff = VDEV_BOOT_OFFSET + off;
lb = howmany(soff + bytes, DEV_BSIZE);
poff = soff;
while (poff < soff + bytes) {
nb = lb - poff / DEV_BSIZE;
if (nb > READ_BUF_SIZE / DEV_BSIZE)
nb = READ_BUF_SIZE / DEV_BSIZE;
if (dskread(zbuf, poff / DEV_BSIZE, nb))
break;
if ((poff / DEV_BSIZE + nb) * DEV_BSIZE > soff + bytes)
len = soff + bytes - poff;
else
len = (poff / DEV_BSIZE + nb) * DEV_BSIZE - poff;
memcpy(p, zbuf + poff % DEV_BSIZE, len);
p += len;
poff += len;
}
return (poff - soff);
}
static void
loadzfs(void)
{
Elf64_Ehdr eh;
Elf64_Phdr ph;
caddr_t p;
int i;
if (zbread((char *)&eh, 0, sizeof(eh)) != sizeof(eh)) {
printf("Can't read elf header\n");
return;
}
if (!IS_ELF(eh)) {
printf("Not an ELF file\n");
return;
}
for (i = 0; i < eh.e_phnum; i++) {
fs_off = eh.e_phoff + i * eh.e_phentsize;
if (zbread((char *)&ph, fs_off, sizeof(ph)) != sizeof(ph)) {
printf("Can't read program header %d\n", i);
return;
}
if (ph.p_type != PT_LOAD)
continue;
fs_off = ph.p_offset;
p = (caddr_t)ph.p_vaddr;
if (zbread(p, fs_off, ph.p_filesz) != ph.p_filesz) {
printf("Can't read content of section %d\n", i);
return;
}
if (ph.p_filesz != ph.p_memsz)
bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz);
}
ofw_close(bootdev);
(*(void (*)(int, int, int, int, ofwfp_t))eh.e_entry)(0, 0, 0, 0, ofw);
}
#else
#include "ufsread.c"
static struct dmadat __dmadat;
static void
load(const char *fname)
{
Elf64_Ehdr eh;
Elf64_Phdr ph;
caddr_t p;
ufs_ino_t ino;
int i;
if ((ino = lookup(fname)) == 0) {
printf("File %s not found\n", fname);
return;
}
if (fsread(ino, &eh, sizeof(eh)) != sizeof(eh)) {
printf("Can't read elf header\n");
return;
}
if (!IS_ELF(eh)) {
printf("Not an ELF file\n");
return;
}
for (i = 0; i < eh.e_phnum; i++) {
fs_off = eh.e_phoff + i * eh.e_phentsize;
if (fsread(ino, &ph, sizeof(ph)) != sizeof(ph)) {
printf("Can't read program header %d\n", i);
return;
}
if (ph.p_type != PT_LOAD)
continue;
fs_off = ph.p_offset;
p = (caddr_t)ph.p_vaddr;
if (fsread(ino, p, ph.p_filesz) != ph.p_filesz) {
printf("Can't read content of section %d\n", i);
return;
}
if (ph.p_filesz != ph.p_memsz)
bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz);
}
ofw_close(bootdev);
(*(void (*)(int, int, int, int, ofwfp_t))eh.e_entry)(0, 0, 0, 0, ofw);
}
#endif /* ZFSBOOT */
static int
domount(const char *device)
{
if ((bootdev = ofw_open(device)) == -1) {
printf("domount: can't open device\n");
return (-1);
}
#ifndef ZFSBOOT
dmadat = &__dmadat;
if (fsread(0, NULL, 0)) {
printf("domount: can't read superblock\n");
return (-1);
}
#endif
return (0);
}
static int
dskread(void *buf, uint64_t lba, int nblk)
{
/*
* The Open Firmware should open the correct partition for us.
* That means, if we read from offset zero on an open instance handle,
* we should read from offset zero of that partition.
*/
ofw_seek(bootdev, lba * DEV_BSIZE);
ofw_read(bootdev, buf, nblk * DEV_BSIZE);
return (0);
}
static void
panic(const char *fmt, ...)
{
char buf[128];
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, sizeof buf, fmt, ap);
printf("panic: %s\n", buf);
va_end(ap);
exit(1);
}
static int
printf(const char *fmt, ...)
{
va_list ap;
int ret;
va_start(ap, fmt);
ret = vprintf(fmt, ap);
va_end(ap);
return (ret);
}
static int
putchar(char c, void *arg)
{
char buf;
if (c == '\n') {
buf = '\r';
ofw_write(stdouth, &buf, 1);
}
buf = c;
ofw_write(stdouth, &buf, 1);
return (1);
}
static int
vprintf(const char *fmt, va_list ap)
{
int ret;
ret = __printf(fmt, putchar, 0, ap);
return (ret);
}
static int
vsnprintf(char *str, size_t sz, const char *fmt, va_list ap)
{
struct sp_data sp;
int ret;
sp.sp_buf = str;
sp.sp_len = 0;
sp.sp_size = sz;
ret = __printf(fmt, __sputc, &sp, ap);
return (ret);
}
static int
__printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap)
{
char buf[(sizeof(long) * 8) + 1];
char *nbuf;
u_long ul;
u_int ui;
int lflag;
int sflag;
char *s;
int pad;
int ret;
int c;
nbuf = &buf[sizeof buf - 1];
ret = 0;
while ((c = *fmt++) != 0) {
if (c != '%') {
ret += putc(c, arg);
continue;
}
lflag = 0;
sflag = 0;
pad = 0;
reswitch: c = *fmt++;
switch (c) {
case '#':
sflag = 1;
goto reswitch;
case '%':
ret += putc('%', arg);
break;
case 'c':
c = va_arg(ap, int);
ret += putc(c, arg);
break;
case 'd':
if (lflag == 0) {
ui = (u_int)va_arg(ap, int);
if (ui < (int)ui) {
ui = -ui;
ret += putc('-', arg);
}
s = __uitoa(nbuf, ui, 10);
} else {
ul = (u_long)va_arg(ap, long);
if (ul < (long)ul) {
ul = -ul;
ret += putc('-', arg);
}
s = __ultoa(nbuf, ul, 10);
}
ret += __puts(s, putc, arg);
break;
case 'l':
lflag = 1;
goto reswitch;
case 'o':
if (lflag == 0) {
ui = (u_int)va_arg(ap, u_int);
s = __uitoa(nbuf, ui, 8);
} else {
ul = (u_long)va_arg(ap, u_long);
s = __ultoa(nbuf, ul, 8);
}
ret += __puts(s, putc, arg);
break;
case 'p':
ul = (u_long)va_arg(ap, void *);
s = __ultoa(nbuf, ul, 16);
ret += __puts("0x", putc, arg);
ret += __puts(s, putc, arg);
break;
case 's':
s = va_arg(ap, char *);
ret += __puts(s, putc, arg);
break;
case 'u':
if (lflag == 0) {
ui = va_arg(ap, u_int);
s = __uitoa(nbuf, ui, 10);
} else {
ul = va_arg(ap, u_long);
s = __ultoa(nbuf, ul, 10);
}
ret += __puts(s, putc, arg);
break;
case 'x':
if (lflag == 0) {
ui = va_arg(ap, u_int);
s = __uitoa(nbuf, ui, 16);
} else {
ul = va_arg(ap, u_long);
s = __ultoa(nbuf, ul, 16);
}
if (sflag)
ret += __puts("0x", putc, arg);
ret += __puts(s, putc, arg);
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
pad = pad * 10 + c - '0';
goto reswitch;
default:
break;
}
}
return (ret);
}
static int
__sputc(char c, void *arg)
{
struct sp_data *sp;
sp = arg;
if (sp->sp_len < sp->sp_size)
sp->sp_buf[sp->sp_len++] = c;
sp->sp_buf[sp->sp_len] = '\0';
return (1);
}
static int
__puts(const char *s, putc_func_t *putc, void *arg)
{
const char *p;
int ret;
ret = 0;
for (p = s; *p != '\0'; p++)
ret += putc(*p, arg);
return (ret);
}
static char *
__uitoa(char *buf, u_int ui, int base)
{
char *p;
p = buf;
*p = '\0';
do
*--p = digits[ui % base];
while ((ui /= base) != 0);
return (p);
}
static char *
__ultoa(char *buf, u_long ul, int base)
{
char *p;
p = buf;
*p = '\0';
do
*--p = digits[ul % base];
while ((ul /= base) != 0);
return (p);
}

View file

@ -1,56 +0,0 @@
# $FreeBSD$
HAVE_ZFS= ${MK_LOADER_ZFS}
LOADER_DISK_SUPPORT?= yes
LOADER_UFS_SUPPORT?= yes
LOADER_CD9660_SUPPORT?= yes
LOADER_EXT2FS_SUPPORT?= no
LOADER_MSDOS_SUPPORT?= no
LOADER_NET_SUPPORT?= yes
LOADER_NFS_SUPPORT?= yes
LOADER_TFTP_SUPPORT?= yes
LOADER_GZIP_SUPPORT?= yes
LOADER_BZIP2_SUPPORT?= no
LOADER_DEBUG?= no
.include <bsd.init.mk>
PROG?= loader
NEWVERSWHAT?= "bootstrap loader" sparc64
VERSION_FILE= ${.CURDIR}/../loader/version
INSTALLFLAGS= -b
.if ${MK_LOADER_ZFS} != "no"
HAVE_ZFS= yes
.endif
# Architecture-specific loader code
.PATH: ${BOOTSRC}/sparc64/loader
SRCS= locore.S main.c vers.c
.if ${LOADER_DEBUG} == "yes"
CFLAGS+= -DLOADER_DEBUG
.endif
.if exists(${.CURDIR}/help.sparc64)
HELP_FILES= ${.CURDIR}/help.sparc64
.endif
# Always add MI sources
.include "${BOOTSRC}/loader.mk"
LDFLAGS+= -static
.if ${MK_LOADER_ZFS} == "yes"
LINKS= ${BINDIR}/loader ${BINDIR}/zfsloader
.endif
# Open Firmware standalone support library
LIBOFW= ${BOOTOBJ}/libofw/libofw.a
CFLAGS+= -I${BOOTSRC}/libofw
DPADD= ${LDR_INTERP} ${LIBOFW} ${LIBSA}
LDADD= ${LDR_INTERP} ${LIBOFW} ${LIBSA}
.include <bsd.prog.mk>

View file

@ -1,42 +0,0 @@
/*-
* Initial implementation:
* Copyright (c) 2001 Robert Drehmel
* All rights reserved.
*
* As long as the above copyright statement and this notice remain
* unchanged, you can do what ever you want with this file.
*/
#include <machine/asm.h>
__FBSDID("$FreeBSD$");
#define LOCORE
#include <machine/frame.h>
#include <machine/fsr.h>
#include <machine/intr_machdep.h>
#include <machine/pstate.h>
#define PAGE_SIZE 8192
#define PAGE_SHIFT 13
#define STACK_SIZE (2 * PAGE_SIZE)
ENTRY(_start)
/* Limit interrupts. */
wrpr %g0, PIL_TICK - 1, %pil
/*
* PSTATE: privileged, interrupts enabled, floating point
* unit enabled
*/
wrpr %g0, PSTATE_PRIV | PSTATE_IE | PSTATE_PEF, %pstate
wr %g0, FPRS_FEF, %fprs
setx stack + STACK_SIZE - SPOFF - CCFSZ, %l7, %l6
mov %l6, %sp
call main
mov %o4, %o0
sir
.comm stack, STACK_SIZE, 32

View file

@ -1,986 +0,0 @@
/*-
* Initial implementation:
* Copyright (c) 2001 Robert Drehmel
* All rights reserved.
*
* As long as the above copyright statement and this notice remain
* unchanged, you can do what ever you want with this file.
*/
/*-
* Copyright (c) 2008 - 2012 Marius Strobl <marius@FreeBSD.org>
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* FreeBSD/sparc64 kernel loader - machine dependent part
*
* - implements copyin and readin functions that map kernel
* pages on demand. The machine independent code does not
* know the size of the kernel early enough to pre-enter
* TTEs and install just one 4MB mapping seemed to limiting
* to me.
*/
#include <stand.h>
#include <sys/param.h>
#include <sys/exec.h>
#include <sys/linker.h>
#include <sys/queue.h>
#include <sys/types.h>
#ifdef LOADER_ZFS_SUPPORT
#include <sys/vtoc.h>
#include "libzfs.h"
#endif
#include <vm/vm.h>
#include <machine/asi.h>
#include <machine/cmt.h>
#include <machine/cpufunc.h>
#include <machine/elf.h>
#include <machine/fireplane.h>
#include <machine/jbus.h>
#include <machine/lsu.h>
#include <machine/metadata.h>
#include <machine/tte.h>
#include <machine/tlb.h>
#include <machine/upa.h>
#include <machine/ver.h>
#include <machine/vmparam.h>
#include "bootstrap.h"
#include "libofw.h"
#include "dev_net.h"
enum {
HEAPVA = 0x800000,
HEAPSZ = 0x3000000,
LOADSZ = 0x1000000 /* for kernel and modules */
};
/* At least Sun Fire V1280 require page sized allocations to be claimed. */
CTASSERT(HEAPSZ % PAGE_SIZE == 0);
static struct mmu_ops {
void (*tlb_init)(void);
int (*mmu_mapin)(vm_offset_t va, vm_size_t len);
} *mmu_ops;
typedef void kernel_entry_t(vm_offset_t mdp, u_long o1, u_long o2, u_long o3,
void *openfirmware);
static inline u_long dtlb_get_data_sun4u(u_int, u_int);
static int dtlb_enter_sun4u(u_int, u_long data, vm_offset_t);
static vm_offset_t dtlb_va_to_pa_sun4u(vm_offset_t);
static inline u_long itlb_get_data_sun4u(u_int, u_int);
static int itlb_enter_sun4u(u_int, u_long data, vm_offset_t);
static vm_offset_t itlb_va_to_pa_sun4u(vm_offset_t);
static void itlb_relocate_locked0_sun4u(void);
static int sparc64_autoload(void);
static ssize_t sparc64_readin(const int, vm_offset_t, const size_t);
static ssize_t sparc64_copyin(const void *, vm_offset_t, size_t);
static vm_offset_t claim_virt(vm_offset_t, size_t, int);
static vm_offset_t alloc_phys(size_t, int);
static int map_phys(int, size_t, vm_offset_t, vm_offset_t);
static void release_phys(vm_offset_t, u_int);
static int __elfN(exec)(struct preloaded_file *);
static int mmu_mapin_sun4u(vm_offset_t, vm_size_t);
static vm_offset_t init_heap(void);
static phandle_t find_bsp_sun4u(phandle_t, uint32_t);
const char *cpu_cpuid_prop_sun4u(void);
uint32_t cpu_get_mid_sun4u(void);
static void tlb_init_sun4u(void);
#ifdef LOADER_DEBUG
typedef uint64_t tte_t;
static void pmap_print_tlb_sun4u(void);
static void pmap_print_tte_sun4u(tte_t, tte_t);
#endif
static struct mmu_ops mmu_ops_sun4u = { tlb_init_sun4u, mmu_mapin_sun4u };
/* sun4u */
struct tlb_entry *dtlb_store;
struct tlb_entry *itlb_store;
u_int dtlb_slot;
u_int itlb_slot;
static int cpu_impl;
static u_int dtlb_slot_max;
static u_int itlb_slot_max;
static u_int tlb_locked;
static vm_offset_t curkva = 0;
static vm_offset_t heapva;
static char bootpath[64];
static phandle_t root;
#ifdef LOADER_ZFS_SUPPORT
static struct zfs_devdesc zfs_currdev;
#endif
/*
* Machine dependent structures that the machine independent
* loader part uses.
*/
struct devsw *devsw[] = {
#ifdef LOADER_DISK_SUPPORT
&ofwdisk,
#endif
#ifdef LOADER_NET_SUPPORT
&netdev,
#endif
#ifdef LOADER_ZFS_SUPPORT
&zfs_dev,
#endif
NULL
};
struct arch_switch archsw;
static struct file_format sparc64_elf = {
__elfN(loadfile),
__elfN(exec)
};
struct file_format *file_formats[] = {
&sparc64_elf,
NULL
};
struct fs_ops *file_system[] = {
#ifdef LOADER_ZFS_SUPPORT
&zfs_fsops,
#endif
#ifdef LOADER_UFS_SUPPORT
&ufs_fsops,
#endif
#ifdef LOADER_CD9660_SUPPORT
&cd9660_fsops,
#endif
#ifdef LOADER_ZIP_SUPPORT
&zipfs_fsops,
#endif
#ifdef LOADER_GZIP_SUPPORT
&gzipfs_fsops,
#endif
#ifdef LOADER_BZIP2_SUPPORT
&bzipfs_fsops,
#endif
#ifdef LOADER_NFS_SUPPORT
&nfs_fsops,
#endif
#ifdef LOADER_TFTP_SUPPORT
&tftp_fsops,
#endif
NULL
};
struct netif_driver *netif_drivers[] = {
#ifdef LOADER_NET_SUPPORT
&ofwnet,
#endif
NULL
};
extern struct console ofwconsole;
struct console *consoles[] = {
&ofwconsole,
NULL
};
#ifdef LOADER_DEBUG
static int
watch_phys_set_mask(vm_offset_t pa, u_long mask)
{
u_long lsucr;
stxa(AA_DMMU_PWPR, ASI_DMMU, pa & (((2UL << 38) - 1) << 3));
lsucr = ldxa(0, ASI_LSU_CTL_REG);
lsucr = ((lsucr | LSU_PW) & ~LSU_PM_MASK) |
(mask << LSU_PM_SHIFT);
stxa(0, ASI_LSU_CTL_REG, lsucr);
return (0);
}
static int
watch_phys_set(vm_offset_t pa, int sz)
{
u_long off;
off = (u_long)pa & 7;
/* Test for misaligned watch points. */
if (off + sz > 8)
return (-1);
return (watch_phys_set_mask(pa, ((1 << sz) - 1) << off));
}
static int
watch_virt_set_mask(vm_offset_t va, u_long mask)
{
u_long lsucr;
stxa(AA_DMMU_VWPR, ASI_DMMU, va & (((2UL << 41) - 1) << 3));
lsucr = ldxa(0, ASI_LSU_CTL_REG);
lsucr = ((lsucr | LSU_VW) & ~LSU_VM_MASK) |
(mask << LSU_VM_SHIFT);
stxa(0, ASI_LSU_CTL_REG, lsucr);
return (0);
}
static int
watch_virt_set(vm_offset_t va, int sz)
{
u_long off;
off = (u_long)va & 7;
/* Test for misaligned watch points. */
if (off + sz > 8)
return (-1);
return (watch_virt_set_mask(va, ((1 << sz) - 1) << off));
}
#endif
/*
* archsw functions
*/
static int
sparc64_autoload(void)
{
return (0);
}
static ssize_t
sparc64_readin(const int fd, vm_offset_t va, const size_t len)
{
mmu_ops->mmu_mapin(va, len);
return (read(fd, (void *)va, len));
}
static ssize_t
sparc64_copyin(const void *src, vm_offset_t dest, size_t len)
{
mmu_ops->mmu_mapin(dest, len);
memcpy((void *)dest, src, len);
return (len);
}
/*
* other MD functions
*/
static vm_offset_t
claim_virt(vm_offset_t virt, size_t size, int align)
{
vm_offset_t mva;
if (OF_call_method("claim", mmu, 3, 1, virt, size, align, &mva) == -1)
return ((vm_offset_t)-1);
return (mva);
}
static vm_offset_t
alloc_phys(size_t size, int align)
{
cell_t phys_hi, phys_low;
if (OF_call_method("claim", memory, 2, 2, size, align, &phys_low,
&phys_hi) == -1)
return ((vm_offset_t)-1);
return ((vm_offset_t)phys_hi << 32 | phys_low);
}
static int
map_phys(int mode, size_t size, vm_offset_t virt, vm_offset_t phys)
{
return (OF_call_method("map", mmu, 5, 0, (uint32_t)phys,
(uint32_t)(phys >> 32), virt, size, mode));
}
static void
release_phys(vm_offset_t phys, u_int size)
{
(void)OF_call_method("release", memory, 3, 0, (uint32_t)phys,
(uint32_t)(phys >> 32), size);
}
static int
__elfN(exec)(struct preloaded_file *fp)
{
struct file_metadata *fmp;
vm_offset_t mdp;
Elf_Addr entry;
Elf_Ehdr *e;
int error;
if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == 0)
return (EFTYPE);
e = (Elf_Ehdr *)&fmp->md_data;
if ((error = md_load64(fp->f_args, &mdp, NULL)) != 0)
return (error);
printf("jumping to kernel entry at %#lx.\n", e->e_entry);
#ifdef LOADER_DEBUG
pmap_print_tlb_sun4u();
#endif
dev_cleanup();
entry = e->e_entry;
OF_release((void *)heapva, HEAPSZ);
((kernel_entry_t *)entry)(mdp, 0, 0, 0, openfirmware);
panic("%s: exec returned", __func__);
}
static inline u_long
dtlb_get_data_sun4u(u_int tlb, u_int slot)
{
u_long data, pstate;
slot = TLB_DAR_SLOT(tlb, slot);
/*
* We read ASI_DTLB_DATA_ACCESS_REG twice back-to-back in order to
* work around errata of USIII and beyond.
*/
pstate = rdpr(pstate);
wrpr(pstate, pstate & ~PSTATE_IE, 0);
(void)ldxa(slot, ASI_DTLB_DATA_ACCESS_REG);
data = ldxa(slot, ASI_DTLB_DATA_ACCESS_REG);
wrpr(pstate, pstate, 0);
return (data);
}
static inline u_long
itlb_get_data_sun4u(u_int tlb, u_int slot)
{
u_long data, pstate;
slot = TLB_DAR_SLOT(tlb, slot);
/*
* We read ASI_DTLB_DATA_ACCESS_REG twice back-to-back in order to
* work around errata of USIII and beyond.
*/
pstate = rdpr(pstate);
wrpr(pstate, pstate & ~PSTATE_IE, 0);
(void)ldxa(slot, ASI_ITLB_DATA_ACCESS_REG);
data = ldxa(slot, ASI_ITLB_DATA_ACCESS_REG);
wrpr(pstate, pstate, 0);
return (data);
}
static vm_offset_t
dtlb_va_to_pa_sun4u(vm_offset_t va)
{
u_long pstate, reg;
u_int i, tlb;
pstate = rdpr(pstate);
wrpr(pstate, pstate & ~PSTATE_IE, 0);
for (i = 0; i < dtlb_slot_max; i++) {
reg = ldxa(TLB_DAR_SLOT(tlb_locked, i),
ASI_DTLB_TAG_READ_REG);
if (TLB_TAR_VA(reg) != va)
continue;
reg = dtlb_get_data_sun4u(tlb_locked, i);
wrpr(pstate, pstate, 0);
reg >>= TD_PA_SHIFT;
if (cpu_impl == CPU_IMPL_SPARC64V ||
cpu_impl >= CPU_IMPL_ULTRASPARCIII)
return (reg & TD_PA_CH_MASK);
return (reg & TD_PA_SF_MASK);
}
wrpr(pstate, pstate, 0);
return (-1);
}
static vm_offset_t
itlb_va_to_pa_sun4u(vm_offset_t va)
{
u_long pstate, reg;
int i;
pstate = rdpr(pstate);
wrpr(pstate, pstate & ~PSTATE_IE, 0);
for (i = 0; i < itlb_slot_max; i++) {
reg = ldxa(TLB_DAR_SLOT(tlb_locked, i),
ASI_ITLB_TAG_READ_REG);
if (TLB_TAR_VA(reg) != va)
continue;
reg = itlb_get_data_sun4u(tlb_locked, i);
wrpr(pstate, pstate, 0);
reg >>= TD_PA_SHIFT;
if (cpu_impl == CPU_IMPL_SPARC64V ||
cpu_impl >= CPU_IMPL_ULTRASPARCIII)
return (reg & TD_PA_CH_MASK);
return (reg & TD_PA_SF_MASK);
}
wrpr(pstate, pstate, 0);
return (-1);
}
static int
dtlb_enter_sun4u(u_int index, u_long data, vm_offset_t virt)
{
return (OF_call_method("SUNW,dtlb-load", mmu, 3, 0, index, data,
virt));
}
static int
itlb_enter_sun4u(u_int index, u_long data, vm_offset_t virt)
{
if (cpu_impl == CPU_IMPL_ULTRASPARCIIIp && index == 0 &&
(data & TD_L) != 0)
panic("%s: won't enter locked TLB entry at index 0 on USIII+",
__func__);
return (OF_call_method("SUNW,itlb-load", mmu, 3, 0, index, data,
virt));
}
static void
itlb_relocate_locked0_sun4u(void)
{
u_long data, pstate, tag;
int i;
if (cpu_impl != CPU_IMPL_ULTRASPARCIIIp)
return;
pstate = rdpr(pstate);
wrpr(pstate, pstate & ~PSTATE_IE, 0);
data = itlb_get_data_sun4u(tlb_locked, 0);
if ((data & (TD_V | TD_L)) != (TD_V | TD_L)) {
wrpr(pstate, pstate, 0);
return;
}
/* Flush the mapping of slot 0. */
tag = ldxa(TLB_DAR_SLOT(tlb_locked, 0), ASI_ITLB_TAG_READ_REG);
stxa(TLB_DEMAP_VA(TLB_TAR_VA(tag)) | TLB_DEMAP_PRIMARY |
TLB_DEMAP_PAGE, ASI_IMMU_DEMAP, 0);
flush(0); /* The USIII-family ignores the address. */
/*
* Search a replacement slot != 0 and enter the data and tag
* that formerly were in slot 0.
*/
for (i = 1; i < itlb_slot_max; i++) {
if ((itlb_get_data_sun4u(tlb_locked, i) & TD_V) != 0)
continue;
stxa(AA_IMMU_TAR, ASI_IMMU, tag);
stxa(TLB_DAR_SLOT(tlb_locked, i), ASI_ITLB_DATA_ACCESS_REG,
data);
flush(0); /* The USIII-family ignores the address. */
break;
}
wrpr(pstate, pstate, 0);
if (i == itlb_slot_max)
panic("%s: could not find a replacement slot", __func__);
}
static int
mmu_mapin_sun4u(vm_offset_t va, vm_size_t len)
{
vm_offset_t pa, mva;
u_long data;
u_int index;
if (va + len > curkva)
curkva = va + len;
pa = (vm_offset_t)-1;
len += va & PAGE_MASK_4M;
va &= ~PAGE_MASK_4M;
while (len) {
if (dtlb_va_to_pa_sun4u(va) == (vm_offset_t)-1 ||
itlb_va_to_pa_sun4u(va) == (vm_offset_t)-1) {
/* Allocate a physical page, claim the virtual area. */
if (pa == (vm_offset_t)-1) {
pa = alloc_phys(PAGE_SIZE_4M, PAGE_SIZE_4M);
if (pa == (vm_offset_t)-1)
panic("%s: out of memory", __func__);
mva = claim_virt(va, PAGE_SIZE_4M, 0);
if (mva != va)
panic("%s: can't claim virtual page "
"(wanted %#lx, got %#lx)",
__func__, va, mva);
/*
* The mappings may have changed, be paranoid.
*/
continue;
}
/*
* Actually, we can only allocate two pages less at
* most (depending on the kernel TSB size).
*/
if (dtlb_slot >= dtlb_slot_max)
panic("%s: out of dtlb_slots", __func__);
if (itlb_slot >= itlb_slot_max)
panic("%s: out of itlb_slots", __func__);
data = TD_V | TD_4M | TD_PA(pa) | TD_L | TD_CP |
TD_CV | TD_P | TD_W;
dtlb_store[dtlb_slot].te_pa = pa;
dtlb_store[dtlb_slot].te_va = va;
index = dtlb_slot_max - dtlb_slot - 1;
if (dtlb_enter_sun4u(index, data, va) < 0)
panic("%s: can't enter dTLB slot %d data "
"%#lx va %#lx", __func__, index, data,
va);
dtlb_slot++;
itlb_store[itlb_slot].te_pa = pa;
itlb_store[itlb_slot].te_va = va;
index = itlb_slot_max - itlb_slot - 1;
if (itlb_enter_sun4u(index, data, va) < 0)
panic("%s: can't enter iTLB slot %d data "
"%#lx va %#lxd", __func__, index, data,
va);
itlb_slot++;
pa = (vm_offset_t)-1;
}
len -= len > PAGE_SIZE_4M ? PAGE_SIZE_4M : len;
va += PAGE_SIZE_4M;
}
if (pa != (vm_offset_t)-1)
release_phys(pa, PAGE_SIZE_4M);
return (0);
}
static vm_offset_t
init_heap(void)
{
/* There is no need for continuous physical heap memory. */
heapva = (vm_offset_t)OF_claim((void *)HEAPVA, HEAPSZ, 32);
return (heapva);
}
static phandle_t
find_bsp_sun4u(phandle_t node, uint32_t bspid)
{
char type[sizeof("cpu")];
phandle_t child;
uint32_t cpuid;
for (; node > 0; node = OF_peer(node)) {
child = OF_child(node);
if (child > 0) {
child = find_bsp_sun4u(child, bspid);
if (child > 0)
return (child);
} else {
if (OF_getprop(node, "device_type", type,
sizeof(type)) <= 0)
continue;
if (strcmp(type, "cpu") != 0)
continue;
if (OF_getprop(node, cpu_cpuid_prop_sun4u(), &cpuid,
sizeof(cpuid)) <= 0)
continue;
if (cpuid == bspid)
return (node);
}
}
return (0);
}
const char *
cpu_cpuid_prop_sun4u(void)
{
switch (cpu_impl) {
case CPU_IMPL_SPARC64:
case CPU_IMPL_SPARC64V:
case CPU_IMPL_ULTRASPARCI:
case CPU_IMPL_ULTRASPARCII:
case CPU_IMPL_ULTRASPARCIIi:
case CPU_IMPL_ULTRASPARCIIe:
return ("upa-portid");
case CPU_IMPL_ULTRASPARCIII:
case CPU_IMPL_ULTRASPARCIIIp:
case CPU_IMPL_ULTRASPARCIIIi:
case CPU_IMPL_ULTRASPARCIIIip:
return ("portid");
case CPU_IMPL_ULTRASPARCIV:
case CPU_IMPL_ULTRASPARCIVp:
return ("cpuid");
default:
return ("");
}
}
uint32_t
cpu_get_mid_sun4u(void)
{
switch (cpu_impl) {
case CPU_IMPL_SPARC64:
case CPU_IMPL_SPARC64V:
case CPU_IMPL_ULTRASPARCI:
case CPU_IMPL_ULTRASPARCII:
case CPU_IMPL_ULTRASPARCIIi:
case CPU_IMPL_ULTRASPARCIIe:
return (UPA_CR_GET_MID(ldxa(0, ASI_UPA_CONFIG_REG)));
case CPU_IMPL_ULTRASPARCIII:
case CPU_IMPL_ULTRASPARCIIIp:
return (FIREPLANE_CR_GET_AID(ldxa(AA_FIREPLANE_CONFIG,
ASI_FIREPLANE_CONFIG_REG)));
case CPU_IMPL_ULTRASPARCIIIi:
case CPU_IMPL_ULTRASPARCIIIip:
return (JBUS_CR_GET_JID(ldxa(0, ASI_JBUS_CONFIG_REG)));
case CPU_IMPL_ULTRASPARCIV:
case CPU_IMPL_ULTRASPARCIVp:
return (INTR_ID_GET_ID(ldxa(AA_INTR_ID, ASI_INTR_ID)));
default:
return (0);
}
}
static void
tlb_init_sun4u(void)
{
phandle_t bsp;
cpu_impl = VER_IMPL(rdpr(ver));
switch (cpu_impl) {
case CPU_IMPL_SPARC64:
case CPU_IMPL_ULTRASPARCI:
case CPU_IMPL_ULTRASPARCII:
case CPU_IMPL_ULTRASPARCIIi:
case CPU_IMPL_ULTRASPARCIIe:
tlb_locked = TLB_DAR_T32;
break;
case CPU_IMPL_ULTRASPARCIII:
case CPU_IMPL_ULTRASPARCIIIp:
case CPU_IMPL_ULTRASPARCIIIi:
case CPU_IMPL_ULTRASPARCIIIip:
case CPU_IMPL_ULTRASPARCIV:
case CPU_IMPL_ULTRASPARCIVp:
tlb_locked = TLB_DAR_T16;
break;
case CPU_IMPL_SPARC64V:
tlb_locked = TLB_DAR_FTLB;
break;
}
bsp = find_bsp_sun4u(OF_child(root), cpu_get_mid_sun4u());
if (bsp == 0)
panic("%s: no node for bootcpu?!?!", __func__);
if (OF_getprop(bsp, "#dtlb-entries", &dtlb_slot_max,
sizeof(dtlb_slot_max)) == -1 ||
OF_getprop(bsp, "#itlb-entries", &itlb_slot_max,
sizeof(itlb_slot_max)) == -1)
panic("%s: can't get TLB slot max.", __func__);
if (cpu_impl == CPU_IMPL_ULTRASPARCIIIp) {
#ifdef LOADER_DEBUG
printf("pre fixup:\n");
pmap_print_tlb_sun4u();
#endif
/*
* Relocate the locked entry in it16 slot 0 (if existent)
* as part of working around Cheetah+ erratum 34.
*/
itlb_relocate_locked0_sun4u();
#ifdef LOADER_DEBUG
printf("post fixup:\n");
pmap_print_tlb_sun4u();
#endif
}
dtlb_store = malloc(dtlb_slot_max * sizeof(*dtlb_store));
itlb_store = malloc(itlb_slot_max * sizeof(*itlb_store));
if (dtlb_store == NULL || itlb_store == NULL)
panic("%s: can't allocate TLB store", __func__);
}
#ifdef LOADER_ZFS_SUPPORT
static void
sparc64_zfs_probe(void)
{
struct vtoc8 vtoc;
char alias[64], devname[sizeof(alias) + sizeof(":x") - 1];
char type[sizeof("device_type")];
char *bdev, *dev, *odev;
uint64_t guid, *guidp;
int fd, len, part;
phandle_t aliases, options;
guid = 0;
/*
* Get the GUIDs of the ZFS pools on any additional disks listed in
* the boot-device environment variable.
*/
if ((aliases = OF_finddevice("/aliases")) == -1)
goto out;
options = OF_finddevice("/options");
len = OF_getproplen(options, "boot-device");
if (len <= 0)
goto out;
bdev = odev = malloc(len + 1);
if (bdev == NULL)
goto out;
if (OF_getprop(options, "boot-device", bdev, len) <= 0)
goto out;
bdev[len] = '\0';
while ((dev = strsep(&bdev, " ")) != NULL) {
if (*dev == '\0')
continue;
strcpy(alias, dev);
(void)OF_getprop(aliases, dev, alias, sizeof(alias));
if (OF_getprop(OF_finddevice(alias), "device_type", type,
sizeof(type)) == -1)
continue;
if (strcmp(type, "block") != 0)
continue;
/* Find freebsd-zfs slices in the VTOC. */
fd = open(alias, O_RDONLY);
if (fd == -1)
continue;
lseek(fd, 0, SEEK_SET);
if (read(fd, &vtoc, sizeof(vtoc)) != sizeof(vtoc)) {
close(fd);
continue;
}
close(fd);
for (part = 0; part < 8; part++) {
if (part == 2 || vtoc.part[part].tag !=
VTOC_TAG_FREEBSD_ZFS)
continue;
(void)sprintf(devname, "%s:%c", alias, part + 'a');
/* Get the GUID of the ZFS pool on the boot device. */
if (strcmp(devname, bootpath) == 0)
guidp = &guid;
else
guidp = NULL;
if (zfs_probe_dev(devname, guidp) == ENXIO)
break;
}
}
free(odev);
out:
if (guid != 0) {
zfs_currdev.pool_guid = guid;
zfs_currdev.root_guid = 0;
zfs_currdev.dd.d_dev = &zfs_dev;
}
}
#endif /* LOADER_ZFS_SUPPORT */
int
main(int (*openfirm)(void *))
{
char compatible[32];
struct devsw **dp;
/*
* Tell the Open Firmware functions where they find the OFW gate.
*/
OF_init(openfirm);
archsw.arch_getdev = ofw_getdev;
archsw.arch_copyin = sparc64_copyin;
archsw.arch_copyout = ofw_copyout;
archsw.arch_readin = sparc64_readin;
archsw.arch_autoload = sparc64_autoload;
#ifdef LOADER_ZFS_SUPPORT
archsw.arch_zfs_probe = sparc64_zfs_probe;
#endif
if (init_heap() == (vm_offset_t)-1)
OF_exit();
setheap((void *)heapva, (void *)(heapva + HEAPSZ));
/*
* Probe for a console.
*/
cons_probe();
if ((root = OF_peer(0)) == -1)
panic("%s: can't get root phandle", __func__);
OF_getprop(root, "compatible", compatible, sizeof(compatible));
mmu_ops = &mmu_ops_sun4u;
mmu_ops->tlb_init();
/*
* Set up the current device.
*/
OF_getprop(chosen, "bootpath", bootpath, sizeof(bootpath));
/*
* Initialize devices.
*/
for (dp = devsw; *dp != NULL; dp++)
if ((*dp)->dv_init != 0)
(*dp)->dv_init();
#ifdef LOADER_ZFS_SUPPORT
if (zfs_currdev.pool_guid != 0) {
(void)strncpy(bootpath, zfs_fmtdev(&zfs_currdev),
sizeof(bootpath) - 1);
bootpath[sizeof(bootpath) - 1] = '\0';
} else
#endif
/*
* Sun compatible bootable CD-ROMs have a disk label placed before
* the ISO 9660 data, with the actual file system being in the first
* partition, while the other partitions contain pseudo disk labels
* with embedded boot blocks for different architectures, which may
* be followed by UFS file systems.
* The firmware will set the boot path to the partition it boots from
* ('f' in the sun4u/sun4v case), but we want the kernel to be loaded
* from the ISO 9660 file system ('a'), so the boot path needs to be
* altered.
*/
if (bootpath[strlen(bootpath) - 2] == ':' &&
bootpath[strlen(bootpath) - 1] == 'f')
bootpath[strlen(bootpath) - 1] = 'a';
env_setenv("currdev", EV_VOLATILE, bootpath,
ofw_setcurrdev, env_nounset);
env_setenv("loaddev", EV_VOLATILE, bootpath,
env_noset, env_nounset);
printf("\n%s", bootprog_info);
printf("bootpath=\"%s\"\n", bootpath);
/* Give control to the machine independent loader code. */
interact();
return (1);
}
COMMAND_SET(heap, "heap", "show heap usage", command_heap);
static int
command_heap(int argc, char *argv[])
{
mallocstats();
printf("heap base at %p, top at %p, upper limit at %p\n", heapva,
sbrk(0), heapva + HEAPSZ);
return(CMD_OK);
}
COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
static int
command_reboot(int argc, char *argv[])
{
int i;
for (i = 0; devsw[i] != NULL; ++i)
if (devsw[i]->dv_cleanup != NULL)
(devsw[i]->dv_cleanup)();
printf("Rebooting...\n");
OF_exit();
}
/* provide this for panic, as it's not in the startup code */
void
exit(int code)
{
OF_exit();
}
#ifdef LOADER_DEBUG
static const char *const page_sizes[] = {
" 8k", " 64k", "512k", " 4m"
};
static void
pmap_print_tte_sun4u(tte_t tag, tte_t tte)
{
printf("%s %s ",
page_sizes[(tte >> TD_SIZE_SHIFT) & TD_SIZE_MASK],
tag & TD_G ? "G" : " ");
printf(tte & TD_W ? "W " : " ");
printf(tte & TD_P ? "\e[33mP\e[0m " : " ");
printf(tte & TD_E ? "E " : " ");
printf(tte & TD_CV ? "CV " : " ");
printf(tte & TD_CP ? "CP " : " ");
printf(tte & TD_L ? "\e[32mL\e[0m " : " ");
printf(tte & TD_IE ? "IE " : " ");
printf(tte & TD_NFO ? "NFO " : " ");
printf("pa=0x%lx va=0x%lx ctx=%ld\n",
TD_PA(tte), TLB_TAR_VA(tag), TLB_TAR_CTX(tag));
}
static void
pmap_print_tlb_sun4u(void)
{
tte_t tag, tte;
u_long pstate;
int i;
pstate = rdpr(pstate);
for (i = 0; i < itlb_slot_max; i++) {
wrpr(pstate, pstate & ~PSTATE_IE, 0);
tte = itlb_get_data_sun4u(tlb_locked, i);
wrpr(pstate, pstate, 0);
if (!(tte & TD_V))
continue;
tag = ldxa(TLB_DAR_SLOT(tlb_locked, i),
ASI_ITLB_TAG_READ_REG);
printf("iTLB-%2u: ", i);
pmap_print_tte_sun4u(tag, tte);
}
for (i = 0; i < dtlb_slot_max; i++) {
wrpr(pstate, pstate & ~PSTATE_IE, 0);
tte = dtlb_get_data_sun4u(tlb_locked, i);
wrpr(pstate, pstate, 0);
if (!(tte & TD_V))
continue;
tag = ldxa(TLB_DAR_SLOT(tlb_locked, i),
ASI_DTLB_TAG_READ_REG);
printf("dTLB-%2u: ", i);
pmap_print_tte_sun4u(tag, tte);
}
}
#endif

View file

@ -1,6 +0,0 @@
$FreeBSD$
NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE. The format of this
file is important. Make sure the current version number is on line 6.
1.0: I hate the loader.

View file

@ -1,9 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../boot1
PROGNAME= zfsboot
CFLAGS+= -DZFSBOOT
FILES= zfsboot
.include "${.CURDIR}/../boot1/Makefile"