Jakub Czapiga has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/59494 )
Change subject: libpayload/libc/fmap: Use libpayload_boot_device_read for media access ......................................................................
libpayload/libc/fmap: Use libpayload_boot_device_read for media access
Replace cbfs_media with libpayload_boot_device_read in fmap_region_by_name. Default implementation of libpayload_boot_device_read uses cbfs_media as a fallback, so behavior should be the same. This change also includes tests for new implementation of fmap function.
Change-Id: Idbf9016ce73aa58e17f3ee19920ab83dc6c25abb Signed-off-by: Jakub Czapiga jacz@semihalf.com --- M payloads/libpayload/libc/fmap.c A payloads/libpayload/tests/include/mocks/boot_device.h A payloads/libpayload/tests/libc/Makefile.inc A payloads/libpayload/tests/libc/fmap_region_by_name-test.c A payloads/libpayload/tests/mocks/boot_device.c 5 files changed, 185 insertions(+), 16 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/94/59494/1
diff --git a/payloads/libpayload/libc/fmap.c b/payloads/libpayload/libc/fmap.c index b7d6491..f6c28a7 100644 --- a/payloads/libpayload/libc/fmap.c +++ b/payloads/libpayload/libc/fmap.c @@ -37,36 +37,25 @@ uint32_t * const offset, uint32_t * const size) { int i; - struct fmap *fmap; struct fmap fmap_head; - struct cbfs_media default_media; - struct cbfs_media *media = &default_media;
- if (init_default_cbfs_media(media) != 0) + if (libpayload_boot_device_read(&fmap_head, fmap_offset, sizeof(fmap_head)) + != sizeof(fmap_head)) return -1;
- media->open(media); - - if (!media->read(media, &fmap_head, fmap_offset, sizeof(fmap_head))) + if (memcmp(fmap_head.signature, FMAP_SIGNATURE, sizeof(fmap_head.signature))) return -1;
- if (memcmp(fmap_head.signature, FMAP_SIGNATURE, sizeof(fmap_head.signature))) { - return -1; - } - - int fmap_size = sizeof(*fmap) + - fmap_head.nareas * sizeof(struct fmap_area); + int fmap_size = sizeof(*fmap) + fmap_head.nareas * sizeof(struct fmap_area);
fmap = malloc(fmap_size); if (!fmap) return -1;
- if (!media->read(media, fmap, fmap_offset, fmap_size)) + if (libpayload_boot_device_read(fmap, fmap_offset, fmap_size) != fmap_size) goto err;
- media->close(media); - for (i = 0; i < fmap->nareas; i++) { if (strcmp((const char *)fmap->areas[i].name, name) != 0) continue; diff --git a/payloads/libpayload/tests/include/mocks/boot_device.h b/payloads/libpayload/tests/include/mocks/boot_device.h new file mode 100644 index 0000000..fb7d644 --- /dev/null +++ b/payloads/libpayload/tests/include/mocks/boot_device.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <boot_device.h> +#include <tests/test.h> + +#define SETUP_LIBPAYLOAD_BOOT_DEVICE_READ_MOCK_EX(data_buffer, data_size, expected_offset, \ + expected_size) \ + do { \ + expect_value(libpayload_boot_device_read, offset, (expected_offset)); \ + expect_value(libpayload_boot_device_read, size, (expected_size)); \ + will_return(libpayload_boot_device_read, (data_buffer)); \ + will_return(libpayload_boot_device_read, (data_size)); \ + } while (0) + +#define SETUP_LIBPAYLOAD_BOOT_DEVICE_READ_MOCK(data_buffer, expected_offset, expected_size) \ + SETUP_LIBPAYLOAD_BOOT_DEVICE_READ_MOCK_EX((data_buffer), (expected_size), \ + (expected_offset), (expected_size)) + +#define SETUP_LIBPAYLOAD_BOOT_DEVICE_READ_MOCK_FAIL(expected_offset) \ + do { \ + expect_value(libpayload_boot_device_read, offset, (expected_offset)); \ + expect_any(libpayload_boot_device_read, size); \ + will_return(libpayload_boot_device_read, NULL); \ + will_return(libpayload_boot_device_read, 0); \ + } while (0) diff --git a/payloads/libpayload/tests/libc/Makefile.inc b/payloads/libpayload/tests/libc/Makefile.inc new file mode 100644 index 0000000..817c09d --- /dev/null +++ b/payloads/libpayload/tests/libc/Makefile.inc @@ -0,0 +1,6 @@ +tests-y += fmap_region_by_name-test + + +fmap_region_by_name-test-srcs += tests/libc/fmap_region_by_name-test.c +fmap_region_by_name-test-srcs += tests/mocks/boot_device.c +fmap_region_by_name-test-srcs += libc/fmap.c diff --git a/payloads/libpayload/tests/libc/fmap_region_by_name-test.c b/payloads/libpayload/tests/libc/fmap_region_by_name-test.c new file mode 100644 index 0000000..92b6867 --- /dev/null +++ b/payloads/libpayload/tests/libc/fmap_region_by_name-test.c @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <libpayload.h> +#include <mocks/boot_device.h> +#include <tests/test.h> + +void test_fmap_region_by_name_read_fail(void **state) +{ + const uint32_t fmap_offset = 0x1001; + uint32_t out_offset = 0; + uint32_t out_size = 0; + + SETUP_LIBPAYLOAD_BOOT_DEVICE_READ_MOCK_FAIL(fmap_offset); + assert_int_equal(-1, + fmap_region_by_name(fmap_offset, "unknown", &out_offset, &out_size)); +} + +void test_fmap_region_by_name_incorrect_signature(void **state) +{ + const uint32_t fmap_offset = 0x20002; + uint32_t out_offset = 0; + uint32_t out_size = 0; + struct fmap test_fmap = { + .signature = "NOTMAP", + }; + + SETUP_LIBPAYLOAD_BOOT_DEVICE_READ_MOCK(&test_fmap, fmap_offset, sizeof(test_fmap)); + assert_int_equal(-1, + fmap_region_by_name(fmap_offset, "unknown", &out_offset, &out_size)); +} + +void test_fmap_region_by_name_no_areas(void **state) +{ + + const uint32_t fmap_offset = 0x3344; + uint32_t out_offset = 0; + uint32_t out_size = 0; + struct fmap test_fmap = { + .signature = FMAP_SIGNATURE, + .nareas = 0, + }; + + SETUP_LIBPAYLOAD_BOOT_DEVICE_READ_MOCK(&test_fmap, fmap_offset, sizeof(test_fmap)); + SETUP_LIBPAYLOAD_BOOT_DEVICE_READ_MOCK(&test_fmap, fmap_offset, sizeof(test_fmap)); + assert_int_equal(-1, + fmap_region_by_name(fmap_offset, "unknown", &out_offset, &out_size)); +} + +void test_fmap_region_by_name_success(void **state) +{ + const uint32_t fmap_offset = 0x1331; + uint32_t out_offset = 0; + uint32_t out_size = 0; + struct fmap test_fmap = { + .signature = FMAP_SIGNATURE, + .ver_major = 1, + .ver_minor = 1, + .base = 0xAABB, + .size = 0x10000, + .nareas = 3, + }; + struct fmap_area area_1 = { + .size = 0x1100, + .offset = 0x11, + .name = "FIRST_AREA", + .flags = 0, + }; + struct fmap_area area_2 = { + .size = 0x2200, + .offset = 0x1111, + .name = "SECOND_AREA", + .flags = 0, + }; + struct fmap_area area_3 = { + .size = 0x100, + .offset = 0x3311, + .name = "THIRD_AREA", + .flags = 0, + }; + const size_t fmap_size = sizeof(struct fmap) + 3 * sizeof(struct fmap_area); + u8 fmap_buffer[sizeof(struct fmap) + 3 * sizeof(struct fmap_area)]; + memcpy(fmap_buffer, &test_fmap, sizeof(test_fmap)); + memcpy(&fmap_buffer[sizeof(test_fmap)], &area_1, sizeof(area_1)); + memcpy(&fmap_buffer[sizeof(test_fmap) + sizeof(area_1)], &area_2, sizeof(area_2)); + memcpy(&fmap_buffer[sizeof(test_fmap) + sizeof(area_1) + sizeof(area_2)], &area_3, + sizeof(area_3)); + + /* Should fail, because it expects more data */ + SETUP_LIBPAYLOAD_BOOT_DEVICE_READ_MOCK(fmap_buffer, fmap_offset, sizeof(struct fmap)); + SETUP_LIBPAYLOAD_BOOT_DEVICE_READ_MOCK_EX(fmap_buffer, sizeof(struct fmap), fmap_offset, + fmap_size); + assert_int_equal(-1, fmap_region_by_name(fmap_offset, (const char *)area_1.name, + &out_offset, &out_size)); + + SETUP_LIBPAYLOAD_BOOT_DEVICE_READ_MOCK(fmap_buffer, fmap_offset, sizeof(struct fmap)); + SETUP_LIBPAYLOAD_BOOT_DEVICE_READ_MOCK(fmap_buffer, fmap_offset, fmap_size); + assert_int_equal(0, fmap_region_by_name(fmap_offset, (const char *)area_1.name, + &out_offset, &out_size)); + assert_int_equal(area_1.offset, out_offset); + assert_int_equal(area_1.size, out_size); + + SETUP_LIBPAYLOAD_BOOT_DEVICE_READ_MOCK(fmap_buffer, fmap_offset, sizeof(struct fmap)); + SETUP_LIBPAYLOAD_BOOT_DEVICE_READ_MOCK(fmap_buffer, fmap_offset, fmap_size); + assert_int_equal(0, fmap_region_by_name(fmap_offset, (const char *)area_2.name, + &out_offset, &out_size)); + assert_int_equal(area_2.offset, out_offset); + assert_int_equal(area_2.size, out_size); + + SETUP_LIBPAYLOAD_BOOT_DEVICE_READ_MOCK(fmap_buffer, fmap_offset, sizeof(struct fmap)); + SETUP_LIBPAYLOAD_BOOT_DEVICE_READ_MOCK(fmap_buffer, fmap_offset, fmap_size); + assert_int_equal(0, fmap_region_by_name(fmap_offset, (const char *)area_2.name, + &out_offset, &out_size)); + assert_int_equal(area_2.offset, out_offset); + assert_int_equal(area_2.size, out_size); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_fmap_region_by_name_read_fail), + cmocka_unit_test(test_fmap_region_by_name_incorrect_signature), + cmocka_unit_test(test_fmap_region_by_name_no_areas), + cmocka_unit_test(test_fmap_region_by_name_success), + }; + + return lp_run_group_tests(tests, NULL, NULL); +} diff --git a/payloads/libpayload/tests/mocks/boot_device.c b/payloads/libpayload/tests/mocks/boot_device.c new file mode 100644 index 0000000..0565433 --- /dev/null +++ b/payloads/libpayload/tests/mocks/boot_device.c @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <boot_device.h> +#include <string.h> +#include <tests/test.h> + + +ssize_t libpayload_boot_device_read(void *buf, size_t offset, size_t size) +{ + void *outbuf; + size_t outsize; + check_expected(offset); + check_expected(size); + + outbuf = mock_ptr_type(void *); + outsize = mock_type(size_t); + + if (outbuf) + memcpy(buf, outbuf, outsize); + + return outsize; +}