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 
smh_fs_set_blk_dev(struct blk_desc * rbdd,struct disk_partition * info)14 int 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 
smh_fs_read_at(const char * filename,loff_t pos,void * buffer,loff_t maxsize,loff_t * actread)23 static 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 
smh_fs_write_at(const char * filename,loff_t pos,void * buffer,loff_t towrite,loff_t * actwrite)55 static 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 	fd = smh_open(filename, MODE_READ | MODE_BINARY | MODE_PLUS);
61 	if (fd < 0)
62 		return fd;
63 	ret = smh_seek(fd, pos);
64 	if (ret < 0) {
65 		smh_close(fd);
66 		return ret;
67 	}
68 
69 	ret = smh_write(fd, buffer, towrite, &size);
70 	smh_close(fd);
71 	*actwrite = size;
72 	return ret;
73 }
74 
smh_fs_size(const char * filename,loff_t * result)75 int smh_fs_size(const char *filename, loff_t *result)
76 {
77 	long fd, size;
78 
79 	fd = smh_open(filename, MODE_READ | MODE_BINARY);
80 	if (fd < 0)
81 		return fd;
82 
83 	size = smh_flen(fd);
84 	smh_close(fd);
85 
86 	if (size < 0)
87 		return size;
88 
89 	*result = size;
90 	return 0;
91 }
92 
smh_fs_read(const char * filename,void * buf,loff_t offset,loff_t len,loff_t * actread)93 int smh_fs_read(const char *filename, void *buf, loff_t offset, loff_t len,
94 		loff_t *actread)
95 {
96 	int ret;
97 
98 	ret = smh_fs_read_at(filename, offset, buf, len, actread);
99 	if (ret)
100 		printf("** Unable to read file %s **\n", filename);
101 
102 	return ret;
103 }
104 
smh_fs_write(const char * filename,void * buf,loff_t offset,loff_t len,loff_t * actwrite)105 int smh_fs_write(const char *filename, void *buf, loff_t offset,
106 		 loff_t len, loff_t *actwrite)
107 {
108 	int ret;
109 
110 	ret = smh_fs_write_at(filename, offset, buf, len, actwrite);
111 	if (ret)
112 		printf("** Unable to write file %s **\n", filename);
113 
114 	return ret;
115 }
116