1 // Copyright 2017 The Fuchsia Authors
2 //
3 // Use of this source code is governed by a MIT-style
4 // license that can be found in the LICENSE file or at
5 // https://opensource.org/licenses/MIT
6
7 #include <pdev/pdev.h>
8
9 #include <assert.h>
10 #include <lk/init.h>
11 #include <pdev/driver.h>
12 #include <stdio.h>
13
14 static const zbi_header_t* driver_zbi = NULL;
15
16 extern const struct lk_pdev_init_struct __start_lk_pdev_init[];
17 extern const struct lk_pdev_init_struct __stop_lk_pdev_init[];
18
pdev_init_driver(uint32_t type,const void * driver_data,uint32_t length,uint level)19 static void pdev_init_driver(uint32_t type, const void* driver_data, uint32_t length, uint level) {
20 const struct lk_pdev_init_struct* ptr;
21 for (ptr = __start_lk_pdev_init; ptr != __stop_lk_pdev_init; ptr++) {
22 if (ptr->type == type && ptr->level == level) {
23 ptr->hook(driver_data, length);
24 return;
25 }
26 }
27 }
28
pdev_run_hooks(uint level)29 static void pdev_run_hooks(uint level) {
30 if (!driver_zbi) {
31 return;
32 }
33
34 const zbi_header_t* item = driver_zbi;
35 DEBUG_ASSERT(item->type == ZBI_TYPE_CONTAINER);
36 DEBUG_ASSERT(item->extra == ZBI_CONTAINER_MAGIC);
37
38 const uint8_t* start = (uint8_t*)item + sizeof(zbi_header_t);
39 const uint8_t* end = start + item->length;
40
41 while (static_cast<size_t>(end - start) > sizeof(zbi_header_t)) {
42 item = reinterpret_cast<const zbi_header_t*>(start);
43 if (item->type == ZBI_TYPE_KERNEL_DRIVER) {
44 // kernel driver type is in boot item extra
45 // driver data follows boot item
46 pdev_init_driver(item->extra, &item[1], item->length, level);
47 }
48 start += ZBI_ALIGN((uint32_t)sizeof(zbi_header_t) + item->length);
49 }
50 }
51
pdev_init(const zbi_header_t * zbi)52 void pdev_init(const zbi_header_t* zbi) {
53 ASSERT(zbi);
54 driver_zbi = zbi;
55
56 pdev_run_hooks(LK_INIT_LEVEL_PLATFORM_EARLY);
57 }
58
platform_dev_init(uint level)59 static void platform_dev_init(uint level) {
60 pdev_run_hooks(level);
61 }
62
63 LK_INIT_HOOK(platform_dev_init, platform_dev_init, LK_INIT_LEVEL_PLATFORM);
64