TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 1 | /* |
Anna Lyons | 9214341 | 2017-06-05 08:29:55 +1000 | [diff] [blame] | 2 | * Copyright 2017, Data61 |
| 3 | * Commonwealth Scientific and Industrial Research Organisation (CSIRO) |
| 4 | * ABN 41 687 119 230. |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 5 | * |
| 6 | * This software may be distributed and modified according to the terms of |
| 7 | * the BSD 2-Clause license. Note that NO WARRANTY is provided. |
| 8 | * See "LICENSE_BSD2.txt" for details. |
| 9 | * |
Anna Lyons | 9214341 | 2017-06-05 08:29:55 +1000 | [diff] [blame] | 10 | * @TAG(DATA61_BSD) |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 11 | */ |
| 12 | |
| 13 | #include <autoconf.h> |
Yu Hou | e23dc54 | 2019-05-20 15:29:15 +1000 | [diff] [blame] | 14 | #include <sel4platsupport/gen_config.h> |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 15 | |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 16 | #include <sel4platsupport/io.h> |
Adrian Danis | 3209509 | 2017-05-25 17:00:35 +1000 | [diff] [blame] | 17 | #ifdef CONFIG_ARCH_ARM |
Alexander Kroh | 637e0d4 | 2015-06-26 13:44:02 +1000 | [diff] [blame] | 18 | #include <platsupport/clock.h> |
| 19 | #include <platsupport/mux.h> |
| 20 | #endif |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 21 | #include <utils/util.h> |
Anna Lyons | 3a9da54 | 2016-02-29 14:07:08 +1100 | [diff] [blame] | 22 | #include <vspace/page.h> |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 23 | |
| 24 | #include <vspace/vspace.h> |
| 25 | #include <vka/capops.h> |
| 26 | |
Matthew Fernandez | 9270216 | 2016-06-10 15:35:43 +1000 | [diff] [blame] | 27 | #include <stdint.h> |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 28 | #include <stdlib.h> |
| 29 | |
| 30 | typedef struct io_mapping { |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 31 | /* address we returned to the user */ |
| 32 | void *returned_addr; |
| 33 | /* base address of the mapping with respect to the vspace */ |
| 34 | void *mapped_addr; |
Anna Lyons | f2887a5 | 2016-09-30 16:06:15 +1000 | [diff] [blame] | 35 | size_t num_pages; |
| 36 | size_t page_size; |
| 37 | size_t page_size_bits; |
| 38 | /* caps for the mappings (s) */ |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 39 | seL4_CPtr *caps; |
Anna Lyons | f2887a5 | 2016-09-30 16:06:15 +1000 | [diff] [blame] | 40 | /* allocation cookie for allocation(s) */ |
| 41 | seL4_Word *alloc_cookies; |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 42 | struct io_mapping *next, *prev; |
| 43 | } io_mapping_t; |
| 44 | |
| 45 | typedef struct sel4platsupport_io_mapper_cookie { |
Damon Lee | 28c5fdd | 2019-07-23 11:27:46 +1000 | [diff] [blame] | 46 | vspace_t *vspace; |
| 47 | vka_t *vka; |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 48 | io_mapping_t *head; |
| 49 | } sel4platsupport_io_mapper_cookie_t; |
| 50 | |
Yu Hou | e9a9ff4 | 2019-07-18 17:26:01 +1000 | [diff] [blame] | 51 | static void free_node(io_mapping_t *node) |
Alexander Kroh | 637e0d4 | 2015-06-26 13:44:02 +1000 | [diff] [blame] | 52 | { |
Anna Lyons | f2887a5 | 2016-09-30 16:06:15 +1000 | [diff] [blame] | 53 | assert(node); |
| 54 | if (node->caps) { |
| 55 | free(node->caps); |
| 56 | } |
| 57 | if (node->alloc_cookies) { |
| 58 | free(node->alloc_cookies); |
| 59 | } |
| 60 | free(node); |
| 61 | } |
| 62 | |
Yu Hou | e9a9ff4 | 2019-07-18 17:26:01 +1000 | [diff] [blame] | 63 | static io_mapping_t *new_node(size_t num_pages) |
Anna Lyons | f2887a5 | 2016-09-30 16:06:15 +1000 | [diff] [blame] | 64 | { |
| 65 | io_mapping_t *ret = calloc(1, sizeof(io_mapping_t)); |
| 66 | |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 67 | if (!ret) { |
| 68 | return NULL; |
| 69 | } |
Anna Lyons | f2887a5 | 2016-09-30 16:06:15 +1000 | [diff] [blame] | 70 | |
| 71 | ret->caps = calloc(num_pages, sizeof(seL4_CPtr)); |
| 72 | if (!ret->caps) { |
| 73 | free_node(ret); |
| 74 | return NULL; |
| 75 | } |
| 76 | |
| 77 | ret->alloc_cookies = calloc(num_pages, sizeof(seL4_Word)); |
| 78 | if (!ret->alloc_cookies) { |
| 79 | free_node(ret); |
| 80 | return NULL; |
| 81 | } |
| 82 | |
| 83 | ret->num_pages = num_pages; |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 84 | return ret; |
| 85 | } |
| 86 | |
Yu Hou | e9a9ff4 | 2019-07-18 17:26:01 +1000 | [diff] [blame] | 87 | static void destroy_node(vka_t *vka, io_mapping_t *mapping) |
Anna Lyons | f2887a5 | 2016-09-30 16:06:15 +1000 | [diff] [blame] | 88 | { |
| 89 | cspacepath_t path; |
| 90 | for (size_t i = 0; i < mapping->num_pages; i++) { |
| 91 | /* free the allocation */ |
| 92 | vka_utspace_free(vka, kobject_get_type(KOBJECT_FRAME, mapping->page_size_bits), |
| 93 | mapping->page_size_bits, mapping->alloc_cookies[i]); |
| 94 | /* free the caps */ |
Anna Lyons | 6899ede | 2016-10-04 10:05:57 +1100 | [diff] [blame] | 95 | vka_cspace_make_path(vka, mapping->caps[i], &path); |
| 96 | vka_cnode_delete(&path); |
| 97 | vka_cspace_free(vka, mapping->caps[i]); |
Anna Lyons | f2887a5 | 2016-09-30 16:06:15 +1000 | [diff] [blame] | 98 | } |
| 99 | free_node(mapping); |
| 100 | } |
| 101 | |
Yu Hou | e9a9ff4 | 2019-07-18 17:26:01 +1000 | [diff] [blame] | 102 | static void insert_node(sel4platsupport_io_mapper_cookie_t *io_mapper, io_mapping_t *node) |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 103 | { |
| 104 | node->prev = NULL; |
| 105 | node->next = io_mapper->head; |
| 106 | if (io_mapper->head) { |
| 107 | io_mapper->head->prev = node; |
| 108 | } |
| 109 | io_mapper->head = node; |
| 110 | } |
| 111 | |
Yu Hou | e9a9ff4 | 2019-07-18 17:26:01 +1000 | [diff] [blame] | 112 | static io_mapping_t *find_node(sel4platsupport_io_mapper_cookie_t *io_mapper, void *returned_addr) |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 113 | { |
| 114 | io_mapping_t *current; |
| 115 | for (current = io_mapper->head; current; current = current->next) { |
| 116 | if (current->returned_addr == returned_addr) { |
| 117 | return current; |
| 118 | } |
| 119 | } |
| 120 | return NULL; |
| 121 | } |
| 122 | |
Yu Hou | e9a9ff4 | 2019-07-18 17:26:01 +1000 | [diff] [blame] | 123 | static void remove_node(sel4platsupport_io_mapper_cookie_t *io_mapper, io_mapping_t *node) |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 124 | { |
| 125 | if (node->prev) { |
| 126 | node->prev->next = node->next; |
| 127 | } else { |
| 128 | assert(io_mapper->head == node); |
| 129 | io_mapper->head = node->next; |
| 130 | } |
| 131 | if (node->next) { |
| 132 | node->next->prev = node->prev; |
| 133 | } |
| 134 | } |
| 135 | |
Yu Hou | e9a9ff4 | 2019-07-18 17:26:01 +1000 | [diff] [blame] | 136 | static void *sel4platsupport_map_paddr_with_page_size(sel4platsupport_io_mapper_cookie_t *io_mapper, uintptr_t paddr, |
| 137 | size_t size, size_t page_size_bits, bool cached) |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 138 | { |
| 139 | |
Damon Lee | 28c5fdd | 2019-07-23 11:27:46 +1000 | [diff] [blame] | 140 | vka_t *vka = io_mapper->vka; |
| 141 | vspace_t *vspace = io_mapper->vspace; |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 142 | |
| 143 | /* search at start of page */ |
| 144 | int page_size = BIT(page_size_bits); |
| 145 | uintptr_t start = ROUND_DOWN(paddr, page_size); |
Adrian Danis | 5f4e7d1 | 2016-03-03 15:27:15 +1100 | [diff] [blame] | 146 | uintptr_t offset = paddr - start; |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 147 | size += offset; |
| 148 | |
Anna Lyons | f2887a5 | 2016-09-30 16:06:15 +1000 | [diff] [blame] | 149 | io_mapping_t *mapping = new_node(BYTES_TO_SIZE_BITS_PAGES(size, page_size_bits)); |
| 150 | assert(mapping->num_pages << page_size_bits >= size); |
| 151 | if (!mapping) { |
| 152 | ZF_LOGE("Failed to allocate node for %zu pages", mapping->num_pages); |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 153 | return NULL; |
| 154 | } |
Anna Lyons | f2887a5 | 2016-09-30 16:06:15 +1000 | [diff] [blame] | 155 | mapping->page_size_bits = page_size_bits; |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 156 | |
Anna Lyons | f2887a5 | 2016-09-30 16:06:15 +1000 | [diff] [blame] | 157 | seL4_Word type = kobject_get_type(KOBJECT_FRAME, mapping->page_size_bits); |
| 158 | /* allocate all of the physical frame caps */ |
| 159 | for (unsigned int i = 0; i < mapping->num_pages; i++) { |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 160 | /* allocate a cslot */ |
Anna Lyons | f2887a5 | 2016-09-30 16:06:15 +1000 | [diff] [blame] | 161 | int error = vka_cspace_alloc(vka, &mapping->caps[i]); |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 162 | if (error) { |
Anna Lyons | 67c869c | 2016-03-30 11:16:41 +1100 | [diff] [blame] | 163 | ZF_LOGE("cspace alloc failed"); |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 164 | assert(error == 0); |
| 165 | /* we don't clean up as everything has gone to hell */ |
| 166 | return NULL; |
| 167 | } |
| 168 | |
| 169 | /* create a path */ |
| 170 | cspacepath_t path; |
Anna Lyons | f2887a5 | 2016-09-30 16:06:15 +1000 | [diff] [blame] | 171 | vka_cspace_make_path(vka, mapping->caps[i], &path); |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 172 | |
Anna Lyons | f2887a5 | 2016-09-30 16:06:15 +1000 | [diff] [blame] | 173 | /* allocate the frame */ |
| 174 | error = vka_utspace_alloc_at(vka, &path, type, page_size_bits, start + (i * page_size), |
Anna Lyons | 6899ede | 2016-10-04 10:05:57 +1100 | [diff] [blame] | 175 | &mapping->alloc_cookies[i]); |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 176 | if (error) { |
| 177 | /* free this slot, and then do general cleanup of the rest of the slots. |
| 178 | * this avoids a needless seL4_CNode_Delete of this slot, as there is no |
| 179 | * cap in it */ |
Anna Lyons | f2887a5 | 2016-09-30 16:06:15 +1000 | [diff] [blame] | 180 | vka_cspace_free(vka, mapping->caps[i]); |
| 181 | mapping->num_pages = i; |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 182 | goto error; |
| 183 | } |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 184 | } |
| 185 | |
| 186 | /* Now map the frames in */ |
Yu Hou | e9a9ff4 | 2019-07-18 17:26:01 +1000 | [diff] [blame] | 187 | mapping->mapped_addr = vspace_map_pages(vspace, mapping->caps, mapping->alloc_cookies, seL4_AllRights, |
| 188 | mapping->num_pages, |
Anna Lyons | 6899ede | 2016-10-04 10:05:57 +1100 | [diff] [blame] | 189 | mapping->page_size_bits, cached); |
Anna Lyons | f2887a5 | 2016-09-30 16:06:15 +1000 | [diff] [blame] | 190 | if (mapping->mapped_addr != NULL) { |
| 191 | /* fill out and insert node */ |
| 192 | mapping->returned_addr = mapping->mapped_addr + offset; |
| 193 | insert_node(io_mapper, mapping); |
| 194 | return mapping->returned_addr; |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 195 | } |
| 196 | error: |
Anna Lyons | f2887a5 | 2016-09-30 16:06:15 +1000 | [diff] [blame] | 197 | destroy_node(vka, mapping); |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 198 | return NULL; |
| 199 | } |
| 200 | |
Yu Hou | e9a9ff4 | 2019-07-18 17:26:01 +1000 | [diff] [blame] | 201 | static void *sel4platsupport_map_paddr(void *cookie, uintptr_t paddr, size_t size, int cached, |
| 202 | UNUSED ps_mem_flags_t flags) |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 203 | { |
Damon Lee | 0cf1c70 | 2019-07-25 17:11:46 +1000 | [diff] [blame] | 204 | if (!cookie) { |
| 205 | ZF_LOGE("cookie is NULL"); |
| 206 | return NULL; |
| 207 | } |
| 208 | |
Yu Hou | e9a9ff4 | 2019-07-18 17:26:01 +1000 | [diff] [blame] | 209 | sel4platsupport_io_mapper_cookie_t *io_mapper = (sel4platsupport_io_mapper_cookie_t *)cookie; |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 210 | int frame_size_index = 0; |
| 211 | /* find the largest reasonable frame size */ |
Anna Lyons | 3a9da54 | 2016-02-29 14:07:08 +1100 | [diff] [blame] | 212 | while (frame_size_index + 1 < SEL4_NUM_PAGE_SIZES) { |
| 213 | if (size >> sel4_page_sizes[frame_size_index + 1] == 0) { |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 214 | break; |
| 215 | } |
| 216 | frame_size_index++; |
| 217 | } |
Alexander Kroh | 637e0d4 | 2015-06-26 13:44:02 +1000 | [diff] [blame] | 218 | |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 219 | /* try mapping in this and all smaller frame sizes until something works */ |
| 220 | for (int i = frame_size_index; i >= 0; i--) { |
Anna Lyons | 3a9da54 | 2016-02-29 14:07:08 +1100 | [diff] [blame] | 221 | void *result = sel4platsupport_map_paddr_with_page_size(io_mapper, paddr, size, sel4_page_sizes[i], cached); |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 222 | if (result) { |
| 223 | return result; |
| 224 | } |
| 225 | } |
| 226 | |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 227 | /* shit out of luck */ |
Anna Lyons | 67c869c | 2016-03-30 11:16:41 +1100 | [diff] [blame] | 228 | ZF_LOGE("Failed to find a way to map address %p", (void *)paddr); |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 229 | return NULL; |
| 230 | } |
| 231 | |
Yu Hou | e9a9ff4 | 2019-07-18 17:26:01 +1000 | [diff] [blame] | 232 | static void sel4platsupport_unmap_vaddr(void *cookie, void *vaddr, UNUSED size_t size) |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 233 | { |
Damon Lee | 0cf1c70 | 2019-07-25 17:11:46 +1000 | [diff] [blame] | 234 | if (!cookie) { |
| 235 | ZF_LOGE("cookie is NULL"); |
| 236 | } |
| 237 | |
Yu Hou | e9a9ff4 | 2019-07-18 17:26:01 +1000 | [diff] [blame] | 238 | sel4platsupport_io_mapper_cookie_t *io_mapper = cookie; |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 239 | |
Damon Lee | 28c5fdd | 2019-07-23 11:27:46 +1000 | [diff] [blame] | 240 | vspace_t *vspace = io_mapper->vspace; |
| 241 | vka_t *vka = io_mapper->vka; |
Anna Lyons | f2887a5 | 2016-09-30 16:06:15 +1000 | [diff] [blame] | 242 | io_mapping_t *mapping = find_node(io_mapper, vaddr); |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 243 | |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 244 | if (!mapping) { |
Anna Lyons | 67c869c | 2016-03-30 11:16:41 +1100 | [diff] [blame] | 245 | ZF_LOGF("Tried to unmap vaddr %p, which was never mapped in", vaddr); |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 246 | return; |
| 247 | } |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 248 | |
Anna Lyons | f2887a5 | 2016-09-30 16:06:15 +1000 | [diff] [blame] | 249 | /* unmap the pages */ |
| 250 | vspace_unmap_pages(vspace, mapping->mapped_addr, mapping->num_pages, mapping->page_size_bits, |
Alexander Kroh | 637e0d4 | 2015-06-26 13:44:02 +1000 | [diff] [blame] | 251 | VSPACE_PRESERVE); |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 252 | |
Anna Lyons | f2887a5 | 2016-09-30 16:06:15 +1000 | [diff] [blame] | 253 | /* clean up the node */ |
| 254 | remove_node(io_mapper, mapping); |
| 255 | destroy_node(vka, mapping); |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 256 | } |
| 257 | |
Damon Lee | 28c5fdd | 2019-07-23 11:27:46 +1000 | [diff] [blame] | 258 | int sel4platsupport_new_io_mapper(vspace_t *vspace, vka_t *vka, ps_io_mapper_t *io_mapper) |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 259 | { |
Anna Lyons | ebee53e | 2018-03-13 16:30:44 +1100 | [diff] [blame] | 260 | sel4platsupport_io_mapper_cookie_t *cookie = calloc(1, sizeof(sel4platsupport_io_mapper_cookie_t)); |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 261 | if (!cookie) { |
Anna Lyons | f2887a5 | 2016-09-30 16:06:15 +1000 | [diff] [blame] | 262 | ZF_LOGE("Failed to allocate %zu bytes", sizeof(sel4platsupport_io_mapper_cookie_t)); |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 263 | return -1; |
| 264 | } |
Anna Lyons | f2887a5 | 2016-09-30 16:06:15 +1000 | [diff] [blame] | 265 | |
| 266 | cookie->vspace = vspace; |
| 267 | cookie->vka = vka; |
| 268 | io_mapper->cookie = cookie; |
| 269 | io_mapper->io_map_fn = sel4platsupport_map_paddr; |
| 270 | io_mapper->io_unmap_fn = sel4platsupport_unmap_vaddr; |
| 271 | |
TrustworthySystems | cedc056 | 2014-07-22 14:11:16 +1000 | [diff] [blame] | 272 | return 0; |
| 273 | } |
Damon Lee | 3e7189f | 2019-07-18 14:06:09 +1000 | [diff] [blame] | 274 | |
Yu Hou | e9a9ff4 | 2019-07-18 17:26:01 +1000 | [diff] [blame] | 275 | int sel4platsupport_new_malloc_ops(ps_malloc_ops_t *ops) |
Anna Lyons | 40c16d9 | 2017-07-17 09:46:07 +1000 | [diff] [blame] | 276 | { |
Anna Lyons | ef21299 | 2017-09-29 08:57:01 +1000 | [diff] [blame] | 277 | ps_new_stdlib_malloc_ops(ops); |
Anna Lyons | 887abc3 | 2017-07-17 15:29:48 +1000 | [diff] [blame] | 278 | return 0; |
Anna Lyons | 40c16d9 | 2017-07-17 09:46:07 +1000 | [diff] [blame] | 279 | } |
| 280 | |
Damon Lee | 8869a2c | 2019-07-18 14:06:37 +1000 | [diff] [blame] | 281 | static char *sel4platsupport_io_fdt_get(void *cookie) |
| 282 | { |
| 283 | return cookie != NULL ? (char *) cookie : NULL; |
| 284 | } |
| 285 | |
| 286 | int sel4platsupport_new_fdt_ops(ps_io_fdt_t *io_fdt, simple_t *simple, ps_malloc_ops_t *malloc_ops) |
| 287 | { |
| 288 | if (!io_fdt || !simple || !malloc_ops) { |
| 289 | ZF_LOGE("arguments are NULL"); |
| 290 | return -1; |
| 291 | } |
| 292 | |
| 293 | ssize_t block_size = simple_get_extended_bootinfo_length(simple, SEL4_BOOTINFO_HEADER_FDT); |
Damon Lee | 89360ac | 2019-07-25 17:12:48 +1000 | [diff] [blame] | 294 | if (block_size > 0) { |
| 295 | int error = ps_calloc(malloc_ops, 1, block_size, &io_fdt->cookie); |
| 296 | if (error) { |
| 297 | ZF_LOGE("Failed to allocate %zu bytes for the FDT", block_size); |
| 298 | return -1; |
| 299 | } |
Damon Lee | 8869a2c | 2019-07-18 14:06:37 +1000 | [diff] [blame] | 300 | |
Damon Lee | 89360ac | 2019-07-25 17:12:48 +1000 | [diff] [blame] | 301 | /* Copy the FDT from the extended bootinfo */ |
| 302 | ssize_t copied_size = simple_get_extended_bootinfo(simple, SEL4_BOOTINFO_HEADER_FDT, |
| 303 | io_fdt->cookie, block_size); |
| 304 | if (copied_size != block_size) { |
| 305 | ZF_LOGE("Failed to copy the FDT"); |
| 306 | ZF_LOGF_IF(ps_free(malloc_ops, block_size, io_fdt->cookie), |
| 307 | "Failed to clean-up after a failed operation!"); |
| 308 | return -1; |
| 309 | } |
| 310 | |
| 311 | /* Cut off the bootinfo header from the start of the buffer */ |
| 312 | ssize_t fdt_size = block_size - sizeof(seL4_BootInfoHeader); |
| 313 | void *fdt_start = io_fdt->cookie + sizeof(seL4_BootInfoHeader); |
| 314 | memmove(io_fdt->cookie, fdt_start, fdt_size); |
| 315 | |
| 316 | /* Trim off the extra bytes at the end of the FDT */ |
| 317 | void *fdt_end = io_fdt->cookie + fdt_size; |
| 318 | memset(fdt_end, 0, sizeof(seL4_BootInfoHeader)); |
| 319 | } else { |
| 320 | /* No FDT is available so just set the cookie to NULL */ |
| 321 | io_fdt->cookie = NULL; |
Damon Lee | 8869a2c | 2019-07-18 14:06:37 +1000 | [diff] [blame] | 322 | } |
| 323 | |
Damon Lee | 8869a2c | 2019-07-18 14:06:37 +1000 | [diff] [blame] | 324 | /* Set the function pointer inside the io_fdt interface */ |
| 325 | io_fdt->get_fn = sel4platsupport_io_fdt_get; |
| 326 | |
| 327 | return 0; |
| 328 | } |
| 329 | |
Damon Lee | 5ac1874 | 2019-07-25 13:48:54 +1000 | [diff] [blame] | 330 | int sel4platsupport_new_io_ops(vspace_t *vspace, vka_t *vka, simple_t *simple, ps_io_ops_t *io_ops) |
Alexander Kroh | 637e0d4 | 2015-06-26 13:44:02 +1000 | [diff] [blame] | 331 | { |
Anna Lyons | c28e0d4 | 2017-10-04 09:48:23 +1100 | [diff] [blame] | 332 | memset(io_ops, 0, sizeof(ps_io_ops_t)); |
| 333 | |
Damon Lee | 5ac1874 | 2019-07-25 13:48:54 +1000 | [diff] [blame] | 334 | int error = 0; |
| 335 | |
| 336 | /* Initialise the interfaces which do not require memory allocation/need to be initialised first */ |
Damon Lee | 2d74ed2 | 2019-12-03 10:48:45 +1100 | [diff] [blame] | 337 | error = sel4platsupport_new_malloc_ops(&io_ops->malloc_ops); |
Damon Lee | 5ac1874 | 2019-07-25 13:48:54 +1000 | [diff] [blame] | 338 | if (error) { |
| 339 | return error; |
Alexander Kroh | 637e0d4 | 2015-06-26 13:44:02 +1000 | [diff] [blame] | 340 | } |
Anna Lyons | f2887a5 | 2016-09-30 16:06:15 +1000 | [diff] [blame] | 341 | |
Damon Lee | 5ac1874 | 2019-07-25 13:48:54 +1000 | [diff] [blame] | 342 | /* Now allocate the IO-specific interfaces (the ones that can be found in this file) */ |
| 343 | error = sel4platsupport_new_io_mapper(vspace, vka, &io_ops->io_mapper); |
| 344 | if (error) { |
| 345 | return error; |
| 346 | } |
Kofi Doku Atuah | d1ed16a | 2017-11-15 15:32:07 +1100 | [diff] [blame] | 347 | |
Damon Lee | 4a474d3 | 2019-07-25 13:52:21 +1000 | [diff] [blame] | 348 | error = sel4platsupport_new_fdt_ops(&io_ops->io_fdt, simple, &io_ops->malloc_ops); |
| 349 | if (error) { |
| 350 | free(io_ops->io_mapper.cookie); |
| 351 | io_ops->io_mapper.cookie = NULL; |
| 352 | return error; |
| 353 | } |
| 354 | |
Damon Lee | 5ac1874 | 2019-07-25 13:48:54 +1000 | [diff] [blame] | 355 | error = sel4platsupport_new_irq_ops(&io_ops->irq_ops, vka, simple, DEFAULT_IRQ_INTERFACE_CONFIG, |
| 356 | &io_ops->malloc_ops); |
| 357 | if (error) { |
| 358 | free(io_ops->io_mapper.cookie); |
| 359 | io_ops->io_mapper.cookie = NULL; |
Damon Lee | 4a474d3 | 2019-07-25 13:52:21 +1000 | [diff] [blame] | 360 | ssize_t fdt_size = simple_get_extended_bootinfo_length(simple, SEL4_BOOTINFO_HEADER_FDT); |
| 361 | if (fdt_size > 0) { |
| 362 | /* The FDT is available on this platform and we actually copied it, so we free it */ |
| 363 | ps_free(&io_ops->malloc_ops, fdt_size, &io_ops->io_fdt.cookie); |
| 364 | } |
Damon Lee | 5ac1874 | 2019-07-25 13:48:54 +1000 | [diff] [blame] | 365 | return error; |
| 366 | } |
| 367 | |
| 368 | return 0; |
Alexander Kroh | 637e0d4 | 2015-06-26 13:44:02 +1000 | [diff] [blame] | 369 | } |