/*!
 * \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;
}
Example #2
0
/*!
 * \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;
}
Example #3
0
/*!
 * \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;
}
Example #5
0
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;
}