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