2 * file.c - Filesystem related interfaces
4 * Copyright (C) 2001, 2002 Ethan Benson
8 * Copyright (C) 2001 Colin Walters
10 * Copyright (C) 1999 Benjamin Herrenschmidt
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 #include "partition.h"
39 extern char bootdevice[1024];
41 static char *netdev_path_to_filename(const char *path)
43 char *tmp, *args, *filename;
46 DEBUG_F("path = %s\n", path);
51 args = strrchr(path, ':');
55 /* The obp-tftp device arguments should be at the end of
56 * the argument list. Skip over any extra arguments (promiscuous,
57 * speed, duplex, bootp, rarp).
60 tmp = strstr(args, "promiscuous");
61 if (tmp && tmp > args)
62 args = tmp + strlen("promiscuous");
64 tmp = strstr(args, "speed=");
65 if (tmp && tmp > args)
66 args = tmp + strlen("speed=");
68 tmp = strstr(args, "duplex=");
69 if (tmp && tmp > args)
70 args = tmp + strlen("duplex=");
72 tmp = strstr(args, "bootp");
73 if (tmp && tmp > args)
74 args = tmp + strlen("bootp");
76 tmp = strstr(args, "rarp");
77 if (tmp && tmp > args)
78 args = tmp + strlen("rarp");
80 args = strchr(args, ',');
86 /* If the preceding character is ':' then there were no
87 * non-obp-tftp arguments and we know we're right up to the
88 * filename. Otherwise, we must advance args once more.
92 args = strchr(args, ',');
98 /* filename may be empty; e.g. enet:192.168.1.1,,192.168.1.2 */
100 DEBUG_F("null filename\n");
104 /* Now see whether there are more args following the filename. */
105 tmp = strchr(args, ',');
107 len = strlen(args) + 1;
109 len = tmp - args + 1;
111 filename = malloc(len);
115 strncpy(filename, args, len);
116 filename[len - 1] = '\0';
118 DEBUG_F("filename = %s\n", filename);
122 static char *netdev_path_to_dev(const char *path)
127 DEBUG_F("path = %s\n", path);
132 tmp = strchr(path, ':');
137 len = tmp - path + 1;
141 strncpy(dev, path, len);
147 /* This function follows the device path in the devtree and separates
148 the device name, partition number, and other datas (mostly file name)
149 the string passed in parameters is changed since 0 are put in place
150 of some separators to terminate the various strings.
152 when a default device is supplied imagepath will be assumed to be a
153 plain filename unless it contains a : otherwise if defaultdev is
154 NULL imagepath will be assumed to be a device path.
156 returns 1 on success 0 on failure.
159 - /pci@80000000/pci-bridge@d/ADPT,2930CU@2/@1:4
160 - /pci@80000000/pci-bridge@d/ADPT,2930CU@2/@1:4,/boot/vmlinux
162 - enet:10.0.0.1,/tftpboot/vmlinux
163 - enet:,/tftpboot/vmlinux
166 Supported only if defdevice == NULL
168 - any other device path lacking a :
169 Unsupported examples:
170 - hd:2,\\:tbxi <- no filename will be detected due to the extra :
171 - enet:192.168.2.1,bootme,c-iaddr,g-iaddr,subnet-mask,bootp-retries,tftp-retries */
174 parse_device_path(char *imagepath, char *defdevice, int defpart,
175 char *deffile, struct boot_fspec_t *result)
188 else if (!(ipath = strdup(imagepath)))
192 defdev = strdup(defdevice);
193 device_kind = prom_get_devtype(defdev);
195 device_kind = prom_get_devtype(ipath);
197 if (device_kind != FILE_DEVICE_NET && strchr(defdev, ':') != NULL) {
198 if ((ptr = strrchr(defdev, ':')) != NULL)
199 *ptr = 0; /* remove trailing : from defdevice if necessary */
202 /* This will not properly handle an obp-tftp argument list
203 * with elements after the filename; that is handled below.
205 if (device_kind != FILE_DEVICE_NET && strchr(ipath, ':') != NULL) {
206 if ((ptr = strrchr(ipath, ',')) != NULL) {
207 char *colon = strrchr(ipath, ':');
208 /* If a ':' occurs *after* a ',', then we assume that there is
210 if (!colon || colon < ptr) {
211 result->file = strdup(ptr+1);
212 /* Trim the filename off */
218 if (device_kind == FILE_DEVICE_NET) {
219 if (strchr(ipath, ':'))
220 result->file = netdev_path_to_filename(ipath);
222 result->file = strdup(ipath);
225 result->dev = netdev_path_to_dev(ipath);
226 } else if ((ptr = strchr(ipath, ':')) != NULL) {
228 result->dev = strdup(ipath);
230 result->part = simple_strtol(ptr+1, NULL, 10);
231 } else if (!defdev) {
232 result->dev = strdup(ipath);
233 } else if (strlen(ipath)) {
234 result->file = strdup(ipath);
240 if (!result->dev && defdev)
241 result->dev = strdup(defdev);
243 if (result->part < 0)
244 result->part = defpart;
247 result->file = strdup(deffile);
257 file_block_open( struct boot_file_t* file,
258 const char* dev_name,
259 const char* file_name,
262 struct partition_t* parts;
263 struct partition_t* p;
264 struct partition_t* found;
266 parts = partitions_lookup(dev_name);
271 prom_printf("partitions:\n");
273 prom_printf("no partitions found.\n");
275 for (p = parts; p && !found; p=p->next) {
276 DEBUG_F("number: %02d, start: 0x%08lx, length: 0x%08lx\n",
277 p->part_number, p->part_start, p->part_size );
278 if (partition == -1) {
279 file->fs = fs_open( file, dev_name, p, file_name );
280 if (file->fs == NULL || fserrorno != FILE_ERR_OK)
283 partition = p->part_number;
287 if ((partition >= 0) && (partition == p->part_number))
291 prom_printf(" (match)\n");
295 /* Note: we don't skip when found is NULL since we can, in some
296 * cases, let OF figure out a default partition.
298 DEBUG_F( "Using OF defaults.. (found = %p)\n", found );
299 file->fs = fs_open( file, dev_name, found, file_name );
303 partitions_free(parts);
309 file_net_open( struct boot_file_t* file,
310 const char* dev_name,
311 const char* file_name)
313 file->fs = fs_of_netboot;
314 return fs_of_netboot->open(file, dev_name, NULL, file_name);
318 default_read( struct boot_file_t* file,
322 prom_printf("WARNING ! default_read called !\n");
327 default_seek( struct boot_file_t* file,
330 prom_printf("WARNING ! default_seek called !\n");
335 default_close( struct boot_file_t* file)
337 prom_printf("WARNING ! default_close called !\n");
341 static struct fs_t fs_default =
351 int open_file(const struct boot_fspec_t* spec, struct boot_file_t* file)
355 memset(file, 0, sizeof(struct boot_file_t*));
356 file->fs = &fs_default;
358 DEBUG_F("dev_path = %s\nfile_name = %s\npartition = %d\n",
359 spec->dev, spec->file, spec->part);
361 result = prom_get_devtype(spec->dev);
363 file->device_kind = result;
367 switch(file->device_kind) {
368 case FILE_DEVICE_BLOCK:
369 DEBUG_F("device is a block device\n");
370 return file_block_open(file, spec->dev, spec->file, spec->part);
371 case FILE_DEVICE_NET:
372 DEBUG_F("device is a network device\n");
373 return file_net_open(file, spec->dev, spec->file);
380 * c-file-style: "k&r"