Branch data Line data Source code
1 : : /* 2 : : * Copyright (c) 2015-2016 Intel Corporation. 3 : : * 4 : : * SPDX-License-Identifier: Apache-2.0 5 : : */ 6 : : 7 : : #include <string.h> 8 : : #include <device.h> 9 : : #include <sys/atomic.h> 10 : : #include <syscall_handler.h> 11 : : 12 : : extern const struct init_entry __init_start[]; 13 : : extern const struct init_entry __init_PRE_KERNEL_1_start[]; 14 : : extern const struct init_entry __init_PRE_KERNEL_2_start[]; 15 : : extern const struct init_entry __init_POST_KERNEL_start[]; 16 : : extern const struct init_entry __init_APPLICATION_start[]; 17 : : extern const struct init_entry __init_end[]; 18 : : 19 : : #ifdef CONFIG_SMP 20 : : extern const struct init_entry __init_SMP_start[]; 21 : : #endif 22 : : 23 : : extern const struct device __device_start[]; 24 : : extern const struct device __device_end[]; 25 : : 26 : : 27 : : /** 28 : : * @brief Initialize state for all static devices. 29 : : * 30 : : * The state object is always zero-initialized, but this may not be 31 : : * sufficient. 32 : : */ 33 : 1 : void z_device_state_init(void) 34 : : { 35 : 1 : const struct device *dev = __device_start; 36 : : 37 [ + + ]: 5 : while (dev < __device_end) { 38 : 4 : z_object_init(dev); 39 : 4 : ++dev; 40 : : } 41 : 1 : } 42 : : 43 : : /** 44 : : * @brief Execute all the init entry initialization functions at a given level 45 : : * 46 : : * @details Invokes the initialization routine for each init entry object 47 : : * created by the INIT_ENTRY_DEFINE() macro using the specified level. 48 : : * The linker script places the init entry objects in memory in the order 49 : : * they need to be invoked, with symbols indicating where one level leaves 50 : : * off and the next one begins. 51 : : * 52 : : * @param level init level to run. 53 : : */ 54 : 4 : void z_sys_init_run_level(int32_t level) 55 : : { 56 : : static const struct init_entry *levels[] = { 57 : : __init_PRE_KERNEL_1_start, 58 : : __init_PRE_KERNEL_2_start, 59 : : __init_POST_KERNEL_start, 60 : : __init_APPLICATION_start, 61 : : #ifdef CONFIG_SMP 62 : : __init_SMP_start, 63 : : #endif 64 : : /* End marker */ 65 : : __init_end, 66 : : }; 67 : : const struct init_entry *entry; 68 : : 69 [ + + ]: 15 : for (entry = levels[level]; entry < levels[level+1]; entry++) { 70 : 11 : const struct device *dev = entry->dev; 71 : 11 : int rc = entry->init(dev); 72 : : 73 [ + + ]: 11 : if (dev != NULL) { 74 : : /* Mark device initialized. If initialization 75 : : * failed, record the error condition. 76 : : */ 77 [ - + ]: 4 : if (rc != 0) { 78 [ # # ]: 0 : if (rc < 0) { 79 : 0 : rc = -rc; 80 : : } 81 [ # # ]: 0 : if (rc > UINT8_MAX) { 82 : 0 : rc = UINT8_MAX; 83 : : } 84 : 0 : dev->state->init_res = rc; 85 : : } 86 : 4 : dev->state->initialized = true; 87 : : } 88 : : } 89 : 4 : } 90 : : 91 : 0 : const struct device *z_impl_device_get_binding(const char *name) 92 : : { 93 : : const struct device *dev; 94 : : 95 : : /* A null string identifies no device. So does an empty 96 : : * string. 97 : : */ 98 [ # # # # ]: 0 : if ((name == NULL) || (name[0] == '\0')) { 99 : 0 : return NULL; 100 : : } 101 : : 102 : : /* Split the search into two loops: in the common scenario, where 103 : : * device names are stored in ROM (and are referenced by the user 104 : : * with CONFIG_* macros), only cheap pointer comparisons will be 105 : : * performed. Reserve string comparisons for a fallback. 106 : : */ 107 [ # # ]: 0 : for (dev = __device_start; dev != __device_end; dev++) { 108 [ # # # # ]: 0 : if (z_device_is_ready(dev) && (dev->name == name)) { 109 : 0 : return dev; 110 : : } 111 : : } 112 : : 113 [ # # ]: 0 : for (dev = __device_start; dev != __device_end; dev++) { 114 [ # # # # ]: 0 : if (z_device_is_ready(dev) && (strcmp(name, dev->name) == 0)) { 115 : 0 : return dev; 116 : : } 117 : : } 118 : : 119 : 0 : return NULL; 120 : : } 121 : : 122 : : #ifdef CONFIG_USERSPACE 123 : : static inline const struct device *z_vrfy_device_get_binding(const char *name) 124 : : { 125 : : char name_copy[Z_DEVICE_MAX_NAME_LEN]; 126 : : 127 : : if (z_user_string_copy(name_copy, (char *)name, sizeof(name_copy)) 128 : : != 0) { 129 : : return NULL; 130 : : } 131 : : 132 : : return z_impl_device_get_binding(name_copy); 133 : : } 134 : : #include <syscalls/device_get_binding_mrsh.c> 135 : : 136 : : static inline bool z_vrfy_device_is_ready(const struct device *dev) 137 : : { 138 : : Z_OOPS(Z_SYSCALL_OBJ_INIT(dev, K_OBJ_ANY)); 139 : : 140 : : return z_impl_device_is_ready(dev); 141 : : } 142 : : #include <syscalls/device_is_ready_mrsh.c> 143 : : #endif /* CONFIG_USERSPACE */ 144 : : 145 : 0 : size_t z_device_get_all_static(struct device const **devices) 146 : : { 147 : 0 : *devices = __device_start; 148 : 0 : return __device_end - __device_start; 149 : : } 150 : : 151 : 1 : bool z_device_is_ready(const struct device *dev) 152 : : { 153 : : /* 154 : : * if an invalid device pointer is passed as argument, this call 155 : : * reports the `device` as not ready for usage. 156 : : */ 157 [ - + ]: 1 : if (dev == NULL) { 158 : 0 : return false; 159 : : } 160 : : 161 [ + - + - ]: 1 : return dev->state->initialized && (dev->state->init_res == 0U); 162 : : } 163 : : 164 : 0 : static int device_visitor(const device_handle_t *handles, 165 : : size_t handle_count, 166 : : device_visitor_callback_t visitor_cb, 167 : : void *context) 168 : : { 169 : : /* Iterate over fixed devices */ 170 [ # # ]: 0 : for (size_t i = 0; i < handle_count; ++i) { 171 : 0 : device_handle_t dh = handles[i]; 172 : 0 : const struct device *rdev = device_from_handle(dh); 173 : 0 : int rc = visitor_cb(rdev, context); 174 : : 175 [ # # ]: 0 : if (rc < 0) { 176 : 0 : return rc; 177 : : } 178 : : } 179 : : 180 : 0 : return handle_count; 181 : : } 182 : : 183 : 0 : int device_required_foreach(const struct device *dev, 184 : : device_visitor_callback_t visitor_cb, 185 : : void *context) 186 : : { 187 : 0 : size_t handle_count = 0; 188 : 0 : const device_handle_t *handles = device_required_handles_get(dev, &handle_count); 189 : : 190 : 0 : return device_visitor(handles, handle_count, visitor_cb, context); 191 : : } 192 : : 193 : 0 : int device_supported_foreach(const struct device *dev, 194 : : device_visitor_callback_t visitor_cb, 195 : : void *context) 196 : : { 197 : 0 : size_t handle_count = 0; 198 : 0 : const device_handle_t *handles = device_supported_handles_get(dev, &handle_count); 199 : : 200 : 0 : return device_visitor(handles, handle_count, visitor_cb, context); 201 : : }