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