Пример #1
0
static int _loki_write_android_header(MbBiWriter *biw, MbFile *file,
                                      const AndroidHeader *ahdr)
{
    AndroidHeader dup = *ahdr;
    size_t n;
    int ret;

    android_fix_header_byte_order(&dup);

    ret = mb_file_seek(file, 0, SEEK_SET, nullptr);
    if (ret != MB_FILE_OK) {
        mb_bi_writer_set_error(biw, mb_file_error(file),
                               "Failed to seek to beginning: %s",
                               mb_file_error_string(file));
        return ret == MB_FILE_FATAL ? MB_BI_FATAL : MB_BI_FAILED;
    }

    ret = mb_file_write_fully(file, &dup, sizeof(dup), &n);
    if (ret != MB_FILE_OK) {
        mb_bi_writer_set_error(biw, mb_file_error(file),
                               "Failed to write Android header: %s",
                               mb_file_error_string(file));
        return ret == MB_FILE_FATAL ? MB_BI_FATAL : MB_BI_FAILED;
    } else if (n != sizeof(dup)) {
        mb_bi_writer_set_error(biw, MB_BI_ERROR_FILE_FORMAT,
                               "Unexpected EOF when writing Android header: %s",
                               mb_file_error_string(file));
        return MB_BI_FAILED;
    }

    return MB_BI_OK;
}
Пример #2
0
oc::result<void> MtkFormatWriter::close(File &file)
{
    auto reset_state = finally([&] {
        m_hdr = {};
        m_seg = {};
    });

    if (m_writer.is_open()) {
        auto swentry = m_seg->entry();

        // If successful, finish up the boot image
        if (swentry == m_seg->entries().end()) {
            auto file_size = file.seek(0, SEEK_CUR);
            if (!file_size) {
                if (file.is_fatal()) { m_writer.set_fatal(); }
                return file_size.as_failure();
            }

            // Truncate to set size
            auto truncate_ret = file.truncate(file_size.value());
            if (!truncate_ret) {
                if (file.is_fatal()) { m_writer.set_fatal(); }
                return truncate_ret.as_failure();
            }

            // Update MTK header sizes
            for (auto const &entry : m_seg->entries()) {
                if (entry.type == ENTRY_TYPE_MTK_KERNEL_HEADER) {
                    OUTCOME_TRYV(_mtk_header_update_size(
                            m_writer, file, entry.offset,
                            static_cast<uint32_t>(
                                    m_hdr.kernel_size - sizeof(MtkHeader))));
                } else if (entry.type == ENTRY_TYPE_MTK_RAMDISK_HEADER) {
                    OUTCOME_TRYV(_mtk_header_update_size(
                            m_writer, file, entry.offset,
                            static_cast<uint32_t>(
                                    m_hdr.ramdisk_size - sizeof(MtkHeader))));
                }
            }

            // We need to take the performance hit and compute the SHA1 here.
            // We can't fill in the sizes in the MTK headers when we're writing
            // them. Thus, if we calculated the SHA1sum during write, it would
            // be incorrect.
            OUTCOME_TRYV(_mtk_compute_sha1(
                    m_writer, *m_seg, file,
                    reinterpret_cast<unsigned char *>(m_hdr.id)));

            // Convert fields back to little-endian
            android_fix_header_byte_order(m_hdr);

            // Seek back to beginning to write header
            auto seek_ret = file.seek(0, SEEK_SET);
            if (!seek_ret) {
                if (file.is_fatal()) { m_writer.set_fatal(); }
                return seek_ret.as_failure();
            }

            // Write header
            auto ret = file_write_exact(file, &m_hdr, sizeof(m_hdr));
            if (!ret) {
                if (file.is_fatal()) { m_writer.set_fatal(); }
                return ret.as_failure();
            }
        }
    }

    return oc::success();
}
Пример #3
0
MB_BEGIN_C_DECLS

/*!
 * \brief Find and read Android boot image header
 *
 * \note The integral fields in the header will be converted to the host's byte
 *       order.
 *
 * \pre The file position can be at any offset prior to calling this function.
 *
 * \post The file pointer position is undefined after this function returns.
 *       Use mb_file_seek() to return to a known position.
 *
 * \param[in] bir MbBiReader for setting error messages
 * \param[in] file MbFile handle
 * \param[in] max_header_offset Maximum offset that a header can start (must be
 *                              less than #ANDROID_MAX_HEADER_OFFSET)
 * \param[out] header_out Pointer to store header
 * \param[out] offset_out Pointer to store header offset
 *
 * \return
 *   * #MB_BI_OK if the header is found
 *   * #MB_BI_WARN if the header is not found
 *   * #MB_BI_FAILED if any file operation fails non-fatally
 *   * #MB_BI_FATAL if any file operation fails fatally
 */
int find_android_header(MbBiReader *bir, MbFile *file,
                        uint64_t max_header_offset,
                        AndroidHeader *header_out, uint64_t *offset_out)
{
    unsigned char buf[ANDROID_MAX_HEADER_OFFSET + sizeof(AndroidHeader)];
    size_t n;
    int ret;
    void *ptr;
    size_t offset;

    if (max_header_offset > ANDROID_MAX_HEADER_OFFSET) {
        mb_bi_reader_set_error(bir, MB_BI_ERROR_INVALID_ARGUMENT,
                               "Max header offset (%" PRIu64
                               ") must be less than %d",
                               max_header_offset, ANDROID_MAX_HEADER_OFFSET);
        return MB_BI_WARN;
    }

    ret = mb_file_seek(file, 0, SEEK_SET, nullptr);
    if (ret != MB_FILE_OK) {
        mb_bi_reader_set_error(bir, mb_file_error(file),
                               "Failed to seek to beginning: %s",
                               mb_file_error_string(file));
        return ret == MB_FILE_FATAL ? MB_BI_FATAL : MB_BI_FAILED;
    }

    ret = mb_file_read_fully(
            file, buf, max_header_offset + sizeof(AndroidHeader), &n);
    if (ret != MB_FILE_OK) {
        mb_bi_reader_set_error(bir, mb_file_error(file),
                               "Failed to read header: %s",
                               mb_file_error_string(file));
        return ret == MB_FILE_FATAL ? MB_BI_FATAL : MB_BI_FAILED;
    }

    ptr = mb_memmem(buf, n, ANDROID_BOOT_MAGIC, ANDROID_BOOT_MAGIC_SIZE);
    if (!ptr) {
        mb_bi_reader_set_error(bir, MB_BI_ERROR_FILE_FORMAT,
                               "Android magic not found in first %d bytes",
                               ANDROID_MAX_HEADER_OFFSET);
        return MB_BI_WARN;
    }

    offset = static_cast<unsigned char *>(ptr) - buf;

    if (n - offset < sizeof(AndroidHeader)) {
        mb_bi_reader_set_error(bir, MB_BI_ERROR_FILE_FORMAT,
                               "Android header at %" MB_PRIzu
                               " exceeds file size", offset);
        return MB_BI_WARN;
    }

    // Copy header
    memcpy(header_out, ptr, sizeof(AndroidHeader));
    android_fix_header_byte_order(header_out);
    *offset_out = offset;

    return MB_BI_OK;
}