Coverage Report

Created: 2026-03-11 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/u-boot/test/boot/bootdev.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0+
2
/*
3
 * Test for bootdev functions. All start with 'bootdev'
4
 *
5
 * Copyright 2021 Google LLC
6
 * Written by Simon Glass <sjg@chromium.org>
7
 */
8
9
#include <bootstd.h>
10
#include <dm.h>
11
#include <bootdev.h>
12
#include <bootflow.h>
13
#include <env.h>
14
#include <mapmem.h>
15
#include <os.h>
16
#include <test/ut.h>
17
#include "bootstd_common.h"
18
19
/* Check 'bootdev list' command */
20
static int bootdev_test_cmd_list(struct unit_test_state *uts)
21
0
{
22
0
  int probed;
23
24
0
  for (probed = 0; probed < 2; probed++) {
25
0
    int probe_ch = probed ? '+' : ' ';
26
27
0
    ut_assertok(run_command(probed ? "bootdev list -p" :
28
0
      "bootdev list", 0));
29
0
    ut_assert_nextline("Seq  Probed  Status  Uclass    Name");
30
0
    ut_assert_nextlinen("---");
31
0
    ut_assert_nextline("%3x   [ %c ]  %6s  %-8s  %s", 0, probe_ch, "OK",
32
0
           "mmc", "mmc2.bootdev");
33
0
    ut_assert_nextline("%3x   [ %c ]  %6s  %-8s  %s", 1, probe_ch, "OK",
34
0
           "mmc", "mmc1.bootdev");
35
0
    ut_assert_nextline("%3x   [ %c ]  %6s  %-8s  %s", 2, probe_ch, "OK",
36
0
           "mmc", "mmc0.bootdev");
37
0
    ut_assert_nextlinen("---");
38
0
    ut_assert_nextline("(3 bootdevs)");
39
0
    ut_assert_console_end();
40
0
  }
41
42
0
  return 0;
43
0
}
44
BOOTSTD_TEST(bootdev_test_cmd_list, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
45
46
/* Check 'bootdev select' and 'info' commands */
47
static int bootdev_test_cmd_select(struct unit_test_state *uts)
48
0
{
49
0
  struct bootstd_priv *std;
50
51
  /* get access to the CLI's cur_bootdev */
52
0
  ut_assertok(bootstd_get_priv(&std));
53
54
0
  ut_asserteq(1, run_command("bootdev info", 0));
55
0
  ut_assert_nextlinen("Please use");
56
0
  ut_assert_console_end();
57
58
  /* select by sequence */
59
0
  ut_assertok(run_command("bootdev select 0", 0));
60
0
  ut_assert_console_end();
61
62
0
  ut_assertok(run_command("bootdev info", 0));
63
0
  ut_assert_nextline("Name:      mmc2.bootdev");
64
0
  ut_assert_nextline("Sequence:  0");
65
0
  ut_assert_nextline("Status:    Probed");
66
0
  ut_assert_nextline("Uclass:    mmc");
67
0
  ut_assert_nextline("Bootflows: 0 (0 valid)");
68
0
  ut_assert_console_end();
69
70
  /* select by bootdev name */
71
0
  ut_assertok(run_command("bootdev select mmc1.bootdev", 0));
72
0
  ut_assert_console_end();
73
0
  ut_assertnonnull(std->cur_bootdev);
74
0
  ut_asserteq_str("mmc1.bootdev", std->cur_bootdev->name);
75
76
  /* select by bootdev label*/
77
0
  ut_assertok(run_command("bootdev select mmc1", 0));
78
0
  ut_assert_console_end();
79
0
  ut_assertnonnull(std->cur_bootdev);
80
0
  ut_asserteq_str("mmc1.bootdev", std->cur_bootdev->name);
81
82
  /* deselect */
83
0
  ut_assertok(run_command("bootdev select", 0));
84
0
  ut_assert_console_end();
85
0
  ut_assertnull(std->cur_bootdev);
86
87
0
  ut_asserteq(1, run_command("bootdev info", 0));
88
0
  ut_assert_nextlinen("Please use");
89
0
  ut_assert_console_end();
90
91
0
  return 0;
92
0
}
93
BOOTSTD_TEST(bootdev_test_cmd_select, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
94
95
/* Check bootdev labels */
96
static int bootdev_test_labels(struct unit_test_state *uts)
97
0
{
98
0
  struct udevice *dev, *media;
99
0
  int mflags = 0;
100
101
0
  ut_assertok(bootdev_find_by_label("mmc2", &dev, &mflags));
102
0
  ut_asserteq(UCLASS_BOOTDEV, device_get_uclass_id(dev));
103
0
  ut_asserteq(0, mflags);
104
0
  media = dev_get_parent(dev);
105
0
  ut_asserteq(UCLASS_MMC, device_get_uclass_id(media));
106
0
  ut_asserteq_str("mmc2", media->name);
107
108
  /* Check method flags */
109
0
  ut_assertok(bootdev_find_by_label("pxe", &dev, &mflags));
110
0
  ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_PXE_ONLY,
111
0
        mflags);
112
0
  ut_assertok(bootdev_find_by_label("dhcp", &dev, &mflags));
113
0
  ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_DHCP_ONLY,
114
0
        mflags);
115
116
  /* Check invalid uclass */
117
0
  ut_asserteq(-EPFNOSUPPORT,
118
0
        bootdev_find_by_label("fred0", &dev, &mflags));
119
120
  /* Check unknown sequence number */
121
0
  ut_asserteq(-ENOENT, bootdev_find_by_label("mmc6", &dev, &mflags));
122
123
0
  return 0;
124
0
}
125
BOOTSTD_TEST(bootdev_test_labels, UTF_DM | UTF_SCAN_FDT | UTF_ETH_BOOTDEV);
126
127
/* Check bootdev_find_by_any() */
128
static int bootdev_test_any(struct unit_test_state *uts)
129
0
{
130
0
  struct udevice *dev, *media;
131
0
  char *seq;
132
0
  int mflags;
133
134
  /*
135
   * with ethernet enabled we have 8 devices ahead of the mmc ones:
136
   *
137
   * ut_assertok(run_command("bootdev list", 0));
138
   * Seq  Probed  Status  Uclass    Name
139
   * ---  ------  ------  --------  ------------------
140
   * 0   [ + ]      OK  ethernet  eth@10002000.bootdev
141
   * 1   [   ]      OK  ethernet  eth@10003000.bootdev
142
   * 2   [   ]      OK  ethernet  sbe5.bootdev
143
   * 3   [   ]      OK  ethernet  eth@10004000.bootdev
144
   * 4   [   ]      OK  ethernet  phy-test-eth.bootdev
145
   * 5   [   ]      OK  ethernet  dsa-test-eth.bootdev
146
   * 6   [   ]      OK  ethernet  dsa-test@0.bootdev
147
   * 7   [   ]      OK  ethernet  dsa-test@1.bootdev
148
   * 8   [   ]      OK  mmc       mmc2.bootdev
149
   * 9   [ + ]      OK  mmc       mmc1.bootdev
150
   * a   [   ]      OK  mmc       mmc0.bootdev
151
   *
152
   * However if DSA_SANDBOX is disabled the dsa-test@{0,1} devices
153
   * are not there.
154
   */
155
0
  if (CONFIG_IS_ENABLED(DSA_SANDBOX))
156
0
    seq = "8";
157
0
  else
158
0
    seq = "6";
159
160
0
  ut_assertok(bootdev_find_by_any(seq, &dev, &mflags));
161
0
  ut_asserteq(UCLASS_BOOTDEV, device_get_uclass_id(dev));
162
0
  ut_asserteq(BOOTFLOW_METHF_SINGLE_DEV, mflags);
163
0
  media = dev_get_parent(dev);
164
0
  ut_asserteq(UCLASS_MMC, device_get_uclass_id(media));
165
0
  ut_asserteq_str("mmc2", media->name);
166
0
  ut_assert_console_end();
167
168
  /* there should not be this many bootdevs */
169
0
  ut_asserteq(-ENODEV, bootdev_find_by_any("50", &dev, &mflags));
170
0
  ut_assert_nextline("Cannot find '50' (err=-19)");
171
0
  ut_assert_console_end();
172
173
  /* Check method flags */
174
0
  ut_assertok(bootdev_find_by_any("pxe", &dev, &mflags));
175
0
  ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_PXE_ONLY,
176
0
        mflags);
