2 * Copyright (c) 2011-2012 The Chromium OS Authors.
3 * SPDX-License-Identifier: GPL-2.0+
10 #include <asm/state.h>
12 /* Main state record for the sandbox */
13 static struct sandbox_state main_state
;
14 static struct sandbox_state
*state
; /* Pointer to current state record */
16 void state_record_exit(enum exit_type_id exit_type
)
18 state
->exit_type
= exit_type
;
21 static int state_ensure_space(int extra_size
)
23 void *blob
= state
->state_fdt
;
28 used
= fdt_off_dt_strings(blob
) + fdt_size_dt_strings(blob
);
29 size
= fdt_totalsize(blob
);
31 if (free
> extra_size
)
34 size
= used
+ extra_size
;
35 buf
= os_malloc(size
);
39 ret
= fdt_open_into(blob
, buf
, size
);
46 state
->state_fdt
= buf
;
50 static int state_read_file(struct sandbox_state
*state
, const char *fname
)
56 size
= os_get_filesize(fname
);
58 printf("Cannot find sandbox state file '%s'\n", fname
);
61 state
->state_fdt
= os_malloc(size
);
62 if (!state
->state_fdt
) {
63 puts("No memory to read sandbox state\n");
66 fd
= os_open(fname
, OS_O_RDONLY
);
68 printf("Cannot open sandbox state file '%s'\n", fname
);
72 if (os_read(fd
, state
->state_fdt
, size
) != size
) {
73 printf("Cannot read sandbox state file '%s'\n", fname
);
83 os_free(state
->state_fdt
);
84 state
->state_fdt
= NULL
;
90 * sandbox_read_state_nodes() - Read state associated with a driver
92 * This looks through all compatible nodes and calls the read function on
93 * each one, to read in the state.
95 * If nothing is found, it still calls the read function once, to set up a
96 * single global state for that driver.
98 * @state: Sandbox state
99 * @io: Method to use for reading state
100 * @blob: FDT containing state
101 * @return 0 if OK, -EINVAL if the read function returned failure
103 int sandbox_read_state_nodes(struct sandbox_state
*state
,
104 struct sandbox_state_io
*io
, const void *blob
)
110 debug(" - read %s\n", io
->name
);
117 node
= fdt_node_offset_by_compatible(blob
, node
, io
->compat
);
119 return 0; /* No more */
120 debug(" - read node '%s'\n", fdt_get_name(blob
, node
, NULL
));
121 ret
= io
->read(blob
, node
);
123 printf("Unable to read state for '%s'\n", io
->compat
);
130 * If we got no saved state, call the read function once without a
131 * node, to set up the global state.
134 debug(" - read global\n");
135 ret
= io
->read(NULL
, -1);
137 printf("Unable to read global state for '%s'\n",
146 int sandbox_read_state(struct sandbox_state
*state
, const char *fname
)
148 struct sandbox_state_io
*io
;
153 if (state
->read_state
&& fname
) {
154 ret
= state_read_file(state
, fname
);
155 if (ret
== -ENOENT
&& state
->ignore_missing_state_on_read
)
161 /* Call all the state read funtcions */
163 blob
= state
->state_fdt
;
164 io
= ll_entry_start(struct sandbox_state_io
, state_io
);
165 for (; io
< ll_entry_end(struct sandbox_state_io
, state_io
); io
++) {
166 ret
= sandbox_read_state_nodes(state
, io
, blob
);
171 if (state
->read_state
&& fname
) {
172 debug("Read sandbox state from '%s'%s\n", fname
,
173 got_err
? " (with errors)" : "");
176 return got_err
? -1 : 0;
180 * sandbox_write_state_node() - Write state associated with a driver
182 * This calls the write function to write out global state for that driver.
184 * TODO(sjg@chromium.org): Support writing out state from multiple drivers
185 * of the same time. We don't need this yet,and it will be much easier to
186 * do when driver model is available.
188 * @state: Sandbox state
189 * @io: Method to use for writing state
190 * @return 0 if OK, -EIO if there is a fatal error (such as out of space
191 * for adding the data), -EINVAL if the write function failed.
193 int sandbox_write_state_node(struct sandbox_state
*state
,
194 struct sandbox_state_io
*io
)
203 ret
= state_ensure_space(SANDBOX_STATE_MIN_SPACE
);
205 printf("Failed to add more space for state\n");
209 /* The blob location can change when the size increases */
210 blob
= state
->state_fdt
;
211 node
= fdt_node_offset_by_compatible(blob
, -1, io
->compat
);
212 if (node
== -FDT_ERR_NOTFOUND
) {
213 node
= fdt_add_subnode(blob
, 0, io
->name
);
215 printf("Cannot create node '%s': %s\n", io
->name
,
220 if (fdt_setprop_string(blob
, node
, "compatible", io
->compat
)) {
221 puts("Cannot set compatible\n");
224 } else if (node
< 0) {
225 printf("Cannot access node '%s': %s\n", io
->name
,
229 debug("Write state for '%s' to node %d\n", io
->compat
, node
);
230 ret
= io
->write(blob
, node
);
232 printf("Unable to write state for '%s'\n", io
->compat
);
239 int sandbox_write_state(struct sandbox_state
*state
, const char *fname
)
241 struct sandbox_state_io
*io
;
247 /* Create a state FDT if we don't have one */
248 if (!state
->state_fdt
) {
250 state
->state_fdt
= os_malloc(size
);
251 if (!state
->state_fdt
) {
252 puts("No memory to create FDT\n");
255 ret
= fdt_create_empty_tree(state
->state_fdt
, size
);
257 printf("Cannot create empty state FDT: %s\n",
264 /* Call all the state write funtcions */
266 io
= ll_entry_start(struct sandbox_state_io
, state_io
);
268 for (; io
< ll_entry_end(struct sandbox_state_io
, state_io
); io
++) {
269 ret
= sandbox_write_state_node(state
, io
);
277 printf("Could not write sandbox state\n");
281 ret
= fdt_pack(state
->state_fdt
);
283 printf("Cannot pack state FDT: %s\n", fdt_strerror(ret
));
287 size
= fdt_totalsize(state
->state_fdt
);
288 fd
= os_open(fname
, OS_O_WRONLY
| OS_O_CREAT
);
290 printf("Cannot open sandbox state file '%s'\n", fname
);
294 if (os_write(fd
, state
->state_fdt
, size
) != size
) {
295 printf("Cannot write sandbox state file '%s'\n", fname
);
301 debug("Wrote sandbox state to '%s'%s\n", fname
,
302 got_err
? " (with errors)" : "");
308 os_free(state
->state_fdt
);
313 int state_setprop(int node
, const char *prop_name
, const void *data
, int size
)
319 fdt_getprop(state
->state_fdt
, node
, prop_name
, &len
);
321 /* Add space for the new property, its name and some overhead */
322 ret
= state_ensure_space(size
- len
+ strlen(prop_name
) + 32);
326 /* This should succeed, barring a mutiny */
327 blob
= state
->state_fdt
;
328 ret
= fdt_setprop(blob
, node
, prop_name
, data
, size
);
330 printf("%s: Unable to set property '%s' in node '%s': %s\n",
331 __func__
, prop_name
, fdt_get_name(blob
, node
, NULL
),
339 struct sandbox_state
*state_get_current(void)
349 state
->ram_size
= CONFIG_SYS_SDRAM_SIZE
;
350 state
->ram_buf
= os_malloc(state
->ram_size
);
351 assert(state
->ram_buf
);
354 * Example of how to use GPIOs:
356 * sandbox_gpio_set_direction(170, 0);
357 * sandbox_gpio_set_value(170, 0);
362 int state_uninit(void)
368 if (state
->write_ram_buf
&& !state
->ram_buf_rm
) {
369 err
= os_write_ram_buf(state
->ram_buf_fname
);
371 printf("Failed to write RAM buffer\n");
376 if (state
->write_state
) {
377 if (sandbox_write_state(state
, state
->state_fname
)) {
378 printf("Failed to write sandbox state\n");
383 /* Delete this at the last moment so as not to upset gdb too much */
384 if (state
->jumped_fname
)
385 os_unlink(state
->jumped_fname
);
387 if (state
->state_fdt
)
388 os_free(state
->state_fdt
);
389 memset(state
, '\0', sizeof(*state
));