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 static int state_ensure_space(int extra_size
)
18 void *blob
= state
->state_fdt
;
23 used
= fdt_off_dt_strings(blob
) + fdt_size_dt_strings(blob
);
24 size
= fdt_totalsize(blob
);
26 if (free
> extra_size
)
29 size
= used
+ extra_size
;
30 buf
= os_malloc(size
);
34 ret
= fdt_open_into(blob
, buf
, size
);
41 state
->state_fdt
= buf
;
45 static int state_read_file(struct sandbox_state
*state
, const char *fname
)
51 ret
= os_get_filesize(fname
, &size
);
53 printf("Cannot find sandbox state file '%s'\n", fname
);
56 state
->state_fdt
= os_malloc(size
);
57 if (!state
->state_fdt
) {
58 puts("No memory to read sandbox state\n");
61 fd
= os_open(fname
, OS_O_RDONLY
);
63 printf("Cannot open sandbox state file '%s'\n", fname
);
67 if (os_read(fd
, state
->state_fdt
, size
) != size
) {
68 printf("Cannot read sandbox state file '%s'\n", fname
);
78 os_free(state
->state_fdt
);
79 state
->state_fdt
= NULL
;
85 * sandbox_read_state_nodes() - Read state associated with a driver
87 * This looks through all compatible nodes and calls the read function on
88 * each one, to read in the state.
90 * If nothing is found, it still calls the read function once, to set up a
91 * single global state for that driver.
93 * @state: Sandbox state
94 * @io: Method to use for reading state
95 * @blob: FDT containing state
96 * @return 0 if OK, -EINVAL if the read function returned failure
98 int sandbox_read_state_nodes(struct sandbox_state
*state
,
99 struct sandbox_state_io
*io
, const void *blob
)
105 debug(" - read %s\n", io
->name
);
112 node
= fdt_node_offset_by_compatible(blob
, node
, io
->compat
);
114 return 0; /* No more */
115 debug(" - read node '%s'\n", fdt_get_name(blob
, node
, NULL
));
116 ret
= io
->read(blob
, node
);
118 printf("Unable to read state for '%s'\n", io
->compat
);
125 * If we got no saved state, call the read function once without a
126 * node, to set up the global state.
129 debug(" - read global\n");
130 ret
= io
->read(NULL
, -1);
132 printf("Unable to read global state for '%s'\n",
141 int sandbox_read_state(struct sandbox_state
*state
, const char *fname
)
143 struct sandbox_state_io
*io
;
148 if (state
->read_state
&& fname
) {
149 ret
= state_read_file(state
, fname
);
150 if (ret
== -ENOENT
&& state
->ignore_missing_state_on_read
)
156 /* Call all the state read funtcions */
158 blob
= state
->state_fdt
;
159 io
= ll_entry_start(struct sandbox_state_io
, state_io
);
160 for (; io
< ll_entry_end(struct sandbox_state_io
, state_io
); io
++) {
161 ret
= sandbox_read_state_nodes(state
, io
, blob
);
166 if (state
->read_state
&& fname
) {
167 debug("Read sandbox state from '%s'%s\n", fname
,
168 got_err
? " (with errors)" : "");
171 return got_err
? -1 : 0;
175 * sandbox_write_state_node() - Write state associated with a driver
177 * This calls the write function to write out global state for that driver.
179 * TODO(sjg@chromium.org): Support writing out state from multiple drivers
180 * of the same time. We don't need this yet,and it will be much easier to
181 * do when driver model is available.
183 * @state: Sandbox state
184 * @io: Method to use for writing state
185 * @return 0 if OK, -EIO if there is a fatal error (such as out of space
186 * for adding the data), -EINVAL if the write function failed.
188 int sandbox_write_state_node(struct sandbox_state
*state
,
189 struct sandbox_state_io
*io
)
198 ret
= state_ensure_space(SANDBOX_STATE_MIN_SPACE
);
200 printf("Failed to add more space for state\n");
204 /* The blob location can change when the size increases */
205 blob
= state
->state_fdt
;
206 node
= fdt_node_offset_by_compatible(blob
, -1, io
->compat
);
207 if (node
== -FDT_ERR_NOTFOUND
) {
208 node
= fdt_add_subnode(blob
, 0, io
->name
);
210 printf("Cannot create node '%s': %s\n", io
->name
,
215 if (fdt_setprop_string(blob
, node
, "compatible", io
->compat
)) {
216 puts("Cannot set compatible\n");
219 } else if (node
< 0) {
220 printf("Cannot access node '%s': %s\n", io
->name
,
224 debug("Write state for '%s' to node %d\n", io
->compat
, node
);
225 ret
= io
->write(blob
, node
);
227 printf("Unable to write state for '%s'\n", io
->compat
);
234 int sandbox_write_state(struct sandbox_state
*state
, const char *fname
)
236 struct sandbox_state_io
*io
;
242 /* Create a state FDT if we don't have one */
243 if (!state
->state_fdt
) {
245 state
->state_fdt
= os_malloc(size
);
246 if (!state
->state_fdt
) {
247 puts("No memory to create FDT\n");
250 ret
= fdt_create_empty_tree(state
->state_fdt
, size
);
252 printf("Cannot create empty state FDT: %s\n",
259 /* Call all the state write funtcions */
261 io
= ll_entry_start(struct sandbox_state_io
, state_io
);
263 for (; io
< ll_entry_end(struct sandbox_state_io
, state_io
); io
++) {
264 ret
= sandbox_write_state_node(state
, io
);
272 printf("Could not write sandbox state\n");
276 ret
= fdt_pack(state
->state_fdt
);
278 printf("Cannot pack state FDT: %s\n", fdt_strerror(ret
));
282 size
= fdt_totalsize(state
->state_fdt
);
283 fd
= os_open(fname
, OS_O_WRONLY
| OS_O_CREAT
);
285 printf("Cannot open sandbox state file '%s'\n", fname
);
289 if (os_write(fd
, state
->state_fdt
, size
) != size
) {
290 printf("Cannot write sandbox state file '%s'\n", fname
);
296 debug("Wrote sandbox state to '%s'%s\n", fname
,
297 got_err
? " (with errors)" : "");
303 os_free(state
->state_fdt
);
308 int state_setprop(int node
, const char *prop_name
, const void *data
, int size
)
314 fdt_getprop(state
->state_fdt
, node
, prop_name
, &len
);
316 /* Add space for the new property, its name and some overhead */
317 ret
= state_ensure_space(size
- len
+ strlen(prop_name
) + 32);
321 /* This should succeed, barring a mutiny */
322 blob
= state
->state_fdt
;
323 ret
= fdt_setprop(blob
, node
, prop_name
, data
, size
);
325 printf("%s: Unable to set property '%s' in node '%s': %s\n",
326 __func__
, prop_name
, fdt_get_name(blob
, node
, NULL
),
334 struct sandbox_state
*state_get_current(void)
340 void state_set_skip_delays(bool skip_delays
)
342 struct sandbox_state
*state
= state_get_current();
344 state
->skip_delays
= skip_delays
;
347 bool state_get_skip_delays(void)
349 struct sandbox_state
*state
= state_get_current();
351 return state
->skip_delays
;
358 state
->ram_size
= CONFIG_SYS_SDRAM_SIZE
;
359 state
->ram_buf
= os_malloc(state
->ram_size
);
360 assert(state
->ram_buf
);
362 /* No reset yet, so mark it as such. Always allow power reset */
363 state
->last_reset
= RESET_COUNT
;
364 state
->reset_allowed
[RESET_POWER
] = true;
367 * Example of how to use GPIOs:
369 * sandbox_gpio_set_direction(170, 0);
370 * sandbox_gpio_set_value(170, 0);
375 int state_uninit(void)
381 if (state
->write_ram_buf
&& !state
->ram_buf_rm
) {
382 err
= os_write_ram_buf(state
->ram_buf_fname
);
384 printf("Failed to write RAM buffer\n");
389 if (state
->write_state
) {
390 if (sandbox_write_state(state
, state
->state_fname
)) {
391 printf("Failed to write sandbox state\n");
396 /* Delete this at the last moment so as not to upset gdb too much */
397 if (state
->jumped_fname
)
398 os_unlink(state
->jumped_fname
);
400 if (state
->state_fdt
)
401 os_free(state
->state_fdt
);
402 memset(state
, '\0', sizeof(*state
));