xref: /haiku/src/tests/system/boot/loader/platform_devices.cpp (revision c90684742e7361651849be4116d0e5de3a817194)
1 /*
2  * Copyright 2003-2007, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "Handle.h"
8 
9 #include <boot/platform.h>
10 #include <util/kernel_cpp.h>
11 
12 #include <unistd.h>
13 #include <errno.h>
14 #include <dirent.h>
15 #include <limits.h>
16 #include <string.h>
17 #include <stdio.h>
18 
19 
20 // we're using some libroot specials
21 extern int __libc_argc;
22 extern char **__libc_argv;
23 extern const char *__progname;
24 
25 extern bool gShowMenu;
26 
27 
28 static status_t
29 get_device(const char *path, Node **_device)
30 {
31 	Handle *device = new Handle(path);
32 	if (device == NULL)
33 		return B_NO_MEMORY;
34 
35 	if (device->InitCheck() != B_OK) {
36 		fprintf(stderr, "%s: Could not open image \"%s\": %s\n",
37 			__progname, path, strerror(device->InitCheck()));
38 
39 		delete device;
40 		return B_ERROR;
41 	}
42 
43 	*_device = device;
44 	return B_OK;
45 }
46 
47 
48 static status_t
49 add_device(const char *path, NodeList *list)
50 {
51 	Node *device;
52 	status_t status = get_device(path, &device);
53 	if (status < B_OK)
54 		return status;
55 
56 	printf("add \"%s\" to list of boot devices\n", path);
57 	list->Add(device);
58 
59 	return B_OK;
60 }
61 
62 
63 static status_t
64 recursive_add_device(const char *path, NodeList *list)
65 {
66 	DIR *dir = opendir(path);
67 	if (dir == NULL)
68 		return errno;
69 
70 	struct dirent *dirent;
71 	while ((dirent = readdir(dir)) != NULL) {
72 		// we don't care about names with a leading dot (incl. "." and "..")
73 		if (dirent->d_name[0] == '.')
74 			continue;
75 
76 		char nextPath[PATH_MAX];
77 		strcpy(nextPath, path);
78 		strcat(nextPath, "/");
79 		strcat(nextPath, dirent->d_name);
80 
81 		// Note, this doesn't care about if it's a directory or not!
82 		if (!strcmp(dirent->d_name, "raw")
83 			&& add_device(nextPath, list) == B_OK)
84 			continue;
85 
86 		recursive_add_device(nextPath, list);
87 	}
88 	closedir(dir);
89 
90 	return B_OK;
91 }
92 
93 
94 static char *
95 get_next_argument(int32 *cookie, bool options)
96 {
97 	int32 i = *cookie + 1;
98 
99 	if (i == 1 && !options) {
100 		// filter out options at the start
101 		while (i < __libc_argc && __libc_argv[i][0] == '-')
102 			i++;
103 	}
104 
105 	for (; i < __libc_argc; i++) {
106 		// Options come at the start
107 		if (options && __libc_argv[i][0] != '-')
108 			return NULL;
109 
110 		*cookie = i;
111 		return __libc_argv[i];
112 	}
113 
114 	return NULL;
115 }
116 
117 
118 static char *
119 get_next_option(int32 *cookie)
120 {
121 	return get_next_argument(cookie, true);
122 }
123 
124 
125 static char *
126 get_next_device(int32 *cookie)
127 {
128 	return get_next_argument(cookie, false);
129 }
130 
131 
132 //	#pragma mark -
133 
134 
135 status_t
136 platform_add_boot_device(struct stage2_args *args, NodeList *devicesList)
137 {
138 	// we accept a boot device from the command line
139 	status_t status = B_ERROR;
140 	Node *device;
141 
142 	int32 cookie = 0;
143 	char *path = get_next_device(&cookie);
144 	if (path != NULL)
145 		status = get_device(path, &device);
146 	else
147 		status = get_device("/boot/home/test-file-device", &device);
148 
149 	if (status == B_OK)
150 		devicesList->Add(device);
151 
152 	return status;
153 }
154 
155 
156 status_t
157 platform_get_boot_partition(struct stage2_args *args, Node *device,
158 	NodeList *list, boot::Partition **_partition)
159 {
160 	NodeIterator iterator = list->GetIterator();
161 	boot::Partition *partition = NULL;
162 	while ((partition = (boot::Partition *)iterator.Next()) != NULL) {
163 		// just take the first partition
164 		*_partition = partition;
165 		return B_OK;
166 	}
167 
168 	return B_ENTRY_NOT_FOUND;
169 }
170 
171 
172 status_t
173 platform_add_block_devices(struct stage2_args *args, NodeList *list)
174 {
175 	int32 cookie = 0;
176 	if (get_next_device(&cookie) != NULL) {
177 		// add the devices provided on the command line
178 		char *path;
179 		while ((path = get_next_device(&cookie)) != NULL)
180 			add_device(path, list);
181 	}
182 
183 	bool addDevices = true;
184 	bool scsi = true;
185 	char *option;
186 	cookie = 0;
187 	while ((option = get_next_option(&cookie)) != NULL) {
188 		if (!strcmp(option, "--no-devices"))
189 			addDevices = false;
190 		else if (!strcmp(option, "--no-scsi"))
191 			scsi = false;
192 		else if (!strcmp(option, "--menu"))
193 			gShowMenu = true;
194 		else {
195 			fprintf(stderr, "usage: %s [OPTIONS] [image ...]\n"
196 				"  --no-devices\tDon't add real devices from /dev/disk\n"
197 				"  --no-scsi\tDon't add SCSI devices (might be problematic with some\n"
198 				"\t\tUSB mass storage drivers)\n"
199 				"  --menu\tShow boot menu\n", __progname);
200 			exit(0);
201 		}
202 	}
203 
204 	if (addDevices) {
205 		recursive_add_device("/dev/disk/ide", list);
206 		recursive_add_device("/dev/disk/virtual", list);
207 
208 		if (scsi)
209 			recursive_add_device("/dev/disk/scsi", list);
210 	}
211 
212 	return B_OK;
213 }
214 
215 
216 status_t
217 platform_register_boot_device(Node *device)
218 {
219 	return B_OK;
220 }
221