1 /* $OpenBSD: autoconf.c,v 1.17 2022/09/02 20:06:56 miod Exp $ */
2 /*
3 * Copyright (c) 2009 Miodrag Vallat.
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/conf.h>
21 #include <sys/device.h>
22 #include <sys/reboot.h>
23
24 #include <machine/autoconf.h>
25
26 #define DUID_SIZE 8
27
28 extern void dumpconf(void);
29 int parseduid(const char *, u_char *);
30
31 int cold = 1;
32 struct device *bootdv = NULL;
33 char bootdev[16];
34 char uboot_rootdev[64];
35 enum devclass bootdev_class = DV_DULL;
36
37 void
cpu_configure(void)38 cpu_configure(void)
39 {
40 (void)splhigh();
41
42 softintr_init();
43 (void)config_rootfound("mainbus", NULL);
44
45 unmap_startup();
46
47 splinit();
48 cold = 0;
49 }
50
51 struct devmap {
52 char *dev;
53 enum devclass class;
54 };
55
56 enum devclass
findtype(void)57 findtype(void)
58 {
59 static const struct devmap devmap[] = {
60 { "wd", DV_DISK },
61 { "sd", DV_DISK },
62 { "octcf", DV_DISK },
63 { "amdcf", DV_DISK },
64 { NULL, DV_IFNET }
65 };
66 const struct devmap *dp = &devmap[0];
67
68 if (strlen(bootdev) < 2)
69 return DV_DISK;
70
71 while (dp->dev) {
72 if (strncmp(bootdev, dp->dev, strlen(dp->dev)) == 0)
73 break;
74 dp++;
75 }
76 return dp->class;
77 }
78
79 void
parse_uboot_root(const char * p)80 parse_uboot_root(const char *p)
81 {
82 const char *base;
83 size_t len;
84
85 /*
86 * Turn the U-Boot root device (/dev/octcf0) into a boot device.
87 */
88
89 if (strlen(uboot_rootdev) != 0)
90 return;
91
92 /* Get device basename. */
93 base = strrchr(p, '/');
94 if (base != NULL)
95 p = base + 1;
96
97 if (parseduid(p, bootduid) == 0) {
98 strlcpy(uboot_rootdev, p, sizeof(uboot_rootdev));
99 bootdev_class = DV_DISK;
100 return;
101 }
102
103 len = strlen(p);
104 if (len <= 2 || len >= sizeof bootdev - 1)
105 return;
106
107 strlcpy(bootdev, p, sizeof(bootdev));
108 strlcpy(uboot_rootdev, p, sizeof(uboot_rootdev));
109 bootdev_class = findtype();
110 }
111
112 static unsigned int
parsehex(int c)113 parsehex(int c)
114 {
115 if (c >= 'a')
116 return c - 'a' + 10;
117 else
118 return c - '0';
119 }
120
121 int
parseduid(const char * str,u_char * duid)122 parseduid(const char *str, u_char *duid)
123 {
124 int i;
125
126 for (i = 0; i < DUID_SIZE * 2; i++) {
127 if (!(str[i] >= '0' && str[i] <= '9') &&
128 !(str[i] >= 'a' && str[i] <= 'f'))
129 return -1;
130 }
131 if (str[DUID_SIZE * 2] != '\0')
132 return -1;
133
134 for (i = 0; i < DUID_SIZE; i++) {
135 duid[i] = parsehex(str[i * 2]) * 0x10 +
136 parsehex(str[i * 2 + 1]);
137 }
138
139 return 0;
140 }
141
142 void
diskconf(void)143 diskconf(void)
144 {
145 if (bootdv != NULL)
146 printf("boot device: %s\n", bootdv->dv_xname);
147
148 setroot(bootdv, 0, RB_USERREQ);
149 dumpconf();
150 }
151
152 void
device_register(struct device * dev,void * aux)153 device_register(struct device *dev, void *aux)
154 {
155 if (bootdv != NULL || dev->dv_class != bootdev_class)
156 return;
157
158 switch (bootdev_class) {
159 case DV_DISK:
160 case DV_IFNET:
161 if (strcmp(dev->dv_xname, bootdev) == 0)
162 bootdv = dev;
163 break;
164 default:
165 break;
166 }
167 }
168
169 const struct nam2blk nam2blk[] = {
170 { "sd", 0 },
171 { "vnd", 2 },
172 { "cd", 3 },
173 { "wd", 4 },
174 { "rd", 8 },
175 { "octcf", 15 },
176 { "amdcf", 19 },
177 { NULL, -1 }
178 };
179