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 2007 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/param.h> 29 #include <sys/sunddi.h> 30 #include <sys/bootconf.h> 31 #include <sys/bootvfs.h> 32 #include <sys/filep.h> 33 #include <sys/kobj.h> 34 #include <sys/varargs.h> 35 #include <sys/reboot.h> 36 37 extern void (*_kobj_printf)(void *, const char *fmt, ...); 38 extern int get_weakish_int(int *); 39 extern struct bootops *ops; 40 extern struct boot_fs_ops bufs_ops, bhsfs_ops; 41 extern int kmem_ready; 42 43 static uint64_t rd_start, rd_end; 44 struct boot_fs_ops *bfs_ops; 45 struct boot_fs_ops *bfs_tab[] = {&bufs_ops, &bhsfs_ops, NULL}; 46 47 static uintptr_t scratch_max; 48 49 #define _kmem_ready get_weakish_int(&kmem_ready) 50 51 /* 52 * This one reads the ramdisk. If fi_memp is set, we copy the 53 * ramdisk content to the designated buffer. Otherwise, we 54 * do a "cached" read (set fi_memp to the actual ramdisk buffer). 55 */ 56 int 57 diskread(fileid_t *filep) 58 { 59 uint_t blocknum; 60 caddr_t diskloc; 61 62 /* add in offset of root slice */ 63 blocknum = filep->fi_blocknum; 64 65 diskloc = (caddr_t)(uintptr_t)rd_start + blocknum * DEV_BSIZE; 66 if (diskloc + filep->fi_count > (caddr_t)(uintptr_t)rd_end) { 67 _kobj_printf(ops, "diskread: start = 0x%p, size = 0x%x\n", 68 diskloc, filep->fi_count); 69 _kobj_printf(ops, "reading beyond end of ramdisk\n"); 70 return (-1); 71 } 72 73 if (filep->fi_memp) { 74 bcopy(diskloc, filep->fi_memp, filep->fi_count); 75 } else { 76 /* "cached" read */ 77 filep->fi_memp = diskloc; 78 } 79 80 return (0); 81 } 82 83 int 84 kobj_boot_mountroot() 85 { 86 int i; 87 88 if (BOP_GETPROPLEN(ops, "ramdisk_start") != 8 || 89 BOP_GETPROP(ops, "ramdisk_start", (void *)&rd_start) != 0 || 90 BOP_GETPROPLEN(ops, "ramdisk_end") != 8 || 91 BOP_GETPROP(ops, "ramdisk_end", (void *)&rd_end) != 0) { 92 _kobj_printf(ops, 93 "failed to get ramdisk from boot\n"); 94 return (-1); 95 } 96 #ifdef KOBJ_DEBUG 97 _kobj_printf(ops, 98 "ramdisk range: 0x%llx-%llx\n", rd_start, rd_end); 99 #endif 100 101 for (i = 0; bfs_tab[i] != NULL; i++) { 102 bfs_ops = bfs_tab[i]; 103 if (BRD_MOUNTROOT(bfs_ops, "dummy") == 0) 104 return (0); 105 } 106 _kobj_printf(ops, "failed to mount ramdisk from boot\n"); 107 return (-1); 108 } 109 110 void 111 kobj_boot_unmountroot() 112 { 113 #ifdef DEBUG 114 if (boothowto & RB_VERBOSE) 115 _kobj_printf(ops, "boot scratch memory used: 0x%lx\n", 116 scratch_max); 117 #endif 118 (void) BRD_UNMOUNTROOT(bfs_ops); 119 } 120 121 /* 122 * Boot time wrappers for memory allocators. Called for both permanent 123 * and temporary boot memory allocations. We have to track which allocator 124 * (boot or kmem) was used so that we know how to free. 125 */ 126 void * 127 bkmem_alloc(size_t size) 128 { 129 /* allocate from boot scratch memory */ 130 void *addr; 131 132 if (_kmem_ready) 133 return (kobj_alloc(size, 0)); 134 135 /* 136 * Remember the highest BOP_ALLOC allocated address and don't free 137 * anything below it. 138 */ 139 addr = BOP_ALLOC(ops, 0, size, 0); 140 if (scratch_max < (uintptr_t)addr + size) 141 scratch_max = (uintptr_t)addr + size; 142 return (addr); 143 } 144 145 /*ARGSUSED*/ 146 void 147 bkmem_free(void *p, size_t size) 148 { 149 /* 150 * Free only if it's not boot scratch memory. 151 */ 152 if ((uintptr_t)p >= scratch_max) 153 kobj_free(p, size); 154 } 155 156 /*PRINTFLIKE1*/ 157 void 158 kobj_printf(char *fmt, ...) 159 { 160 va_list adx; 161 162 va_start(adx, fmt); 163 _kobj_printf(ops, fmt, adx); 164 va_end(adx); 165 } 166