xref: /haiku/src/system/boot/platform/openfirmware/devices.cpp (revision 5ac9b506412b11afb993bb52d161efe7666958a5)
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 #define DUMPED_BLOCK_SIZE 16
136 
137 void
138 dumpBlock(const char *buffer, int size, const char *prefix)
139 {
140 	int i;
141 
142 	for (i = 0; i < size;) {
143 		int start = i;
144 
145 		printf(prefix);
146 		for (; i < start+DUMPED_BLOCK_SIZE; i++) {
147 			if (!(i % 4))
148 				printf(" ");
149 
150 			if (i >= size)
151 				printf("  ");
152 			else
153 				printf("%02x", *(unsigned char *)(buffer + i));
154 		}
155 		printf("  ");
156 
157 		for (i = start; i < start + DUMPED_BLOCK_SIZE; i++) {
158 			if (i < size) {
159 				char c = buffer[i];
160 
161 				if (c < 30)
162 					printf(".");
163 				else
164 					printf("%c", c);
165 			} else
166 				break;
167 		}
168 		printf("\n");
169 	}
170 }
171 
172 
173 status_t
174 platform_add_block_devices(stage2_args *args, NodeList *devicesList)
175 {
176 	// add all block devices to the list of possible boot devices
177 
178 	int cookie = 0;
179 	char path[256];
180 	status_t status;
181 	while ((status = of_get_next_device(&cookie, 0, "block", path,
182 			sizeof(path))) == B_OK) {
183 		if (!strcmp(path, sBootPath)) {
184 			// don't add the boot device twice
185 			continue;
186 		}
187 
188 		// Adjust the arguments passed to the open command so that
189 		// the disk-label package is by-passed - unfortunately,
190 		// this is implementation specific (and I found no docs
191 		// for the Apple OF disk-label usage, of course)
192 
193 		// SUN's OpenBoot:
194 		//strcpy(path + strlen(path), ":nolabel");
195 		// Apple:
196 		if (gMachine & MACHINE_MAC)
197 			strcpy(path + strlen(path), ":0");
198 
199 		printf("\t%s\n", path);
200 
201 		int handle = of_open(path);
202 		if (handle == OF_FAILED) {
203 			puts("\t\t(failed)");
204 			continue;
205 		}
206 
207 		Handle *device = new(nothrow) Handle(handle);
208 		printf("\t\t(could open device, handle = %p, node = %p)\n",
209 			(void *)handle, device);
210 
211 		devicesList->Add(device);
212 	}
213 	printf("\t(loop ended with %ld)\n", status);
214 
215 	return B_OK;
216 }
217 
218 
219 status_t
220 platform_register_boot_device(Node *device)
221 {
222 	disk_identifier disk;
223 
224 	disk.bus_type = UNKNOWN_BUS;
225 	disk.device_type = UNKNOWN_DEVICE;
226 	disk.device.unknown.size = device->Size();
227 
228 	gBootVolume.SetData(BOOT_VOLUME_DISK_IDENTIFIER, B_RAW_TYPE, &disk,
229 		sizeof(disk_identifier));
230 
231 	return B_OK;
232 }
233 
234