diff options
| author | Tom Rini <trini@ti.com> | 2013-06-24 22:27:44 -0400 | 
|---|---|---|
| committer | Tom Rini <trini@ti.com> | 2013-06-24 22:27:44 -0400 | 
| commit | ca85eb8c4271509aaac1ccb26ae3eb1a7827b4e6 (patch) | |
| tree | 1532b13194c3d7daa8f1f10f3263fb806911cd67 /common/cmd_pxe.c | |
| parent | 4e78e0317d3aab42c381b01033a0cd869ea28979 (diff) | |
| parent | 433a2c5325b982b49b099e526d373d07d0cc5e97 (diff) | |
| download | olio-uboot-2014.01-ca85eb8c4271509aaac1ccb26ae3eb1a7827b4e6.tar.xz olio-uboot-2014.01-ca85eb8c4271509aaac1ccb26ae3eb1a7827b4e6.zip | |
Merge branch 'master' of git://git.denx.de/u-boot-net
Diffstat (limited to 'common/cmd_pxe.c')
| -rw-r--r-- | common/cmd_pxe.c | 221 | 
1 files changed, 136 insertions, 85 deletions
| diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c index 2dbd49cbd..1fb75d8ae 100644 --- a/common/cmd_pxe.c +++ b/common/cmd_pxe.c @@ -26,12 +26,21 @@  #define MAX_TFTP_PATH_LEN 127 +const char *pxe_default_paths[] = { +#ifdef CONFIG_SYS_SOC +	"default-" CONFIG_SYS_ARCH "-" CONFIG_SYS_SOC, +#endif +	"default-" CONFIG_SYS_ARCH, +	"default", +	NULL +}; +  /*   * Like getenv, but prints an error if envvar isn't defined in the   * environment.  It always returns what getenv does, so it can be used in   * place of getenv without changing error handling otherwise.   */ -static char *from_env(char *envvar) +static char *from_env(const char *envvar)  {  	char *ret; @@ -55,37 +64,21 @@ static char *from_env(char *envvar)   */  static int format_mac_pxe(char *outbuf, size_t outbuf_len)  { -	size_t ethaddr_len; -	char *p, *ethaddr; - -	ethaddr = from_env("ethaddr"); +	uchar ethaddr[6]; -	if (!ethaddr) -		return -ENOENT; - -	ethaddr_len = strlen(ethaddr); - -	/* -	 * ethaddr_len + 4 gives room for "01-", ethaddr, and a NUL byte at -	 * the end. -	 */ -	if (outbuf_len < ethaddr_len + 4) { -		printf("outbuf is too small (%d < %d)\n", -				outbuf_len, ethaddr_len + 4); +	if (outbuf_len < 21) { +		printf("outbuf is too small (%d < 21)\n", outbuf_len);  		return -EINVAL;  	} -	strcpy(outbuf, "01-"); - -	for (p = outbuf + 3; *ethaddr; ethaddr++, p++) { -		if (*ethaddr == ':') -			*p = '-'; -		else -			*p = tolower(*ethaddr); -	} +	if (!eth_getenv_enetaddr_by_index("eth", eth_get_dev_index(), +					  ethaddr)) +		return -ENOENT; -	*p = '\0'; +	sprintf(outbuf, "01-%02x-%02x-%02x-%02x-%02x-%02x", +		ethaddr[0], ethaddr[1], ethaddr[2], +		ethaddr[3], ethaddr[4], ethaddr[5]);  	return 1;  } @@ -131,14 +124,14 @@ static int get_bootfile_path(const char *file_path, char *bootfile_path,  	return 1;  } -static int (*do_getfile)(char *file_path, char *file_addr); +static int (*do_getfile)(const char *file_path, char *file_addr); -static int do_get_tftp(char *file_path, char *file_addr) +static int do_get_tftp(const char *file_path, char *file_addr)  {  	char *tftp_argv[] = {"tftp", NULL, NULL, NULL};  	tftp_argv[1] = file_addr; -	tftp_argv[2] = file_path; +	tftp_argv[2] = (void *)file_path;  	if (do_tftpb(NULL, 0, 3, tftp_argv))  		return -ENOENT; @@ -148,12 +141,12 @@ static int do_get_tftp(char *file_path, char *file_addr)  static char *fs_argv[5]; -static int do_get_ext2(char *file_path, char *file_addr) +static int do_get_ext2(const char *file_path, char *file_addr)  {  #ifdef CONFIG_CMD_EXT2  	fs_argv[0] = "ext2load";  	fs_argv[3] = file_addr; -	fs_argv[4] = file_path; +	fs_argv[4] = (void *)file_path;  	if (!do_ext2load(NULL, 0, 5, fs_argv))  		return 1; @@ -161,12 +154,12 @@ static int do_get_ext2(char *file_path, char *file_addr)  	return -ENOENT;  } -static int do_get_fat(char *file_path, char *file_addr) +static int do_get_fat(const char *file_path, char *file_addr)  {  #ifdef CONFIG_CMD_FAT  	fs_argv[0] = "fatload";  	fs_argv[3] = file_addr; -	fs_argv[4] = file_path; +	fs_argv[4] = (void *)file_path;  	if (!do_fat_fsload(NULL, 0, 5, fs_argv))  		return 1; @@ -182,7 +175,7 @@ static int do_get_fat(char *file_path, char *file_addr)   *   * Returns 1 for success, or < 0 on error.   */ -static int get_relfile(char *file_path, void *file_addr) +static int get_relfile(const char *file_path, void *file_addr)  {  	size_t path_len;  	char relfile[MAX_TFTP_PATH_LEN+1]; @@ -221,7 +214,7 @@ static int get_relfile(char *file_path, void *file_addr)   *   * Returns 1 on success, or < 0 for error.   */ -static int get_pxe_file(char *file_path, void *file_addr) +static int get_pxe_file(const char *file_path, void *file_addr)  {  	unsigned long config_file_size;  	char *tftp_filesize; @@ -258,7 +251,7 @@ static int get_pxe_file(char *file_path, void *file_addr)   *   * Returns 1 on success or < 0 on error.   */ -static int get_pxelinux_path(char *file, void *pxefile_addr_r) +static int get_pxelinux_path(const char *file, void *pxefile_addr_r)  {  	size_t base_len = strlen(PXELINUX_DIR);  	char path[MAX_TFTP_PATH_LEN+1]; @@ -355,7 +348,7 @@ do_pxe_get(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  {  	char *pxefile_addr_str;  	unsigned long pxefile_addr_r; -	int err; +	int err, i = 0;  	do_getfile = do_get_tftp; @@ -376,16 +369,23 @@ do_pxe_get(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  	 * Keep trying paths until we successfully get a file we're looking  	 * for.  	 */ -	if (pxe_uuid_path((void *)pxefile_addr_r) > 0 -		|| pxe_mac_path((void *)pxefile_addr_r) > 0 -		|| pxe_ipaddr_paths((void *)pxefile_addr_r) > 0 -		|| get_pxelinux_path("default", (void *)pxefile_addr_r) > 0) { - +	if (pxe_uuid_path((void *)pxefile_addr_r) > 0 || +	    pxe_mac_path((void *)pxefile_addr_r) > 0 || +	    pxe_ipaddr_paths((void *)pxefile_addr_r) > 0) {  		printf("Config file found\n");  		return 0;  	} +	while (pxe_default_paths[i]) { +		if (get_pxelinux_path(pxe_default_paths[i], +				      (void *)pxefile_addr_r) > 0) { +			printf("Config file found\n"); +			return 0; +		} +		i++; +	} +  	printf("Config file not found\n");  	return 1; @@ -398,7 +398,7 @@ do_pxe_get(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])   *   * Returns 1 on success or < 0 on error.   */ -static int get_relfile_envaddr(char *file_path, char *envaddr_name) +static int get_relfile_envaddr(const char *file_path, const char *envaddr_name)  {  	unsigned long file_addr;  	char *envaddr; @@ -445,14 +445,17 @@ static int get_relfile_envaddr(char *file_path, char *envaddr_name)   * list - lets these form a list, which a pxe_menu struct will hold.   */  struct pxe_label { +	char num[4];  	char *name;  	char *menu;  	char *kernel;  	char *append;  	char *initrd;  	char *fdt; +	int ipappend;  	int attempted;  	int localboot; +	int localboot_val;  	struct list_head list;  }; @@ -533,21 +536,9 @@ static void label_destroy(struct pxe_label *label)  static void label_print(void *data)  {  	struct pxe_label *label = data; -	const char *c = label->menu ? label->menu : label->kernel; - -	printf("%s:\t%s\n", label->name, c); - -	if (label->kernel) -		printf("\t\tkernel: %s\n", label->kernel); - -	if (label->append) -		printf("\t\tappend: %s\n", label->append); +	const char *c = label->menu ? label->menu : label->name; -	if (label->initrd) -		printf("\t\tinitrd: %s\n", label->initrd); - -	if (label->fdt) -		printf("\tfdt: %s\n", label->fdt); +	printf("%s:\t%s\n", label->num, c);  }  /* @@ -591,34 +582,43 @@ static int label_localboot(struct pxe_label *label)   * If the label specifies an 'append' line, its contents will overwrite that   * of the 'bootargs' environment variable.   */ -static void label_boot(struct pxe_label *label) +static int label_boot(struct pxe_label *label)  {  	char *bootm_argv[] = { "bootm", NULL, NULL, NULL, NULL }; +	char initrd_str[22]; +	char mac_str[29] = ""; +	char ip_str[68] = ""; +	char *bootargs;  	int bootm_argc = 3; +	int len = 0;  	label_print(label);  	label->attempted = 1;  	if (label->localboot) { -		label_localboot(label); -		return; +		if (label->localboot_val >= 0) +			label_localboot(label); +		return 0;  	}  	if (label->kernel == NULL) {  		printf("No kernel given, skipping %s\n",  				label->name); -		return; +		return 1;  	}  	if (label->initrd) {  		if (get_relfile_envaddr(label->initrd, "ramdisk_addr_r") < 0) {  			printf("Skipping %s for failure retrieving initrd\n",  					label->name); -			return; +			return 1;  		} -		bootm_argv[2] = getenv("ramdisk_addr_r"); +		bootm_argv[2] = initrd_str; +		strcpy(bootm_argv[2], getenv("ramdisk_addr_r")); +		strcat(bootm_argv[2], ":"); +		strcat(bootm_argv[2], getenv("filesize"));  	} else {  		bootm_argv[2] = "-";  	} @@ -626,11 +626,43 @@ static void label_boot(struct pxe_label *label)  	if (get_relfile_envaddr(label->kernel, "kernel_addr_r") < 0) {  		printf("Skipping %s for failure retrieving kernel\n",  				label->name); -		return; +		return 1; +	} + +	if (label->ipappend & 0x1) { +		sprintf(ip_str, " ip=%s:%s:%s:%s", +			getenv("ipaddr"), getenv("serverip"), +			getenv("gatewayip"), getenv("netmask")); +		len += strlen(ip_str); +	} + +	if (label->ipappend & 0x2) { +		int err; +		strcpy(mac_str, " BOOTIF="); +		err = format_mac_pxe(mac_str + 8, sizeof(mac_str) - 8); +		if (err < 0) +			mac_str[0] = '\0'; +		len += strlen(mac_str);  	}  	if (label->append) -		setenv("bootargs", label->append); +		len += strlen(label->append); + +	if (len) { +		bootargs = malloc(len + 1); +		if (!bootargs) +			return 1; +		bootargs[0] = '\0'; +		if (label->append) +			strcpy(bootargs, label->append); +		strcat(bootargs, ip_str); +		strcat(bootargs, mac_str); + +		setenv("bootargs", bootargs); +		printf("append: %s\n", bootargs); + +		free(bootargs); +	}  	bootm_argv[1] = getenv("kernel_addr_r"); @@ -654,7 +686,7 @@ static void label_boot(struct pxe_label *label)  		if (get_relfile_envaddr(label->fdt, "fdt_addr_r") < 0) {  			printf("Skipping %s for failure retrieving fdt\n",  					label->name); -			return; +			return 1;  		}  	} else  		bootm_argv[3] = getenv("fdt_addr"); @@ -663,6 +695,12 @@ static void label_boot(struct pxe_label *label)  		bootm_argc = 4;  	do_bootm(NULL, 0, bootm_argc, bootm_argv); + +#ifdef CONFIG_CMD_BOOTZ +	/* Try booting a zImage if do_bootm returns */ +	do_bootz(NULL, 0, bootm_argc, bootm_argv); +#endif +	return 1;  }  /* @@ -685,6 +723,8 @@ enum token_type {  	T_PROMPT,  	T_INCLUDE,  	T_FDT, +	T_ONTIMEOUT, +	T_IPAPPEND,  	T_INVALID  }; @@ -713,6 +753,8 @@ static const struct token keywords[] = {  	{"initrd", T_INITRD},  	{"include", T_INCLUDE},  	{"fdt", T_FDT}, +	{"ontimeout", T_ONTIMEOUT,}, +	{"ipappend", T_IPAPPEND,},  	{NULL, T_INVALID}  }; @@ -903,7 +945,6 @@ static int parse_integer(char **c, int *dst)  {  	struct token t;  	char *s = *c; -	unsigned long temp;  	get_token(c, &t, L_SLITERAL); @@ -912,12 +953,7 @@ static int parse_integer(char **c, int *dst)  		return -EINVAL;  	} -	if (strict_strtoul(t.val, 10, &temp) < 0) { -		printf("Expected unsigned integer: %s\n", t.val); -		return -EINVAL; -	} - -	*dst = (int)temp; +	*dst = simple_strtol(t.val, NULL, 10);  	free(t.val); @@ -1016,10 +1052,8 @@ static int parse_label_menu(char **c, struct pxe_menu *cfg,  	switch (t.type) {  	case T_DEFAULT: -		if (cfg->default_label) -			free(cfg->default_label); - -		cfg->default_label = strdup(label->name); +		if (!cfg->default_label) +			cfg->default_label = strdup(label->name);  		if (!cfg->default_label)  			return -ENOMEM; @@ -1108,7 +1142,12 @@ static int parse_label(char **c, struct pxe_menu *cfg)  			break;  		case T_LOCALBOOT: -			err = parse_integer(c, &label->localboot); +			label->localboot = 1; +			err = parse_integer(c, &label->localboot_val); +			break; + +		case T_IPAPPEND: +			err = parse_integer(c, &label->ipappend);  			break;  		case T_EOL: @@ -1164,6 +1203,7 @@ static int parse_pxefile_top(char *p, struct pxe_menu *cfg, int nest_level)  		err = 0;  		switch (t.type) {  		case T_MENU: +			cfg->prompt = 1;  			err = parse_menu(&p, cfg, b, nest_level);  			break; @@ -1176,6 +1216,7 @@ static int parse_pxefile_top(char *p, struct pxe_menu *cfg, int nest_level)  			break;  		case T_DEFAULT: +		case T_ONTIMEOUT:  			err = parse_sliteral(&p, &label_name);  			if (label_name) { @@ -1193,7 +1234,7 @@ static int parse_pxefile_top(char *p, struct pxe_menu *cfg, int nest_level)  			break;  		case T_PROMPT: -			err = parse_integer(&p, &cfg->prompt); +			eol_or_eof(&p);  			break;  		case T_EOL: @@ -1276,6 +1317,8 @@ static struct menu *pxe_menu_to_menu(struct pxe_menu *cfg)  	struct list_head *pos;  	struct menu *m;  	int err; +	int i = 1; +	char *default_num = NULL;  	/*  	 * Create a menu and add items for all the labels. @@ -1289,18 +1332,23 @@ static struct menu *pxe_menu_to_menu(struct pxe_menu *cfg)  	list_for_each(pos, &cfg->labels) {  		label = list_entry(pos, struct pxe_label, list); -		if (menu_item_add(m, label->name, label) != 1) { +		sprintf(label->num, "%d", i++); +		if (menu_item_add(m, label->num, label) != 1) {  			menu_destroy(m);  			return NULL;  		} +		if (cfg->default_label && +		    (strcmp(label->name, cfg->default_label) == 0)) +			default_num = label->num; +  	}  	/*  	 * After we've created items for each label in the menu, set the  	 * menu's default label if one was specified.  	 */ -	if (cfg->default_label) { -		err = menu_default_set(m, cfg->default_label); +	if (default_num) { +		err = menu_default_set(m, default_num);  		if (err != 1) {  			if (err != -ENOENT) {  				menu_destroy(m); @@ -1367,10 +1415,13 @@ static void handle_pxe_menu(struct pxe_menu *cfg)  	 * we give up.  	 */ -	if (err == 1) -		label_boot(choice); -	else if (err != -ENOENT) +	if (err == 1) { +		err = label_boot(choice); +		if (!err) +			return; +	} else if (err != -ENOENT) {  		return; +	}  	boot_unattempted_labels(cfg);  } |