[PATCH v2 32/71] part: Add a function to find the first bootable partition

Simon Glass sjg at chromium.org
Sun Jan 8 03:50:08 CET 2023


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 <sjg at chromium.org>
---

(no changes since v1)

 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
zcmV--28j9KB7h@*{Wp48S^xk9=GL at E0stWa8~^|S5YJf5|NmMBd|dzlZ~gpA<{Uz|
zzgb+hQv3zT1yKgH@;2zWF3PJ~6cavY at U&ANJ0gCP at g^CK!(rj at H-&MG2+zt#VrMq1
z-bKm%b2F*>ab%+I**3 at 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 at 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 at W#?<Ar+4>43SjFfDh&0r#>&hl5~mNbUgZ8U1#x{hSCvZikVj<Ab&
zbCz7PQ*nReV8Up!azo-eA!KemoFEGODQW6jTa`gICYLDmA at i8-1_wn>1k;>{8^d^7
zLg>&U at 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+ at 1Ydj{@IW at FEnmg>)#(gV4|lVc9LZ64Ot3r`x`b9TwuPQS117K6VKm
zl4s4)`kLs1X<z^ogIa#)ROp|?#lGd;UypSU)1^a at UmRdq(1>`71Z at E(8n)q_&iJAu
zxrcxBv2_h4N#VeAIVRirRLy0xDeR^;;Vt?=n$Td*Al4sMA_xLBPMEI_h7m8eKcl<M
z{|upLU8vxj)k6=(dq8(Euht38iCG*3$4MQ3K{Ui{za9MDk_C>nG!mg*6f3 at RV!!Dy
zYU+!M?V<y8_f~8MZ)Yn)OFlq2ta~XZ at lJo<c~1HE8S<{2f^$;~<VJe^w6%mOI8y*^
zo<kVZU(F{4b at 4G<9saho^b+e(PK{anN!YrSS{?-WmHF+h5FZk5_y$|D{K2pF at 4hd<
zm3NXpLh8E=J}Xo?Sxt?J9iaz>T~mD+f6->%5e(H(O~9j2-0lS3Zz)dxe0S#EnU;TS
z1+1Ngg5l(_;}Gf<HpOLNNMV(1KgvJwuQCtVC>W7P-o32Rt7w0p$R at 00nGCgd@1H>W
z>mvvhif|1nW{sZiRe4N<^SQN<<#+#?0AH6Dij6NKGjqrw3#H*wc1Om*DX%Y_j=q%{
zXCpEp3>^z at l5blk3EN&soj}hZr(J*5Kyt+`<ueH37$m*7UT62oA2gzw^cKPvg$3`d
z>2QqO39ZhCv?^TkQZF(NvEooQvZb5Y<iqIG9ZZPiuMu>Q2_Ok;$%a*I2t at M5()&$Q
zuV=`l72@)HIyule&bL9;-q&H&xA3Xxc|8DS`hJ-e^zB)(=ryl3L>8eKYJh+Ke!cK(
zwmHfOzQ8A%A?^JQAX0xp!To?PeLc at XvxgAG7QpKBDB5$%SMwfIwI>kGz&<(}KCq79
z_uig^In$u^bS?|I(*e!CouC=N%slEv86cwifl_Dsu3QefK_gtT&7j at j63>@_2q)R4
zrZV2K-w`h{0z<J3Cd(N;$*6y&y`piW(sI>YK~I_WYrIP0<ACL2sjTK`R~zIY$%{DZ
z0`tLhD+3xi49C-Im-e&t04juSaVzNf8xJ2by5oA0w>NLdKl+jI3O9iA8VaviOYeV(
zTKFljND&c=eUd343kD+Rb078iL#ms`<tQ`-xn<ZG!+QZns~8Wwr9^+`fZp?|160SU
zA_7uPQLXxkg{eW&3&r>bg7moAG7Pd;l?P40x+rM2QzGdz?dmEn*GYUkzwP^7jB&Wh
zfS-SG_ at D&{8E!xr<E**sjws;Z0?GA7(s3|N_UNc4l2qEV5F8{5-#YxAMSRs=>xM!T
zJ!haq_%|(J-Rp9)<VG>}RPcy(EHK-`P*jm3mj(l0$#6Rqz%n<Or4<3C=%WcL?5h7-
zCaiJ{7LupFIgcdalTiyV1x$(G+xD^$F#)m=F#)m=F#)m=F#)m=F#)m=F#)m=F#)m=
zF#)m=G65?I3jhTG#f?^#n*c{~)fG7pq8I=H+#-O0fC>YslFG5fXZr#G00004Sz0zM
B8fpLl

delta 1580
zcmV+{2GjX~Bj6%`{Wp48S^xk9=GL at E0stWa761SMbT8$j|Nr9#SzQ1CZ~gp9mywT@
zX9SH~J$HQgn~xH8r*R%x at 0<=h+lgT<_xrs-<w`xbRIw|E&$gheUrHepu{KmP1B)_~
zM8<xh5C?0oE?x{<-@`|Q`0vF~UZ=nbS6u7XQHW+SB;W8rb_fO2_8U;JWbdWX*Hr3S
zcy7{e*Ne)CKVLEX$WQ1KJ-6e4x+AFg28-GCf7T5fKYe$rgA^fd(banMJ`_`8lYbCT
zf8Z|5A>znV_419+K~}pr5i6t;;X5H=eceQvOcz_m&Of`5M?Jg<Tn2?0R!MXtuX*BF
z+4(C_$BiyXY&LRfHp at aTx>ubSFnsOe+W}JM1vca*@H`m~N2QSki3RrWs?u`efk)`Q
z1I4j(WS_wYySbVdeqbLrhyrft+P^Wzf571<6mAn+(ayStI^6-?9Fj{Gs}2- at F;yAl
zAQOk)7XLbruq4a2$s4F#dasOsO^R3gu)9P6O%UzUxh^V$sh<-dfsA}`+boMeRiGPY
zHb_fTFwNahDh<r6Eb+8J37g*;%p||ZZ5x=`YuX;ofY(C}ssHAEjO()c*|a}7f3vtr
zzdz&9*wuZW;{Hq+l2l*EtIE;DNjbR3z^+P$Z9%FO>gBW3n>8?}IRO(WSH}POQ<0wl
zF!z5*OIwmO-cwSxzreS*!N~4_jW?h<+JIB;zC;lmb+L<aG~E!0>P&V;{_Lr_1Kndj
zqC4_Y7L)_}b=<n;N5yRXC_inse|eiRAIt_yf4<PYBan at S9YsR?t at s{>v{EpiRcl{@
z(6s$?Vc$rX3-Bu2_dtb&zY9Uk?{0C)>TF*|z<yZ_PEMgaS5;bZ!26iM1R#x9D#2Mh
zT0gTSAb(^xcf|bw%gIYq$tlLV5E}4EAcj{`<|OI>{<P$=$&tE)Mf&wff601DZ-A;U
zZF{_;HK}x9>)b5M>QOyU2(e%>yohpf1>1(R#|F^Hc-17;yAyM~LkW#W2`CT75_U7J
zxojLkA%oKe7gYnM614d2W`i%suCVf(9QPuGO$GLNTPdH0EpA*&OIR~b2Pe~|1|4<k
z7!~U^Ot_B19!X-!Ek952e=(G*;-?ahy)9{>#c*3#T*fO7SGKF^YW7GpTbWD$R-k(a
zP`C~@itq8#G#Cb%4OWwphP_No3N9Voq<nNZGfaDMFtdKj<7GoqSxbelhYGjiBBOfW
zk{V9{cDtUBxVAy()2g1K65E%{vyy3ZXAb}_EfCGP?g}j>QpA$)fAzcK!YH%-PC0q)
zHc`?8x(xn~H?y)XqTn)90O>*@{&pI<cYrAf>95tQm6NY}2?gPsKGDD<4lc)Q;-uK&
zVRB7<Rqo8Y0Vp2&OqN>!Xz7-)wq(Y*`$x=Rkg26+lHFQf>(vzXE8oiK$7v at 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- at A$}(cds-s8=12K?Z3J<xfAbZ?K#=O<LnU6KRVK+?
z95hvl*1hk%*8aftJraq7u~tk0*f!SQ``IU0bc57?#lH7!od>JadoXCDN)@Dot{Yl<
zdq^?V9nxMDrw#2SM at Xeo;Gh1K0t`TUEtkL!x_NFC(EMPASHtlBC;wb<9CV}n5={?B
zq3451GV+&de{TMM-hczKl26E4EHe`3n&yWhCX?@KX`(lZlX0TZV?Zj5_|v|NqU at l7
zm;}ZS?8YON!pN()9pDTEVzXKJbDDG1gk8N?HvAmPpT|AQ-syX5hWnN{b>b=Ktj(Lo
zE at t+o7-y~t`5t!!)3~}CU2nmN3!7;VkF^<ERXO3k8lpZ{WqwHX&~#RVoCI#nz1irB
zt(PtTF6)|;a1d4mtO^=%v%w9M1GA6}#00aD3}ON=fCz#B1pvR!##;aY0000~`63&P
ec4B=10l6Z8fPf0>Hmj1c#Ao{g000001X)@WZu`Cf

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
-- 
2.39.0.314.g84b9a713c41-goog



More information about the U-Boot mailing list