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 <assert.h> 8#include <stdio.h> 9#include <pdev/driver.h> 10#include <pdev/pdev.h> 11#include <lk/init.h> 12 13static const zbi_header_t* driver_zbi = NULL; 14 15extern const struct lk_pdev_init_struct __start_lk_pdev_init[]; 16extern const struct lk_pdev_init_struct __stop_lk_pdev_init[]; 17 18static void pdev_init_driver(uint32_t type, const void* driver_data, uint32_t length, uint level) { 19 const struct lk_pdev_init_struct *ptr; 20 for (ptr = __start_lk_pdev_init; ptr != __stop_lk_pdev_init; ptr++) { 21 if (ptr->type == type && ptr->level == level) { 22 ptr->hook(driver_data, length); 23 return; 24 } 25 } 26} 27 28static void pdev_run_hooks(uint level) { 29 if (!driver_zbi) return; 30 31 const zbi_header_t* item = driver_zbi; 32 DEBUG_ASSERT(item->type == ZBI_TYPE_CONTAINER); 33 DEBUG_ASSERT(item->extra == ZBI_CONTAINER_MAGIC); 34 35 const uint8_t* start = (uint8_t*)item + sizeof(zbi_header_t); 36 const uint8_t* end = start + item->length; 37 38 while ((uint32_t)(end - start) > sizeof(zbi_header_t)) { 39 item = (const zbi_header_t*)start; 40 if (item->type == ZBI_TYPE_KERNEL_DRIVER) { 41 // kernel driver type is in boot item extra 42 // driver data follows boot item 43 pdev_init_driver(item->extra, &item[1], item->length, level); 44 } 45 start += ZBI_ALIGN(sizeof(zbi_header_t) + item->length); 46 } 47} 48 49void pdev_init(const zbi_header_t* zbi) { 50 ASSERT(zbi); 51 driver_zbi = zbi; 52 53 pdev_run_hooks(LK_INIT_LEVEL_PLATFORM_EARLY); 54} 55 56static void platform_dev_init(uint level) { 57 pdev_run_hooks(level); 58} 59 60LK_INIT_HOOK(platform_dev_init, platform_dev_init, LK_INIT_LEVEL_PLATFORM); 61