177
178
  /* Check invalid uclass */
179
0
  mflags = 123;
180
0
  ut_asserteq(-EPFNOSUPPORT, bootdev_find_by_any("fred0", &dev, &mflags));
181
0
  ut_assert_nextline("Cannot find bootdev 'fred0' (err=-96)");
182
0
  ut_asserteq(123, mflags);
183
0
  ut_assert_console_end();
184
185
0
  return 0;
186
0
}
187
BOOTSTD_TEST(bootdev_test_any, UTF_DM | UTF_SCAN_FDT | UTF_ETH_BOOTDEV |
188
       UTF_CONSOLE);
189
190
/*
191
 * Check bootdev ordering with the bootdev-order property and boot_targets
192
 * environment variable
193
 */
194
static int bootdev_test_order(struct unit_test_state *uts)
195
0
{
196
0
  struct bootflow_iter iter;
197
0
  struct bootflow bflow;
198
199
0
  test_set_skip_delays(true);
200
201
  /* Start up USB which gives us three additional bootdevs */
202
0
  bootstd_reset_usb();
203
0
  ut_assertok(run_command("usb start", 0));
204
205
  /*
206
   * First try the order set by the bootdev-order property
207
   * Like all sandbox unit tests this relies on the devicetree setting up
208
   * the required devices:
209
   *
210
   * mmc0 - nothing connected
211
   * mmc1 - connected to mmc1.img file
212
   * mmc2 - nothing connected
213
   */
214
0
  ut_assertok(env_set("boot_targets", NULL));
215
0
  ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
216
0
  ut_asserteq(2, iter.num_devs);
217
0
  ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
218
0
  ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
219
0
  bootflow_iter_uninit(&iter);
220
221
  /* Use the environment variable to override it */
222
0
  ut_assertok(env_set("boot_targets", "mmc1 mmc2 usb"));
223
0
  ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
224
225
  /* get the usb device which has a backing file (flash1.img) */
226
0
  ut_asserteq(0, bootflow_scan_next(&iter, &bflow));
227
228
0
  ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
229
0
  ut_asserteq(5, iter.num_devs);
230
0
  ut_asserteq_str("mmc1.bootdev", iter.dev_used[0]->name);
231
0
  ut_asserteq_str("mmc2.bootdev", iter.dev_used[1]->name);
232
0
  ut_asserteq_str("usb_mass_storage.lun0.bootdev",
233
0
      iter.dev_used[2]->name);
234
0
  bootflow_iter_uninit(&iter);
235
236
  /* Try a single uclass */
237
0
  ut_assertok(env_set("boot_targets", NULL));
238
0
  ut_assertok(bootflow_scan_first(NULL, "mmc", &iter, 0, &bflow));
239
0
  ut_asserteq(2, iter.num_devs);
240
241
  /* Now scan past mmc1 and make sure that only mmc0 shows up */
242
0
  ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
243
0
  ut_asserteq(3, iter.num_devs);
244
0
  ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
245
0
  ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
246
0
  ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name);
