3 Copyright (C) 1999 Benjamin Herrenschmidt
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
26 #include "partition.h"
30 extern char bootdevice[1024];
32 /* This function follows the device path in the devtree and separates
33 the device name, partition number, and other datas (mostly file name)
34 the string passed in parameters is changed since 0 are put in place
35 of some separators to terminate the various strings
39 parse_device_path(char *imagepath, char *defdevice, int defpart,
40 char *deffile, struct boot_fspec_t *result)
43 char *ipath = strdup(imagepath);
44 char *defdev = strdup(defdevice);
50 if (!strstr(defdev, "ethernet") && !strstr(defdev, "enet")) {
51 if ((ptr = strrchr(defdev, ':')) != NULL)
52 *ptr = 0; /* remove trailing : from defdevice if necessary */
58 if ((ptr = strrchr(ipath, ',')) != NULL) {
59 result->file = strdup(ptr+1);
60 /* Trim the filename off */
64 if (strstr(ipath, "ethernet") || strstr(ipath, "enet"))
65 if ((ptr = strstr(ipath, "bootp")) != NULL) { /* `n' key booting boots enet:bootp */
67 result->dev = strdup(ipath);
69 result->dev = strdup(ipath);
70 else if ((ptr = strchr(ipath, ':')) != NULL) {
72 result->dev = strdup(ipath);
74 result->part = simple_strtol(ptr+1, NULL, 10);
75 } else if (strlen(ipath)) {
76 result->file = strdup(ipath);
83 result->dev = strdup(defdev);
86 result->part = defpart;
89 result->file = strdup(deffile);
96 parse_device_path(char *of_device, char **file_spec, int *partition)
105 DEBUG_F("of_device before parsing: %s\n", of_device);
106 p = strchr(of_device, ':');
107 DEBUG_F("of_device after parsing: %s\n", p);
109 if (!p) { /* if null terminated we are finished */
110 DEBUG_F("of_device: %s\n", of_device);
113 #if 0 /* this is broken crap, breaks netboot entirely */
114 else if (strstr(of_device, "ethernet") != NULL)
115 p = strchr(of_device, ','); /* skip over ip all the way to the ',' */
116 else if (strstr(of_device, "enet") != NULL)
117 p = strchr(of_device, ','); /* skip over ip all the way to the ',' */
120 last = ++p; /* sets to start of second part */
121 while(*p && *p != ',') {
131 *partition = simple_strtol(last, NULL, 10);
136 DEBUG_F("of_device: %s\n", of_device);
137 strcat(of_device, ":");
138 DEBUG_F("of_device after strcat: %s\n", of_device);
143 validate_fspec( struct boot_fspec_t* spec,
144 char* default_device,
148 spec->file = spec->dev;
151 if (spec->part == -1)
152 spec->part = default_part;
154 spec->dev = default_device;
156 return FILE_BAD_PATH;
157 else if (spec->file[0] == ',')
166 file_block_open( struct boot_file_t* file,
167 const char* dev_name,
168 const char* file_name,
171 struct partition_t* parts;
172 struct partition_t* p;
173 struct partition_t* found;
175 parts = partitions_lookup(dev_name);
180 prom_printf("partitions:\n");
182 prom_printf("no partitions found.\n");
184 for (p = parts; p && !found; p=p->next) {
185 DEBUG_F("number: %02d, start: 0x%08lx, length: 0x%08lx\n",
186 p->part_number, p->part_start, p->part_size );
187 if (partition == -1) {
188 file->fs = fs_open( file, dev_name, p, file_name );
189 if (file->fs != NULL)
192 if ((partition >= 0) && (partition == p->part_number))
196 prom_printf(" (match)\n");
200 /* Note: we don't skip when found is NULL since we can, in some
201 * cases, let OF figure out a default partition.
203 DEBUG_F( "Using OF defaults.. (found = %p)\n", found );
204 file->fs = fs_open( file, dev_name, found, file_name );
208 partitions_free(parts);
214 file_net_open( struct boot_file_t* file,
215 const char* dev_name,
216 const char* file_name)
218 file->fs = fs_of_netboot;
219 return fs_of_netboot->open(file, dev_name, NULL, file_name);
223 default_read( struct boot_file_t* file,
227 prom_printf("WARNING ! default_read called !\n");
232 default_seek( struct boot_file_t* file,
235 prom_printf("WARNING ! default_seek called !\n");
240 default_close( struct boot_file_t* file)
242 prom_printf("WARNING ! default_close called !\n");
246 static struct fs_t fs_default =
256 int open_file( const struct boot_fspec_t* spec,
257 struct boot_file_t* file)
259 // static char temp[1024];
260 static char temps[64];
262 // char *file_name = NULL;
267 memset(file, 0, sizeof(struct boot_file_t*));
268 file->fs = &fs_default;
270 /* Lookup the OF device path */
271 /* First, see if a device was specified for the kernel
272 * if not, we hope that the user wants a kernel on the same
273 * drive and partition as yaboot itself */
274 #if 0 /* this is crap */
276 strcpy(spec->dev, bootdevice);
277 strncpy(temp,spec->dev,1024);
278 dev_name = parse_device_path(temp, &file_name, &partition);
279 if (file_name == NULL)
280 file_name = (char *)spec->file;
281 if (file_name == NULL) {
282 prom_printf("Configuration error: null filename\n");
283 return FILE_ERR_NOTFOUND;
287 partition = spec->part;
290 DEBUG_F("dev_path = %s\nfile_name = %s\npartition = %d\n",
291 spec->dev, spec->file, partition);
293 /* Find OF device phandle */
294 dev = prom_finddevice(spec->dev);
295 if (dev == PROM_INVALID_HANDLE) {
296 return FILE_ERR_BADDEV;
299 DEBUG_F("dev_phandle = %p\n", dev);
301 /* Check the kind of device */
302 result = prom_getprop(dev, "device_type", temps, 63);
304 prom_printf("can't get <device_type> for device\n");
305 return FILE_ERR_BADDEV;
308 if (!strcmp(temps, "block"))
309 file->device_kind = FILE_DEVICE_BLOCK;
310 else if (!strcmp(temps, "network"))
311 file->device_kind = FILE_DEVICE_NET;
313 prom_printf("Unkown device type <%s>\n", temps);
314 return FILE_ERR_BADDEV;
317 switch(file->device_kind) {
318 case FILE_DEVICE_BLOCK:
319 DEBUG_F("device is a block device\n");
320 return file_block_open(file, spec->dev, spec->file, partition);
321 case FILE_DEVICE_NET:
322 DEBUG_F("device is a network device\n");
323 return file_net_open(file, spec->dev, spec->file);
330 * c-file-style: "K&R"