libsel4platsupport: Add IO FDT ops implementation This commit adds an implementation of the IO FDT ops interface in libplatsupport.
diff --git a/libsel4platsupport/include/sel4platsupport/io.h b/libsel4platsupport/include/sel4platsupport/io.h index 9da11b2..f6d4986 100644 --- a/libsel4platsupport/include/sel4platsupport/io.h +++ b/libsel4platsupport/include/sel4platsupport/io.h
@@ -42,6 +42,16 @@ int sel4platsupport_new_malloc_ops(ps_malloc_ops_t *ops); /** + * Create a new FDT ops structure using a provided simple + * + * @param io_fdt Interface to fill in + * @param simple An initialised simple interface + * + * @return returns 0 on success + */ +int sel4platsupport_new_fdt_ops(ps_io_fdt_t *io_fdt, simple_t *simple, ps_malloc_ops_t *malloc_ops); + +/** * Creates a new implementation of the platsupport io_ops interface using a * provided vspace and vka *
diff --git a/libsel4platsupport/src/io.c b/libsel4platsupport/src/io.c index 90a78e4..500bf16 100644 --- a/libsel4platsupport/src/io.c +++ b/libsel4platsupport/src/io.c
@@ -269,6 +269,51 @@ return 0; } +static char *sel4platsupport_io_fdt_get(void *cookie) +{ + return cookie != NULL ? (char *) cookie : NULL; +} + +int sel4platsupport_new_fdt_ops(ps_io_fdt_t *io_fdt, simple_t *simple, ps_malloc_ops_t *malloc_ops) +{ + if (!io_fdt || !simple || !malloc_ops) { + ZF_LOGE("arguments are NULL"); + return -1; + } + + ssize_t block_size = simple_get_extended_bootinfo_length(simple, SEL4_BOOTINFO_HEADER_FDT); + + int error = ps_calloc(malloc_ops, 1, block_size, &io_fdt->cookie); + if (error) { + ZF_LOGE("Failed to allocate %zu bytes for the FDT", block_size); + return -1; + } + + /* Copy the FDT from the extended bootinfo */ + ssize_t copied_size = simple_get_extended_bootinfo(simple, SEL4_BOOTINFO_HEADER_FDT, + io_fdt->cookie, block_size); + if (copied_size != block_size) { + ZF_LOGE("Failed to copy the FDT"); + ZF_LOGF_IF(ps_free(malloc_ops, block_size, io_fdt->cookie), + "Failed to clean-up after a failed operation!"); + return -1; + } + + /* Cut off the bootinfo header from the start of the buffer */ + ssize_t fdt_size = block_size - sizeof(seL4_BootInfoHeader); + void *fdt_start = io_fdt->cookie + sizeof(seL4_BootInfoHeader); + memmove(io_fdt->cookie, fdt_start, fdt_size); + + /* Trim off the extra bytes at the end of the FDT */ + void *fdt_end = io_fdt->cookie + fdt_size; + memset(fdt_end, 0, sizeof(seL4_BootInfoHeader)); + + /* Set the function pointer inside the io_fdt interface */ + io_fdt->get_fn = sel4platsupport_io_fdt_get; + + return 0; +} + #ifdef CONFIG_PLAT_TK1 #include <platsupport/gpio.h>