247
0
  bootflow_iter_uninit(&iter);
248
249
  /* Try a single uclass with boot_targets */
250
0
  ut_assertok(env_set("boot_targets", "mmc"));
251
0
  ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
252
0
  ut_asserteq(2, iter.num_devs);
253
254
  /* Now scan past mmc1 and make sure that only mmc0 shows up */
255
0
  ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
256
0
  ut_asserteq(3, iter.num_devs);
257
0
  ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
258
0
  ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
259
0
  ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name);
260
0
  bootflow_iter_uninit(&iter);
261
262
  /* Try a single uclass with boot_targets */
263
0
  ut_assertok(env_set("boot_targets", "mmc usb"));
264
0
  ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
265
0
  ut_asserteq(2, iter.num_devs);
266
267
  /*
268
   * Now scan past mmc1 and make sure that the 3 USB devices show up. The
269
   * first one has a backing file so returns success
270
   */
271
0
  ut_asserteq(0, bootflow_scan_next(&iter, &bflow));
272
0
  ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
273
0
  ut_asserteq(6, iter.num_devs);
274
0
  ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
275
0
  ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
276
0
  ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name);
277
0
  ut_asserteq_str("usb_mass_storage.lun0.bootdev",
278
0
      iter.dev_used[3]->name);
279
0
  bootflow_iter_uninit(&iter);
280
281
0
  return 0;
282
0
}
283
BOOTSTD_TEST(bootdev_test_order, UTF_DM | UTF_SCAN_FDT);
284
285
/* Check default bootdev ordering  */
286
static int bootdev_test_order_default(struct unit_test_state *uts)
287
0
{
288
0
  struct bootflow_iter iter;
289
0
  struct bootflow bflow;
290
291
  /*
292
   * Now drop both orderings, to check the default (prioriy/sequence)
293
   * ordering
294
   */
295
0
  ut_assertok(env_set("boot_targets", NULL));
296
0
  ut_assertok(bootstd_test_drop_bootdev_order(uts));
297
298
0
  ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
299
0
  ut_asserteq(2, iter.num_devs);
300
0
  ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
301
0
  ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
302
303
0
  ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
304
0
  ut_asserteq(3, iter.num_devs);
305
0
  ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name);
