1cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* 2cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * Copyright 2014 The Chromium OS Authors. All rights reserved. 3cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * Use of this source code is governed by a BSD-style license that can be 4cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * found in the LICENSE file. 5cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson */ 6cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 7cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <stdint.h> 8cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <stdio.h> 9cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 102559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson#include "file_type.h" 11cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "fmap.h" 12cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "futility.h" 13cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "traversal.h" 14cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 15cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* What functions do we invoke for a particular operation and component? */ 16cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 17cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* FUTIL_OP_SHOW */ 186f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardsonstatic int (* const cb_show_funcs[])(struct futil_traverse_state_s *state) = { 19cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson futil_cb_show_begin, /* CB_BEGIN_TRAVERSAL */ 20cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson NULL, /* CB_END_TRAVERSAL */ 21cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson futil_cb_show_gbb, /* CB_FMAP_GBB */ 22cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson futil_cb_show_fw_preamble, /* CB_FMAP_VBLOCK_A */ 23cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson futil_cb_show_fw_preamble, /* CB_FMAP_VBLOCK_B */ 246f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson futil_cb_show_fw_main, /* CB_FMAP_FW_MAIN_A */ 256f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson futil_cb_show_fw_main, /* CB_FMAP_FW_MAIN_B */ 264805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson futil_cb_show_pubkey, /* CB_PUBKEY */ 276f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson futil_cb_show_keyblock, /* CB_KEYBLOCK */ 28cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson futil_cb_show_gbb, /* CB_GBB */ 29cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson futil_cb_show_fw_preamble, /* CB_FW_PREAMBLE */ 305f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson futil_cb_show_kernel_preamble, /* CB_KERN_PREAMBLE */ 316f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson NULL, /* CB_RAW_FIRMWARE */ 326f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson NULL, /* CB_RAW_KERNEL */ 334805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson futil_cb_show_privkey, /* CB_PRIVKEY */ 34cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}; 35cf6e78dbd54684ebba0c3bfc2524426f61193416Bill RichardsonBUILD_ASSERT(ARRAY_SIZE(cb_show_funcs) == NUM_CB_COMPONENTS); 36cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 3715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson/* FUTIL_OP_SIGN */ 386f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardsonstatic int (* const cb_sign_funcs[])(struct futil_traverse_state_s *state) = { 3915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson futil_cb_sign_begin, /* CB_BEGIN_TRAVERSAL */ 4015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson futil_cb_sign_end, /* CB_END_TRAVERSAL */ 4115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson NULL, /* CB_FMAP_GBB */ 425f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson futil_cb_sign_fw_vblock, /* CB_FMAP_VBLOCK_A */ 435f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson futil_cb_sign_fw_vblock, /* CB_FMAP_VBLOCK_B */ 445f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson futil_cb_sign_fw_main, /* CB_FMAP_FW_MAIN_A */ 455f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson futil_cb_sign_fw_main, /* CB_FMAP_FW_MAIN_B */ 465f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson futil_cb_sign_pubkey, /* CB_PUBKEY */ 475f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson NULL, /* CB_KEYBLOCK */ 485f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson NULL, /* CB_GBB */ 495f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson NULL, /* CB_FW_PREAMBLE */ 505f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson futil_cb_resign_kernel_part, /* CB_KERN_PREAMBLE */ 515f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson futil_cb_sign_raw_firmware, /* CB_RAW_FIRMWARE */ 525f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson futil_cb_create_kernel_part, /* CB_RAW_KERNEL */ 534805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson NULL, /* CB_PRIVKEY */ 5415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson}; 5515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill RichardsonBUILD_ASSERT(ARRAY_SIZE(cb_sign_funcs) == NUM_CB_COMPONENTS); 5615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 576f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardsonstatic int (* const * const cb_func[])(struct futil_traverse_state_s *state) = { 58cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson cb_show_funcs, 5915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson cb_sign_funcs, 60cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}; 61cf6e78dbd54684ebba0c3bfc2524426f61193416Bill RichardsonBUILD_ASSERT(ARRAY_SIZE(cb_func) == NUM_FUTIL_OPS); 62cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 63cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* 64cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * File types that don't need iterating can use a lookup table to determine the 65cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * callback component and name. The index is the file type. 66cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson */ 67cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic const struct { 68cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson enum futil_cb_component component; 69cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson const char * const name; 70cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} direct_callback[] = { 71cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {0, NULL}, /* FILE_TYPE_UNKNOWN */ 72cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {CB_PUBKEY, "VbPublicKey"}, /* FILE_TYPE_PUBKEY */ 73cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {CB_KEYBLOCK, "VbKeyBlock"}, /* FILE_TYPE_KEYBLOCK */ 746f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson {CB_FW_PREAMBLE, "FW Preamble"}, /* FILE_TYPE_FW_PREAMBLE */ 75cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {CB_GBB, "GBB"}, /* FILE_TYPE_GBB */ 76cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {0, NULL}, /* FILE_TYPE_BIOS_IMAGE */ 77cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {0, NULL}, /* FILE_TYPE_OLD_BIOS_IMAGE */ 786f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson {CB_KERN_PREAMBLE, "Kernel Preamble"}, /* FILE_TYPE_KERN_PREAMBLE */ 796f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson {CB_RAW_FIRMWARE, "raw firmware"}, /* FILE_TYPE_RAW_FIRMWARE */ 806f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson {CB_RAW_KERNEL, "raw kernel"}, /* FILE_TYPE_RAW_KERNEL */ 812559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson {0, "chromiumos disk"}, /* FILE_TYPE_CHROMIUMOS_DISK */ 824805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson {CB_PRIVKEY, "VbPrivateKey"}, /* FILE_TYPE_PRIVKEY */ 83cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}; 84cf6e78dbd54684ebba0c3bfc2524426f61193416Bill RichardsonBUILD_ASSERT(ARRAY_SIZE(direct_callback) == NUM_FILE_TYPES); 85cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 86cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* 87cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * The Chrome OS BIOS must contain specific FMAP areas, and we generally want 88cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * to look at each one in a certain order. 89cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson */ 90cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstruct bios_area_s { 91cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson const char * const name; 92cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson enum futil_cb_component component; 93cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}; 94cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 95cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* This are the expected areas, in order of traversal. */ 96cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic const struct bios_area_s bios_area[] = { 97cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {"GBB", CB_FMAP_GBB}, 98cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {"FW_MAIN_A", CB_FMAP_FW_MAIN_A}, 99cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {"FW_MAIN_B", CB_FMAP_FW_MAIN_B}, 100cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {"VBLOCK_A", CB_FMAP_VBLOCK_A}, 101cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {"VBLOCK_B", CB_FMAP_VBLOCK_B}, 102cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {0, 0} 103cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}; 104cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 105cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* Really old BIOS images had different names, but worked the same. */ 106cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic const struct bios_area_s old_bios_area[] = { 107cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {"GBB Area", CB_FMAP_GBB}, 108cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {"Firmware A Data", CB_FMAP_FW_MAIN_A}, 109cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {"Firmware B Data", CB_FMAP_FW_MAIN_B}, 110cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {"Firmware A Key", CB_FMAP_VBLOCK_A}, 111cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {"Firmware B Key", CB_FMAP_VBLOCK_B}, 112cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {0, 0} 113cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}; 114cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 115cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic int has_all_areas(uint8_t *buf, uint32_t len, FmapHeader *fmap, 116cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson const struct bios_area_s *area) 117cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 1186f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson /* We must have all the expected areas */ 1196f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson for (; area->name; area++) 120cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (!fmap_find_by_name(buf, len, fmap, area->name, 0)) 121cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 0; 122cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 123cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* Found 'em all */ 124cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 125cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 126cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 1272559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardsonenum futil_file_type recognize_bios_image(uint8_t *buf, uint32_t len) 1282559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson{ 1292559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson FmapHeader *fmap = fmap_find(buf, len); 1302559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson if (fmap) { 1312559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson if (has_all_areas(buf, len, fmap, bios_area)) 1322559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson return FILE_TYPE_BIOS_IMAGE; 1332559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson if (has_all_areas(buf, len, fmap, old_bios_area)) 1342559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson return FILE_TYPE_OLD_BIOS_IMAGE; 1352559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson } 1362559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson return FILE_TYPE_UNKNOWN; 1372559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson} 1386f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson 1397ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardsonstatic const char * const futil_cb_component_str[] = { 1406f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson "CB_BEGIN_TRAVERSAL", 1416f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson "CB_END_TRAVERSAL", 1426f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson "CB_FMAP_GBB", 1436f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson "CB_FMAP_VBLOCK_A", 1446f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson "CB_FMAP_VBLOCK_B", 1456f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson "CB_FMAP_FW_MAIN_A", 1466f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson "CB_FMAP_FW_MAIN_B", 1476f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson "CB_PUBKEY", 1486f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson "CB_KEYBLOCK", 1496f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson "CB_GBB", 1506f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson "CB_FW_PREAMBLE", 1516f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson "CB_KERN_PREAMBLE", 1526f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson "CB_RAW_FIRMWARE", 1536f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson "CB_RAW_KERNEL", 1544805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson "CB_PRIVKEY", 1556f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson}; 1566f72ffa8037acb69de4fc4346783ea10298a7e57Bill RichardsonBUILD_ASSERT(ARRAY_SIZE(futil_cb_component_str) == NUM_CB_COMPONENTS); 1576f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson 1586f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardsonstatic int invoke_callback(struct futil_traverse_state_s *state, 1596f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson enum futil_cb_component c, const char *name, 1606f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson uint32_t offset, uint8_t *buf, uint32_t len) 1616f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson{ 1626f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson Debug("%s: name \"%s\" op %d component %s" 1636f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson " offset=0x%08x len=0x%08x, buf=%p\n", 1646f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson __func__, name, state->op, futil_cb_component_str[c], 1656f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson offset, len, buf); 1666f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson 16705987b159acb9737707b9ef92b818ac434ef8c3dDavid Riley if ((int) c < 0 || c >= NUM_CB_COMPONENTS) { 1686f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson fprintf(stderr, "Invalid component %d\n", c); 1696f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson return 1; 1706f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson } 1716f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson 1726f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson state->component = c; 1736f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson state->name = name; 1746f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson state->cb_area[c].offset = offset; 1756f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson state->cb_area[c].buf = buf; 1766f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson state->cb_area[c].len = len; 1776f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson state->my_area = &state->cb_area[c]; 1786f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson 1796f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson if (cb_func[state->op][c]) 1806f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson return cb_func[state->op][c](state); 1816f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson 1826f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson return 0; 1836f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson} 1846f72ffa8037acb69de4fc4346783ea10298a7e57Bill Richardson 1857ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardsonstatic void fmap_limit_area(FmapAreaHeader *ah, uint32_t len) 1867ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson{ 1877ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson uint32_t sum = ah->area_offset + ah->area_size; 1887ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson if (sum < ah->area_size || sum > len) { 1897ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson Debug("%s(%s) 0x%x + 0x%x > 0x%x\n", 1907ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson __func__, ah->area_name, 1917ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson ah->area_offset, ah->area_size, len); 1927ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson ah->area_offset = 0; 1937ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson ah->area_size = 0; 1947ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson } 1957ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson} 1967ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson 197b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardsonint futil_traverse(uint8_t *buf, uint32_t len, 198b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson struct futil_traverse_state_s *state, 199b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson enum futil_file_type type) 200cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 201cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson FmapHeader *fmap; 202cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson FmapAreaHeader *ah = 0; 203cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson const struct bios_area_s *area; 204cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson int retval = 0; 205cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 20605987b159acb9737707b9ef92b818ac434ef8c3dDavid Riley if ((int) state->op < 0 || state->op >= NUM_FUTIL_OPS) { 207b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson fprintf(stderr, "Invalid op %d\n", state->op); 208b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson return 1; 209b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson } 210b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson 211b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson if (type == FILE_TYPE_UNKNOWN) 2122559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson type = futil_file_type_buf(buf, len); 213cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->in_type = type; 214cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 215cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->errors = retval; 216cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson retval |= invoke_callback(state, CB_BEGIN_TRAVERSAL, "<begin>", 217cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 0, buf, len); 218cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->errors = retval; 219cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 220cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson switch (type) { 221cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case FILE_TYPE_BIOS_IMAGE: 222cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* We've already checked, so we know this will work. */ 223cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fmap = fmap_find(buf, len); 224cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson for (area = bios_area; area->name; area++) { 225cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* We know this will work, too */ 226cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fmap_find_by_name(buf, len, fmap, area->name, &ah); 2277ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson /* But the file might be truncated */ 2287ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson fmap_limit_area(ah, len); 229cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson retval |= invoke_callback(state, 230cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson area->component, 231cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson area->name, 232cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson ah->area_offset, 233cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson buf + ah->area_offset, 234cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson ah->area_size); 235cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->errors = retval; 236cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 237cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 238cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 239cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case FILE_TYPE_OLD_BIOS_IMAGE: 240cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* We've already checked, so we know this will work. */ 241cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fmap = fmap_find(buf, len); 242cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson for (area = old_bios_area; area->name; area++) { 243cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* We know this will work, too */ 244cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fmap_find_by_name(buf, len, fmap, area->name, &ah); 2457ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson /* But the file might be truncated */ 2467ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson fmap_limit_area(ah, len); 247cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson retval |= invoke_callback(state, 248cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson area->component, 249cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson area->name, 250cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson ah->area_offset, 251cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson buf + ah->area_offset, 252cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson ah->area_size); 253cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->errors = retval; 254cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 255cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 256cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 2577ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson case FILE_TYPE_UNKNOWN: 2587ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson case FILE_TYPE_CHROMIUMOS_DISK: 2597ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson /* Nothing to do for these file types (yet) */ 2607ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson break; 2617ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson 262cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson default: 2637ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson /* All other file types have their own callbacks */ 2642559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson retval |= invoke_callback(state, 2652559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson direct_callback[type].component, 2662559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson direct_callback[type].name, 2672559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson 0, buf, len); 2682559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson state->errors = retval; 2692559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson break; 270cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 271cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 272cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson retval |= invoke_callback(state, CB_END_TRAVERSAL, "<end>", 273cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 0, buf, len); 274cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return retval; 275cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 276