From patchwork Tue Sep 16 00:23:39 2008 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chandra Seetharaman X-Patchwork-Id: 22973 Return-Path: X-Original-To: yaboot-devel@ozlabs.org Delivered-To: yaboot-devel@ozlabs.org Received: from e33.co.us.ibm.com (e33.co.us.ibm.com [32.97.110.151]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "e33.co.us.ibm.com", Issuer "Equifax" (verified OK)) by ozlabs.org (Postfix) with ESMTPS id BAEB9DDEEA for ; Tue, 16 Sep 2008 10:24:21 +1000 (EST) Received: from d03relay02.boulder.ibm.com (d03relay02.boulder.ibm.com [9.17.195.227]) by e33.co.us.ibm.com (8.13.8/8.13.8) with ESMTP id m8G0OIVe015176 for ; Mon, 15 Sep 2008 20:24:18 -0400 Received: from d03av02.boulder.ibm.com (d03av02.boulder.ibm.com [9.17.195.168]) by d03relay02.boulder.ibm.com (8.13.8/8.13.8/NCO v9.1) with ESMTP id m8G0OI2q197412 for ; Mon, 15 Sep 2008 18:24:18 -0600 Received: from d03av02.boulder.ibm.com (loopback [127.0.0.1]) by d03av02.boulder.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id m8G6OIWs027106 for ; Tue, 16 Sep 2008 00:24:18 -0600 Received: from [127.0.1.1] (chandra-ubuntu.beaverton.ibm.com [9.47.17.98]) by d03av02.boulder.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id m8G6OH15027079; Tue, 16 Sep 2008 00:24:17 -0600 From: Chandra Seetharaman To: yaboot devel Date: Mon, 15 Sep 2008 17:23:39 -0700 Message-Id: <20080916002339.21364.76870.sendpatchset@chandra-ubuntu> In-Reply-To: <20080916002327.21364.99723.sendpatchset@chandra-ubuntu> References: <20080916002327.21364.99723.sendpatchset@chandra-ubuntu> Subject: [PATCH 2/4] handle arguments for ipv4 boot X-BeenThere: yaboot-devel@ozlabs.org X-Mailman-Version: 2.1.11 Precedence: list List-Id: Technical and development discussion regarding yaboot List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 16 Sep 2008 00:24:22 -0000 Currently, yaboot works properly when there is a tftp boot server serving the broadcast requests sent in the network. If the user specifies siaddr, ciaddr, and other arguments in the command line, it is not handled appropriately. This patch changes that behavior and make yaboot work properly in both cases. The semantics specified in section 4.1 of http://playground.sun.com/1275/practice/obp-tftp/tftp1_0.pdf is followed. ([bootp,]siaddr,filename,ciaddr,giaddr,bootp-retries,tftp-retries) Signed-off-by: Chandra Seetharaman --- include/file.h | 6 +++ second/file.c | 125 +++++++++++++++++++++++++++++++++++--------------------- second/fs_of.c | 23 ++++++++-- second/yaboot.c | 4 ++ 4 files changed, 107 insertions(+), 51 deletions(-) Index: yaboot.git_head/include/file.h =================================================================== --- yaboot.git_head.orig/include/file.h +++ yaboot.git_head/include/file.h @@ -39,7 +39,13 @@ struct boot_file_t; struct boot_fspec_t { char* dev; /* OF device path */ int part; /* Partition number or -1 */ + char* siaddr; /* Server address */ char* file; /* File path */ + char* ciaddr; /* Client address */ + char* giaddr; /* Gateway address */ + char* bootp_retries; /* Bootp retries */ + char* tftp_retries; /* TFTP retries */ + char* addl_params; /* copy all additional parameters */ }; struct boot_file_t { Index: yaboot.git_head/second/file.c =================================================================== --- yaboot.git_head.orig/second/file.c +++ yaboot.git_head/second/file.c @@ -38,19 +38,48 @@ extern char bootdevice[]; -static char *netdev_path_to_filename(const char *path) +/* + * Copy the string from source to dest till newline or comma(,) is seen + * in the source. + * Move source and dest pointers respectively. + * Returns pointer to the start of the string that has just been copied. + */ +static char * +scopy(char **dest, char **source) { - char *tmp, *args, *filename; - size_t len; - - DEBUG_F("path = %s\n", path); + char *ret = *dest; - if (!path) + if (!**source) return NULL; - args = strrchr(path, ':'); + while (**source != ',' && **source != '\0') + *(*dest)++ = *(*source)++; + if (**source != '\0') + *(*source)++; + **dest = '\0'; + *(*dest)++; + return ret; +} + +/* + * Extract all the arguments provided in the imagepath and fill it in result. + * Returns 1 on success, 0 on failure. + */ +static int +extract_args_from_netdev_path(char *imagepath, struct boot_fspec_t *result) +{ + char *tmp, *args, *str, *start; + + DEBUG_F("imagepath = %s\n", imagepath); + + if (!imagepath) + return 1; + + args = strrchr(imagepath, ':'); if (!args) - return NULL; + return 1; + + start = args; /* used to see if we read any optional parameters */ /* The obp-tftp device arguments should be at the end of * the argument list. Skip over any extra arguments (promiscuous, @@ -77,46 +106,42 @@ static char *netdev_path_to_filename(con 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 != ':') { + if (args != start) /* we read some parameters, so go past the next comma(,) */ 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; - } + if (!args) + return 1; - /* Now see whether there are more args following the filename. */ - tmp = strchr(args, ','); - if (!tmp) - len = strlen(args) + 1; - else - len = tmp - args + 1; + str = malloc(strlen(args) + 1); /*long enough to hold all strings */ + if (!str) + return 0; - filename = malloc(len); - if (!filename) - return NULL; + if (args[-1] != ':') + args++; /* If comma(,) is not immediately followed by ':' then go past the , */ - strncpy(filename, args, len); - filename[len - 1] = '\0'; + /* + * read the arguments in order: siaddr,filename,ciaddr,giaddr, + * bootp-retries,tftp-retries,addl_prameters + */ + result->siaddr = scopy(&str, &args); + result->file = scopy(&str, &args); + result->ciaddr = scopy(&str, &args); + result->giaddr = scopy(&str, &args); + result->bootp_retries = scopy(&str, &args); + result->tftp_retries = scopy(&str, &args); + if (*args) { + result->addl_params = strdup(args); + if (!result->addl_params) + return 0; + } - DEBUG_F("filename = %s\n", filename); - return filename; + DEBUG_F("siaddr = <%s>\n", result->siaddr); + DEBUG_F("file = <%s>\n", result->file); + DEBUG_F("ciaddr = <%s>\n", result->ciaddr); + DEBUG_F("giaddr = <%s>\n", result->giaddr); + DEBUG_F("bootp_retries = <%s>\n", result->bootp_retries); + DEBUG_F("tftp_retries = <%s>\n", result->tftp_retries); + DEBUG_F("addl_params = <%s>\n", result->addl_params); + return 1; } static char *netdev_path_to_dev(const char *path) @@ -163,6 +188,10 @@ static char *netdev_path_to_dev(const ch - enet:,/tftpboot/vmlinux - enet:bootp - enet:0 + - arguments for obp-tftp open as specified in section 4.1 of + http://playground.sun.com/1275/practice/obp-tftp/tftp1_0.pdf + [bootp,]siaddr,filename,ciaddr,giaddr,bootp-retries,tftp-retries + ex: enet:bootp,10.0.0.11,bootme,10.0.0.12,10.0.0.1,5,5 Supported only if defdevice == NULL - disc - any other device path lacking a : @@ -179,6 +208,9 @@ parse_device_path(char *imagepath, char char *defdev = NULL; int device_kind = -1; + DEBUG_F("imagepath = %s; defdevice %s; defpart %d, deffile %s\n", + imagepath, defdevice, defpart, deffile); + result->dev = NULL; result->part = -1; result->file = NULL; @@ -247,9 +279,10 @@ parse_device_path(char *imagepath, char } if (device_kind == FILE_DEVICE_NET) { - if (strchr(ipath, ':')) - result->file = netdev_path_to_filename(ipath); - else + if (strchr(ipath, ':')) { + if (extract_args_from_netdev_path(ipath, result) == 0) + return 0; + } else result->file = strdup(ipath); if (!defdev) Index: yaboot.git_head/second/fs_of.c =================================================================== --- yaboot.git_head.orig/second/fs_of.c +++ yaboot.git_head/second/fs_of.c @@ -135,23 +135,36 @@ of_net_open(struct boot_file_t* file, struct partition_t* part, struct boot_fspec_t* fspec) { static char buffer[1024]; - char *filename; + char *filename = NULL; char *p; DEBUG_ENTER; DEBUG_OPEN; - strncpy(buffer, fspec->dev, 768); if (fspec->file && strlen(fspec->file)) { - strcat(buffer, ","); filename = strdup(fspec->file); for (p = filename; *p; p++) if (*p == '/') *p = '\\'; - strcat(buffer, filename); - free(filename); } + DEBUG_F("siaddr <%s>; filename <%s>; ciaddr <%s>; giaddr <%s>;\n", + fspec->siaddr, filename, fspec->ciaddr, fspec->giaddr); + strncpy(buffer, fspec->dev, 768); + strcat(buffer, fspec->siaddr); + strcat(buffer, ","); + strcat(buffer, filename); + strcat(buffer, ","); + strcat(buffer, fspec->ciaddr); + strcat(buffer, ","); + strcat(buffer, fspec->giaddr); + strcat(buffer, ","); + strcat(buffer, fspec->bootp_retries); + strcat(buffer, ","); + strcat(buffer, fspec->tftp_retries); + strcat(buffer, ","); + strcat(buffer, fspec->addl_params); + DEBUG_F("Opening: \"%s\"\n", buffer); file->of_device = prom_open(buffer); Index: yaboot.git_head/second/yaboot.c =================================================================== --- yaboot.git_head.orig/second/yaboot.c +++ yaboot.git_head/second/yaboot.c @@ -300,6 +300,7 @@ void print_message_file(char *filename) } strncpy(msgpath, filename, sizeof(msgpath)); + msgfile = boot; /* Copy all the original paramters */ if (!parse_device_path(msgpath, defdev, defpart, "/etc/yaboot.msg", &msgfile)) { prom_printf("%s: Unable to parse\n", msgpath); goto done; @@ -990,6 +991,7 @@ int get_params(struct boot_param_t* para if (!label && password) check_password ("To boot a custom image you must enter the password."); + params->kernel = boot; /* Copy all the original paramters */ if (!parse_device_path(imagepath, defdevice, defpart, "/vmlinux", ¶ms->kernel)) { prom_printf("%s: Unable to parse\n", imagepath); @@ -1011,6 +1013,7 @@ int get_params(struct boot_param_t* para strncpy(initrdpath, p, 1024); DEBUG_F("Parsing initrd path <%s>\n", initrdpath); + params->rd = boot; /* Copy all the original paramters */ if (!parse_device_path(initrdpath, defdevice, defpart, "/root.bin", ¶ms->rd)) { prom_printf("%s: Unable to parse\n", imagepath); @@ -1021,6 +1024,7 @@ int get_params(struct boot_param_t* para if (p && *p) { DEBUG_F("Parsing sysmap path <%s>\n", p); strncpy(sysmappath, p, 1024); + params->sysmap = boot; /* Copy all the original paramters */ if (!parse_device_path(sysmappath, defdevice, defpart, "/boot/System.map", ¶ms->sysmap)) { prom_printf("%s: Unable to parse\n", imagepath);