306
0
  bootflow_iter_uninit(&iter);
307
308
0
  return 0;
309
0
}
310
BOOTSTD_TEST(bootdev_test_order_default, UTF_DM | UTF_SCAN_FDT);
311
312
/* Check bootdev ordering with the uclass priority */
313
static int bootdev_test_prio(struct unit_test_state *uts)
314
0
{
315
0
  struct bootdev_uc_plat *ucp;
316
0
  struct bootflow_iter iter;
317
0
  struct bootflow bflow;
318
0
  struct udevice *blk;
319
320
0
  test_set_skip_delays(true);
321
322
  /* disable ethernet since the hunter will run dhcp */
323
0
  test_set_eth_enable(false);
324
325
  /* Start up USB which gives us three additional bootdevs */
326
0
  bootstd_reset_usb();
327
0
  ut_assertok(run_command("usb start", 0));
328
329
0
  ut_assertok(bootstd_test_drop_bootdev_order(uts));
330
331
  /* 3 MMC and 3 USB bootdevs: MMC should come before USB */
332
0
  ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
333
334
  /* get the usb device which has a backing file (flash1.img) */
335
0
  ut_asserteq(0, bootflow_scan_next(&iter, &bflow));
336
337
0
  ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
338
0
  ut_asserteq(6, iter.num_devs);
339
0
  ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
340
0
  ut_asserteq_str("usb_mass_storage.lun0.bootdev",
341
0
      iter.dev_used[3]->name);
342
343
0
  ut_assertok(bootdev_get_sibling_blk(iter.dev_used[3], &blk));
344
0
  ut_asserteq_str("usb_mass_storage.lun0", blk->name);
345
346
  /* adjust the priority of the first USB bootdev to the highest */
347
0
  ucp = dev_get_uclass_plat(iter.dev_used[3]);
348
0
  ucp->prio = BOOTDEVP_1_PRE_SCAN;
349
350
  /* try again but enable hunting, which brings in SCSI */
351
0
  bootflow_iter_uninit(&iter);
352
0
  ut_assertok(bootflow_scan_first(NULL, NULL, &iter, BOOTFLOWIF_HUNT,
353
0
          &bflow));
354
355
  /* get the usb device which has a backing file (flash1.img) */
356
0
  ut_asserteq(0, bootflow_scan_next(&iter, &bflow));
357
358
0
  ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
359
0
  ut_asserteq(7, iter.num_devs);
360
0
  ut_asserteq_str("usb_mass_storage.lun0.bootdev",
361
0
      iter.dev_used[0]->name);
362
0
  ut_asserteq_str("mmc2.bootdev", iter.dev_used[1]->name);
363
364
0
  return 0;
365
0
}
366
BOOTSTD_TEST(bootdev_test_prio, UTF_DM | UTF_SCAN_FDT);
367
368
/* Check listing hunters */
369
static int bootdev_test_hunter(struct unit_test_state *uts)
370
0
{
371
0
  struct bootstd_priv *std;
372
373
0
  bootstd_reset_usb();
374
0
  test_set_skip_delays(true);
375
376
  /* get access to the used hunters */
377
0
  ut_assertok(bootstd_get_priv(&std));
378
379
0
  bootdev_list_hunters(std);
380
0
  ut_assert_nextline("Prio  Used  Uclass           Hunter");
381
0
  ut_assert_nextlinen("----");
382
0
  ut_assert_nextline("   6        ethernet         eth_bootdev");
383
0
  ut_assert_nextline("   5        ide              ide_bootdev");
384
0
  ut_assert_nextline("   2        mmc              mmc_bootdev");
385
0
  ut_assert_nextline("   4        nvme             nvme_bootdev");
386
0
  ut_assert_nextline("   4        qfw              qfw_bootdev");
387
0
  ut_assert_nextline("   4        scsi             scsi_bootdev");
388
0
  ut_assert_nextline("   4        spi_flash        sf_bootdev");
389
0
  ut_assert_nextline("   5        usb              usb_bootdev");
390
0
  ut_assert_nextline("   4        virtio           virtio_bootdev");
391
0
  ut_assert_nextline("(total hunters: 9)");
392
0
  ut_assert_console_end();
393
394
0
  ut_assertok(bootdev_hunt("usb1", false));
395
0
  ut_assert_skip_to_line("Bus usb@1: 5 USB Device(s) found");
396
0
  ut_assert_console_end();
397
398
  /* USB is 8th in the list, so bit 7 */
399
0
  ut_asserteq(BIT(7), std->hunters_used);
400
401
0
  return 0;
402
0
}
403
BOOTSTD_TEST(bootdev_test_hunter, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
404
405
/* Check 'bootdev hunt' command */
406
static int bootdev_test_cmd_hunt(struct unit_test_state *uts)
407
0
{
408
0
  struct bootstd_priv *std;
409
410
0
  test_set_skip_delays(true);
411
0
  bootstd_reset_usb();
412
413
  /* get access to the used hunters */
414
0
  ut_assertok(bootstd_get_priv(&std));
415
416
0
  ut_assertok(run_command("bootdev hunt -l", 0));
417
0
  ut_assert_nextline("Prio  Used  Uclass           Hunter");
418
0
  ut_assert_nextlinen("----");
419
0
  ut_assert_nextline("   6        ethernet         eth_bootdev");
420
0
  ut_assert_skip_to_line("(total hunters: 9)");
421
0
  ut_assert_console_end();
422
423
  /* Use the MMC hunter and see that it updates */
424
0
  ut_assertok(run_command("bootdev hunt mmc", 0));
425
0
  ut_assertok(run_command("bootdev hunt -l", 0));
426
0
  ut_assert_skip_to_line("   5        ide              ide_bootdev");
427
0
  ut_assert_nextline("   2     *  mmc              mmc_bootdev");
428
0
  ut_assert_skip_to_line("(total hunters: 9)");
429
0
  ut_assert_console_end();
430
431
  /* Scan all hunters */
432
0
  test_set_eth_enable(false);
433
0
  test_set_skip_delays(true);
434
0
  ut_assertok(run_command("bootdev hunt", 0));
435
0
  ut_assert_nextline("Hunting with: ethernet");
436
437
  /* This is the extension feature which has no uclass at present */
438
0
  ut_assert_nextline("Hunting with: ide");
439
440
  /* mmc hunter has already been used so should not run again */
441
442
0
  ut_assert_nextline("Hunting with: nvme");
443
0
  ut_assert_nextline("Hunting with: qfw");
444
0
  ut_assert_nextline("Hunting with: scsi");
445
0
  ut_assert_nextline("scanning bus for devices...");
446
0
  ut_assert_skip_to_line("Hunting with: spi_flash");
447
0
  ut_assert_nextline("Hunting with: usb");
448
0
  ut_assert_skip_to_line("Bus usb@1: 5 USB Device(s) found");
449
0
  ut_assert_nextline("Hunting with: virtio");
450
0
  ut_assert_console_end();
451
452
  /* List available hunters */
453
0
  ut_assertok(run_command("bootdev hunt -l", 0));
454
0
  ut_assert_nextlinen("Prio");
455
0
  ut_assert_nextlinen("----");
456
0
  ut_assert_nextline("   6     *  ethernet         eth_bootdev");
457
0
  ut_assert_nextline("   5     *  ide              ide_bootdev");
458
0
  ut_assert_nextline("   2     *  mmc              mmc_bootdev");
459
0
  ut_assert_nextline("   4     *  nvme             nvme_bootdev");
460
0
  ut_assert_nextline("   4     *  qfw              qfw_bootdev");
461
0
  ut_assert_nextline("   4     *  scsi             scsi_bootdev");
462
0
  ut_assert_nextline("   4     *  spi_flash        sf_bootdev");
463
0
  ut_assert_nextline("   5     *  usb              usb_bootdev");
464
0
  ut_assert_nextline("   4     *  virtio           virtio_bootdev");
465
0
  ut_assert_nextline("(total hunters: 9)");
466
0
  ut_assert_console_end();
467
468
0
  ut_asserteq(GENMASK(MAX_HUNTER, 0), std->hunters_used);
469
470
0
  return 0;
471
0
}
472
BOOTSTD_TEST(bootdev_test_cmd_hunt, UTF_DM | UTF_SCAN_FDT | UTF_ETH_BOOTDEV |
473
       UTF_CONSOLE);
474
475
/* Check searching for bootdevs using the hunters */
476
static int bootdev_test_hunt_scan(struct unit_test_state *uts)
477
0
{
478
0
  struct bootflow_iter iter;
479
0
  struct bootstd_priv *std;
480
0
  struct bootflow bflow;
481
482
  /* get access to the used hunters */
483
0
  ut_assertok(bootstd_get_priv(&std));
484
485
0
  ut_assertok(bootstd_test_drop_bootdev_order(uts));
486
0
  ut_assertok(bootflow_scan_first(NULL, NULL, &iter,
487
0
          BOOTFLOWIF_SHOW | BOOTFLOWIF_HUNT |
488
0
          BOOTFLOWIF_SKIP_GLOBAL, &bflow));
489
0
  ut_asserteq(BIT(MMC_HUNTER), std->hunters_used);
490
491
0
  return 0;
492
0
}
493
BOOTSTD_TEST(bootdev_test_hunt_scan, UTF_DM | UTF_SCAN_FDT);
494
495
/* Check that only bootable partitions are processed */
496
static int bootdev_test_bootable(struct unit_test_state *uts)
497
0
{
498
0
  struct bootflow_iter iter;
499
0
  struct bootflow bflow;
500
0
  struct udevice *blk;
501
502
0
  memset(&iter, '\0', sizeof(iter));
503
0
  memset(&bflow, '\0', sizeof(bflow));
504
0
  iter.part = 0;
505
0
  ut_assertok(uclass_get_device_by_name(UCLASS_BLK, "mmc1.blk", &blk));
506
0
  iter.dev = blk;
507
0
  iter.flags = BOOTFLOWIF_ONLY_BOOTABLE;
508
0
  ut_assertok(device_find_next_child(&iter.dev));
509
0
  uclass_first_device(UCLASS_BOOTMETH, &bflow.method);
510
511
  /*
512
   * initially we don't have any knowledge of which partitions are
513
   * bootable, but mmc1 has two partitions, with the first one being
514
   * bootable
515
   */
516
0
  iter.part = 2;
517
0
  ut_asserteq(-EINVAL, bootdev_find_in_blk(iter.dev, blk, &iter, &bflow));
518
0
  ut_asserteq(0, iter.first_bootable);
519
520
  /* scan with part == 0 to get the partition info */
521
0
  iter.part = 0;
522
0
  ut_asserteq(-ENOENT, bootdev_find_in_blk(iter.dev, blk, &iter, &bflow));
523
0
  ut_asserteq(1, iter.first_bootable);
524
525
  /* now it will refuse to use non-bootable partitions */
526
0
  iter.part = 2;
527
0
  ut_asserteq(-EINVAL, bootdev_find_in_blk(iter.dev, blk, &iter, &bflow));
528
529
0
  return 0;
530
0
}
531
BOOTSTD_TEST(bootdev_test_bootable, UTF_DM | UTF_SCAN_FDT);
532
533
/* Check hunting for bootdev of a particular priority */
534
static int bootdev_test_hunt_prio(struct unit_test_state *uts)
535
0
{
536
0
  bootstd_reset_usb();
537
0
  test_set_skip_delays(true);
538
539
0
  ut_assertok(bootdev_hunt_prio(BOOTDEVP_4_SCAN_FAST, false));
540
0
  ut_assert_nextline("scanning bus for devices...");
541
0
  ut_assert_skip_to_line("            Type: Hard Disk");
542
0
  ut_assert_nextlinen("            Capacity:");
543
0
  ut_assert_console_end();
544
545
  /* now try a different priority, verbosely */
546
0
  ut_assertok(bootdev_hunt_prio(BOOTDEVP_5_SCAN_SLOW, true));
547
0
  ut_assert_nextline("Hunting with: ide");
548
0
  ut_assert_nextline("Hunting with: usb");
549
0
  ut_assert_skip_to_line("Bus usb@1: 5 USB Device(s) found");
550
0
  ut_assert_console_end();
551
552
0
  return 0;
553
0
}
554
BOOTSTD_TEST(bootdev_test_hunt_prio, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
555
556
/* Check hunting for bootdevs with a particular label */
557
static int bootdev_test_hunt_label(struct unit_test_state *uts)
558
0
{
559
0
  struct udevice *dev, *old;
560
0
  struct bootstd_priv *std;
561
0
  int mflags;
562
563
0
  bootstd_reset_usb();
564
565
  /* get access to the used hunters */
566
0
  ut_assertok(bootstd_get_priv(&std));
567
568
  /* scan an unknown uclass */
569
0
  old = (void *)&mflags;   /* arbitrary pointer to check against dev */
570
0
  dev = old;
571
0
  mflags = 123;
572
0
  ut_asserteq(-EPFNOSUPPORT,
573
0
        bootdev_hunt_and_find_by_label("fred", &dev, &mflags));
574
0
  ut_asserteq_ptr(old, dev);
575
0
  ut_asserteq(123, mflags);
576
0
  ut_assert_console_end();
577
0
  ut_asserteq(0, std->hunters_used);
578
579
  /* scan an invalid mmc controllers */
580
0
  ut_asserteq(-ENOENT,
581
0
        bootdev_hunt_and_find_by_label("mmc4", &dev, &mflags));
582
0
  ut_asserteq_ptr(old, dev);
583
0
  ut_asserteq(123, mflags);
584
0
  ut_assert_console_end();
585
586
0
  ut_assertok(bootstd_test_check_mmc_hunter(uts));
587
588
  /* scan for a particular mmc controller */
589
0
  ut_assertok(bootdev_hunt_and_find_by_label("mmc1", &dev, &mflags));
590
0
  ut_assertnonnull(dev);
591
0
  ut_asserteq_str("mmc1.bootdev", dev->name);
592
0
  ut_asserteq(0, mflags);
593
0
  ut_assert_console_end();
594
595
  /* scan all of usb */
596
0
  test_set_skip_delays(true);
597
0
  ut_assertok(bootdev_hunt_and_find_by_label("usb", &dev, &mflags));
598
0
  ut_assertnonnull(dev);
599
0
  ut_asserteq_str("usb_mass_storage.lun0.bootdev", dev->name);
600
0
  ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS, mflags);
601
0
  ut_assert_nextline("Bus usb@1: 5 USB Device(s) found");
602
0
  ut_assert_console_end();
603
604
0
  return 0;
605
0
}
606
BOOTSTD_TEST(bootdev_test_hunt_label, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
607
608
/* Check iterating to the next label in a list */
609
static int bootdev_test_next_label(struct unit_test_state *uts)
610
0
{
611
0
  const char *const labels[] = {"mmc0", "scsi", "dhcp", "pxe", NULL};
612
0
  struct bootflow_iter iter;
613
0
  struct bootstd_priv *std;
614
0
  struct bootflow bflow;
615
0
  struct udevice *dev;
616
0
  int mflags;
617
618
0
  test_set_eth_enable(false);
619
620
  /* get access to the used hunters */
621
0
  ut_assertok(bootstd_get_priv(&std));
622
623
0
  memset(&iter, '\0', sizeof(iter));
624
0
  memset(&bflow, '\0', sizeof(bflow));
625
0
  iter.part = 0;
626
0
  uclass_first_device(UCLASS_BOOTMETH, &bflow.method);
627
0
  iter.cur_label = -1;
628
0
  iter.labels = labels;
629
630
0
  dev = NULL;
631
0
  mflags = 123;
632
0
  ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
633
0
  ut_assert_console_end();
634
0
  ut_assertnonnull(dev);
635
0
  ut_asserteq_str("mmc0.bootdev", dev->name);
636
0
  ut_asserteq(0, mflags);
637
638
0
  ut_assertok(bootstd_test_check_mmc_hunter(uts));
639
640
0
  ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
641
0
  ut_assert_nextline("scanning bus for devices...");
642
0
  ut_assert_skip_to_line(
643
0
    "            Capacity: 2.0 MB = 0.0 GB (4096 x 512)");
644
0
  ut_assert_console_end();
645
0
  ut_assertnonnull(dev);
646
0
  ut_asserteq_str("scsi.id0lun0.bootdev", dev->name);
647
0
  ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS, mflags);
648
649
  /* SCSI is 6th in the list, so bit 5 */
650
0
  ut_asserteq(BIT(MMC_HUNTER) | BIT(5), std->hunters_used);
651
652
0
  ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
653
0
  ut_assert_console_end();
654
0
  ut_assertnonnull(dev);
655
0
  ut_asserteq_str("eth@10002000.bootdev", dev->name);
656
0
  ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_DHCP_ONLY,
657
0
        mflags);
658
659
  /* dhcp: Ethernet is first so bit 0 */
660
0
  ut_asserteq(BIT(MMC_HUNTER) | BIT(5) | BIT(0), std->hunters_used);
661
662
0
  ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
663
0
  ut_assert_console_end();
664
0
  ut_assertnonnull(dev);
665
0
  ut_asserteq_str("eth@10002000.bootdev", dev->name);
666
0
  ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_PXE_ONLY,
667
0
        mflags);
