X-Git-Url: http://git.ozlabs.org/?p=yaboot.git;a=blobdiff_plain;f=second%2Ffile.c;h=8f86a6eaefb0b11e685ae5831bfd799617a59ba3;hp=b88706977b7dad3b54db7ebc95ecb647c6dd81d2;hb=c864c0961c4405bda1179fa4dc438fad3005e119;hpb=678d83ff8608534ece0f1e912eddedef4f0bb67a diff --git a/second/file.c b/second/file.c index b887069..8f86a6e 100644 --- a/second/file.c +++ b/second/file.c @@ -1,20 +1,28 @@ -/* File related stuff - - Copyright (C) 1999 Benjamin Herrenschmidt - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* + * file.c - Filesystem related interfaces + * + * Copyright (C) 2001, 2002 Ethan Benson + * + * parse_device_path() + * + * Copyright (C) 2001 Colin Walters + * + * Copyright (C) 1999 Benjamin Herrenschmidt + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ #include "ctype.h" #include "types.h" @@ -30,6 +38,112 @@ extern char bootdevice[1024]; +static char *netdev_path_to_filename(const char *path) +{ + char *tmp, *args, *filename; + size_t len; + + DEBUG_F("path = %s\n", path); + + if (!path) + return NULL; + + args = strrchr(path, ':'); + if (!args) + return NULL; + + /* The obp-tftp device arguments should be at the end of + * the argument list. Skip over any extra arguments (promiscuous, + * speed, duplex, bootp, rarp). + */ + + tmp = strstr(args, "promiscuous"); + if (tmp && tmp > args) + args = tmp + strlen("promiscuous"); + + tmp = strstr(args, "speed="); + if (tmp && tmp > args) + args = tmp + strlen("speed="); + + tmp = strstr(args, "duplex="); + if (tmp && tmp > args) + args = tmp + strlen("duplex="); + + tmp = strstr(args, "bootp"); + if (tmp && tmp > args) + args = tmp + strlen("bootp"); + + tmp = strstr(args, "rarp"); + if (tmp && tmp > args) + args = tmp + strlen("rarp"); + + args = strchr(args, ','); + if (!args) + return NULL; + + tmp = args; + tmp--; + /* If the preceding character is ':' then there were no + * non-obp-tftp arguments and we know we're right up to the + * filename. Otherwise, we must advance args once more. + */ + args++; + if (*tmp != ':') { + args = strchr(args, ','); + if (!args) + return NULL; + args++; + } + + /* filename may be empty; e.g. enet:192.168.1.1,,192.168.1.2 */ + if (*args == ',') { + DEBUG_F("null filename\n"); + return NULL; + } + + /* Now see whether there are more args following the filename. */ + tmp = strchr(args, ','); + if (!tmp) + len = strlen(args) + 1; + else + len = tmp - args + 1; + + filename = malloc(len); + if (!filename) + return NULL; + + strncpy(filename, args, len); + filename[len - 1] = '\0'; + + DEBUG_F("filename = %s\n", filename); + return filename; +} + +static char *netdev_path_to_dev(const char *path) +{ + char *dev, *tmp; + size_t len; + + DEBUG_F("path = %s\n", path); + + if (!path) + return NULL; + + tmp = strchr(path, ':'); + if (!tmp) + return strdup(path); + tmp++; + + len = tmp - path + 1; + + dev = malloc(len); + if (dev) { + strncpy(dev, path, len); + dev[len - 1] = '\0'; + } + return dev; +} + /* This function follows the device path in the devtree and separates the device name, partition number, and other datas (mostly file name) the string passed in parameters is changed since 0 are put in place @@ -63,6 +177,7 @@ parse_device_path(char *imagepath, char *defdevice, int defpart, char *ptr; char *ipath = NULL; char *defdev = NULL; + int device_kind; result->dev = NULL; result->part = -1; @@ -70,37 +185,45 @@ parse_device_path(char *imagepath, char *defdevice, int defpart, if (!imagepath) return 0; - else - ipath = strdup(imagepath); + else if (!(ipath = strdup(imagepath))) + return 0; - if (defdevice) + if (defdevice) { defdev = strdup(defdevice); + device_kind = prom_get_devtype(defdev); + } else + device_kind = prom_get_devtype(ipath); - if (defdev) { - if (!strstr(defdev, "ethernet") && !strstr(defdev, "enet")) { - if ((ptr = strrchr(defdev, ':')) != NULL) - *ptr = 0; /* remove trailing : from defdevice if necessary */ - } + if (device_kind != FILE_DEVICE_NET && strchr(defdev, ':') != NULL) { + if ((ptr = strrchr(defdev, ':')) != NULL) + *ptr = 0; /* remove trailing : from defdevice if necessary */ } - if ((ptr = strrchr(ipath, ',')) != NULL) { - char *colon = strrchr(ipath, ':'); - /* If a ':' occurs *after* a ',', then we assume that there is - no filename */ - if (!colon || colon < ptr) { - result->file = strdup(ptr+1); - /* Trim the filename off */ - *ptr = 0; + /* This will not properly handle an obp-tftp argument list + * with elements after the filename; that is handled below. + */ + if (device_kind != FILE_DEVICE_NET && strchr(ipath, ':') != NULL) { + if ((ptr = strrchr(ipath, ',')) != NULL) { + char *colon = strrchr(ipath, ':'); + /* If a ':' occurs *after* a ',', then we assume that there is + no filename */ + if (!colon || colon < ptr) { + result->file = strdup(ptr+1); + /* Trim the filename off */ + *ptr = 0; + } } } - if (strstr(ipath, "ethernet") || strstr(ipath, "enet")) - if ((ptr = strstr(ipath, "bootp")) != NULL) { /* `n' key booting boots enet:bootp */ - *ptr = 0; - result->dev = strdup(ipath); - } else - result->dev = strdup(ipath); - else if ((ptr = strchr(ipath, ':')) != NULL) { + if (device_kind == FILE_DEVICE_NET) { + if (strchr(ipath, ':')) + result->file = netdev_path_to_filename(ipath); + else + result->file = strdup(ipath); + + if (!defdev) + result->dev = netdev_path_to_dev(ipath); + } else if ((ptr = strchr(ipath, ':')) != NULL) { *ptr = 0; result->dev = strdup(ipath); if (*(ptr+1)) @@ -110,6 +233,7 @@ parse_device_path(char *imagepath, char *defdevice, int defpart, } else if (strlen(ipath)) { result->file = strdup(ipath); } else { + free(defdev); return 0; } @@ -124,7 +248,7 @@ parse_device_path(char *imagepath, char *defdevice, int defpart, free(ipath); if (defdev) - free(defdev); + free(defdev); return 1; } @@ -153,8 +277,12 @@ file_block_open( struct boot_file_t* file, p->part_number, p->part_start, p->part_size ); if (partition == -1) { file->fs = fs_open( file, dev_name, p, file_name ); - if (file->fs != NULL) - goto bail; + if (file->fs == NULL || fserrorno != FILE_ERR_OK) + continue; + else { + partition = p->part_number; + goto done; + } } if ((partition >= 0) && (partition == p->part_number)) found = p; @@ -170,7 +298,7 @@ file_block_open( struct boot_file_t* file, DEBUG_F( "Using OF defaults.. (found = %p)\n", found ); file->fs = fs_open( file, dev_name, found, file_name ); -bail: +done: if (parts) partitions_free(parts);