summaryrefslogtreecommitdiff
path: root/flashimg/cpu_main/flash_static.c
blob: 4529ab2639a8cced4278ad56e2beb1b214e09418 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/* flashimg/cpu_main/flash_static.c - Serve static files from flash over 9P
 *
 * Copyright (C) 2024-2025  Luke T. Shumaker <lukeshu@lukeshu.com>
 * SPDX-License-Identifier: AGPL-3.0-or-later
 */

#include <hardware/flash.h>

#include <libmisc/assert.h>

#include "flashio.h"

#include "flash_static.h"

LO_IMPLEMENTATION_C(lib9p_srv_file, struct flash_static_file, flash_static_file);
LO_IMPLEMENTATION_STATIC(lib9p_srv_fio, struct flash_static_file, flash_static_fio);

/******************************************************************************/

#ifdef NDEBUG
#define flash_static_assert(self) ((void)0)
#else
static void flash_static_assert(struct flash_static_file *self) {
	assert(self);
	assert(self->io);
	assert(XIP_BASE <= (uintptr_t)self->data_start);
	assert((uintptr_t)self->data_start <= (uintptr_t)self->data_end);
	assert((uintptr_t)self->data_end <= XIP_BASE+PICO_FLASH_SIZE_BYTES);
}
#endif

static inline size_t flash_static_size(struct flash_static_file *file) {
	flash_static_assert(file);

	return (size_t)((uintptr_t)file->data_end - (uintptr_t)file->data_start);
}

/******************************************************************************/

void flash_static_file_free(struct flash_static_file *self) {
	flash_static_assert(self);
}
struct lib9p_qid flash_static_file_qid(struct flash_static_file *self) {
	flash_static_assert(self);

	return (struct lib9p_qid){
		.type = LIB9P_QT_FILE,
		.vers = 1,
		.path = self->c.pathnum,
	};
}
error flash_static_file_stat(struct flash_static_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat *out) {
	flash_static_assert(self);
	assert(ctx);
	assert(out);

	*out = ((struct lib9p_srv_stat){
		.qid                 = flash_static_file_qid(self),
		.mode                = self->c.perm & 0444,
		.atime_sec           = self->c.atime,
		.mtime_sec           = self->c.mtime,
		.size                = (uint64_t)flash_static_size(self),
		.name                = lib9p_str(self->c.name),
		.owner_uid           = { .name = lib9p_str(self->c.u_name), .num = self->c.u_num },
		.owner_gid           = { .name = lib9p_str(self->c.g_name), .num = self->c.g_num },
		.last_modifier_uid   = { .name = lib9p_str(self->c.m_name), .num = self->c.m_num },
		.extension           = lib9p_str(NULL),
	});
	return ERROR_NULL;
}
error flash_static_file_wstat(struct flash_static_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat) {
	flash_static_assert(self);
	assert(ctx);

	return error_new(E_POSIX_EROFS, "read-only part of filesystem");
}
error flash_static_file_remove(struct flash_static_file *self, struct lib9p_srv_ctx *ctx) {
	flash_static_assert(self);
	assert(ctx);

	return error_new(E_POSIX_EROFS, "read-only part of filesystem");
}

LIB9P_SRV_NOTDIR(, struct flash_static_file, flash_static_file);

lib9p_srv_fio_or_error flash_static_file_fopen(struct flash_static_file *self, struct lib9p_srv_ctx *ctx, bool rd, bool wr, bool trunc) {
	flash_static_assert(self);
	assert(ctx);
	assert(rd);
	assert(!wr);
	assert(!trunc);
	return ERROR_NEW_VAL(lib9p_srv_fio, LO_BOX(lib9p_srv_fio, self));
}

/******************************************************************************/

static struct lib9p_qid flash_static_fio_ioqid(struct flash_static_file *self) {
	return flash_static_file_qid(self);
}
static void flash_static_fio_iofree(struct flash_static_file *self) {
	flash_static_assert(self);
}
static uint32_t flash_static_fio_iounit(struct flash_static_file *self) {
	flash_static_assert(self);
	return 0;
}
static error flash_static_fio_pread(struct flash_static_file *self, struct lib9p_srv_ctx *ctx, lo_interface io_writer dst, uint64_t byte_offset, uint32_t byte_count) {
	flash_static_assert(self);
	assert(ctx);

	size_t data_size = flash_static_size(self);
	if (byte_offset > (uint64_t)data_size)
		return error_new(E_POSIX_EINVAL, "offset is past end-of-file length");

	if (byte_count > data_size - byte_offset)
		byte_count = data_size - byte_offset;

	return flashio_pread_to(self->io, dst, ((uintptr_t)self->data_start - XIP_BASE) + byte_offset, byte_count).err;
}
static uint32_t_or_error flash_static_fio_pwrite(struct flash_static_file *self, struct lib9p_srv_ctx *ctx,
                                                 const void *LM_UNUSED(buf),
                                                 uint32_t LM_UNUSED(byte_count),
                                                 uint64_t LM_UNUSED(byte_offset)) {
	flash_static_assert(self);
	assert(ctx);

	return ERROR_NEW_ERR(uint32_t, error_new(E_POSIX_EROFS, "read-only part of filesystem"));
}