Remove sparc64 support from the boot loader.
Remove all the sparc64 specific bits, both files and ifdefs.
This commit is contained in:
parent
c68c82324f
commit
eb24e1491f
@ -49,55 +49,6 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include "geliboot.h"
|
#include "geliboot.h"
|
||||||
#endif
|
#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
|
static int
|
||||||
md_getboothowto(char *kargs)
|
md_getboothowto(char *kargs)
|
||||||
{
|
{
|
||||||
@ -106,15 +57,10 @@ md_getboothowto(char *kargs)
|
|||||||
/* Parse kargs */
|
/* Parse kargs */
|
||||||
howto = boot_parse_cmdline(kargs);
|
howto = boot_parse_cmdline(kargs);
|
||||||
howto |= boot_env_to_howto();
|
howto |= boot_env_to_howto();
|
||||||
#if defined(__sparc64__)
|
|
||||||
if (md_bootserial() != -1)
|
|
||||||
howto |= RB_SERIAL;
|
|
||||||
#else
|
|
||||||
if (!strcmp(getenv("console"), "comconsole"))
|
if (!strcmp(getenv("console"), "comconsole"))
|
||||||
howto |= RB_SERIAL;
|
howto |= RB_SERIAL;
|
||||||
if (!strcmp(getenv("console"), "nullconsole"))
|
if (!strcmp(getenv("console"), "nullconsole"))
|
||||||
howto |= RB_MUTE;
|
howto |= RB_MUTE;
|
||||||
#endif
|
|
||||||
return(howto);
|
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
|
#ifdef LOADER_GELI_SUPPORT
|
||||||
geli_export_key_metadata(kfp);
|
geli_export_key_metadata(kfp);
|
||||||
#endif
|
#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;
|
*modulep = addr;
|
||||||
size = md_copymodules(0, kern64);
|
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);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(__sparc64__)
|
|
||||||
int
|
int
|
||||||
md_load(char *args, vm_offset_t *modulep, vm_offset_t *dtb)
|
md_load(char *args, vm_offset_t *modulep, vm_offset_t *dtb)
|
||||||
{
|
{
|
||||||
return (md_load_dual(args, modulep, dtb, 0));
|
return (md_load_dual(args, modulep, dtb, 0));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__mips__) || defined(__powerpc__) || defined(__sparc64__)
|
#if defined(__mips__) || defined(__powerpc__)
|
||||||
int
|
int
|
||||||
md_load64(char *args, vm_offset_t *modulep, vm_offset_t *dtb)
|
md_load64(char *args, vm_offset_t *modulep, vm_offset_t *dtb)
|
||||||
{
|
{
|
||||||
|
@ -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 */
|
|
@ -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__*/
|
|
@ -62,9 +62,7 @@ struct preloaded_file;
|
|||||||
struct file_format;
|
struct file_format;
|
||||||
|
|
||||||
/* MD code implementing MI interfaces */
|
/* MD code implementing MI interfaces */
|
||||||
#if !defined(__sparc64__)
|
|
||||||
vm_offset_t md_load(char *args, vm_offset_t *modulep, vm_offset_t *dtb);
|
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);
|
vm_offset_t md_load64(char *args, vm_offset_t *modulep, vm_offset_t *dtb);
|
||||||
|
|
||||||
extern void reboot(void);
|
extern void reboot(void);
|
||||||
|
@ -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)
|
|
@ -19,9 +19,6 @@ SRCS+= load_elf32.c reloc_elf32.c
|
|||||||
SRCS+= load_elf32.c reloc_elf32.c
|
SRCS+= load_elf32.c reloc_elf32.c
|
||||||
SRCS+= load_elf64.c reloc_elf64.c
|
SRCS+= load_elf64.c reloc_elf64.c
|
||||||
SRCS+= metadata.c
|
SRCS+= metadata.c
|
||||||
.elif ${MACHINE_CPUARCH} == "sparc64"
|
|
||||||
SRCS+= load_elf64.c reloc_elf64.c
|
|
||||||
SRCS+= metadata.c
|
|
||||||
.elif ${MACHINE_ARCH:Mmips64*} != ""
|
.elif ${MACHINE_ARCH:Mmips64*} != ""
|
||||||
SRCS+= load_elf64.c reloc_elf64.c
|
SRCS+= load_elf64.c reloc_elf64.c
|
||||||
SRCS+= metadata.c
|
SRCS+= metadata.c
|
||||||
|
@ -632,7 +632,7 @@ Modifies kernel option
|
|||||||
Limits the amount of KVM reserved for use by the
|
Limits the amount of KVM reserved for use by the
|
||||||
buffer cache, specified in bytes.
|
buffer cache, specified in bytes.
|
||||||
The default maximum is 200MB on i386,
|
The default maximum is 200MB on i386,
|
||||||
and 400MB on amd64 and sparc64.
|
and 400MB on amd64.
|
||||||
This parameter is used to
|
This parameter is used to
|
||||||
prevent the buffer cache from eating too much
|
prevent the buffer cache from eating too much
|
||||||
KVM in large-memory machine configurations.
|
KVM in large-memory machine configurations.
|
||||||
|
@ -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>
|
|
@ -1,5 +0,0 @@
|
|||||||
# $FreeBSD$
|
|
||||||
|
|
||||||
LDFLAGS+= -nostdlib
|
|
||||||
|
|
||||||
.include "../Makefile.inc"
|
|
@ -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>
|
|
@ -1,8 +0,0 @@
|
|||||||
/* $FreeBSD$ */
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl _start
|
|
||||||
_start:
|
|
||||||
call ofw_init
|
|
||||||
nop
|
|
||||||
sir
|
|
@ -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);
|
|
||||||
}
|
|
@ -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>
|
|
@ -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
|
|
@ -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
|
|
@ -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.
|
|
@ -1,9 +0,0 @@
|
|||||||
# $FreeBSD$
|
|
||||||
|
|
||||||
.PATH: ${.CURDIR}/../boot1
|
|
||||||
|
|
||||||
PROGNAME= zfsboot
|
|
||||||
CFLAGS+= -DZFSBOOT
|
|
||||||
FILES= zfsboot
|
|
||||||
|
|
||||||
.include "${.CURDIR}/../boot1/Makefile"
|
|
Loading…
Reference in New Issue
Block a user