bloblist.c 17 KB

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