// Copyright 2018 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "aml.h" #include #include namespace { // Simplified Amlogic data structures. struct ExtInfo { uint32_t read_info; uint32_t new_type; uint32_t pages_per_block; uint32_t xlc; // slc=1, mlc=2, tlc=3. uint32_t ce_mask; uint32_t boot_num; uint32_t each_boot_pages; uint32_t bbt_occupy_pages; uint32_t bbt_start_block; }; struct Page0 { uint32_t config; uint16_t id; uint16_t max; uint8_t page_list[16]; uint16_t retry_usr[32]; ExtInfo ext_info; }; // The number of pages on a single table. uint32_t g_bbt_size = 0; // Returns the number of valid bad block tables found. int GetNumTables(const char* oob, const nand_info_t& info) { int found = 0; for (uint32_t page = 0; page < info.pages_per_block; page++) { if (memcmp(oob + page * info.oob_size, "nbbt", 4) != 0) { break; } found++; } return found / g_bbt_size; } } // namespace void DumpPage0(const void* data) { const Page0* page0 = reinterpret_cast(data); printf("Config: 0x%x\n", page0->config); printf("ECC step: %u\n", page0->config & 0x3f); printf("Page size (encoded): %u\n", (page0->config >> 6) & 0x7f); printf("Pages per block: %u\n", page0->ext_info.pages_per_block); printf("Boot type: %u\n", page0->ext_info.boot_num); printf("Boot pages: %u\n", page0->ext_info.each_boot_pages); printf("BBT size (pages): %u\n", page0->ext_info.bbt_occupy_pages); printf("BBT block start: %u\n", page0->ext_info.bbt_start_block); } void GetBbtLocation(const void* data, uint32_t* first_block, uint32_t* num_blocks) { const Page0* page0 = reinterpret_cast(data); g_bbt_size = page0->ext_info.bbt_occupy_pages; *first_block = page0->ext_info.bbt_start_block; *num_blocks = 4; } int DumpBbt(const void* data, const void* oob, const nand_info_t& info) { if (g_bbt_size * info.page_size < info.num_blocks) { printf("BBT too small\n"); return 0; } const char* table = reinterpret_cast(data); const char* oob_data = reinterpret_cast(oob); int num_tables = GetNumTables(oob_data, info); for (int cur_table = 0; cur_table < num_tables; cur_table++) { printf("BBT Table %d\n", cur_table); for (uint32_t block = 0; block < info.num_blocks; block++) { if (table[block]) { printf("Block %d marked bad\n", block); } } oob_data += info.oob_size * g_bbt_size; table += info.page_size * g_bbt_size; } return num_tables; }