1 /* $NetBSD: autoconf.c,v 1.25 2023/10/28 17:53:06 mrg Exp $ */ 2 3 /*- 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Matt Thomas <matt (at) 3am-software.com>. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.25 2023/10/28 17:53:06 mrg Exp $"); 34 35 #include "opt_md.h" 36 #include "opt_ddb.h" 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/reboot.h> 41 #include <sys/disklabel.h> 42 #include <sys/device.h> 43 #include <sys/conf.h> 44 #include <sys/kernel.h> 45 #include <sys/kmem.h> 46 47 #include <machine/autoconf.h> 48 #include <machine/intr.h> 49 #include <machine/bootconfig.h> 50 51 void (*evbarm_device_register)(device_t, void *); 52 void (*evbarm_device_register_post_config)(device_t, void *); 53 void (*evbarm_cpu_rootconf)(void); 54 55 extern struct cfdata cfdata[]; 56 57 #ifndef MEMORY_DISK_IS_ROOT 58 static int get_device(char *name, device_t *, int *); 59 static void set_root_device(void); 60 #endif 61 62 #ifndef MEMORY_DISK_IS_ROOT 63 /* Decode a device name to a major and minor number */ 64 65 static int 66 get_device(char *name, device_t *dvp, int *partp) 67 { 68 int unit, part; 69 char devname[16], *cp; 70 device_t dv; 71 72 if (strncmp(name, "/dev/", 5) == 0) 73 name += 5; 74 75 if (devsw_name2blk(name, devname, sizeof(devname)) == -1) 76 return 0; 77 78 name += strlen(devname); 79 unit = part = 0; 80 81 cp = name; 82 while (*cp >= '0' && *cp <= '9') 83 unit = (unit * 10) + (*cp++ - '0'); 84 if (cp == name) 85 return 0; 86 87 if (*cp >= 'a' && *cp < ('a' + MAXPARTITIONS)) 88 part = *cp - 'a'; 89 else if (*cp != '\0' && *cp != ' ') 90 return 0; 91 if ((dv = device_find_by_driver_unit(devname, unit)) != NULL) { 92 *dvp = dv; 93 *partp = part; 94 return 1; 95 } 96 97 return 0; 98 } 99 100 /* Set the rootdev variable from the root specifier in the boot args */ 101 102 static char *bootspec_buf = NULL; 103 static size_t bootspec_buflen = 0; 104 105 static void 106 set_root_device(void) 107 { 108 char *ptr, *end, *buf; 109 size_t len; 110 111 if (boot_args == NULL) 112 return; 113 114 if (!get_bootconf_option(boot_args, "root", BOOTOPT_TYPE_STRING, &ptr)) 115 return; 116 117 if (get_device(ptr, &booted_device, &booted_partition)) 118 return; 119 120 /* NUL-terminate string, get_bootconf_option doesn't */ 121 for (end = ptr; *end != '\0'; ++end) { 122 if (*end == ' ' || *end == '\t') { 123 break; 124 } 125 } 126 127 if (end == ptr) 128 return; 129 130 len = end - ptr; 131 132 buf = kmem_alloc(len + 1, KM_SLEEP); 133 memcpy(buf, ptr, len); 134 buf[len] = '\0'; 135 136 if (bootspec_buf != NULL) 137 kmem_free(bootspec_buf, bootspec_buflen + 1); 138 139 bootspec_buf = buf; 140 bootspec_buflen = len; 141 142 bootspec = bootspec_buf; 143 } 144 #endif 145 146 /* 147 * Set up the root device from the boot args. 148 * 149 * cpu_bootconf() is called before RAIDframe root detection, 150 * and cpu_rootconf() is called after. 151 */ 152 void 153 cpu_bootconf(void) 154 { 155 #ifndef MEMORY_DISK_IS_ROOT 156 set_root_device(); 157 if (evbarm_cpu_rootconf) 158 (*evbarm_cpu_rootconf)(); 159 #endif 160 } 161 162 void 163 cpu_rootconf(void) 164 { 165 cpu_bootconf(); 166 aprint_normal("boot device: %s\n", 167 booted_device != NULL ? device_xname(booted_device) : "<unknown>"); 168 rootconf(); 169 } 170 171 172 /* 173 * void cpu_configure() 174 * 175 * Configure all the root devices 176 * The root devices are expected to configure their own children 177 */ 178 void 179 cpu_configure(void) 180 { 181 struct mainbus_attach_args maa; 182 struct cfdata *cf; 183 184 #ifdef DDB 185 if (boothowto & RB_KDB) { 186 printf("Entering DDB...\n"); 187 cpu_Debugger(); 188 } 189 #endif 190 191 (void) splhigh(); 192 193 for (cf = &cfdata[0]; cf->cf_name; cf++) { 194 if (cf->cf_pspec == NULL) { 195 maa.ma_name = cf->cf_name; 196 if (config_rootfound(cf->cf_name, &maa) != NULL) 197 break; 198 } 199 } 200 201 /* Time to start taking interrupts so lets open the flood gates .... */ 202 spl0(); 203 } 204 205 void 206 device_register(device_t dev, void *aux) 207 { 208 if (evbarm_device_register != NULL) 209 (*evbarm_device_register)(dev, aux); 210 } 211 212 213 void 214 device_register_post_config(device_t dev, void *aux) 215 { 216 if (evbarm_device_register_post_config != NULL) 217 (*evbarm_device_register_post_config)(dev, aux); 218 } 219 220