1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/types.h> 29 #include <sys/promif.h> 30 #include <sys/bootconf.h> 31 #include <sys/salib.h> 32 #include <sys/boot.h> 33 #include "boot_plat.h" 34 35 char *v2path, *kernname, *systype; 36 char *my_own_name = "boot"; 37 char v2args_buf[V2ARGS_BUF_SZ]; 38 char *v2args = v2args_buf; 39 char *mfg_name; 40 char *impl_arch_name; 41 char *bootp_response; 42 char *module_path; 43 int cache_state; 44 uint64_t memlistextent; /* replacement for old member of bootops */ 45 46 /* These are the various memory lists */ 47 struct memlist *pfreelistp, /* physmem available */ 48 *vfreelistp, /* virtmem available */ 49 *pinstalledp; /* physmem installed */ 50 51 char *boot_message; 52 53 char *netdev_path; 54 55 /* 56 * Support new boot properties "boot-start" and "boot-end" for 57 * Freeze/Thaw project. 58 */ 59 caddr_t start_addr, end_addr; 60 61 #define BOOT_BADPROP -1 62 #define BOOT_SUCCESS 0 63 #define BOOT_FAILURE -1 64 #define NIL 0 65 66 #define strequal(p, q) (strcmp((p), (q)) == 0) 67 68 69 /* 70 * This routine is used by stand/lib/$PROC/libnfs.a in case it comes up with a 71 * default filename, and by bootflags() if a default filename is specified in 72 * the boot arguments. 73 */ 74 void 75 set_default_filename(char *filename) 76 { 77 kernname = filename; 78 } 79 80 81 static const struct bplist { 82 char *name; 83 void *val; 84 uint_t size; 85 } bprop_tab[] = { 86 "boot-args", &v2args, 0, 87 "boot-path", &v2path, 0, 88 "fstype", &systype, 0, 89 "whoami", &my_own_name, 0, 90 "mfg-name", &mfg_name, 0, 91 "impl-arch-name", &impl_arch_name, 0, 92 "module-path", &module_path, 0, 93 "virt-avail", &vfreelistp, 0, 94 "phys-avail", &pfreelistp, 0, 95 "phys-installed", &pinstalledp, 0, 96 "default-name", &kernname, 0, 97 "extent", &memlistextent, sizeof (memlistextent), 98 "vac", &vac, sizeof (vac), 99 "cache-on?", &cache_state, sizeof (int), 100 "memory-update", 0, 0, 101 "boot-start", &start_addr, sizeof (start_addr), 102 "boot-end", &scratchmemp, sizeof (scratchmemp), 103 "boot-message", &boot_message, 0, 104 "bootp-response", &bootp_response, 0, 105 "netdev-path", &netdev_path, 0, 106 0, 0, 0 107 }; 108 109 /* 110 * These routines implement the boot getprop interface. 111 * They are designed to mimic the corresponding devr_{getprop,getproplen} 112 * functions. 113 * The assumptions is that the basic property is an unsigned int. Other 114 * types (including lists) are special cases. 115 */ 116 117 /*ARGSUSED*/ 118 int 119 bgetproplen(struct bootops *bop, char *name) 120 { 121 int size = 0; 122 struct bplist *p; 123 struct memlist *ml; 124 125 /* this prop has side effects only. No length. */ 126 if (strequal(name, "memory-update")) 127 return (BOOT_SUCCESS); 128 129 for (p = (struct bplist *)bprop_tab; p->name != (char *)0; p++) { 130 131 /* got a linked list? */ 132 if ((strequal(name, "virt-avail") && strequal(name, p->name)) || 133 (strequal(name, "phys-avail") && strequal(name, p->name)) || 134 (strequal(name, "phys-installed") && 135 strequal(name, p->name))) { 136 137 for (ml = *((struct memlist **)p->val); 138 ml != NIL; 139 ml = ml->next) 140 141 /* 142 * subtract out the ptrs for our local 143 * linked list. The application will 144 * only see an array. 145 */ 146 size += (int)(sizeof (struct memlist) - 147 2*sizeof (struct memlist *)); 148 return (size); 149 150 } else if (strequal(name, p->name)) { 151 152 /* if we already know the size, return it */ 153 if (p->size != 0) 154 return (p->size); 155 else { 156 if (*((char **)p->val) == NIL) 157 return (0); /* NULL is allowed */ 158 159 /* don't forget the null termination */ 160 return (strlen(*((char **)p->val)) + 1); 161 } 162 } 163 } 164 return (BOOT_BADPROP); 165 } 166 167 /*ARGSUSED*/ 168 int 169 bgetprop(struct bootops *bop, char *name, void *buf) 170 { 171 struct bplist *p; 172 struct memlist *ml; 173 174 if (strequal(name, "memory-update")) { 175 /* 176 * dprintf("bgetprop: updating memlists.\n"); 177 */ 178 update_memlist("virtual-memory", "available", &vfreelistp); 179 update_memlist("memory", "available", &pfreelistp); 180 return (BOOT_SUCCESS); 181 } 182 183 if (strequal(name, "boot-start")) { 184 start_addr = (caddr_t)_start; 185 bcopy((char *)(&start_addr), buf, sizeof (start_addr)); 186 return (BOOT_SUCCESS); 187 } 188 189 if (strequal(name, "boot-end")) { 190 /* 191 * The true end of boot should be scratchmemp, 192 * boot gets its dynamic memory from the scratchmem 193 * which is the first 4M of the physical memory, 194 * and they are mapped 1:1. 195 */ 196 end_addr = scratchmemp; 197 bcopy((char *)(&end_addr), buf, sizeof (scratchmemp)); 198 return (BOOT_SUCCESS); 199 } 200 201 for (p = (struct bplist *)bprop_tab; p->name != (char *)0; p++) { 202 203 /* gotta linked list? */ 204 if ((strequal(name, "virt-avail") && strequal(name, p->name)) || 205 (strequal(name, "phys-avail") && strequal(name, p->name)) || 206 (strequal(name, "phys-installed") && 207 strequal(name, p->name))) { 208 209 u_longlong_t *t = buf; 210 211 for (ml = *((struct memlist **)p->val); 212 ml != NIL; 213 ml = ml->next) { 214 215 /* copy out into an array */ 216 *t++ = ml->address; 217 *t++ = ml->size; 218 } 219 return (BOOT_SUCCESS); 220 } else if (strequal(name, p->name)) { 221 if (p->size != 0) { 222 bcopy(p->val, buf, p->size); 223 } else { 224 (void) strcpy((char *)buf, *((char **)p->val)); 225 } 226 return (BOOT_SUCCESS); 227 } 228 } 229 return (BOOT_FAILURE); 230 } 231 232 /* 233 * If the user wants the first property in the list, he passes in a 234 * null string. The routine will always return a ptr to the name of the 235 * next prop, except when there are no more props. In that case, it will 236 * return a null string. 237 */ 238 239 /*ARGSUSED*/ 240 char * 241 bnextprop(struct bootops *bop, char *prev) 242 { 243 struct bplist *p; 244 245 /* user wants the firstprop */ 246 if (*prev == 0) 247 return (bprop_tab->name); 248 249 for (p = (struct bplist *)bprop_tab; p->name != (char *)0; p++) { 250 251 if (strequal(prev, p->name)) 252 /* 253 * if prev is the last valid prop, 254 * we will return our terminator (0). 255 */ 256 return ((++p)->name); 257 258 259 } 260 return ((char *)0); 261 } 262