mirror of
				https://xff.cz/git/u-boot/
				synced 2025-10-31 10:26:10 +01:00 
			
		
		
		
	bootstd: Support reading a script from network or SPI flash
At present this bootmeth only supports a block device and the sandbox host filesystem. Add support for obtaining the script from a network device. Also implement the set_bootflow() method so that it is easy for other bootdevs (such as enabling SPI flash to support scripts). Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
		| @@ -19,18 +19,14 @@ | |||||||
| #include <image.h> | #include <image.h> | ||||||
| #include <malloc.h> | #include <malloc.h> | ||||||
| #include <mapmem.h> | #include <mapmem.h> | ||||||
|  | #include <net.h> | ||||||
|  |  | ||||||
| #define SCRIPT_FNAME1	"boot.scr.uimg" | #define SCRIPT_FNAME1	"boot.scr.uimg" | ||||||
| #define SCRIPT_FNAME2	"boot.scr" | #define SCRIPT_FNAME2	"boot.scr" | ||||||
|  |  | ||||||
| static int script_check(struct udevice *dev, struct bootflow_iter *iter) | static int script_check(struct udevice *dev, struct bootflow_iter *iter) | ||||||
| { | { | ||||||
| 	int ret; | 	/* This works on block devices, network devices and SPI Flash */ | ||||||
|  |  | ||||||
| 	/* This only works on block devices */ |  | ||||||
| 	ret = bootflow_iter_check_blk(iter); |  | ||||||
| 	if (ret) |  | ||||||
| 		return log_msg_ret("blk", ret); |  | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| @@ -65,11 +61,11 @@ static int script_fill_info(struct bootflow *bflow) | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int script_read_bootflow(struct udevice *dev, struct bootflow *bflow) | static int script_read_bootflow_file(struct udevice *bootstd, | ||||||
|  | 				     struct bootflow *bflow) | ||||||
| { | { | ||||||
| 	struct blk_desc *desc = NULL; | 	struct blk_desc *desc = NULL; | ||||||
| 	const char *const *prefixes; | 	const char *const *prefixes; | ||||||
| 	struct udevice *bootstd; |  | ||||||
| 	const char *prefix; | 	const char *prefix; | ||||||
| 	int ret, i; | 	int ret, i; | ||||||
|  |  | ||||||
| @@ -77,12 +73,12 @@ static int script_read_bootflow(struct udevice *dev, struct bootflow *bflow) | |||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return log_msg_ret("std", ret); | 		return log_msg_ret("std", ret); | ||||||
|  |  | ||||||
| 	/* We require a partition table */ | 	if (bflow->blk) { | ||||||
| 	if (!bflow->part) | 		/* We require a partition table */ | ||||||
| 		return -ENOENT; | 		if (!bflow->part) | ||||||
|  | 			return -ENOENT; | ||||||
| 	if (bflow->blk) |  | ||||||
| 		 desc = dev_get_uclass_plat(bflow->blk); | 		 desc = dev_get_uclass_plat(bflow->blk); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	prefixes = bootstd_get_prefixes(bootstd); | 	prefixes = bootstd_get_prefixes(bootstd); | ||||||
| 	i = 0; | 	i = 0; | ||||||
| @@ -116,6 +112,76 @@ static int script_read_bootflow(struct udevice *dev, struct bootflow *bflow) | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static int script_read_bootflow_net(struct bootflow *bflow) | ||||||
|  | { | ||||||
|  | 	const char *addr_str; | ||||||
|  | 	int size, ret; | ||||||
|  | 	char *fname; | ||||||
|  | 	ulong addr; | ||||||
|  |  | ||||||
|  | 	/* figure out the load address */ | ||||||
|  | 	addr_str = env_get("scriptaddr"); | ||||||
|  | 	addr = addr_str ? hextoul(addr_str, NULL) : image_load_addr; | ||||||
|  |  | ||||||
|  | 	fname = env_get("boot_script_dhcp"); | ||||||
|  | 	if (!fname) | ||||||
|  | 		return log_msg_ret("dhc", -EINVAL); | ||||||
|  |  | ||||||
|  | 	ret = dhcp_run(addr, fname, true); | ||||||
|  | 	if (ret) | ||||||
|  | 		return log_msg_ret("dhc", ret); | ||||||
|  |  | ||||||
|  | 	size = env_get_hex("filesize", 0); | ||||||
|  | 	if (!size) | ||||||
|  | 		return log_msg_ret("sz", -EINVAL); | ||||||
|  |  | ||||||
|  | 	bflow->buf = malloc(size + 1); | ||||||
|  | 	if (!bflow->buf) | ||||||
|  | 		return log_msg_ret("buf", -ENOMEM); | ||||||
|  | 	memcpy(bflow->buf, map_sysmem(addr, size), size); | ||||||
|  | 	bflow->buf[size] = '\0'; | ||||||
|  | 	bflow->size = size; | ||||||
|  | 	bflow->state = BOOTFLOWST_READY; | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int script_read_bootflow(struct udevice *dev, struct bootflow *bflow) | ||||||
|  | { | ||||||
|  | 	const struct udevice *media = dev_get_parent(bflow->dev); | ||||||
|  | 	struct udevice *bootstd; | ||||||
|  | 	int ret; | ||||||
|  |  | ||||||
|  | 	ret = uclass_first_device_err(UCLASS_BOOTSTD, &bootstd); | ||||||
|  | 	if (ret) | ||||||
|  | 		return log_msg_ret("std", ret); | ||||||
|  |  | ||||||
|  | 	if (IS_ENABLED(CONFIG_CMD_DHCP) && | ||||||
|  | 	    device_get_uclass_id(media) == UCLASS_ETH) { | ||||||
|  | 		/* we only support reading from one device, so ignore 'dev' */ | ||||||
|  | 		ret = script_read_bootflow_net(bflow); | ||||||
|  | 		if (ret) | ||||||
|  | 			return log_msg_ret("net", ret); | ||||||
|  | 	} else { | ||||||
|  | 		ret = script_read_bootflow_file(bootstd, bflow); | ||||||
|  | 		if (ret) | ||||||
|  | 			return log_msg_ret("blk", ret); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int script_set_bootflow(struct udevice *dev, struct bootflow *bflow, | ||||||
|  | 			       char *buf, int size) | ||||||
|  | { | ||||||
|  | 	buf[size] = '\0'; | ||||||
|  | 	bflow->buf = buf; | ||||||
|  | 	bflow->size = size; | ||||||
|  | 	bflow->state = BOOTFLOWST_READY; | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| static int script_boot(struct udevice *dev, struct bootflow *bflow) | static int script_boot(struct udevice *dev, struct bootflow *bflow) | ||||||
| { | { | ||||||
| 	struct blk_desc *desc = dev_get_uclass_plat(bflow->blk); | 	struct blk_desc *desc = dev_get_uclass_plat(bflow->blk); | ||||||
| @@ -162,6 +228,7 @@ static int script_bootmeth_bind(struct udevice *dev) | |||||||
| static struct bootmeth_ops script_bootmeth_ops = { | static struct bootmeth_ops script_bootmeth_ops = { | ||||||
| 	.check		= script_check, | 	.check		= script_check, | ||||||
| 	.read_bootflow	= script_read_bootflow, | 	.read_bootflow	= script_read_bootflow, | ||||||
|  | 	.set_bootflow	= script_set_bootflow, | ||||||
| 	.read_file	= bootmeth_common_read_file, | 	.read_file	= bootmeth_common_read_file, | ||||||
| 	.boot		= script_boot, | 	.boot		= script_boot, | ||||||
| }; | }; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user