Home | History | Annotate | Line # | Download | only in evbarm
      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