668
669
  /* pxe: Ethernet is first so bit 0 */
670
0
  ut_asserteq(BIT(MMC_HUNTER) | BIT(5) | BIT(0), std->hunters_used);
671
672
0
  mflags = 123;
673
0
  ut_asserteq(-ENODEV, bootdev_next_label(&iter, &dev, &mflags));
674
0
  ut_asserteq(123, mflags);
675
0
  ut_assert_console_end();
676
677
  /* no change */
678
0
  ut_asserteq(BIT(MMC_HUNTER) | BIT(5) | BIT(0), std->hunters_used);
679
680
0
  return 0;
681
0
}
682
BOOTSTD_TEST(bootdev_test_next_label, UTF_DM | UTF_SCAN_FDT | UTF_ETH_BOOTDEV |
683
       UTF_SF_BOOTDEV | UTF_CONSOLE);
684
685
/* Check iterating to the next prioirty in a list */
686
static int bootdev_test_next_prio(struct unit_test_state *uts)
687
0
{
688
0
  struct bootflow_iter iter;
689
0
  struct bootstd_priv *std;
690
0
  struct bootflow bflow;
691
0
  struct udevice *dev;
692
0
  int ret;
693
694
0
  test_set_eth_enable(false);
695
0
  test_set_skip_delays(true);
696
697
  /* get access to the used hunters */
698
0
  ut_assertok(bootstd_get_priv(&std));
699
700
0
  memset(&iter, '\0', sizeof(iter));
701
0
  memset(&bflow, '\0', sizeof(bflow));
702
0
  iter.part = 0;
703
0
  uclass_first_device(UCLASS_BOOTMETH, &bflow.method);
704
0
  iter.cur_prio = 0;
705
0
  iter.flags = BOOTFLOWIF_SHOW;
706
707
0
  dev = NULL;
708
0
  ut_assertok(bootdev_next_prio(&iter, &dev));
709
0
  ut_assertnonnull(dev);
710
0
  ut_asserteq_str("mmc2.bootdev", dev->name);
711
712
  /* hunt flag not set, so this should not use any hunters */
713
0
  ut_asserteq(0, std->hunters_used);
714
0
  ut_assert_console_end();
715
716
  /* now try again with hunting enabled */
717
0
  iter.flags = BOOTFLOWIF_SHOW | BOOTFLOWIF_HUNT;
718
0
  iter.cur_prio = 0;
719
0
  iter.part = 0;
720
721
0
  ut_assertok(bootdev_next_prio(&iter, &dev));
722
0
  ut_asserteq_str("mmc2.bootdev", dev->name);
723
0
  ut_assert_nextline("Hunting with: mmc");
724
0
  ut_assert_console_end();
725
726
0
  ut_asserteq(BIT(MMC_HUNTER), std->hunters_used);
727
728
0
  ut_assertok(bootdev_next_prio(&iter, &dev));
729
0
  ut_asserteq_str("mmc1.bootdev", dev->name);
730
731
0
  ut_assertok(bootdev_next_prio(&iter, &dev));
732
0
  ut_asserteq_str("mmc0.bootdev", dev->name);
733
0
  ut_assert_console_end();
734
735
0
  ut_assertok(bootdev_next_prio(&iter, &dev));
736
0
  ut_asserteq_str("spi.bin@0.bootdev", dev->name);
737
0
  ut_assert_skip_to_line("Hunting with: spi_flash");
738
739
  /*
740
   * this scans all bootdevs of priority BOOTDEVP_4_SCAN_FAST before it
741
   * starts looking at the devices, so we se virtio as well
742
   */
743
0
  ut_assert_nextline("Hunting with: virtio");
744
0
  ut_assert_nextlinen("SF: Detected m25p16");
745
746
0
  ut_assertok(bootdev_next_prio(&iter, &dev));
747
0
  ut_asserteq_str("spi.bin@1.bootdev", dev->name);
748
0
  ut_assert_nextlinen("SF: Detected m25p16");
749
0
  ut_assert_console_end();
750
751
  /* keep going until there are no more bootdevs */
752
0
  do {
753
0
    ret = bootdev_next_prio(&iter, &dev);
754
0
  } while (!ret);
755
0
  ut_asserteq(-ENODEV, ret);
756
0
  ut_assertnull(dev);
757
0
  ut_asserteq(GENMASK(MAX_HUNTER, 0), std->hunters_used);
758
759
0
  ut_assert_skip_to_line("Hunting with: ethernet");
760
0
  ut_assert_console_end();
761
762
0
  return 0;
763
0
}
764
BOOTSTD_TEST(bootdev_test_next_prio, UTF_DM | UTF_SCAN_FDT | UTF_SF_BOOTDEV |
765
       UTF_CONSOLE);