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