/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright (c) 2016 by Delphix. All rights reserved. */ #include #include #include #include #include #include "boot_plat.h" char *v2path, *kernname, *systype; char *my_own_name = "boot"; char v2args_buf[V2ARGS_BUF_SZ]; char *v2args = v2args_buf; char *mfg_name; char *impl_arch_name; char *bootp_response; char *module_path; int cache_state; uint64_t memlistextent; /* replacement for old member of bootops */ /* These are the various memory lists */ struct memlist *pfreelistp, /* physmem available */ *vfreelistp, /* virtmem available */ *pinstalledp; /* physmem installed */ char *boot_message; char *netdev_path; /* * Support new boot properties "boot-start" and "boot-end" for * Freeze/Thaw project. */ caddr_t start_addr, end_addr; #define BOOT_BADPROP -1 #define BOOT_SUCCESS 0 #define BOOT_FAILURE -1 #define NIL 0 #define strequal(p, q) (strcmp((p), (q)) == 0) /* * This routine is used by stand/lib/$PROC/libnfs.a in case it comes up with a * default filename, and by bootflags() if a default filename is specified in * the boot arguments. */ void set_default_filename(char *filename) { kernname = filename; } static const struct bplist { char *name; void *val; uint_t size; } bprop_tab[] = { "boot-args", &v2args, 0, "boot-path", &v2path, 0, "fstype", &systype, 0, "whoami", &my_own_name, 0, "mfg-name", &mfg_name, 0, "impl-arch-name", &impl_arch_name, 0, "module-path", &module_path, 0, "virt-avail", &vfreelistp, 0, "phys-avail", &pfreelistp, 0, "phys-installed", &pinstalledp, 0, "default-name", &kernname, 0, "extent", &memlistextent, sizeof (memlistextent), "vac", &vac, sizeof (vac), "cache-on?", &cache_state, sizeof (int), "memory-update", 0, 0, "boot-start", &start_addr, sizeof (start_addr), "boot-end", &scratchmemp, sizeof (scratchmemp), "boot-message", &boot_message, 0, "bootp-response", &bootp_response, 0, "netdev-path", &netdev_path, 0, 0, 0, 0 }; /* * These routines implement the boot getprop interface. * They are designed to mimic the corresponding devr_{getprop,getproplen} * functions. * The assumptions is that the basic property is an unsigned int. Other * types (including lists) are special cases. */ /*ARGSUSED*/ int bgetproplen(struct bootops *bop, char *name) { int size = 0; struct bplist *p; struct memlist *ml; /* this prop has side effects only. No length. */ if (strequal(name, "memory-update")) return (BOOT_SUCCESS); for (p = (struct bplist *)bprop_tab; p->name != (char *)0; p++) { /* got a linked list? */ if ((strequal(name, "virt-avail") && strequal(name, p->name)) || (strequal(name, "phys-avail") && strequal(name, p->name)) || (strequal(name, "phys-installed") && strequal(name, p->name))) { for (ml = *((struct memlist **)p->val); ml != NIL; ml = ml->ml_next) /* * subtract out the ptrs for our local * linked list. The application will * only see an array. */ size += (int)(sizeof (struct memlist) - 2*sizeof (struct memlist *)); return (size); } else if (strequal(name, p->name)) { /* if we already know the size, return it */ if (p->size != 0) return (p->size); else { if (*((char **)p->val) == NIL) return (0); /* NULL is allowed */ /* don't forget the null termination */ return (strlen(*((char **)p->val)) + 1); } } } return (BOOT_BADPROP); } /*ARGSUSED*/ int bgetprop(struct bootops *bop, char *name, void *buf) { struct bplist *p; struct memlist *ml; if (strequal(name, "memory-update")) { /* * dprintf("bgetprop: updating memlists.\n"); */ update_memlist("virtual-memory", "available", &vfreelistp); update_memlist("memory", "available", &pfreelistp); return (BOOT_SUCCESS); } if (strequal(name, "boot-start")) { start_addr = (caddr_t)_start; bcopy((char *)(&start_addr), buf, sizeof (start_addr)); return (BOOT_SUCCESS); } if (strequal(name, "boot-end")) { /* * The true end of boot should be scratchmemp, * boot gets its dynamic memory from the scratchmem * which is the first 4M of the physical memory, * and they are mapped 1:1. */ end_addr = scratchmemp; bcopy((char *)(&end_addr), buf, sizeof (scratchmemp)); return (BOOT_SUCCESS); } for (p = (struct bplist *)bprop_tab; p->name != (char *)0; p++) { /* gotta linked list? */ if ((strequal(name, "virt-avail") && strequal(name, p->name)) || (strequal(name, "phys-avail") && strequal(name, p->name)) || (strequal(name, "phys-installed") && strequal(name, p->name))) { u_longlong_t *t = buf; for (ml = *((struct memlist **)p->val); ml != NIL; ml = ml->ml_next) { /* copy out into an array */ *t++ = ml->ml_address; *t++ = ml->ml_size; } return (BOOT_SUCCESS); } else if (strequal(name, p->name)) { if (p->size != 0) { bcopy(p->val, buf, p->size); } else { (void) strcpy((char *)buf, *((char **)p->val)); } return (BOOT_SUCCESS); } } return (BOOT_FAILURE); } /* * If the user wants the first property in the list, they pass in a * null string. The routine will always return a ptr to the name of the * next prop, except when there are no more props. In that case, it will * return a null string. */ /*ARGSUSED*/ char * bnextprop(struct bootops *bop, char *prev) { struct bplist *p; /* user wants the firstprop */ if (*prev == 0) return (bprop_tab->name); for (p = (struct bplist *)bprop_tab; p->name != (char *)0; p++) { if (strequal(prev, p->name)) /* * if prev is the last valid prop, * we will return our terminator (0). */ return ((++p)->name); } return ((char *)0); }