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"
|
||||
#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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
/* 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);
|
||||
|
@ -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_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
|
||||
|
@ -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.
|
||||
|
@ -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