util.c revision fa9e4066f08beec538e775443c5be79dd423fcab
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/promimpl.h>
#include "cprboot.h"
static int reset_input = 0;
static char kbd_input[] = "keyboard input";
static char null_input[] = "\" /nulldev\" input";
/*
* Ask prom to open a disk file given either the OBP device path, or the
* path of the file. Handle file pathnames with or without leading '/'.
* if fs points to a null char, it indicates that we are opening a device.
*/
/* ARGSUSED */
int
{
char full_path[OBP_MAXPATHLEN];
char *fp;
int handle;
int c;
/*
* instead of using specialstate, we use fs as the flag
*/
/* IEEE1275 prom_open returns 0 on failure; we return -1 */
}
/*
* IEEE 1275 prom needs "device-path,|file-path" where
* file-path can have embedded |'s.
*/
*fp++ = ',';
*fp++ = '|';
/* Skip a leading slash in file path -- we provided for it above. */
if (*path == '/')
path++;
/* Copy file path and convert separators. */
while ((c = *path++) != '\0')
if (c == '/')
*fp++ = '|';
else
*fp++ = c;
*fp = '\0';
if (verbose) {
fp++;
else
}
/*
* IEEE1275 prom_open returns 0 on failure; we return -1
*/
}
/*
* Ask prom to open a disk file given the device path representing
* Handle file pathnames with or without leading '/'. if fs points
* to a null char, it indicates that we are opening a device.
*/
/* ARGSUSED */
int
{
/*
* screen invalid state, then just use the other code rather than
* duplicating it
*/
return (ERR);
}
}
/*
* On sun4u there's no difference here, since prom groks ufs directly
*/
int
{
}
int
{
}
int
cpr_ufs_close(int fd)
{
return (prom_close(fd));
}
int
cpr_statefile_close(int fd)
{
return (prom_close(fd));
}
void
cb_spin(void)
{
static int spindex = 0;
}
/*
* translate vaddr to phys page number
*/
{
if (valid != -1)
return (PFN_INVALID);
return (paddr >> MMU_PAGESHIFT);
}
/*
* unmap virt, then map virt to new phys;
* see remap definition below
*/
int
{
int rv;
immu = prom_mmu_ihandle();
return (ERR);
if (rv)
return (rv); /* Service "call-method" failed */
return (0);
}
/*
* install remap definition in /virtual-memory node;
* used for replacing a virt->phys mapping in one promif call;
* this needs to be atomic from the client's perspective to
* avoid faults while relocating client text.
*/
void
install_remap(void)
{
static char remap_def[] =
"\" /virtual-memory\" find-device "
": remap ( phys.lo virt size -- )"
" 2dup unmap ( phys.lo virt size )"
" 0 -rot -1 map ( ) ; "
"device-end";
prom_interpret(remap_def, 0, 0, 0, 0, 0);
}
/*
* allocate virt and phys space without any mapping;
* stores virt and phys addrs at *vap and *pap
*/
int
{
return (ERR);
return (ERR);
}
return (0);
}
static int
{
return (ERR);
return (0);
}
/*
* find cpu node for the boot processor
*
* sets globals:
* cb_mid
*/
static pnode_t
get_cpu_node(void)
{
int err;
str = "get_cpu_node";
name = "cpu";
if (node == OBP_NONODE) {
prom_printf("\n%s: cant find node for devtype \"%s\"\n",
break;
}
CB_VPRINTF((" cpu node 0x%x, "
"prop \"%s\", cpu_id %d\n",
if (err == 0)
break;
}
return (node);
}
return (OBP_NONODE);
}
/*
* lookup prom properties
*
* sets globals:
* cb_dents
* cb_clock_freq
* cpu_delay
*/
int
cb_get_props(void)
{
"#dtlb-entries", &cb_dents,
"clock-frequency", &cb_clock_freq,
};
node = get_cpu_node();
if (node == OBP_NONODE)
return (ERR);
prom_printf("\n%s: getprop error, "
"node 0x%x, prop \"%s\"\n",
return (ERR);
}
CB_VPRINTF((" \"%s\" = 0x%x\n",
}
/*
* setup cpu_delay for cb_usec_wait
*/
CB_VPRINTF((" clock_mhz %d, cpu_delay %d\n",
return (0);
}
/*
* map-in data pages
* size should fit tte_bit.sz
* rw should be 0 or TTE_HWWR_INT
*/
void
{
}
static char *
{
return (string);
c = *subp;
while (*strp) {
if (*strp++ == c) {
;
if (c == '\0')
return (tmp - 1);
c = *subp;
}
}
return (NULL);
}
static void
cb_set_idev(char *istr)
{
if (reset_input) {
prom_interpret(istr, 0, 0, 0, 0, 0);
}
}
/*
* workaround for USB keyboard:
* USB DMA activity has been known to corrupt kernel pages while cprboot
* is restoring them. to quiesce the USB chip, we craft a "null" device
* and temporarily use that as the prom's input device. this effectively
* disables the USB keyboard until the cpr module restores the original
* prom and a kernel driver re-inits and takes-over control of USB.
*
* may set globals:
* reset_input
*/
int
cb_usb_setup(void)
{
char sp[OBP_MAXPATHLEN];
static char cb_nulldev[] = {
"\" /\" select-dev "
"new-device "
"\" nulldev\" device-name "
": read 2drop -2 ; "
": open true ; "
": close ; "
": install-abort ; "
": remove-abort ; "
": write 2drop 0 ; "
": restore ; "
"finish-device "
"unselect-dev"
};
prom_interpret("stdin @ ihandle>devname swap -rot move",
prom_interpret(cb_nulldev, 0, 0, 0, 0, 0);
reset_input = 1;
}
return (0);
}
/*
* switch input to keyboard before entering the prom, and switch to the
* crafted nulldev after returning from the prom. this occurs only when
* stdinpath is a USB keyboard; entering the prom is usually done only
* for debugging purposes - see check_halt() and above DMA comment.
*/
void
cb_enter_mon(void)
{
}
/*
* similar to above before exiting to the prom
*/
void
cb_exit_to_mon(void)
{
}