X-Git-Url: http://git.ozlabs.org/?p=yaboot.git;a=blobdiff_plain;f=second%2Ffile.c;h=b5763a235f6d5db62ad5fb1b4c92254b89775270;hp=3c98be1e7f46bd16a89b0dc915c9bd4f2afe173d;hb=e80797f9e8b7a05aeb239ca9087ba57e7641a231;hpb=da7857367944c983abf98f956241dcc614b2f453 diff --git a/second/file.c b/second/file.c index 3c98be1..b5763a2 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" @@ -33,33 +41,70 @@ extern char bootdevice[1024]; /* 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 - of some separators to terminate the various strings - */ + of some separators to terminate the various strings. + + when a default device is supplied imagepath will be assumed to be a + plain filename unless it contains a : otherwise if defaultdev is + NULL imagepath will be assumed to be a device path. + + returns 1 on success 0 on failure. + + Supported examples: + - /pci@80000000/pci-bridge@d/ADPT,2930CU@2/@1:4 + - /pci@80000000/pci-bridge@d/ADPT,2930CU@2/@1:4,/boot/vmlinux + - hd:3,/boot/vmlinux + - enet:10.0.0.1,/tftpboot/vmlinux + - enet:,/tftpboot/vmlinux + - enet:bootp + - enet:0 + Supported only if defdevice == NULL + - disc + - any other device path lacking a : + Unsupported examples: + - hd:2,\\:tbxi <- no filename will be detected due to the extra : + - enet:192.168.2.1,bootme,c-iaddr,g-iaddr,subnet-mask,bootp-retries,tftp-retries */ int parse_device_path(char *imagepath, char *defdevice, int defpart, char *deffile, struct boot_fspec_t *result) { char *ptr; - char *ipath = strdup(imagepath); - char *defdev = strdup(defdevice); + char *ipath = NULL; + char *defdev = NULL; result->dev = NULL; result->part = -1; result->file = NULL; - if (!strstr(defdev, "ethernet") && !strstr(defdev, "enet")) { - if ((ptr = strrchr(defdev, ':')) != NULL) - *ptr = 0; /* remove trailing : from defdevice if necessary */ + if (!imagepath) + return 0; + else + ipath = strdup(imagepath); + + if (defdevice) + defdev = strdup(defdevice); + + if (defdev) { + if (!strstr(defdev, "ethernet") && !strstr(defdev, "enet")) { + if ((ptr = strrchr(defdev, ':')) != NULL) + *ptr = 0; /* remove trailing : from defdevice if necessary */ + } } - if (!imagepath) - goto punt; + /* if there is no : then there is no filename or partition. must + use strrchr() since enet:,10.0.0.1,file is legal */ - if ((ptr = strrchr(ipath, ',')) != NULL) { - result->file = strdup(ptr+1); - /* Trim the filename off */ - *ptr = 0; + if (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")) @@ -73,14 +118,15 @@ parse_device_path(char *imagepath, char *defdevice, int defpart, result->dev = strdup(ipath); if (*(ptr+1)) result->part = simple_strtol(ptr+1, NULL, 10); + } else if (!defdev) { + result->dev = strdup(ipath); } else if (strlen(ipath)) { result->file = strdup(ipath); } else { return 0; } - -punt: - if (!result->dev) + + if (!result->dev && defdev) result->dev = strdup(defdev); if (result->part < 0) @@ -88,7 +134,10 @@ punt: if (!result->file) result->file = strdup(deffile); + free(ipath); + if (defdev) + free(defdev); return 1; } @@ -117,8 +166,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; @@ -134,7 +187,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);