os.c 5.92 KB
Newer Older
1
2
3
4
5
6
#include "epicardium.h"

#include "py/obj.h"
#include "py/runtime.h"

#include <string.h>
7
8
9
10
11
12
#include <strings.h>

#include <stdbool.h>

#include "os.h"

13
bool pycrd_filename_restricted(const char *path)
14
15
16
17
18
{
	// files that cannot be opened in write modes
	const char *const forbidden_files[] = {
		"card10.bin", "menu.py", "main.py", "card10.cfg"
	};
19
20
21
22
23
24

	const char *fname = strchr(path, '/');
	while (fname) {
		path  = fname + 1;
		fname = strchr(path, '/');
	}
25
26
27
28
29
	fname = strchr(path, '\\');
	while (fname) {
		path  = fname + 1;
		fname = strchr(path, '\\');
	}
30
31
	fname = path;

32
	for (size_t i = 0;
33
34
35
36
37
38
39
40
	     i < sizeof(forbidden_files) / sizeof(forbidden_files[0]);
	     i++) {
		if (strcasecmp(fname, forbidden_files[i]) == 0) {
			return true;
		}
	}
	return false;
}
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

static mp_obj_t mp_os_exit(size_t n_args, const mp_obj_t *args)
{
	int ret = 0;
	if (n_args == 1) {
		ret = mp_obj_get_int(args[0]);
	}

	epic_exit(ret);

	/* unreachable */
	return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(exit_obj, 0, 1, mp_os_exit);

static mp_obj_t mp_os_exec(mp_obj_t name_in)
{
	const char *name_ptr;
	char name_str[256];
	size_t len, maxlen;

	name_ptr = mp_obj_str_get_data(name_in, &len);

	/*
	 * The string retrieved from MicroPython is not NULL-terminated so we
	 * first need to copy it and add a NULL-byte.
	 */
	maxlen = len < (sizeof(name_str) - 1) ? len : (sizeof(name_str) - 1);
	memcpy(name_str, name_ptr, maxlen);
	name_str[maxlen] = '\0';

	int ret = epic_exec(name_str);

	/*
	 * If epic_exec() returns, something went wrong.  We can raise an
	 * exception in all cases.
	 */
	mp_raise_OSError(-ret);

	/* unreachable */
	return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(exec_obj, mp_os_exec);

Rahix's avatar
Rahix committed
85
86
87
88
89
90
91
92
93
static mp_obj_t mp_os_reset(void)
{
	epic_system_reset();

	/* unreachable */
	return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_0(reset_obj, mp_os_reset);

94
static mp_obj_t mp_os_listdir(size_t n_args, const mp_obj_t *args)
95
{
96
97
98
99
100
101
102
103
	const char *path;
	if (n_args == 1) {
		path = mp_obj_str_get_str(args[0]);
	} else {
		path = "";
	}

	int fd = epic_file_opendir(path);
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

	if (fd < 0) {
		mp_raise_OSError(-fd);
	}
	struct epic_stat entry;
	mp_obj_list_t *list = mp_obj_new_list(0, NULL);
	for (;;) {
		int res = epic_file_readdir(fd, &entry);
		if (res < 0) {
			m_del_obj(mp_obj_list_t, list);
			epic_file_close(fd);
			mp_raise_OSError(-res);
		}
		if (entry.type == EPICSTAT_NONE) {
			break;
		}
		mp_obj_list_append(
			list, mp_obj_new_str(entry.name, strlen(entry.name))
		);
	}
	epic_file_close(fd);
	return MP_OBJ_FROM_PTR(list);
}
127
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(listdir_obj, 0, 1, mp_os_listdir);
128
129
130
131

static mp_obj_t mp_os_unlink(mp_obj_t py_path)
{
	const char *path = mp_obj_str_get_str(py_path);
132
133
134
135
	if (pycrd_filename_restricted(path)) {
		mp_raise_OSError(-EACCES);
	}
	int rc = epic_file_unlink(path);
136
137
138
139
140
141
142
143

	if (rc < 0) {
		mp_raise_OSError(-rc);
	}
	return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(unlink_obj, mp_os_unlink);

swym's avatar
swym committed
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
static mp_obj_t mp_os_mkdir(mp_obj_t py_path)
{
	const char *path = mp_obj_str_get_str(py_path);
	int rc           = epic_file_mkdir(path);

	if (rc < 0) {
		mp_raise_OSError(-rc);
	}
	return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(mkdir_obj, mp_os_mkdir);

static mp_obj_t mp_os_rename(mp_obj_t py_oldp, mp_obj_t py_newp)
{
	const char *oldp = mp_obj_str_get_str(py_oldp);
	const char *newp = mp_obj_str_get_str(py_newp);
160
161
162
163
164
	if (pycrd_filename_restricted(oldp) ||
	    pycrd_filename_restricted(newp)) {
		mp_raise_OSError(-EACCES);
	}
	int rc = epic_file_rename(oldp, newp);
swym's avatar
swym committed
165
166
167
168
169
170
171
172

	if (rc < 0) {
		mp_raise_OSError(-rc);
	}
	return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_2(rename_obj, mp_os_rename);

173
174
175
176
177
178
179
180
181
182
183
184
static mp_obj_t mp_os_read_battery()
{
	float result;
	int res = epic_read_battery_voltage(&result);
	if (res < 0) {
		mp_raise_OSError(-res);
	}

	return mp_obj_new_float(result);
}
static MP_DEFINE_CONST_FUN_OBJ_0(read_battery_obj, mp_os_read_battery);

Rahix's avatar
Rahix committed
185
186
187
188
189
190
static mp_obj_t mp_os_urandom(mp_obj_t size_in)
{
	size_t size = mp_obj_get_int(size_in);
	vstr_t vstr;

	vstr_init_len(&vstr, size);
191
	epic_trng_read((uint8_t *)vstr.buf, size);
Rahix's avatar
Rahix committed
192
193
194
195
196

	return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
static MP_DEFINE_CONST_FUN_OBJ_1(urandom_obj, mp_os_urandom);

swym's avatar
swym committed
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
enum usb_config_device {
	USB_DEVICE_NONE,
	USB_DEVICE_FLASH,
	USB_DEVICE_SERIAL,
};

static mp_obj_t mp_os_usbconfig(mp_obj_t dev)
{
	int device = mp_obj_get_int(dev);
	switch (device) {
	case USB_DEVICE_NONE:
		epic_usb_shutdown();
		break;
	case USB_DEVICE_FLASH:
		epic_usb_storage();
		break;
	case USB_DEVICE_SERIAL:
		epic_usb_cdcacm();
		break;
	default:
		mp_raise_ValueError("Invalid parameter");
	}
	return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(usbconfig_obj, mp_os_usbconfig);

223
static const mp_rom_map_elem_t os_module_globals_table[] = {
224
225
	{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_os) },
	{ MP_ROM_QSTR(MP_QSTR_exit), MP_ROM_PTR(&exit_obj) },
koalo's avatar
koalo committed
226
	{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&reset_obj) },
227
	{ MP_ROM_QSTR(MP_QSTR_exec), MP_ROM_PTR(&exec_obj) },
228
229
	{ MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&listdir_obj) },
	{ MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&unlink_obj) },
swym's avatar
swym committed
230
231
	{ MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mkdir_obj) },
	{ MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&rename_obj) },
232
	{ MP_ROM_QSTR(MP_QSTR_read_battery), MP_ROM_PTR(&read_battery_obj) },
Rahix's avatar
Rahix committed
233
	{ MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&urandom_obj) },
swym's avatar
swym committed
234
235
236
237
238
	{ MP_ROM_QSTR(MP_QSTR_usbconfig), MP_ROM_PTR(&usbconfig_obj) },

	{ MP_ROM_QSTR(MP_QSTR_USB_SERIAL), MP_ROM_INT(USB_DEVICE_SERIAL) },
	{ MP_ROM_QSTR(MP_QSTR_USB_FLASH), MP_ROM_INT(USB_DEVICE_FLASH) },
	{ MP_ROM_QSTR(MP_QSTR_USB_NONE), MP_ROM_INT(USB_DEVICE_NONE) },
239
240
};

241
242
243
static MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);

// Define module object.
244
245
246
247
248
249
250
251
const mp_obj_module_t os_module = {
	.base    = { &mp_type_module },
	.globals = (mp_obj_dict_t *)&os_module_globals,
};

/* This is a special macro that will make MicroPython aware of this module */
/* clang-format off */
MP_REGISTER_MODULE(MP_QSTR_os, os_module, MODULE_OS_ENABLED);