1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2022 Sean Anderson <sean.anderson@seco.com>
4  */
5 
6 #include <image.h>
7 #include <log.h>
8 #include <semihosting.h>
9 #include <spl.h>
10 #include <spl_load.h>
11 
smh_fit_read(struct spl_load_info * load,ulong file_offset,ulong size,void * buf)12 static ulong smh_fit_read(struct spl_load_info *load, ulong file_offset,
13 			  ulong size, void *buf)
14 {
15 	long fd = *(long *)load->priv;
16 	ulong ret;
17 
18 	if (smh_seek(fd, file_offset))
19 		return 0;
20 
21 	ret = smh_read(fd, buf, size);
22 	return ret < 0 ? 0 : ret;
23 }
24 
spl_smh_load_image(struct spl_image_info * spl_image,struct spl_boot_device * bootdev)25 static int spl_smh_load_image(struct spl_image_info *spl_image,
26 			      struct spl_boot_device *bootdev)
27 {
28 	const char *filename = CONFIG_SPL_FS_LOAD_PAYLOAD_NAME;
29 	int ret;
30 	long fd, len;
31 	struct spl_load_info load;
32 
33 	fd = smh_open(filename, MODE_READ | MODE_BINARY);
34 	if (fd < 0) {
35 		log_debug("could not open %s: %ld\n", filename, fd);
36 		return fd;
37 	}
38 
39 	ret = smh_flen(fd);
40 	if (ret < 0) {
41 		log_debug("could not get length of image: %d\n", ret);
42 		goto out;
43 	}
44 	len = ret;
45 
46 	spl_load_init(&load, smh_fit_read, &fd, 1);
47 	ret = spl_load(spl_image, bootdev, &load, len, 0);
48 	if (ret)
49 		log_debug("could not read %s: %d\n", filename, ret);
50 out:
51 	smh_close(fd);
52 	return ret;
53 }
54 SPL_LOAD_IMAGE_METHOD("SEMIHOSTING", 0, BOOT_DEVICE_SMH, spl_smh_load_image);
55