libpayload/libcbfs: Fix file hash check

Fix the buffer pointer passed to cbfs_file_hash_mismatch().

Add a test case with LZ4 compression, which would catch the bug we are
fixing.

Change-Id: I36605e2dbc0423fa6743087512f2042b37c49d35
Signed-off-by: Yu-Ping Wu <yupingso@chromium.org>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/65149
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Paul Menzel <paulepanter@mailbox.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
diff --git a/payloads/libpayload/libcbfs/cbfs.c b/payloads/libpayload/libcbfs/cbfs.c
index ff19179..0694c4f 100644
--- a/payloads/libpayload/libcbfs/cbfs.c
+++ b/payloads/libpayload/libcbfs/cbfs.c
@@ -120,7 +120,7 @@
 		goto out;
 	}
 
-	if (cbfs_file_hash_mismatch(buffer, in_size, mdata, skip_verification))
+	if (cbfs_file_hash_mismatch(load, in_size, mdata, skip_verification))
 		goto out;
 
 	switch (compression) {
diff --git a/payloads/libpayload/tests/libcbfs/cbfs-verification-test.c b/payloads/libpayload/tests/libcbfs/cbfs-verification-test.c
index 1dcccf9..8e50f39 100644
--- a/payloads/libpayload/tests/libcbfs/cbfs-verification-test.c
+++ b/payloads/libpayload/tests/libcbfs/cbfs-verification-test.c
@@ -43,14 +43,18 @@
 unsigned long ulzman(const unsigned char *src, unsigned long srcn, unsigned char *dst,
 		     unsigned long dstn)
 {
-	fail_msg("Unexpected call to %s", __func__);
-	return 0;
+	size_t copy_size = MIN(srcn, dstn);
+	function_called();
+	memcpy(dst, src, copy_size);
+	return copy_size;
 }
 
 size_t ulz4fn(const void *src, size_t srcn, void *dst, size_t dstn)
 {
-	fail_msg("Unexpected call to %s", __func__);
-	return 0;
+	size_t copy_size = MIN(srcn, dstn);
+	function_called();
+	memcpy(dst, src, copy_size);
+	return copy_size;
 }
 
 enum cb_err cbfs_mcache_lookup(const void *mcache, size_t mcache_size, const char *name,
@@ -167,7 +171,7 @@
 	}
 }
 
-static void test_cbfs_map_valid_hash(void **state)
+static void test_cbfs_map_valid_hash_impl(void **state, bool lz4_compressed)
 {
 	void *mapping = NULL;
 	size_t size = 0;
@@ -181,8 +185,17 @@
 	expect_cbfs_lookup(TEST_DATA_1_FILENAME, CB_SUCCESS,
 			   (const union cbfs_mdata *)&file_valid_hash,
 			   be32toh(file_valid_hash.header.offset));
-	will_return(cbfs_find_attr, NULL);
 
+	if (lz4_compressed) {
+		struct cbfs_file_attr_compression cattr = {
+			.compression = htobe32(CBFS_COMPRESS_LZ4),
+			.decompressed_size = htobe32(TEST_DATA_1_SIZE),
+		};
+		will_return(cbfs_find_attr, &cattr);
+		expect_function_call(ulz4fn);
+	} else {
+		will_return(cbfs_find_attr, NULL);
+	}
 
 	if (CONFIG(LP_CBFS_VERIFICATION)) {
 		will_return(cbfs_file_hash, &hash);
@@ -203,6 +216,16 @@
 	}
 }
 
+static void test_cbfs_map_valid_hash(void **state)
+{
+	test_cbfs_map_valid_hash_impl(state, false);
+}
+
+static void test_cbfs_map_valid_hash_with_lz4(void **state)
+{
+	test_cbfs_map_valid_hash_impl(state, true);
+}
+
 static void test_cbfs_map_invalid_hash(void **state)
 {
 	void *mapping = NULL;
@@ -240,6 +263,7 @@
 	const struct CMUnitTest tests[] = {
 		cmocka_unit_test_setup(test_cbfs_map_no_hash, setup_test_cbfs),
 		cmocka_unit_test_setup(test_cbfs_map_valid_hash, setup_test_cbfs),
+		cmocka_unit_test_setup(test_cbfs_map_valid_hash_with_lz4, setup_test_cbfs),
 		cmocka_unit_test_setup(test_cbfs_map_invalid_hash, setup_test_cbfs),
 	};