10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*2484Sszhou * Common Development and Distribution License (the "License"). 6*2484Sszhou * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*2484Sszhou * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <sys/types.h> 290Sstevel@tonic-gate #include <sys/promif.h> 300Sstevel@tonic-gate #include <sys/bootconf.h> 310Sstevel@tonic-gate #include <sys/salib.h> 320Sstevel@tonic-gate #include <sys/boot.h> 330Sstevel@tonic-gate #include "boot_plat.h" 340Sstevel@tonic-gate 350Sstevel@tonic-gate char *v2path, *kernname, *systype; 360Sstevel@tonic-gate char *my_own_name = "boot"; 370Sstevel@tonic-gate char v2args_buf[V2ARGS_BUF_SZ]; 380Sstevel@tonic-gate char *v2args = v2args_buf; 390Sstevel@tonic-gate char *mfg_name; 400Sstevel@tonic-gate char *impl_arch_name; 410Sstevel@tonic-gate char *bootp_response; 420Sstevel@tonic-gate char *module_path; 430Sstevel@tonic-gate int cache_state; 440Sstevel@tonic-gate uint64_t memlistextent; /* replacement for old member of bootops */ 450Sstevel@tonic-gate 460Sstevel@tonic-gate /* These are the various memory lists */ 470Sstevel@tonic-gate struct memlist *pfreelistp, /* physmem available */ 480Sstevel@tonic-gate *vfreelistp, /* virtmem available */ 490Sstevel@tonic-gate *pinstalledp; /* physmem installed */ 500Sstevel@tonic-gate 510Sstevel@tonic-gate char *boot_message; 520Sstevel@tonic-gate 530Sstevel@tonic-gate char *netdev_path; 540Sstevel@tonic-gate 550Sstevel@tonic-gate /* 560Sstevel@tonic-gate * Support new boot properties "boot-start" and "boot-end" for 570Sstevel@tonic-gate * Freeze/Thaw project. 580Sstevel@tonic-gate */ 590Sstevel@tonic-gate caddr_t start_addr, end_addr; 600Sstevel@tonic-gate 610Sstevel@tonic-gate #define BOOT_BADPROP -1 620Sstevel@tonic-gate #define BOOT_SUCCESS 0 630Sstevel@tonic-gate #define BOOT_FAILURE -1 640Sstevel@tonic-gate #define NIL 0 650Sstevel@tonic-gate 660Sstevel@tonic-gate #define strequal(p, q) (strcmp((p), (q)) == 0) 670Sstevel@tonic-gate 680Sstevel@tonic-gate 690Sstevel@tonic-gate /* 700Sstevel@tonic-gate * This routine is used by stand/lib/$PROC/libnfs.a in case it comes up with a 710Sstevel@tonic-gate * default filename, and by bootflags() if a default filename is specified in 720Sstevel@tonic-gate * the boot arguments. 730Sstevel@tonic-gate */ 740Sstevel@tonic-gate void 750Sstevel@tonic-gate set_default_filename(char *filename) 760Sstevel@tonic-gate { 770Sstevel@tonic-gate kernname = filename; 780Sstevel@tonic-gate } 790Sstevel@tonic-gate 800Sstevel@tonic-gate 810Sstevel@tonic-gate static const struct bplist { 820Sstevel@tonic-gate char *name; 830Sstevel@tonic-gate void *val; 840Sstevel@tonic-gate uint_t size; 850Sstevel@tonic-gate } bprop_tab[] = { 860Sstevel@tonic-gate "boot-args", &v2args, 0, 870Sstevel@tonic-gate "boot-path", &v2path, 0, 880Sstevel@tonic-gate "fstype", &systype, 0, 890Sstevel@tonic-gate "whoami", &my_own_name, 0, 900Sstevel@tonic-gate "mfg-name", &mfg_name, 0, 910Sstevel@tonic-gate "impl-arch-name", &impl_arch_name, 0, 920Sstevel@tonic-gate "module-path", &module_path, 0, 930Sstevel@tonic-gate "virt-avail", &vfreelistp, 0, 940Sstevel@tonic-gate "phys-avail", &pfreelistp, 0, 950Sstevel@tonic-gate "phys-installed", &pinstalledp, 0, 960Sstevel@tonic-gate "default-name", &kernname, 0, 970Sstevel@tonic-gate "extent", &memlistextent, sizeof (memlistextent), 980Sstevel@tonic-gate "vac", &vac, sizeof (vac), 990Sstevel@tonic-gate "cache-on?", &cache_state, sizeof (int), 1000Sstevel@tonic-gate "memory-update", 0, 0, 1010Sstevel@tonic-gate "boot-start", &start_addr, sizeof (start_addr), 1020Sstevel@tonic-gate "boot-end", &scratchmemp, sizeof (scratchmemp), 1030Sstevel@tonic-gate "boot-message", &boot_message, 0, 1040Sstevel@tonic-gate "bootp-response", &bootp_response, 0, 1050Sstevel@tonic-gate "netdev-path", &netdev_path, 0, 1060Sstevel@tonic-gate 0, 0, 0 1070Sstevel@tonic-gate }; 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate /* 1100Sstevel@tonic-gate * These routines implement the boot getprop interface. 1110Sstevel@tonic-gate * They are designed to mimic the corresponding devr_{getprop,getproplen} 1120Sstevel@tonic-gate * functions. 1130Sstevel@tonic-gate * The assumptions is that the basic property is an unsigned int. Other 1140Sstevel@tonic-gate * types (including lists) are special cases. 1150Sstevel@tonic-gate */ 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate /*ARGSUSED*/ 1180Sstevel@tonic-gate int 1190Sstevel@tonic-gate bgetproplen(struct bootops *bop, char *name) 1200Sstevel@tonic-gate { 1210Sstevel@tonic-gate int size = 0; 1220Sstevel@tonic-gate struct bplist *p; 1230Sstevel@tonic-gate struct memlist *ml; 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate /* this prop has side effects only. No length. */ 1260Sstevel@tonic-gate if (strequal(name, "memory-update")) 1270Sstevel@tonic-gate return (BOOT_SUCCESS); 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate for (p = (struct bplist *)bprop_tab; p->name != (char *)0; p++) { 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate /* got a linked list? */ 1320Sstevel@tonic-gate if ((strequal(name, "virt-avail") && strequal(name, p->name)) || 1330Sstevel@tonic-gate (strequal(name, "phys-avail") && strequal(name, p->name)) || 1340Sstevel@tonic-gate (strequal(name, "phys-installed") && 1350Sstevel@tonic-gate strequal(name, p->name))) { 1360Sstevel@tonic-gate 1370Sstevel@tonic-gate for (ml = *((struct memlist **)p->val); 1380Sstevel@tonic-gate ml != NIL; 1390Sstevel@tonic-gate ml = ml->next) 1400Sstevel@tonic-gate 1410Sstevel@tonic-gate /* 1420Sstevel@tonic-gate * subtract out the ptrs for our local 1430Sstevel@tonic-gate * linked list. The application will 1440Sstevel@tonic-gate * only see an array. 1450Sstevel@tonic-gate */ 1460Sstevel@tonic-gate size += (int)(sizeof (struct memlist) - 1470Sstevel@tonic-gate 2*sizeof (struct memlist *)); 1480Sstevel@tonic-gate return (size); 1490Sstevel@tonic-gate 1500Sstevel@tonic-gate } else if (strequal(name, p->name)) { 1510Sstevel@tonic-gate 1520Sstevel@tonic-gate /* if we already know the size, return it */ 1530Sstevel@tonic-gate if (p->size != 0) 1540Sstevel@tonic-gate return (p->size); 1550Sstevel@tonic-gate else { 1560Sstevel@tonic-gate if (*((char **)p->val) == NIL) 1570Sstevel@tonic-gate return (0); /* NULL is allowed */ 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate /* don't forget the null termination */ 1600Sstevel@tonic-gate return (strlen(*((char **)p->val)) + 1); 1610Sstevel@tonic-gate } 1620Sstevel@tonic-gate } 1630Sstevel@tonic-gate } 1640Sstevel@tonic-gate return (BOOT_BADPROP); 1650Sstevel@tonic-gate } 1660Sstevel@tonic-gate 1670Sstevel@tonic-gate /*ARGSUSED*/ 1680Sstevel@tonic-gate int 1690Sstevel@tonic-gate bgetprop(struct bootops *bop, char *name, void *buf) 1700Sstevel@tonic-gate { 1710Sstevel@tonic-gate struct bplist *p; 1720Sstevel@tonic-gate struct memlist *ml; 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate if (strequal(name, "memory-update")) { 1750Sstevel@tonic-gate /* 1760Sstevel@tonic-gate * dprintf("bgetprop: updating memlists.\n"); 1770Sstevel@tonic-gate */ 1780Sstevel@tonic-gate update_memlist("virtual-memory", "available", &vfreelistp); 1790Sstevel@tonic-gate update_memlist("memory", "available", &pfreelistp); 1800Sstevel@tonic-gate return (BOOT_SUCCESS); 1810Sstevel@tonic-gate } 1820Sstevel@tonic-gate 1830Sstevel@tonic-gate if (strequal(name, "boot-start")) { 1840Sstevel@tonic-gate start_addr = (caddr_t)_start; 1850Sstevel@tonic-gate bcopy((char *)(&start_addr), buf, sizeof (start_addr)); 1860Sstevel@tonic-gate return (BOOT_SUCCESS); 1870Sstevel@tonic-gate } 1880Sstevel@tonic-gate 1890Sstevel@tonic-gate if (strequal(name, "boot-end")) { 1900Sstevel@tonic-gate /* 1910Sstevel@tonic-gate * The true end of boot should be scratchmemp, 1920Sstevel@tonic-gate * boot gets its dynamic memory from the scratchmem 1930Sstevel@tonic-gate * which is the first 4M of the physical memory, 1940Sstevel@tonic-gate * and they are mapped 1:1. 1950Sstevel@tonic-gate */ 1960Sstevel@tonic-gate end_addr = scratchmemp; 1970Sstevel@tonic-gate bcopy((char *)(&end_addr), buf, sizeof (scratchmemp)); 1980Sstevel@tonic-gate return (BOOT_SUCCESS); 1990Sstevel@tonic-gate } 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate for (p = (struct bplist *)bprop_tab; p->name != (char *)0; p++) { 2020Sstevel@tonic-gate 2030Sstevel@tonic-gate /* gotta linked list? */ 2040Sstevel@tonic-gate if ((strequal(name, "virt-avail") && strequal(name, p->name)) || 2050Sstevel@tonic-gate (strequal(name, "phys-avail") && strequal(name, p->name)) || 2060Sstevel@tonic-gate (strequal(name, "phys-installed") && 2070Sstevel@tonic-gate strequal(name, p->name))) { 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate u_longlong_t *t = buf; 2100Sstevel@tonic-gate 2110Sstevel@tonic-gate for (ml = *((struct memlist **)p->val); 2120Sstevel@tonic-gate ml != NIL; 2130Sstevel@tonic-gate ml = ml->next) { 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate /* copy out into an array */ 2160Sstevel@tonic-gate *t++ = ml->address; 2170Sstevel@tonic-gate *t++ = ml->size; 2180Sstevel@tonic-gate } 2190Sstevel@tonic-gate return (BOOT_SUCCESS); 2200Sstevel@tonic-gate } else if (strequal(name, p->name)) { 2210Sstevel@tonic-gate if (p->size != 0) { 2220Sstevel@tonic-gate bcopy(p->val, buf, p->size); 2230Sstevel@tonic-gate } else { 2240Sstevel@tonic-gate (void) strcpy((char *)buf, *((char **)p->val)); 2250Sstevel@tonic-gate } 2260Sstevel@tonic-gate return (BOOT_SUCCESS); 2270Sstevel@tonic-gate } 2280Sstevel@tonic-gate } 2290Sstevel@tonic-gate return (BOOT_FAILURE); 2300Sstevel@tonic-gate } 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate /* 2330Sstevel@tonic-gate * If the user wants the first property in the list, he passes in a 2340Sstevel@tonic-gate * null string. The routine will always return a ptr to the name of the 2350Sstevel@tonic-gate * next prop, except when there are no more props. In that case, it will 2360Sstevel@tonic-gate * return a null string. 2370Sstevel@tonic-gate */ 2380Sstevel@tonic-gate 2390Sstevel@tonic-gate /*ARGSUSED*/ 2400Sstevel@tonic-gate char * 2410Sstevel@tonic-gate bnextprop(struct bootops *bop, char *prev) 2420Sstevel@tonic-gate { 2430Sstevel@tonic-gate struct bplist *p; 2440Sstevel@tonic-gate 2450Sstevel@tonic-gate /* user wants the firstprop */ 2460Sstevel@tonic-gate if (*prev == 0) 2470Sstevel@tonic-gate return (bprop_tab->name); 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate for (p = (struct bplist *)bprop_tab; p->name != (char *)0; p++) { 2500Sstevel@tonic-gate 2510Sstevel@tonic-gate if (strequal(prev, p->name)) 2520Sstevel@tonic-gate /* 2530Sstevel@tonic-gate * if prev is the last valid prop, 2540Sstevel@tonic-gate * we will return our terminator (0). 2550Sstevel@tonic-gate */ 2560Sstevel@tonic-gate return ((++p)->name); 2570Sstevel@tonic-gate 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate } 2600Sstevel@tonic-gate return ((char *)0); 2610Sstevel@tonic-gate } 262