/* 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)
- goto punt;
+ 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 ((ptr = strrchr(ipath, ',')) != NULL) {
- result->file = strdup(ptr+1);
- /* Trim the filename off */
- *ptr = 0;
+ 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"))
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)
if (!result->file)
result->file = strdup(deffile);
+
free(ipath);
+ if (defdev)
+ free(defdev);
return 1;
}