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
platform_add_boot_device(struct stage2_args * args,NodeList * devicesList)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 intptr_t 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 intptr_t 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
platform_get_boot_partitions(struct stage2_args * args,Node * device,NodeList * list,NodeList * partitionList)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
platform_cleanup_devices()136 platform_cleanup_devices()
137 {
138 net_stack_cleanup();
139 }
140
141
142 #define DUMPED_BLOCK_SIZE 16
143
144 void
dumpBlock(const char * buffer,int size,const char * prefix)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
platform_add_block_devices(stage2_args * args,NodeList * devicesList)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
platform_register_boot_device(Node * device)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