1 /* $OpenBSD: autoconf.c,v 1.11 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 #include <sys/hibernate.h>
24
25 #include <machine/autoconf.h>
26
27 #define DUID_SIZE 8
28
29 extern void dumpconf(void);
30 int parseduid(const char *, u_char *);
31 void parsepmonbp(void);
32
33 int cold = 1;
34 struct device *bootdv = NULL;
35 char bootdev[16];
36 enum devclass bootdev_class = DV_DULL;
37
38 extern char pmon_bootp[];
39
40 void
cpu_configure(void)41 cpu_configure(void)
42 {
43 (void)splhigh();
44
45 softintr_init();
46 (void)config_rootfound("mainbus", NULL);
47
48 unmap_startup();
49
50 splinit();
51 cold = 0;
52 }
53
54 void
parsepmonbp(void)55 parsepmonbp(void)
56 {
57 char *p = NULL;
58 char *q;
59 size_t len = 0;
60
61 if (strncmp(pmon_bootp, "tftp://", 7) == 0) {
62 bootdev_class = DV_IFNET;
63 strlcpy(bootdev, "netboot", sizeof bootdev);
64 return;
65 }
66 strlcpy(bootdev, "unknown", sizeof bootdev);
67
68 if (strncmp(pmon_bootp, "/dev/disk/", 10) == 0) {
69 /* kernel loaded by our boot blocks */
70 p = pmon_bootp + 10;
71 len = strlen(p);
72 } else if (strncmp(pmon_bootp, "bootduid=", 9) == 0) {
73 /* kernel loaded by our boot blocks */
74 if (parseduid(pmon_bootp + 9, bootduid) != 0)
75 return;
76 } else {
77 /* kernel loaded by PMON */
78 p = strchr(pmon_bootp, '@');
79 if (p == NULL)
80 return;
81 p++;
82
83 q = strchr(p, '/');
84 if (q == NULL)
85 return;
86 len = q - p;
87 }
88
89 if (len <= 2 || len >= sizeof bootdev - 1)
90 return;
91 memcpy(bootdev, p, len);
92 bootdev[len] = '\0';
93 bootdev_class = DV_DISK;
94 }
95
96 static unsigned int
parsehex(int c)97 parsehex(int c)
98 {
99 if (c >= 'a')
100 return c - 'a' + 10;
101 else
102 return c - '0';
103 }
104
105 int
parseduid(const char * str,u_char * duid)106 parseduid(const char *str, u_char *duid)
107 {
108 int i;
109
110 for (i = 0; i < DUID_SIZE * 2; i++) {
111 if (!(str[i] >= '0' && str[i] <= '9') &&
112 !(str[i] >= 'a' && str[i] <= 'f'))
113 return -1;
114 }
115 if (str[DUID_SIZE * 2] != '\0')
116 return -1;
117
118 for (i = 0; i < DUID_SIZE; i++) {
119 duid[i] = parsehex(str[i * 2]) * 0x10 +
120 parsehex(str[i * 2 + 1]);
121 }
122
123 return 0;
124 }
125
126 void
diskconf(void)127 diskconf(void)
128 {
129 if (*pmon_bootp != '\0')
130 printf("pmon bootpath: %s\n", pmon_bootp);
131
132 if (bootdv != NULL)
133 printf("boot device: %s\n", bootdv->dv_xname);
134
135 setroot(bootdv, 0, RB_USERREQ);
136 dumpconf();
137
138 #ifdef HIBERNATE
139 hibernate_resume();
140 #endif /* HIBERNATE */
141 }
142
143 void
device_register(struct device * dev,void * aux)144 device_register(struct device *dev, void *aux)
145 {
146 if (bootdv != NULL)
147 return;
148
149 (*sys_platform->device_register)(dev, aux);
150 }
151
152 const struct nam2blk nam2blk[] = {
153 { "sd", 0 },
154 { "vnd", 2 },
155 { "cd", 3 },
156 { "wd", 4 },
157 { "rd", 8 },
158 { NULL, -1 }
159 };
160