blob: f7dd289286d442dc258faffbea017e8f11b313d9 [file] [log] [blame]
Sean Anderson89346ad2022-03-22 16:59:19 -04001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2022 Sean Anderson <sean.anderson@seco.com>
4 */
5
6#include <common.h>
7#include <image.h>
8#include <log.h>
9#include <semihosting.h>
10#include <spl.h>
11
12static int smh_read_full(long fd, void *memp, size_t len)
13{
14 long read;
15
16 read = smh_read(fd, memp, len);
17 if (read < 0)
18 return read;
19 if (read != len)
20 return -EIO;
21 return 0;
22}
23
Heinrich Schuchardt22e22a22023-07-22 21:27:48 +020024static ulong smh_fit_read(struct spl_load_info *load, ulong file_offset,
25 ulong size, void *buf)
26{
27 long fd;
28 ulong ret;
29
30 fd = smh_open(load->filename, MODE_READ | MODE_BINARY);
31 if (fd < 0) {
32 log_debug("could not open %s: %ld\n", load->filename, fd);
33 return 0;
34 }
35 ret = smh_read(fd, buf, size);
36 smh_close(fd);
37
38 return ret;
39}
40
Sean Anderson89346ad2022-03-22 16:59:19 -040041static int spl_smh_load_image(struct spl_image_info *spl_image,
42 struct spl_boot_device *bootdev)
43{
44 const char *filename = CONFIG_SPL_FS_LOAD_PAYLOAD_NAME;
45 int ret;
46 long fd, len;
Simon Glassbb7d3bb2022-09-06 20:26:52 -060047 struct legacy_img_hdr *header =
Sean Anderson89346ad2022-03-22 16:59:19 -040048 spl_get_load_buffer(-sizeof(*header), sizeof(*header));
49
50 fd = smh_open(filename, MODE_READ | MODE_BINARY);
51 if (fd < 0) {
52 log_debug("could not open %s: %ld\n", filename, fd);
53 return fd;
54 }
55
56 ret = smh_flen(fd);
57 if (ret < 0) {
58 log_debug("could not get length of image: %d\n", ret);
59 goto out;
60 }
61 len = ret;
62
Simon Glassbb7d3bb2022-09-06 20:26:52 -060063 ret = smh_read_full(fd, header, sizeof(struct legacy_img_hdr));
Sean Anderson89346ad2022-03-22 16:59:19 -040064 if (ret) {
65 log_debug("could not read image header: %d\n", ret);
66 goto out;
67 }
68
Heinrich Schuchardt22e22a22023-07-22 21:27:48 +020069 if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
70 image_get_magic(header) == FDT_MAGIC) {
71 struct spl_load_info load;
72
73 debug("Found FIT\n");
74 load.read = smh_fit_read;
75 load.bl_len = 1;
76 load.filename = filename;
77 load.priv = NULL;
78 smh_close(fd);
79
80 return spl_load_simple_fit(spl_image, &load, 0, header);
81 }
82
Sean Anderson89346ad2022-03-22 16:59:19 -040083 ret = spl_parse_image_header(spl_image, bootdev, header);
84 if (ret) {
85 log_debug("failed to parse image header: %d\n", ret);
86 goto out;
87 }
88
89 ret = smh_seek(fd, 0);
90 if (ret) {
91 log_debug("could not seek to start of image: %d\n", ret);
92 goto out;
93 }
94
95 ret = smh_read_full(fd, (void *)spl_image->load_addr, len);
96 if (ret)
97 log_debug("could not read %s: %d\n", filename, ret);
98out:
99 smh_close(fd);
100 return ret;
101}
102SPL_LOAD_IMAGE_METHOD("SEMIHOSTING", 0, BOOT_DEVICE_SMH, spl_smh_load_image);