-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwebcm.c
147 lines (128 loc) · 4.28 KB
/
webcm.c
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include "cartesi-machine/machine-c-api.h"
#include <emscripten.h>
#define MINIZ_NO_ARCHIVE_APIS
#define MINIZ_NO_STDIO
#define MINIZ_NO_TIME
#define MINIZ_EXPORT static
#include "third-party/miniz.h"
#include "third-party/miniz.c"
#define RAM_SIZE 128*1024*1024
#define ROOTFS_SIZE 128*1024*1024
#define RAM_START UINT64_C(0x80000000)
#define ROOTFS_START UINT64_C(0x80000000000000)
static uint8_t linux_bin_zz[] = {
#embed "linux.bin.zz"
};
static uint8_t rootfs_ext2_zz[] = {
#embed "rootfs.ext2.zz"
};
typedef struct uncompress_env {
cm_machine *machine;
uint64_t offset;
} uncompress_env;
int uncompress_cb(uint8_t *data, int size, uncompress_env *env) {
if (cm_write_memory(env->machine, env->offset, data, size) != CM_ERROR_OK) {
printf("failed to write machine memory: %s\n", cm_get_last_error_message());
exit(1);
}
env->offset += size;
return 1;
}
uint64_t uncompress_memory(cm_machine *machine, uint64_t paddr, uint8_t *data, uint64_t size) {
uncompress_env env = {machine, paddr};
size_t uncompressed_size = size;
if (tinfl_decompress_mem_to_callback(data, &uncompressed_size, (tinfl_put_buf_func_ptr)uncompress_cb, &env, TINFL_FLAG_PARSE_ZLIB_HEADER) != 1) {
printf("failed to uncompress memory\n");
exit(1);
}
return uncompressed_size;
}
int main() {
printf("Allocating...\n");
// Set machine configuration
unsigned long long now = (unsigned long long)time(NULL);
char config[4096];
snprintf(config, sizeof(config), "{\
\"dtb\": {\
\"bootargs\": \"quiet earlycon=sbi console=hvc1 root=/dev/pmem0 rw init=/usr/sbin/cartesi-init\",\
\"init\": \"date -s @%llu >> /dev/null\",\
\"entrypoint\": \"exec ash -l\"\
},\
\"flash_drive\": [\
{\"length\": %u}\
],\
\"virtio\": [\
{\"type\": \"console\"}\
],\
\"processor\": {\
\"iunrep\": 1\
},\
\"ram\": {\"length\": %u}\
}", now, RAM_SIZE, ROOTFS_SIZE);
// Create a new machine
cm_machine *machine = NULL;
if (cm_create_new(config, NULL, &machine) != CM_ERROR_OK) {
printf("failed to create machine: %s\n", cm_get_last_error_message());
exit(1);
}
printf("Decompressing...\n");
// Decompress kernel and rootfs
uncompress_memory(machine, RAM_START, linux_bin_zz, sizeof(linux_bin_zz));
uncompress_memory(machine, ROOTFS_START, rootfs_ext2_zz, sizeof(rootfs_ext2_zz));
printf("Booting...\n");
// Run the machine
cm_break_reason break_reason;
do {
uint64_t mcycle;
if (cm_read_reg(machine, CM_REG_MCYCLE, &mcycle) != CM_ERROR_OK) {
printf("failed to read machine cycle: %s\n", cm_get_last_error_message());
cm_delete(machine);
exit(1);
}
if (cm_run(machine, mcycle + 4*1024*1024, &break_reason) != CM_ERROR_OK) {
printf("failed to run machine: %s\n", cm_get_last_error_message());
cm_delete(machine);
exit(1);
}
emscripten_sleep(0);
} while(break_reason == CM_BREAK_REASON_REACHED_TARGET_MCYCLE);
// Print reason for run interruption
switch (break_reason) {
case CM_BREAK_REASON_HALTED:
printf("Halted\n");
break;
case CM_BREAK_REASON_YIELDED_MANUALLY:
printf("Yielded manually\n");
break;
case CM_BREAK_REASON_YIELDED_AUTOMATICALLY:
printf("Yielded automatically\n");
break;
case CM_BREAK_REASON_YIELDED_SOFTLY:
printf("Yielded softly\n");
break;
case CM_BREAK_REASON_REACHED_TARGET_MCYCLE:
printf("Reached target machine cycle\n");
break;
case CM_BREAK_REASON_FAILED:
default:
printf("Interpreter failed\n");
break;
}
// Read and print machine cycles
uint64_t mcycle;
if (cm_read_mcycle(machine, &mcycle) != CM_ERROR_OK) {
printf("failed to read machine cycle: %s\n", cm_get_last_error_message());
cm_delete(machine);
exit(1);
}
printf("Cycles: %lu\n", (unsigned long)mcycle);
// Cleanup and exit
cm_delete(machine);
return 0;
}