1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2022, Sean Anderson <sean.anderson@seco.com>
4 * Copyright (c) 2012, Google Inc.
5 */
6
7#include <common.h>
8#include <fs.h>
9#include <malloc.h>
10#include <os.h>
11#include <semihosting.h>
12#include <semihostingfs.h>
13
14int smh_fs_set_blk_dev(struct blk_desc *rbdd, struct disk_partition *info)
15{
16	/*
17	 * Only accept a NULL struct blk_desc for the semihosting, which is when
18	 * hostfs interface is used
19	 */
20	return !!rbdd;
21}
22
23static int smh_fs_read_at(const char *filename, loff_t pos, void *buffer,
24			  loff_t maxsize, loff_t *actread)
25{
26	long fd, size, ret;
27
28	fd = smh_open(filename, MODE_READ | MODE_BINARY);
29	if (fd < 0)
30		return fd;
31	ret = smh_seek(fd, pos);
32	if (ret < 0) {
33		smh_close(fd);
34		return ret;
35	}
36	if (!maxsize) {
37		size = smh_flen(fd);
38		if (ret < 0) {
39			smh_close(fd);
40			return size;
41		}
42
43		maxsize = size;
44	}
45
46	size = smh_read(fd, buffer, maxsize);
47	smh_close(fd);
48	if (size < 0)
49		return size;
50
51	*actread = size;
52	return 0;
53}
54
55static int smh_fs_write_at(const char *filename, loff_t pos, void *buffer,
56			   loff_t towrite, loff_t *actwrite)
57{
58	long fd, size, ret;
59
60	/* Try to open existing file */
61	fd = smh_open(filename, MODE_READ | MODE_BINARY | MODE_PLUS);
62	if (fd < 0)
63		/* Create new file */
64		fd = smh_open(filename, MODE_WRITE | MODE_BINARY);
65	if (fd < 0)
66		return fd;
67	ret = smh_seek(fd, pos);
68	if (ret < 0) {
69		smh_close(fd);
70		return ret;
71	}
72
73	ret = smh_write(fd, buffer, towrite, &size);
74	smh_close(fd);
75	*actwrite = size;
76	return ret;
77}
78
79int smh_fs_size(const char *filename, loff_t *result)
80{
81	long fd, size;
82
83	fd = smh_open(filename, MODE_READ | MODE_BINARY);
84	if (fd < 0)
85		return fd;
86
87	size = smh_flen(fd);
88	smh_close(fd);
89
90	if (size < 0)
91		return size;
92
93	*result = size;
94	return 0;
95}
96
97int smh_fs_read(const char *filename, void *buf, loff_t offset, loff_t len,
98		loff_t *actread)
99{
100	int ret;
101
102	ret = smh_fs_read_at(filename, offset, buf, len, actread);
103	if (ret)
104		printf("** Unable to read file %s **\n", filename);
105
106	return ret;
107}
108
109int smh_fs_write(const char *filename, void *buf, loff_t offset,
110		 loff_t len, loff_t *actwrite)
111{
112	int ret;
113
114	ret = smh_fs_write_at(filename, offset, buf, len, actwrite);
115	if (ret)
116		printf("** Unable to write file %s **\n", filename);
117
118	return ret;
119}
120