bloblist.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (c) 2018, Google Inc. All rights reserved.
  4. */
  5. #include <common.h>
  6. #include <bloblist.h>
  7. #include <log.h>
  8. #include <mapmem.h>
  9. #include <asm/global_data.h>
  10. #include <test/suites.h>
  11. #include <test/test.h>
  12. #include <test/ut.h>
  13. DECLARE_GLOBAL_DATA_PTR;
  14. /* Declare a new bloblist test */
  15. #define BLOBLIST_TEST(_name, _flags) \
  16. UNIT_TEST(_name, _flags, bloblist_test)
  17. enum {
  18. TEST_TAG = BLOBLISTT_U_BOOT_SPL_HANDOFF,
  19. TEST_TAG2 = BLOBLISTT_VBOOT_CTX,
  20. TEST_TAG_MISSING = 0x10000,
  21. TEST_SIZE = 10,
  22. TEST_SIZE2 = 20,
  23. TEST_SIZE_LARGE = 0x3e0,
  24. TEST_ADDR = CONFIG_BLOBLIST_ADDR,
  25. TEST_BLOBLIST_SIZE = 0x400,
  26. ERASE_BYTE = '\xff',
  27. };
  28. static const char test1_str[] = "the eyes are open";
  29. static const char test2_str[] = "the mouth moves";
  30. static struct bloblist_hdr *clear_bloblist(void)
  31. {
  32. struct bloblist_hdr *hdr;
  33. /*
  34. * Clear out any existing bloblist so we have a clean slate. Zero the
  35. * header so that existing records are removed, but set everything else
  36. * to 0xff for testing purposes.
  37. */
  38. hdr = map_sysmem(CONFIG_BLOBLIST_ADDR, TEST_BLOBLIST_SIZE);
  39. memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
  40. memset(hdr, '\0', sizeof(*hdr));
  41. return hdr;
  42. }
  43. static int check_zero(void *data, int size)
  44. {
  45. u8 *ptr;
  46. int i;
  47. for (ptr = data, i = 0; i < size; i++, ptr++) {
  48. if (*ptr)
  49. return -EINVAL;
  50. }
  51. return 0;
  52. }
  53. static int bloblist_test_init(struct unit_test_state *uts)
  54. {
  55. struct bloblist_hdr *hdr;
  56. hdr = clear_bloblist();
  57. ut_asserteq(-ENOENT, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  58. ut_asserteq_ptr(NULL, bloblist_check_magic(TEST_ADDR));
  59. ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
  60. ut_asserteq_ptr(hdr, bloblist_check_magic(TEST_ADDR));
  61. hdr->version++;
  62. ut_asserteq(-EPROTONOSUPPORT, bloblist_check(TEST_ADDR,
  63. TEST_BLOBLIST_SIZE));
  64. ut_asserteq(-ENOSPC, bloblist_new(TEST_ADDR, 0x10, 0));
  65. ut_asserteq(-EFAULT, bloblist_new(1, TEST_BLOBLIST_SIZE, 0));
  66. ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
  67. ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  68. ut_assertok(bloblist_finish());
  69. ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  70. hdr->magic++;
  71. ut_asserteq_ptr(NULL, bloblist_check_magic(TEST_ADDR));
  72. hdr->magic--;
  73. hdr->flags++;
  74. ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  75. return 1;
  76. }
  77. BLOBLIST_TEST(bloblist_test_init, 0);
  78. static int bloblist_test_blob(struct unit_test_state *uts)
  79. {
  80. struct bloblist_hdr *hdr;
  81. struct bloblist_rec *rec, *rec2;
  82. char *data;
  83. /* At the start there should be no records */
  84. hdr = clear_bloblist();
  85. ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
  86. ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
  87. ut_asserteq(TEST_BLOBLIST_SIZE, bloblist_get_size());
  88. ut_asserteq(TEST_ADDR, bloblist_get_base());
  89. ut_asserteq(map_to_sysmem(hdr), TEST_ADDR);
  90. /* Add a record and check that we can find it */
  91. data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
  92. rec = (void *)(hdr + 1);
  93. ut_asserteq_addr(rec + 1, data);
  94. data = bloblist_find(TEST_TAG, TEST_SIZE);
  95. ut_asserteq_addr(rec + 1, data);
  96. /* Check the data is zeroed */
  97. ut_assertok(check_zero(data, TEST_SIZE));
  98. /* Check the 'ensure' method */
  99. ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
  100. ut_assertnull(bloblist_ensure(TEST_TAG, TEST_SIZE2));
  101. rec2 = (struct bloblist_rec *)(data + ALIGN(TEST_SIZE, BLOBLIST_ALIGN));
  102. ut_assertok(check_zero(data, TEST_SIZE));
  103. /* Check for a non-existent record */
  104. ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
  105. ut_asserteq_addr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2));
  106. ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0));
  107. return 0;
  108. }
  109. BLOBLIST_TEST(bloblist_test_blob, 0);
  110. /* Check bloblist_ensure_size_ret() */
  111. static int bloblist_test_blob_ensure(struct unit_test_state *uts)
  112. {
  113. void *data, *data2;
  114. int size;
  115. /* At the start there should be no records */
  116. clear_bloblist();
  117. ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
  118. /* Test with an empty bloblist */
  119. size = TEST_SIZE;
  120. ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
  121. ut_asserteq(TEST_SIZE, size);
  122. ut_assertok(check_zero(data, TEST_SIZE));
  123. /* Check that we get the same thing again */
  124. ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data2));
  125. ut_asserteq(TEST_SIZE, size);
  126. ut_asserteq_addr(data, data2);
  127. /* Check that the size remains the same */
  128. size = TEST_SIZE2;
  129. ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
  130. ut_asserteq(TEST_SIZE, size);
  131. /* Check running out of space */
  132. size = TEST_SIZE_LARGE;
  133. ut_asserteq(-ENOSPC, bloblist_ensure_size_ret(TEST_TAG2, &size, &data));
  134. return 0;
  135. }
  136. BLOBLIST_TEST(bloblist_test_blob_ensure, 0);
  137. static int bloblist_test_bad_blob(struct unit_test_state *uts)
  138. {
  139. struct bloblist_hdr *hdr;
  140. void *data;
  141. hdr = clear_bloblist();
  142. ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
  143. data = hdr + 1;
  144. data += sizeof(struct bloblist_rec);
  145. ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
  146. ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
  147. return 0;
  148. }
  149. BLOBLIST_TEST(bloblist_test_bad_blob, 0);
  150. static int bloblist_test_checksum(struct unit_test_state *uts)
  151. {
  152. struct bloblist_hdr *hdr;
  153. char *data, *data2;
  154. hdr = clear_bloblist();
  155. ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
  156. ut_assertok(bloblist_finish());
  157. ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  158. /*
  159. * Now change things amd make sure that the checksum notices. We cannot
  160. * change the size or alloced fields, since that will crash the code.
  161. * It has to rely on these being correct.
  162. */
  163. hdr->flags--;
  164. ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  165. hdr->flags++;
  166. hdr->size--;
  167. ut_asserteq(-EFBIG, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  168. hdr->size++;
  169. hdr->spare++;
  170. ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  171. hdr->spare--;
  172. hdr->chksum++;
  173. ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  174. hdr->chksum--;
  175. /* Make sure the checksum changes when we add blobs */
  176. data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
  177. ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  178. data2 = bloblist_add(TEST_TAG2, TEST_SIZE2, 0);
  179. ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  180. ut_assertok(bloblist_finish());
  181. /* It should also change if we change the data */
  182. ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  183. *data += 1;
  184. ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  185. *data -= 1;
  186. ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  187. *data2 += 1;
  188. ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  189. *data2 -= 1;
  190. /*
  191. * Changing data outside the range of valid data should not affect
  192. * the checksum.
  193. */
  194. ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  195. data[TEST_SIZE]++;
  196. data2[TEST_SIZE2]++;
  197. ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  198. return 0;
  199. }
  200. BLOBLIST_TEST(bloblist_test_checksum, 0);
  201. /* Test the 'bloblist info' command */
  202. static int bloblist_test_cmd_info(struct unit_test_state *uts)
  203. {
  204. struct bloblist_hdr *hdr;
  205. char *data, *data2;
  206. hdr = clear_bloblist();
  207. ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
  208. data = bloblist_ensure(TEST_TAG, TEST_SIZE);
  209. data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
  210. console_record_reset_enable();
  211. ut_silence_console(uts);
  212. console_record_reset();
  213. run_command("bloblist info", 0);
  214. ut_assert_nextline("base: %lx", (ulong)map_to_sysmem(hdr));
  215. ut_assert_nextline("size: 400 1 KiB");
  216. ut_assert_nextline("alloced: 70 112 Bytes");
  217. ut_assert_nextline("free: 390 912 Bytes");
  218. ut_assert_console_end();
  219. ut_unsilence_console(uts);
  220. return 0;
  221. }
  222. BLOBLIST_TEST(bloblist_test_cmd_info, 0);
  223. /* Test the 'bloblist list' command */
  224. static int bloblist_test_cmd_list(struct unit_test_state *uts)
  225. {
  226. struct bloblist_hdr *hdr;
  227. char *data, *data2;
  228. hdr = clear_bloblist();
  229. ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
  230. data = bloblist_ensure(TEST_TAG, TEST_SIZE);
  231. data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
  232. console_record_reset_enable();
  233. ut_silence_console(uts);
  234. console_record_reset();
  235. run_command("bloblist list", 0);
  236. ut_assert_nextline("Address Size Tag Name");
  237. ut_assert_nextline("%08lx %8x 8000 SPL hand-off",
  238. (ulong)map_to_sysmem(data), TEST_SIZE);
  239. ut_assert_nextline("%08lx %8x 106 Chrome OS vboot context",
  240. (ulong)map_to_sysmem(data2), TEST_SIZE2);
  241. ut_assert_console_end();
  242. ut_unsilence_console(uts);
  243. return 0;
  244. }
  245. BLOBLIST_TEST(bloblist_test_cmd_list, 0);
  246. /* Test alignment of bloblist blobs */
  247. static int bloblist_test_align(struct unit_test_state *uts)
  248. {
  249. struct bloblist_hdr *hdr;
  250. ulong addr;
  251. char *data;
  252. int i;
  253. /* At the start there should be no records */
  254. hdr = clear_bloblist();
  255. ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
  256. ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
  257. /* Check the default alignment */
  258. for (i = 0; i < 3; i++) {
  259. int size = i * 3;
  260. ulong addr;
  261. char *data;
  262. int j;
  263. data = bloblist_add(i, size, 0);
  264. ut_assertnonnull(data);
  265. addr = map_to_sysmem(data);
  266. ut_asserteq(0, addr & (BLOBLIST_ALIGN - 1));
  267. /* Only the bytes in the blob data should be zeroed */
  268. for (j = 0; j < size; j++)
  269. ut_asserteq(0, data[j]);
  270. for (; j < BLOBLIST_ALIGN; j++)
  271. ut_asserteq(ERASE_BYTE, data[j]);
  272. }
  273. /* Check larger alignment */
  274. for (i = 0; i < 3; i++) {
  275. int align = 32 << i;
  276. data = bloblist_add(3 + i, i * 4, align);
  277. ut_assertnonnull(data);
  278. addr = map_to_sysmem(data);
  279. ut_asserteq(0, addr & (align - 1));
  280. }
  281. /* Check alignment with an bloblist starting on a smaller alignment */
  282. hdr = map_sysmem(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE);
  283. memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
  284. memset(hdr, '\0', sizeof(*hdr));
  285. ut_assertok(bloblist_new(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE,
  286. 0));
  287. data = bloblist_add(1, 5, BLOBLIST_ALIGN * 2);
  288. ut_assertnonnull(data);
  289. addr = map_to_sysmem(data);
  290. ut_asserteq(0, addr & (BLOBLIST_ALIGN * 2 - 1));
  291. return 0;
  292. }
  293. BLOBLIST_TEST(bloblist_test_align, 0);
  294. /* Test relocation of a bloblist */
  295. static int bloblist_test_reloc(struct unit_test_state *uts)
  296. {
  297. const uint large_size = TEST_BLOBLIST_SIZE;
  298. const uint small_size = 0x20;
  299. void *old_ptr, *new_ptr;
  300. void *blob1, *blob2;
  301. ulong new_addr;
  302. ulong new_size;
  303. ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
  304. old_ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
  305. /* Add one blob and then one that won't fit */
  306. blob1 = bloblist_add(TEST_TAG, small_size, 0);
  307. ut_assertnonnull(blob1);
  308. blob2 = bloblist_add(TEST_TAG2, large_size, 0);
  309. ut_assertnull(blob2);
  310. /* Relocate the bloblist somewhere else, a bit larger */
  311. new_addr = TEST_ADDR + TEST_BLOBLIST_SIZE;
  312. new_size = TEST_BLOBLIST_SIZE + 0x100;
  313. new_ptr = map_sysmem(new_addr, TEST_BLOBLIST_SIZE);
  314. bloblist_reloc(new_ptr, new_size, old_ptr, TEST_BLOBLIST_SIZE);
  315. gd->bloblist = new_ptr;
  316. /* Check the old blob is there and that we can now add the bigger one */
  317. ut_assertnonnull(bloblist_find(TEST_TAG, small_size));
  318. ut_assertnull(bloblist_find(TEST_TAG2, small_size));
  319. blob2 = bloblist_add(TEST_TAG2, large_size, 0);
  320. ut_assertnonnull(blob2);
  321. return 0;
  322. }
  323. BLOBLIST_TEST(bloblist_test_reloc, 0);
  324. /* Test expansion of a blob */
  325. static int bloblist_test_grow(struct unit_test_state *uts)
  326. {
  327. const uint small_size = 0x20;
  328. void *blob1, *blob2, *blob1_new;
  329. struct bloblist_hdr *hdr;
  330. void *ptr;
  331. ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
  332. hdr = ptr;
  333. memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
  334. /* Create two blobs */
  335. ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
  336. blob1 = bloblist_add(TEST_TAG, small_size, 0);
  337. ut_assertnonnull(blob1);
  338. ut_assertok(check_zero(blob1, small_size));
  339. strcpy(blob1, test1_str);
  340. blob2 = bloblist_add(TEST_TAG2, small_size, 0);
  341. ut_assertnonnull(blob2);
  342. strcpy(blob2, test2_str);
  343. ut_asserteq(sizeof(struct bloblist_hdr) +
  344. sizeof(struct bloblist_rec) * 2 + small_size * 2,
  345. hdr->alloced);
  346. /* Resize the first one */
  347. ut_assertok(bloblist_resize(TEST_TAG, small_size + 4));
  348. /* The first one should not have moved, just got larger */
  349. blob1_new = bloblist_find(TEST_TAG, small_size + 4);
  350. ut_asserteq_ptr(blob1, blob1_new);
  351. /* The new space should be zeroed */
  352. ut_assertok(check_zero(blob1 + small_size, 4));
  353. /* The second one should have moved */
  354. blob2 = bloblist_find(TEST_TAG2, small_size);
  355. ut_assertnonnull(blob2);
  356. ut_asserteq_str(test2_str, blob2);
  357. /* The header should have more bytes in use */
  358. hdr = ptr;
  359. ut_asserteq(sizeof(struct bloblist_hdr) +
  360. sizeof(struct bloblist_rec) * 2 + small_size * 2 +
  361. BLOBLIST_ALIGN,
  362. hdr->alloced);
  363. return 0;
  364. }
  365. BLOBLIST_TEST(bloblist_test_grow, 0);
  366. /* Test shrinking of a blob */
  367. static int bloblist_test_shrink(struct unit_test_state *uts)
  368. {
  369. const uint small_size = 0x20;
  370. void *blob1, *blob2, *blob1_new;
  371. struct bloblist_hdr *hdr;
  372. int new_size;
  373. void *ptr;
  374. ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
  375. /* Create two blobs */
  376. ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
  377. blob1 = bloblist_add(TEST_TAG, small_size, 0);
  378. ut_assertnonnull(blob1);
  379. strcpy(blob1, test1_str);
  380. blob2 = bloblist_add(TEST_TAG2, small_size, 0);
  381. ut_assertnonnull(blob2);
  382. strcpy(blob2, test2_str);
  383. hdr = ptr;
  384. ut_asserteq(sizeof(struct bloblist_hdr) +
  385. sizeof(struct bloblist_rec) * 2 + small_size * 2,
  386. hdr->alloced);
  387. /* Resize the first one */
  388. new_size = small_size - BLOBLIST_ALIGN - 4;
  389. ut_assertok(bloblist_resize(TEST_TAG, new_size));
  390. /* The first one should not have moved, just got smaller */
  391. blob1_new = bloblist_find(TEST_TAG, new_size);
  392. ut_asserteq_ptr(blob1, blob1_new);
  393. /* The second one should have moved */
  394. blob2 = bloblist_find(TEST_TAG2, small_size);
  395. ut_assertnonnull(blob2);
  396. ut_asserteq_str(test2_str, blob2);
  397. /* The header should have fewer bytes in use */
  398. hdr = ptr;
  399. ut_asserteq(sizeof(struct bloblist_hdr) +
  400. sizeof(struct bloblist_rec) * 2 + small_size * 2 -
  401. BLOBLIST_ALIGN,
  402. hdr->alloced);
  403. return 0;
  404. }
  405. BLOBLIST_TEST(bloblist_test_shrink, 0);
  406. /* Test failing to adjust a blob size */
  407. static int bloblist_test_resize_fail(struct unit_test_state *uts)
  408. {
  409. const uint small_size = 0x20;
  410. struct bloblist_hdr *hdr;
  411. void *blob1, *blob2;
  412. int new_size;
  413. void *ptr;
  414. ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
  415. /* Create two blobs */
  416. ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
  417. blob1 = bloblist_add(TEST_TAG, small_size, 0);
  418. ut_assertnonnull(blob1);
  419. blob2 = bloblist_add(TEST_TAG2, small_size, 0);
  420. ut_assertnonnull(blob2);
  421. hdr = ptr;
  422. ut_asserteq(sizeof(struct bloblist_hdr) +
  423. sizeof(struct bloblist_rec) * 2 + small_size * 2,
  424. hdr->alloced);
  425. /* Resize the first one, to check the boundary conditions */
  426. ut_asserteq(-EINVAL, bloblist_resize(TEST_TAG, -1));
  427. new_size = small_size + (hdr->size - hdr->alloced);
  428. ut_asserteq(-ENOSPC, bloblist_resize(TEST_TAG, new_size + 1));
  429. ut_assertok(bloblist_resize(TEST_TAG, new_size));
  430. return 0;
  431. }
  432. BLOBLIST_TEST(bloblist_test_resize_fail, 0);
  433. /* Test expanding the last blob in a bloblist */
  434. static int bloblist_test_resize_last(struct unit_test_state *uts)
  435. {
  436. const uint small_size = 0x20;
  437. struct bloblist_hdr *hdr;
  438. void *blob1, *blob2, *blob2_new;
  439. int alloced_val;
  440. void *ptr;
  441. ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
  442. memset(ptr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
  443. hdr = ptr;
  444. /* Create two blobs */
  445. ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
  446. blob1 = bloblist_add(TEST_TAG, small_size, 0);
  447. ut_assertnonnull(blob1);
  448. blob2 = bloblist_add(TEST_TAG2, small_size, 0);
  449. ut_assertnonnull(blob2);
  450. /* Check the byte after the last blob */
  451. alloced_val = sizeof(struct bloblist_hdr) +
  452. sizeof(struct bloblist_rec) * 2 + small_size * 2;
  453. ut_asserteq(alloced_val, hdr->alloced);
  454. ut_asserteq_ptr((void *)hdr + alloced_val, blob2 + small_size);
  455. ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->alloced));
  456. /* Resize the second one, checking nothing changes */
  457. ut_asserteq(0, bloblist_resize(TEST_TAG2, small_size + 4));
  458. blob2_new = bloblist_find(TEST_TAG2, small_size + 4);
  459. ut_asserteq_ptr(blob2, blob2_new);
  460. /*
  461. * the new blob should encompass the byte we checked now, so it should
  462. * be zeroed. This zeroing should affect only the four new bytes added
  463. * to the blob.
  464. */
  465. ut_asserteq(0, *((u8 *)hdr + alloced_val));
  466. ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + alloced_val + 4));
  467. /* Check that the new top of the allocated blobs has not been touched */
  468. alloced_val += BLOBLIST_ALIGN;
  469. ut_asserteq(alloced_val, hdr->alloced);
  470. ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->alloced));
  471. return 0;
  472. }
  473. BLOBLIST_TEST(bloblist_test_resize_last, 0);
  474. /* Check a completely full bloblist */
  475. static int bloblist_test_blob_maxsize(struct unit_test_state *uts)
  476. {
  477. void *ptr;
  478. int size;
  479. /* At the start there should be no records */
  480. clear_bloblist();
  481. ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
  482. /* Add a blob that takes up all space */
  483. size = TEST_BLOBLIST_SIZE - sizeof(struct bloblist_hdr) -
  484. sizeof(struct bloblist_rec);
  485. ptr = bloblist_add(TEST_TAG, size, 0);
  486. ut_assertnonnull(ptr);
  487. ptr = bloblist_add(TEST_TAG, size + 1, 0);
  488. ut_assertnull(ptr);
  489. return 0;
  490. }
  491. BLOBLIST_TEST(bloblist_test_blob_maxsize, 0);
  492. int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
  493. char *const argv[])
  494. {
  495. struct unit_test *tests = UNIT_TEST_SUITE_START(bloblist_test);
  496. const int n_ents = UNIT_TEST_SUITE_COUNT(bloblist_test);
  497. return cmd_ut_category("bloblist", "bloblist_test_",
  498. tests, n_ents, argc, argv);
  499. }