/*! * \brief Perform a bid * * \return * * If \>= 0, the number of bits that conform to the Android format * * #MB_BI_WARN if this is a bid that can't be won * * #MB_BI_FAILED if any file operations fail non-fatally * * #MB_BI_FATAL if any file operations fail fatally */ int android_reader_bid(MbBiReader *bir, void *userdata, int best_bid) { AndroidReaderCtx *const ctx = static_cast<AndroidReaderCtx *>(userdata); int bid = 0; int ret; if (best_bid >= (ANDROID_BOOT_MAGIC_SIZE + SAMSUNG_SEANDROID_MAGIC_SIZE) * 8) { // This is a bid we can't win, so bail out return MB_BI_WARN; } // Find the Android header ret = find_android_header(bir, bir->file, ANDROID_MAX_HEADER_OFFSET, &ctx->hdr, &ctx->header_offset); if (ret == MB_BI_OK) { // Update bid to account for matched bits ctx->have_header_offset = true; bid += ANDROID_BOOT_MAGIC_SIZE * 8; } else if (ret == MB_BI_WARN) { // Header not found. This can't be an Android boot image. return 0; } else { return ret; } // Find the Samsung magic ret = find_samsung_seandroid_magic(bir, bir->file, &ctx->hdr, &ctx->samsung_offset); if (ret == MB_BI_OK) { // Update bid to account for matched bits ctx->have_samsung_offset = true; bid += SAMSUNG_SEANDROID_MAGIC_SIZE * 8; } else if (ret == MB_BI_WARN) { // Nothing found. Don't change bid } else { return ret; } return bid; }
/*! * \brief Perform a bid * * \return * * If \>= 0, the number of bits that conform to the Loki format * * #MB_BI_WARN if this is a bid that can't be won * * #MB_BI_FAILED if any file operations fail non-fatally * * #MB_BI_FATAL if any file operations fail fatally */ int loki_reader_bid(MbBiReader *bir, void *userdata, int best_bid) { LokiReaderCtx *const ctx = static_cast<LokiReaderCtx *>(userdata); int bid = 0; int ret; if (best_bid >= (ANDROID_BOOT_MAGIC_SIZE + LOKI_MAGIC_SIZE) * 8) { // This is a bid we can't win, so bail out return MB_BI_WARN; } // Find the Loki header ret = find_loki_header(bir, bir->file, &ctx->loki_hdr, &ctx->loki_offset); if (ret == MB_BI_OK) { // Update bid to account for matched bits ctx->have_loki_offset = true; bid += LOKI_MAGIC_SIZE * 8; } else if (ret == MB_BI_WARN) { // Header not found. This can't be a Loki boot image. return 0; } else { return ret; } // Find the Android header ret = find_android_header(bir, bir->file, LOKI_MAX_HEADER_OFFSET, &ctx->hdr, &ctx->header_offset); if (ret == MB_BI_OK) { // Update bid to account for matched bits ctx->have_header_offset = true; bid += ANDROID_BOOT_MAGIC_SIZE * 8; } else if (ret == MB_BI_WARN) { // Header not found. This can't be an Android boot image. return 0; } else { return ret; } return bid; }
/*! * \brief Perform a bid * * \return * * If \>= 0, the number of bits that conform to the MTK format * * #MB_BI_WARN if this is a bid that can't be won * * #MB_BI_FAILED if any file operations fail non-fatally * * #MB_BI_FATAL if any file operations fail fatally */ int mtk_reader_bid(MbBiReader *bir, void *userdata, int best_bid) { MtkReaderCtx *const ctx = static_cast<MtkReaderCtx *>(userdata); int bid = 0; int ret; if (best_bid >= (ANDROID_BOOT_MAGIC_SIZE + 2 * MTK_MAGIC_SIZE) * 8) { // This is a bid we can't win, so bail out return MB_BI_WARN; } // Find the Android header ret = find_android_header(bir, bir->file, ANDROID_MAX_HEADER_OFFSET, &ctx->hdr, &ctx->header_offset); if (ret == MB_BI_OK) { // Update bid to account for matched bits ctx->have_header_offset = true; bid += ANDROID_BOOT_MAGIC_SIZE * 8; } else if (ret == MB_BI_WARN) { // Header not found. This can't be an Android boot image. return 0; } else { return ret; } ret = find_mtk_headers(bir, bir->file, &ctx->hdr, &ctx->mtk_kernel_hdr, &ctx->mtk_kernel_offset, &ctx->mtk_ramdisk_hdr, &ctx->mtk_ramdisk_offset); if (ret == MB_BI_OK) { // Update bid to account for matched bids ctx->have_mtkhdr_offsets = true; bid += 2 * MTK_MAGIC_SIZE * 8; } else { return ret; } return bid; }
int android_reader_read_header(MbBiReader *bir, void *userdata, MbBiHeader *header) { AndroidReaderCtx *const ctx = static_cast<AndroidReaderCtx *>(userdata); int ret; if (!ctx->have_header_offset) { // A bid might not have been performed if the user forced a particular // format ret = find_android_header(bir, bir->file, ANDROID_MAX_HEADER_OFFSET, &ctx->hdr, &ctx->header_offset); if (ret < 0) { return ret; } ctx->have_header_offset = true; } ret = android_set_header(&ctx->hdr, header); if (ret != MB_BI_OK) { mb_bi_reader_set_error(bir, MB_BI_ERROR_INTERNAL_ERROR, "Failed to set header fields"); return ret; } // Calculate offsets for each section uint64_t pos = 0; uint32_t page_size = mb_bi_header_page_size(header); uint64_t kernel_offset; uint64_t ramdisk_offset; uint64_t second_offset; uint64_t dt_offset; // pos cannot overflow due to the nature of the operands (adding UINT32_MAX // a few times can't overflow a uint64_t). File length overflow is checked // during read. // Header pos += ctx->header_offset; pos += sizeof(AndroidHeader); pos += align_page_size<uint64_t>(pos, page_size); // Kernel kernel_offset = pos; pos += ctx->hdr.kernel_size; pos += align_page_size<uint64_t>(pos, page_size); // Ramdisk ramdisk_offset = pos; pos += ctx->hdr.ramdisk_size; pos += align_page_size<uint64_t>(pos, page_size); // Second bootloader second_offset = pos; pos += ctx->hdr.second_size; pos += align_page_size<uint64_t>(pos, page_size); // Device tree dt_offset = pos; pos += ctx->hdr.dt_size; pos += align_page_size<uint64_t>(pos, page_size); _segment_reader_entries_clear(&ctx->segctx); ret = _segment_reader_entries_add(&ctx->segctx, MB_BI_ENTRY_KERNEL, kernel_offset, ctx->hdr.kernel_size, false, bir); if (ret != MB_BI_OK) return ret; ret = _segment_reader_entries_add(&ctx->segctx, MB_BI_ENTRY_RAMDISK, ramdisk_offset, ctx->hdr.ramdisk_size, false, bir); if (ret != MB_BI_OK) return ret; if (ctx->hdr.second_size > 0) { ret = _segment_reader_entries_add(&ctx->segctx, MB_BI_ENTRY_SECONDBOOT, second_offset, ctx->hdr.second_size, false, bir); if (ret != MB_BI_OK) return ret; } if (ctx->hdr.dt_size > 0) { ret = _segment_reader_entries_add(&ctx->segctx, MB_BI_ENTRY_DEVICE_TREE, dt_offset, ctx->hdr.dt_size, ctx->allow_truncated_dt, bir); if (ret != MB_BI_OK) return ret; } return MB_BI_OK; }
int loki_reader_read_header(MbBiReader *bir, void *userdata, MbBiHeader *header) { LokiReaderCtx *const ctx = static_cast<LokiReaderCtx *>(userdata); int ret; uint64_t kernel_offset; uint64_t ramdisk_offset; uint64_t dt_offset = 0; uint32_t kernel_size; uint32_t ramdisk_size; // A bid might not have been performed if the user forced a particular // format if (!ctx->have_loki_offset) { ret = find_loki_header(bir, bir->file, &ctx->loki_hdr, &ctx->header_offset); if (ret < 0) { return ret; } ctx->have_loki_offset = true; } if (!ctx->have_header_offset) { ret = find_android_header(bir, bir->file, ANDROID_MAX_HEADER_OFFSET, &ctx->hdr, &ctx->header_offset); if (ret < 0) { return ret; } ctx->have_header_offset = true; } // New-style images record the original values of changed fields in the // Android header if (ctx->loki_hdr.orig_kernel_size != 0 && ctx->loki_hdr.orig_ramdisk_size != 0 && ctx->loki_hdr.ramdisk_addr != 0) { ret = loki_read_new_header(bir, bir->file, &ctx->hdr, &ctx->loki_hdr, header, &kernel_offset, &kernel_size, &ramdisk_offset, &ramdisk_size, &dt_offset); } else { ret = loki_read_old_header(bir, bir->file, &ctx->hdr, &ctx->loki_hdr, header, &kernel_offset, &kernel_size, &ramdisk_offset, &ramdisk_size); } if (ret < 0) { return ret; } _segment_reader_entries_clear(&ctx->segctx); ret = _segment_reader_entries_add(&ctx->segctx, MB_BI_ENTRY_KERNEL, kernel_offset, kernel_size, false, bir); if (ret != MB_BI_OK) return ret; ret = _segment_reader_entries_add(&ctx->segctx, MB_BI_ENTRY_RAMDISK, ramdisk_offset, ramdisk_size, false, bir); if (ret != MB_BI_OK) return ret; if (ctx->hdr.dt_size > 0 && dt_offset != 0) { ret = _segment_reader_entries_add(&ctx->segctx, MB_BI_ENTRY_DEVICE_TREE, dt_offset, ctx->hdr.dt_size, false, bir); if (ret != MB_BI_OK) return ret; } return MB_BI_OK; }