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 5ee60a7fb59..d449635254e 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 807370d9429..be75c735495 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 12976005e41..38ffe8fa9be 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 b60687114f1..35e99eeb01a 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 zcmaE$)Sz7d*Ssnsih+UU*|jZhObm*QG7Jn10_P*n{Qn=tRujv>kpK6O*E1QX?fWBR zwg&xSJ;55tw&j!AiyeBWR!4~l+ogZl5-ew}R5$6Pnq=?c#D^cuTMK(Q&YyBmN;g}5 z&-LWrV&j#+3R4!nyJ>d(`tuz|UpJctwd<(H)H3ul>q+?4C)J;LT;lev$s=u%-1a85 z$mu^+xYx^tnr)Ri-1skSiIVU%e%)iKBAn+Q%T0~uFxQWaYxz^FcJ=iZTg9lpZH8|? zt#da?;hi!0&x@d?qKr#lEaudDv+948+L|IBu}RDKS@x?uoE*pLB-!R0eXG+f8vk6K|&wUDiI?bf*My^TL z-Ccbtn>Q`XXYAY1U0ysbW>aus{o{l~8JminA6Y4;*(~ApAAD3lsIUfJ%WQP^oY@ghqOMf#&Kd5}Z_k7yLoLl9` zWT_K8oj!Q>pz%unN~6b1ZJ2XXe%tx{x0exptzYkR^Z1+k zn<|G}ulVN5`7L(joFt>L{qEh>ug|IM*7_yX{BrJ{xql=3neIn^P!iePTB32f`N9RR z#GAUigf9D6EWf?4S61xN+Q8R8s_n`+WhbSdz4&X^i>Ay32I1zYy5}J;<{vq_@9Ew6 z{!;$SOPwdg%Opfx=&0yo$z@cN+V*hHxgU#^cedAm*;vY}>iO_Mv8CGWpCM;cH*3CG zX7*6`m&2?J3Fj29$%iU&Fq!zxSkKocsK3pA@$NJKc^0O}u6Qu}sx$x5YKL-z_18Gh zc1Fsu9QTy1cQiSYvtRbl-ASx{TTO%(#)@d~D@xk`(jetg`KK%nz%O}}6z1q!VryXJ$ z>D${WyO6y#Hn>)z{$koaL7uAtz6TZu+$Nh6NLK-` zW?JvOccGO&&7XH}o$$2$|4fGX>0({I`bx&dClt7sJ`5^zKXyQKz5blOeN!dVm5mg6 zWV!Puu_FSd2IbvhoYmpPmMVqN~rAJ9+&?8q`b+ZnP0>XiM6u6U-Pn{ z=Qiisb8TC+Vm<}w8}V&?6kxh(>FgU%4!^i8>(lXMy+sKVCOxK&bh%J=JYN-EL zxA#N#Hp^2S`wpnjQhfWDS0Sk0@!;PEy;|Gzj+@&Bj))z2^;zRq@u~37a=}~G1wD4guJc*XSjV6ir{lqJvc%URREZT`Zb)skDN{o;o-zr5kD$5j)zo9Caf z|26RgmwCe{DX#Sq-tX%>qJC&@@DLR2s-2{%z|E%gyjcG059d|0k3H2eVcnT}L*j5X zquXi;{yj@w>Yp{-`@E7lC29rMm(Fsr?UGV*rk!N zEm-NL@!MBgde=Q`toOhD9otj5<7C79`hp(|SUDu~93&pE+4;Ip_Mw1~ ziAvMinBz|tSc@DmGM|B`)YND7>AZjY+a>`+M*P@_QJa&SftBHCZ`jn?4DN+jMJ@Rk eNiZD0y}>A#s67#J8>BBKB{EE;M6 delta 1580 zcmZorexOwU*Ssnsih+UU*|jZhObm*QVhjunCHhYn|NsA(Ei#sYA^-0m&*>BUr=+v= zM%$Lx{FvP@RJy!SF7o{xKI_|^iMro^?{#?UWxG9OqjvlGZ3|Y%dnpQUGz&3e?lzk2 za;$El0DJa&y*Qre`-k0Ie!M>#5V!mQXL!u(Yk?hUhAQ_zIFxa)Uj8N>up#CB(u>za zUPV>pUCO)OeX7Gg-thMc{};lx+aEXVQeN?ct^4NJ`fI$>_O<1!n?)4!E?%wrY$p<& zG`U{Dzy5*VX~jn;g1&z0J?|K{+gwn4iO@r9#l+gXE;D_^qmP}l-#x+Ib`M7kTdPEv zXNmIq%1045e`*ID@743jF)PY6JME;mD}1iFLCxDow;6+;v6?+m{a_=>=e~3zYbWcs z_p2@yJ!*7+v6uPi#^RLu2ibS;oF!hDAaCBml=tG+e#2w+2Og@6MrA5 znMvMatNBFg4MQcLCz~zd_~nwv*B;Vyf2n)cbaY|JtzIg~39!ADAf0CB;T>#n_O8Dc@0m3^AGbJg&b}{sMrHr;TdA6y+a!W>Gjqqdte+EyS&tUMq-orb3lF7Z`pl$mPY~OzH#Jh%G^97c-8iL>L za}ks&-Pm1da#x_^l~0-Lzc(v)GT%+MTV(wyP;3hGuhKiap1L2+`J-W+sO1!UMl&9AHuC4c9stX&q(1Sw*2f#k~B;Uxw2sy@O9`9@`}# z^}$1-Ej;L%$}5I{Tb^t@IdNCB>#wgK^(U)5^BY#_;q@Jz)2{+;{W&%! z81CsPDrCLgw)r^Qh2s@hRj%$9F5ctJ+3Uus!GBDs%y`Yt92rN&=F6<&q0GyKw)}XL z)~tVg-G)!IWxgx5__BVhh}N9nrkfYzPDVuERD+$rpran9R4#{~Yoz%7W z|4?r@W!0nQLVbI6GZ!8$h>nOkrp*_=ZS~8nZyqMmGrj+ZEvRM>*uiJk_5R}}6A8AN zykV0kw(a%t;nI`6v!tfP!q}&}z+iLTsmH0#L6P3A>)W}uKT=v;b$^nSKSSB>dHp-K zIX=IqvOb(`ckzHSpWgB8M@w!zOf2%P z4SjcJH=~B!FP~}A3>hz{ZP=D_Y{zf+GYJz`E=`+sH!AM+RgtgS_fNezo~h39@UpLU zaoG0DJa1O^*0(J+s5g>ek@9?XEL!-$0rjS*Je4ie!`@DCSSZ2Yd655Ap_b^cvsOh+ z&X1S+%Wv`fRkNc(byvJFE60a-lC#|7m2bG}{?K_n(!yEQM?9KZ_oAnDFY6 zvufO;P_>gWGA5y&*Y>{ObM4=OueL&+%^Smf7;l(eyZ8I1dPGU{mHMOmzURzkUwygS zAY-wY=#u7j(ot2_9)?$BFU5&0=Y6Z7{*JCXv35^QT-n%jF%rq+;_Ac5u(mAL^*UeB6bAP~l~hD)ko^FiLp%$q0h9AVi! zfhUPczk#EPft6wZxnt1`AQ19XNxG*jsg{9pr&2>h1J^6F)sr?JN&n3Rl4OaD0ss?k B`@R4G diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py index 6958fabfa34..e8c8a6d6bd5 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