From dcffa4428d0359fd09348fc05cf5b5ce2db38c5f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 17 Jan 2023 10:47:41 -0700 Subject: [PATCH] part: Add a function to find the first bootable partition If a disk has a bootable partition we are expected to use it to locate the boot files. Add a function to find it. To test this, update mmc1 to have two paritions, fixing up other tests accordingly. Signed-off-by: Simon Glass --- disk/part.c | 16 ++++++++++++++++ include/part.h | 8 ++++++++ test/boot/bootflow.c | 6 +++--- test/dm/part.c | 13 +++++++++++++ test/py/tests/bootstd/mmc1.img.xz | Bin 4448 -> 4480 bytes test/py/tests/test_ut.py | 13 +++++++++---- 6 files changed, 49 insertions(+), 7 deletions(-) diff --git a/disk/part.c b/disk/part.c index 5ee60a7fb5..d449635254 100644 --- a/disk/part.c +++ b/disk/part.c @@ -770,3 +770,19 @@ void part_set_generic_name(const struct blk_desc *dev_desc, sprintf(name, "%s%c%d", devtype, 'a' + dev_desc->devnum, part_num); } + +int part_get_bootable(struct blk_desc *desc) +{ + struct disk_partition info; + int p; + + for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) { + int ret; + + ret = part_get_info(desc, p, &info); + if (!ret && info.bootable) + return p; + } + + return 0; +} diff --git a/include/part.h b/include/part.h index 807370d942..be75c73549 100644 --- a/include/part.h +++ b/include/part.h @@ -303,6 +303,14 @@ part_get_info_by_dev_and_name_or_num(const char *dev_iface, } #endif +/** + * part_get_bootable() - Find the first bootable partition + * + * @desc: Block-device descriptor + * @return first bootable partition, or 0 if there is none + */ +int part_get_bootable(struct blk_desc *desc); + struct udevice; /** * part_create_block_devices - Create block devices for disk partitions diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index 12976005e4..38ffe8fa9b 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -315,15 +315,15 @@ static int bootflow_iter(struct unit_test_state *uts) ut_asserteq(BOOTFLOWST_FS, bflow.state); bootflow_free(&bflow); - /* Then more to partition 2 which doesn't exist */ - ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow)); + /* Then more to partition 2 which exists but is not bootable */ + ut_asserteq(-EPERM, bootflow_scan_next(&iter, &bflow)); ut_asserteq(2, iter.num_methods); ut_asserteq(0, iter.cur_method); ut_asserteq(2, iter.part); ut_asserteq(0x1e, iter.max_part); ut_asserteq_str("syslinux", iter.method->name); ut_asserteq(0, bflow.err); - ut_asserteq(BOOTFLOWST_MEDIA, bflow.state); + ut_asserteq(BOOTFLOWST_PART, bflow.state); bootflow_free(&bflow); bootflow_iter_uninit(&iter); diff --git a/test/dm/part.c b/test/dm/part.c index b60687114f..35e99eeb01 100644 --- a/test/dm/part.c +++ b/test/dm/part.c @@ -93,3 +93,16 @@ static int dm_test_part(struct unit_test_state *uts) return ret; } DM_TEST(dm_test_part, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_part_bootable(struct unit_test_state *uts) +{ + struct blk_desc *desc; + struct udevice *dev; + + ut_assertok(uclass_get_device_by_name(UCLASS_BLK, "mmc1.blk", &dev)); + desc = dev_get_uclass_plat(dev); + ut_asserteq(1, part_get_bootable(desc)); + + return 0; +} +DM_TEST(dm_test_part_bootable, UT_TESTF_SCAN_FDT); diff --git a/test/py/tests/bootstd/mmc1.img.xz b/test/py/tests/bootstd/mmc1.img.xz index 4e7f39b830eb4bddcb9ff6df39e89f130b5706b9..cebf7b9c53b3ed2370dbc65f0d26dd9bf096fab8 100644 GIT binary patch delta 1655 zcmV--28j9KB7h@*{Wp48S^xk9=GL@E0stWa8~^|S5YJf5|NmMBd|dzlZ~gpA<{Uz| zzgb+hQv3zT1yKgH@;2zWF3PJ~6cavY@U&ANJ0gCP@g^CK!(rj@H-&MG2+zt#VrMq1 z-bKm%b2F*>ab%+I**3@5=eRQUvo=zPEG1lh0FMJM7*2m;f5_u>M)rb8W}+Uqf+ks) z_#_Lj9#uBA9K(VBR-_^mmJcn)WfTd{;~te;2sbZTUWEL8Ce`b-Jt10-wlVDTu17Rv z4VaVs=u)K>0j21p2`cQW|5_%jats!dr@lFlB;k`$3txXy+a#DV!4|8tN&)+Lh{XiP zVol6p;1;M=YgT!hV3^xhq6kT^pvtCdcsw##ssXd#S4+B)%GmE^iJuWCu6oZ}pJD9s z`5K;^&Q>pwgZ@W#?43SjFfDh&0r#>&hl5~mNbUgZ8U1#x{hSCvZikVj1k;>{8^d^7 zLg>&U@uq9E$6xZvh&l$FOl?xq{b&{NB=g?qmeFk5cgCCIZ?CrYEJ-LLMpd6h)hC=q zzRSVQ!8553c{1arJOgZG`#wznKO7b7FMmwg$LxREB*TT&O>G`dqd^Ih93Z#d-K*=) zB)cm55`*cT+@1Ydj{@IW@FEnmg>)#(gV4|lVc9LZ64Ot3r`x`b9TwuPQS117K6VKm zl4s4)`kLs1X`71Z@E(8n)q_&iJAu zxrcxBv2_h4N#VeAIVRirRLy0xDeR^;;Vt?=n$Td*Al4sMA_xLBPMEI_h7m8eKclnG!mg*6f3@RV!!Dy zYU+!M?VT~mD+f6->%5e(H(O~9j2-0lS3Zz)dxe0S#EnU;TS z1+1Ngg5l(_;}GfW7P-o32Rt7w0p$R@00nGCgd@1H>W z>mvvhif|1nW{sZiRe4N<^SQN<<#+#?0AH6Dij6NKGjqrw3#H*wc1Om*DX%Y_j=q%{ zXCpEp3>^z@l5blk3EN&soj}hZr(J*5Kyt+`2QqO39ZhCv?^TkQZF(NvEooQvZb5YQ2_Ok;$%a*I2t@M5()&$Q zuV=`l72@)HIyule&bL9;-q&H&xA3Xxc|8DS`hJ-e^zB)(=ryl3L>8eKYJh+Ke!cK( zwmHfOzQ8A%A?^JQAX0xp!To?PeLc@XvxgAG7QpKBDB5$%SMwfIwI>kGz&<(}KCq79 z_uig^In$u^bS?|I(*e!CouC=N%slEv86cwifl_Dsu3QefK_gtT&7j@j63>@_2q)R4 zrZV2K-w`h{0zYK~I_WYrIP0NLdKl+jI3O9iA8VaviOYeV( zTKFljND&c=eUd343kD+Rb078iL#ms`bg7moAG7Pd;l?P40x+rM2QzGdz?dmEn*GYUkzwP^7jB&Wh zfS-SG_@D&{8E!xrxM!T zJ!haq_%|(J-Rp9)}RPcy(EHK-`P*jm3mj(l0$#6Rqz%nYslFG5fXZr#G00004Sz0zM B8fpLl delta 1580 zcmV+{2GjX~Bj6%`{Wp48S^xk9=GL@E0stWa761SMbT8$j|Nr9#SzQ1CZ~gp9mywT@ zX9SH~J$HQgn~xH8r*R%x@0<=h+lgT<_xrs-znV_419+K~}pr5i6t;;X5H=eceQvOcz_m&Of`5M?JgubSFnsOe+W}JM1vca*@H`m~N2QSki3RrWs?u`efk)`Q z1I4j(WS_wYySbVdeqbLrhyrft+P^Wzf571<6mAn+(ayStI^6-?9Fj{Gs}2-@F;yAl zAQOk)7XLbruq4a2$s4F#dasOsO^R3gu)9P6O%UzUxh^V$sh<-dfsA}`+boMeRiGPY zHb_fTFwNahDhgBW3n>8?}IRO(WSH}POQ<0wl zF!z5*OIwmO-cwSxzreS*!N~4_jW?h<+JIB;zC;lmb+LP&V;{_Lr_1Kndj zqC4_Y7L)_}b=v{EpiRcl{@ z(6s$?Vc$rX3-Bu2_dtb&zY9Uk?{0C)>TF*|z{)b5M>QOyU2(e%>yohpf1>1(R#|F^Hc-17;yAyM~LkW#W2`CT75_U7J zxojLkA%oKe7gYnM614d2W`i%suCVf(9QPuGO$GLNTPdH0EpA*&OIR~b2Pe~|1|4#c*3#T*fO7SGKF^YW7GpTbWD$R-k(a zP`C~@itq8#G#Cb%4OWwphP_No3N9VoqQpA$)fAzcK!YH%-PC0q) zHc`?8x(xn~H?y)XqTn)90O>*@{&pI95tQm6NY}2?gPsKGDD<4lc)Q;-uK& zVRB7!Xz7-)wq(Y*`$x=Rkg26+lHFQf>(vzXE8oiK$7v@B;nPh! zb5^(04D6|me}<(ne=-;Z8cFKLTNA**CxYb+d4!i%?T|pB7!QfT59)C$75dFOasor+ zrB5HUPWpVffF-(L69owH?ird#UnAH>E%?|nRP5f!k?8w3fe<1V|2OGJ9m;yqxw)m> zHooGc=ROmb$F15b2C5~M%n1-@A$}(cds-s8=12K?Z3JJadoXCDN)@Dot{Yl< zdq^?V9nxMDrw#2SM@Xeo;Gh1K0t`TUEtkL!x_NFC(EMPASHtlBC;wb<9CV}n5={?B zq3451GV+&de{TMM-hczKl26E4EHe`3n&yWhCX?@KX`(lZlX0TZV?Zj5_|v|NqU@l7 zm;}ZS?8YON!pN()9pDTEVzXKJbDDG1gk8N?HvAmPpT|AQ-syX5hWnN{b>b=Ktj(Lo zE@t+o7-y~t`5t!!)3~}CU2nmN3!7;VkF^Hmj1c#Ao{g000001X)@WZu`Cf diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py index 6958fabfa3..e8c8a6d6bd 100644 --- a/test/py/tests/test_ut.py +++ b/test/py/tests/test_ut.py @@ -19,13 +19,14 @@ def mkdir_cond(dirname): if not os.path.exists(dirname): os.mkdir(dirname) -def setup_image(cons, mmc_dev, part_type): +def setup_image(cons, mmc_dev, part_type, second_part=False): """Create a 20MB disk image with a single partition Args: cons (ConsoleBase): Console to use mmc_dev (int): MMC device number to use, e.g. 1 part_type (int): Partition type, e.g. 0xc for FAT32 + second_part (bool): True to contain a small second partition Returns: tuple: @@ -36,9 +37,13 @@ def setup_image(cons, mmc_dev, part_type): mnt = os.path.join(cons.config.persistent_data_dir, 'mnt') mkdir_cond(mnt) + spec = f'type={part_type:x}, size=18M, bootable' + if second_part: + spec += '\ntype=c' + u_boot_utils.run_and_log(cons, 'qemu-img create %s 20M' % fname) u_boot_utils.run_and_log(cons, 'sudo sfdisk %s' % fname, - stdin=f'type={part_type:x}'.encode('utf-8')) + stdin=spec.encode('utf-8')) return fname, mnt def mount_image(cons, fname, mnt, fstype): @@ -59,7 +64,7 @@ def mount_image(cons, fname, mnt, fstype): u_boot_utils.run_and_log(cons, f'sudo mkfs.{fstype} {part}') opts = '' if fstype == 'vfat': - opts += ' -o uid={os.getuid()},gid={os.getgid()}' + opts += f' -o uid={os.getuid()},gid={os.getgid()}' u_boot_utils.run_and_log(cons, f'sudo mount -o loop {part} {mnt}{opts}') u_boot_utils.run_and_log(cons, f'sudo chown {getpass.getuser()} {mnt}') return loop @@ -218,7 +223,7 @@ booti ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r} def setup_bootflow_image(cons): """Create a 20MB disk image with a single FAT partition""" mmc_dev = 1 - fname, mnt = setup_image(cons, mmc_dev, 0xc) + fname, mnt = setup_image(cons, mmc_dev, 0xc, second_part=True) loop = None mounted = False