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