xref: /haiku/src/system/boot/platform/openfirmware/devices.cpp (revision cb29eafe2586fdb2d7685afa69fdab5d88a8b576)
1 /*
2  * Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de.
3  * Copyright 2010, Andreas Färber <andreas.faerber@web.de>
4  * All rights reserved. Distributed under the terms of the MIT License.
5  */
6 
7 
8 #include <string.h>
9 
10 #include <boot/partitions.h>
11 #include <boot/platform.h>
12 #include <boot/vfs.h>
13 #include <boot/stdio.h>
14 #include <boot/stage2.h>
15 #include <boot/net/IP.h>
16 #include <boot/net/NetStack.h>
17 #include <boot/net/RemoteDisk.h>
18 #include <platform/openfirmware/devices.h>
19 #include <platform/openfirmware/openfirmware.h>
20 #include <util/kernel_cpp.h>
21 
22 #include "Handle.h"
23 #include "machine.h"
24 
25 
26 #define ENABLE_ISCSI
27 
28 
29 char sBootPath[192];
30 
31 
32 status_t
33 platform_add_boot_device(struct stage2_args *args, NodeList *devicesList)
34 {
35 	// print out the boot path (to be removed later?)
36 
37 	int length = of_getprop(gChosen, "bootpath", sBootPath, sizeof(sBootPath));
38 	if (length <= 1)
39 		return B_ENTRY_NOT_FOUND;
40 	printf("boot path = \"%s\"\n", sBootPath);
41 
42 	int node = of_finddevice(sBootPath);
43 	if (node != OF_FAILED) {
44 		char type[16];
45 		of_getprop(node, "device_type", type, sizeof(type));
46 		printf("boot type = %s\n", type);
47 
48 		// If the boot device is a network device, we try to find a
49 		// "remote disk" at this point.
50 		if (strcmp(type, "network") == 0) {
51 			// init the net stack
52 			status_t error = net_stack_init();
53 			if (error != B_OK)
54 				return error;
55 
56 			ip_addr_t bootAddress = 0;
57 			char* bootArgs = strrchr(sBootPath, ':');
58 			if (bootArgs != NULL) {
59 				bootArgs++;
60 				char* comma = strchr(bootArgs, ',');
61 				if (comma != NULL && comma - bootArgs > 0) {
62 					comma[0] = '\0';
63 					bootAddress = ip_parse_address(bootArgs);
64 					comma[0] = ',';
65 				}
66 			}
67 			if (bootAddress == 0) {
68 				int package = of_finddevice("/options");
69 				char defaultServerIP[16];
70 				int bytesRead = of_getprop(package, "default-server-ip",
71 					defaultServerIP, sizeof(defaultServerIP) - 1);
72 				if (bytesRead != OF_FAILED && bytesRead > 1) {
73 					defaultServerIP[bytesRead] = '\0';
74 					bootAddress = ip_parse_address(defaultServerIP);
75 				}
76 			}
77 
78 			// init a native remote disk, if possible
79 			RemoteDisk *remoteDisk = RemoteDisk::FindAnyRemoteDisk();
80 			if (remoteDisk != NULL) {
81 				devicesList->Add(remoteDisk);
82 				return B_OK;
83 			}
84 
85 			return B_ENTRY_NOT_FOUND;
86 		}
87 
88 		if (strcmp("block", type) != 0) {
89 			printf("boot device is not a block device!\n");
90 			return B_ENTRY_NOT_FOUND;
91 		}
92 	} else
93 		printf("could not open boot path.\n");
94 
95 /*	char name[256];
96 	strcpy(name, sBootPath);
97 	strcat(name, ":kernel_ppc");
98 	int kernel = of_open(name);
99 	if (kernel == OF_FAILED) {
100 		puts("open kernel failed");
101 	} else
102 		puts("open kernel succeeded");
103 */
104 	int handle = of_open(sBootPath);
105 	if (handle == OF_FAILED) {
106 		puts("\t\t(open failed)");
107 		return B_ERROR;
108 	}
109 
110 	Handle *device = new(nothrow) Handle(handle);
111 	if (device == NULL)
112 		return B_NO_MEMORY;
113 
114 	devicesList->Add(device);
115 	return B_OK;
116 }
117 
118 
119 status_t
120 platform_get_boot_partitions(struct stage2_args *args, Node *device,
121 	NodeList *list, NodeList *partitionList)
122 {
123 	NodeIterator iterator = list->GetIterator();
124 	boot::Partition *partition = NULL;
125 	while ((partition = (boot::Partition *)iterator.Next()) != NULL) {
126 		// ToDo: just take the first partition for now
127 		partitionList->Insert(partition);
128 		return B_OK;
129 	}
130 
131 	return B_ENTRY_NOT_FOUND;
132 }
133 
134 
135 void
136 platform_cleanup_devices()
137 {
138 	net_stack_cleanup();
139 }
140 
141 
142 #define DUMPED_BLOCK_SIZE 16
143 
144 void
145 dumpBlock(const char *buffer, int size, const char *prefix)
146 {
147 	int i;
148 
149 	for (i = 0; i < size;) {
150 		int start = i;
151 
152 		printf(prefix);
153 		for (; i < start+DUMPED_BLOCK_SIZE; i++) {
154 			if (!(i % 4))
155 				printf(" ");
156 
157 			if (i >= size)
158 				printf("  ");
159 			else
160 				printf("%02x", *(unsigned char *)(buffer + i));
161 		}
162 		printf("  ");
163 
164 		for (i = start; i < start + DUMPED_BLOCK_SIZE; i++) {
165 			if (i < size) {
166 				char c = buffer[i];
167 
168 				if (c < 30)
169 					printf(".");
170 				else
171 					printf("%c", c);
172 			} else
173 				break;
174 		}
175 		printf("\n");
176 	}
177 }
178 
179 
180 status_t
181 platform_add_block_devices(stage2_args *args, NodeList *devicesList)
182 {
183 	// add all block devices to the list of possible boot devices
184 
185 	intptr_t cookie = 0;
186 	char path[256];
187 	status_t status;
188 	while ((status = of_get_next_device(&cookie, 0, "block", path,
189 			sizeof(path))) == B_OK) {
190 		if (!strcmp(path, sBootPath)) {
191 			// don't add the boot device twice
192 			continue;
193 		}
194 
195 		// Adjust the arguments passed to the open command so that
196 		// the disk-label package is by-passed - unfortunately,
197 		// this is implementation specific (and I found no docs
198 		// for the Apple OF disk-label usage, of course)
199 
200 		// SUN's OpenBoot:
201 		//strcpy(path + strlen(path), ":nolabel");
202 		// Apple:
203 		if (gMachine & MACHINE_MAC)
204 			strcpy(path + strlen(path), ":0");
205 
206 		printf("\t%s\n", path);
207 
208 		intptr_t handle = of_open(path);
209 		if (handle == OF_FAILED) {
210 			puts("\t\t(failed)");
211 			continue;
212 		}
213 
214 		Handle *device = new(nothrow) Handle(handle);
215 		printf("\t\t(could open device, handle = %p, node = %p)\n",
216 			(void *)handle, device);
217 
218 		devicesList->Add(device);
219 	}
220 	printf("\t(loop ended with %ld)\n", status);
221 
222 	return B_OK;
223 }
224 
225 
226 status_t
227 platform_register_boot_device(Node *device)
228 {
229 	disk_identifier disk;
230 
231 	disk.bus_type = UNKNOWN_BUS;
232 	disk.device_type = UNKNOWN_DEVICE;
233 	disk.device.unknown.size = device->Size();
234 
235 	gBootVolume.SetData(BOOT_VOLUME_DISK_IDENTIFIER, B_RAW_TYPE, &disk,
236 		sizeof(disk_identifier));
237 
238 	return B_OK;
239 }
240 
241