/*! * \brief Read header for old-style Loki image * * \param[in] bir MbBiReader to set error message * \param[in] file MbFile handle * \param[in] hdr Android header for image * \param[in] loki_hdr Loki header for image * \param[out] header MbBiHeader instance to store header values * \param[out] kernel_offset_out Pointer to store kernel offset * \param[out] kernel_size_out Pointer to store kernel size * \param[out] ramdisk_offset_out Pointer to store ramdisk offset * \param[out] ramdisk_size_out Pointer to store ramdisk size * * \return * * #MB_BI_OK if the header is successfully read * * #MB_BI_WARN if parts of the header are missing or invalid * * #MB_BI_FAILED if any file operation fails non-fatally * * #MB_BI_FATAL if any file operation fails fatally */ int loki_read_old_header(MbBiReader *bir, MbFile *file, AndroidHeader *hdr, LokiHeader *loki_hdr, MbBiHeader *header, uint64_t *kernel_offset_out, uint32_t *kernel_size_out, uint64_t *ramdisk_offset_out, uint32_t *ramdisk_size_out) { uint32_t tags_addr; uint32_t kernel_size; uint32_t ramdisk_size; uint32_t ramdisk_addr; uint64_t gzip_offset; int ret; if (hdr->page_size == 0) { mb_bi_reader_set_error(bir, MB_BI_ERROR_FILE_FORMAT, "Page size cannot be 0"); return MB_BI_WARN; } // The kernel tags address is invalid in the old loki images, so use the // default for jflte tags_addr = hdr->kernel_addr - ANDROID_DEFAULT_KERNEL_OFFSET + ANDROID_DEFAULT_TAGS_OFFSET; // Try to guess kernel size ret = find_linux_kernel_size(bir, file, hdr->page_size, &kernel_size); if (ret != MB_BI_OK) { return ret; } // Look for gzip offset for the ramdisk ret = loki_old_find_gzip_offset( bir, file, hdr->page_size + kernel_size + align_page_size<uint64_t>(kernel_size, hdr->page_size), &gzip_offset); if (ret != MB_BI_OK) { return ret; } // Try to guess ramdisk size ret = loki_old_find_ramdisk_size(bir, file, hdr, gzip_offset, &ramdisk_size); if (ret != MB_BI_OK) { return ret; } // Guess original ramdisk address ret = loki_find_ramdisk_address(bir, file, hdr, loki_hdr, &ramdisk_addr); if (ret != MB_BI_OK) { return ret; } *kernel_size_out = kernel_size; *ramdisk_size_out = ramdisk_size; char board_name[sizeof(hdr->name) + 1]; char cmdline[sizeof(hdr->cmdline) + 1]; strncpy(board_name, reinterpret_cast<char *>(hdr->name), sizeof(hdr->name)); strncpy(cmdline, reinterpret_cast<char *>(hdr->cmdline), sizeof(hdr->cmdline)); board_name[sizeof(hdr->name)] = '\0'; cmdline[sizeof(hdr->cmdline)] = '\0'; mb_bi_header_set_supported_fields(header, LOKI_OLD_SUPPORTED_FIELDS); ret = mb_bi_header_set_board_name(header, board_name); if (ret != MB_BI_OK) return ret; ret = mb_bi_header_set_kernel_cmdline(header, cmdline); if (ret != MB_BI_OK) return ret; ret = mb_bi_header_set_page_size(header, hdr->page_size); if (ret != MB_BI_OK) return ret; ret = mb_bi_header_set_kernel_address(header, hdr->kernel_addr); if (ret != MB_BI_OK) return ret; ret = mb_bi_header_set_ramdisk_address(header, ramdisk_addr); if (ret != MB_BI_OK) return ret; ret = mb_bi_header_set_secondboot_address(header, hdr->second_addr); if (ret != MB_BI_OK) return ret; ret = mb_bi_header_set_kernel_tags_address(header, tags_addr); if (ret != MB_BI_OK) return ret; uint64_t pos = 0; // 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 += hdr->page_size; // Kernel *kernel_offset_out = pos; pos += kernel_size; pos += align_page_size<uint64_t>(pos, hdr->page_size); // Ramdisk *ramdisk_offset_out = pos = gzip_offset; pos += ramdisk_size; pos += align_page_size<uint64_t>(pos, hdr->page_size); return MB_BI_OK; }
/*! * \brief Read header for old-style Loki image * * \param[in] reader Reader to set error message * \param[in] file File handle * \param[in] hdr Android header for image * \param[in] loki_hdr Loki header for image * \param[out] header Header instance to store header values * \param[out] kernel_offset_out Pointer to store kernel offset * \param[out] kernel_size_out Pointer to store kernel size * \param[out] ramdisk_offset_out Pointer to store ramdisk offset * \param[out] ramdisk_size_out Pointer to store ramdisk size * * \return Nothing if the header is successfully read. Otherwise, a specific * error code. */ oc::result<void> LokiFormatReader::read_header_old(Reader &reader, File &file, const android::AndroidHeader &hdr, const LokiHeader &loki_hdr, Header &header, uint64_t &kernel_offset_out, uint32_t &kernel_size_out, uint64_t &ramdisk_offset_out, uint32_t &ramdisk_size_out) { uint32_t tags_addr; uint32_t kernel_size; uint32_t ramdisk_size; uint32_t ramdisk_addr; uint64_t gzip_offset; if (hdr.page_size == 0) { return LokiError::PageSizeCannotBeZero; } // The kernel tags address is invalid in the old loki images, so use the // default for jflte tags_addr = hdr.kernel_addr - android::DEFAULT_KERNEL_OFFSET + android::DEFAULT_TAGS_OFFSET; // Try to guess kernel size OUTCOME_TRYV(find_linux_kernel_size(reader, file, hdr.page_size, kernel_size)); // Look for gzip offset for the ramdisk OUTCOME_TRYV(find_gzip_offset_old( reader, file, hdr.page_size + kernel_size + align_page_size<uint32_t>(kernel_size, hdr.page_size), gzip_offset)); // Try to guess ramdisk size OUTCOME_TRYV(find_ramdisk_size_old(reader, file, hdr, static_cast<uint32_t>(gzip_offset), ramdisk_size)); // Guess original ramdisk address OUTCOME_TRYV(find_ramdisk_address(reader, file, hdr, loki_hdr, ramdisk_addr)); kernel_size_out = kernel_size; ramdisk_size_out = ramdisk_size; auto *name_ptr = reinterpret_cast<const char *>(hdr.name); auto name_size = strnlen(name_ptr, sizeof(hdr.name)); auto *cmdline_ptr = reinterpret_cast<const char *>(hdr.cmdline); auto cmdline_size = strnlen(cmdline_ptr, sizeof(hdr.cmdline)); header.set_supported_fields(OLD_SUPPORTED_FIELDS); header.set_board_name({{name_ptr, name_size}}); header.set_kernel_cmdline({{cmdline_ptr, cmdline_size}}); header.set_page_size(hdr.page_size); header.set_kernel_address(hdr.kernel_addr); header.set_ramdisk_address(ramdisk_addr); header.set_secondboot_address(hdr.second_addr); header.set_kernel_tags_address(tags_addr); uint64_t pos = 0; // 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 += hdr.page_size; // Kernel kernel_offset_out = pos; pos += kernel_size; pos += align_page_size<uint64_t>(pos, hdr.page_size); // Ramdisk ramdisk_offset_out = pos = gzip_offset; pos += ramdisk_size; pos += align_page_size<uint64_t>(pos, hdr.page_size); return oc::success(); }