[U-Boot] [PATCH 3/4] Add pxecfg command

Wolfgang Denk wd at denx.de
Mon Jun 6 21:45:22 CEST 2011


Dear "Jason Hobbs",

In message <1307386599-4256-4-git-send-email-jason.hobbs at calxeda.com> you wrote:
> Add pxecfg command, which is intended to mimic PXELINUX functionality.
> 'pxecfg get' uses tftp to retrieve a file based on UUID, MAC address or
> IP address. 'pxecfg boot' interprets the contents of PXELINUX config
> like file to boot using a specific initrd, kernel and kernel command
> line.
> 
> This patch also adds a README.pxecfg file - see it for more details on
> the pxecfg command.

Any reason for not calling this command simply "pxe" ?


Is [parts of] this code copied from somewhere? If yes, we need exact
reference (see bullet # 4 at
http://www.denx.de/wiki/view/U-Boot/Patches#Attributing_Code_Copyrights_Sign )

If it is not copied from other projects, then please change the
license to GPLv2+

...
> +	for (p = *outbuf; *p; p++)
> +		if (*p == ':')
> +			*p = '-';

Braces needed for multiline statement.

> +	bootfile_path = strdup(bootfile);
> +
> +	if (bootfile_path == NULL) {
> +		printf("oom\n");

Please use a more readable error message.

> +		return NULL;
> +	}
> +
> +	last_slash = strrchr(bootfile_path, '/');
> +
> +	if (last_slash == NULL) {
> +		printf("Invalid bootfile path (%s), no '/' found\n",
> +				bootfile_path);
> +
> +		return NULL;

Where is the requirement coming from that "bootfile" must contain a
path?  Is there any formal requirement a plain file name is illegal
[and could we not assume a path of "./" then] ?

> +	if (bootfile_path == NULL) {
> +		printf("No bootfile path in environment.\n");
> +		return -ENOENT;
> +	}
> +
> +	path_len = strlen(bootfile_path) + strlen(file_path) + 1;
> +
> +	if (path_len > MAX_TFTP_PATH_LEN) {
> +		printf("Base path too long (%s/%s)\n",
> +				bootfile_path, file_path);
> +
> +		free(bootfile_path);
> +		return -ENAMETOOLONG;
> +	}
> +
> +	sprintf(bootfile, "%s/%s", bootfile_path, file_path);
> +
> +	free(bootfile_path);
> +
> +	printf("Retreiving file: %s\n", bootfile);
> +
> +	sprintf(addr_buf, "%p", file_addr);
> +
> +	tftp_argv[1] = addr_buf;
> +	tftp_argv[2] = bootfile;

This looks like an extremly complicated way for a plain TFTP
download. Why are you performing all this acrobatics and juggling
with bootfile, instead of simply using what the user provided?


> +#define MAX_CFG_PATHS	12

Where is this number coming from?

> +static char **pxecfg_paths(char *uuid_str, char *mac_addr)
> +{
> +	char **ret_array;
> +	char ip_addr[9];
> +	int x, end_masks, mask_pos;
> +	size_t base_len = strlen("pxelinux.cfg/");
> +
> +	sprintf(ip_addr, "%08X", ntohl(NetOurIP));
> +
> +	ret_array = malloc(MAX_CFG_PATHS * sizeof(char *));
> +
> +	if (ret_array == NULL) {
> +		printf("oom\n");
> +		return NULL;
> +	}
> +
> +	for (x = 0; x < MAX_CFG_PATHS; x++)
> +		ret_array[x] = NULL;

Why do we need this array here?  I understand we are tyring one otopn
after the other, so we don't ever need more than a single entry of
this array at any time?

> +	while (iter_label)
> +		if (!strcmp(name, iter_label->name))
> +			return iter_label;
> +		else
> +			iter_label = iter_label->next;

Braces needed for multiline statement.  Please fix globally.

...
> +	/*
> +	 * We must dup the environment variable value here, because getenv
> +	 * returns a pointer directly into the environment, and the contents
> +	 * of the environment might shift during execution of a command.
> +	 */
> +	dupcmd = strdup(localcmd);

What do you mean by "the contents of the environment might shift" ???

> +	if (!dupcmd) {
> +		printf("oom\n");

See before: Please use readable error messages. Please fix globally.

> +		return -ENOMEM;
> +	}
> +
> +	if (label->append)
> +		setenv("bootargs", label->append);
> +
> +	printf("running: %s\n", dupcmd);

This should probably be a debug() ?

> +static void print_menu(struct pxecfg_menu *menu)
> +{
> +	struct pxecfg_menu_item *iter;
> +
> +	if (menu->title)
> +		printf("Menu: %s\n", menu->title);
> +
> +	iter = menu->labels;
> +
> +	while (iter) {
> +		print_label(iter);
> +
> +		iter = iter->next;
> +	}
> +}

Can we please split off the menu part, and make it generally usable?
Eventually we might look at other implementations of such code for
more general use?


> +		pxecfg_ram = getenv("pxecfg_ram");
> +		if (pxecfg_ram == NULL) {
> +			printf("Missing pxecfg_ram in environment\n");
> +			return 1;
> +		}

Eventually you may want to factor out this code which I see
repeatedly, and provide a unified error message with it.

> +int do_pxecfg(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> +{
> +	if (argc < 2) {
> +		printf("pxecfg requires at least one argument\n");
> +		return EINVAL;
> +	}
> +
> +	if (!strcmp(argv[1], "get"))
> +		return get_pxecfg(argc, argv);
> +
> +	if (!strcmp(argv[1], "boot"))
> +		return boot_pxecfg(argc, argv);
> +
> +	printf("Invalid pxecfg command: %s\n", argv[1]);
> +
> +	return EINVAL;
> +}

> diff --git a/include/common.h b/include/common.h
> index fd389e7..597e757 100644
> --- a/include/common.h
> +++ b/include/common.h
> @@ -257,6 +257,11 @@ extern ulong load_addr;		/* Default Load Address */
>  /* common/cmd_doc.c */
>  void	doc_probe(unsigned long physadr);
>  
> +/* common/cmd_net.c */
> +#ifdef CONFIG_CMD_NET
> +int do_tftpb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
> +#endif

You can drop the #ifdef here.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"No one talks peace unless he's ready to back it up with war."
"He talks of peace if it is the only way to live."
	-- Colonel Green and Surak of Vulcan, "The Savage Curtain",
	   stardate 5906.5.


More information about the U-Boot mailing list