1// Copyright 2018 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "aml.h" 6 7#include <stdio.h> 8#include <string.h> 9 10namespace { 11 12// Simplified Amlogic data structures. 13struct ExtInfo { 14 uint32_t read_info; 15 uint32_t new_type; 16 uint32_t pages_per_block; 17 uint32_t xlc; // slc=1, mlc=2, tlc=3. 18 uint32_t ce_mask; 19 uint32_t boot_num; 20 uint32_t each_boot_pages; 21 uint32_t bbt_occupy_pages; 22 uint32_t bbt_start_block; 23}; 24 25struct Page0 { 26 uint32_t config; 27 uint16_t id; 28 uint16_t max; 29 uint8_t page_list[16]; 30 uint16_t retry_usr[32]; 31 ExtInfo ext_info; 32}; 33 34// The number of pages on a single table. 35uint32_t g_bbt_size = 0; 36 37// Returns the number of valid bad block tables found. 38int GetNumTables(const char* oob, const nand_info_t& info) { 39 int found = 0; 40 for (uint32_t page = 0; page < info.pages_per_block; page++) { 41 if (memcmp(oob + page * info.oob_size, "nbbt", 4) != 0) { 42 break; 43 } 44 found++; 45 } 46 return found / g_bbt_size; 47} 48 49} // namespace 50 51void DumpPage0(const void* data) { 52 const Page0* page0 = reinterpret_cast<const Page0*>(data); 53 54 printf("Config: 0x%x\n", page0->config); 55 printf("ECC step: %u\n", page0->config & 0x3f); 56 printf("Page size (encoded): %u\n", (page0->config >> 6) & 0x7f); 57 printf("Pages per block: %u\n", page0->ext_info.pages_per_block); 58 printf("Boot type: %u\n", page0->ext_info.boot_num); 59 printf("Boot pages: %u\n", page0->ext_info.each_boot_pages); 60 printf("BBT size (pages): %u\n", page0->ext_info.bbt_occupy_pages); 61 printf("BBT block start: %u\n", page0->ext_info.bbt_start_block); 62} 63 64void GetBbtLocation(const void* data, uint32_t* first_block, uint32_t* num_blocks) { 65 const Page0* page0 = reinterpret_cast<const Page0*>(data); 66 g_bbt_size = page0->ext_info.bbt_occupy_pages; 67 *first_block = page0->ext_info.bbt_start_block; 68 *num_blocks = 4; 69} 70 71int DumpBbt(const void* data, const void* oob, const nand_info_t& info) { 72 if (g_bbt_size * info.page_size < info.num_blocks) { 73 printf("BBT too small\n"); 74 return 0; 75 } 76 77 const char* table = reinterpret_cast<const char*>(data); 78 const char* oob_data = reinterpret_cast<const char*>(oob); 79 int num_tables = GetNumTables(oob_data, info); 80 81 for (int cur_table = 0; cur_table < num_tables; cur_table++) { 82 printf("BBT Table %d\n", cur_table); 83 for (uint32_t block = 0; block < info.num_blocks; block++) { 84 if (table[block]) { 85 printf("Block %d marked bad\n", block); 86 } 87 } 88 oob_data += info.oob_size * g_bbt_size; 89 table += info.page_size * g_bbt_size; 90 } 91 return num_tables; 92} 93