subr_disk.c 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851
  1. /* $OpenBSD: subr_disk.c,v 1.187 2015/07/29 00:15:36 krw Exp $ */
  2. /* $NetBSD: subr_disk.c,v 1.17 1996/03/16 23:17:08 christos Exp $ */
  3. /*
  4. * Copyright (c) 1995 Jason R. Thorpe. All rights reserved.
  5. * Copyright (c) 1982, 1986, 1988, 1993
  6. * The Regents of the University of California. All rights reserved.
  7. * (c) UNIX System Laboratories, Inc.
  8. * All or some portions of this file are derived from material licensed
  9. * to the University of California by American Telephone and Telegraph
  10. * Co. or Unix System Laboratories, Inc. and are reproduced herein with
  11. * the permission of UNIX System Laboratories, Inc.
  12. *
  13. * Redistribution and use in source and binary forms, with or without
  14. * modification, are permitted provided that the following conditions
  15. * are met:
  16. * 1. Redistributions of source code must retain the above copyright
  17. * notice, this list of conditions and the following disclaimer.
  18. * 2. Redistributions in binary form must reproduce the above copyright
  19. * notice, this list of conditions and the following disclaimer in the
  20. * documentation and/or other materials provided with the distribution.
  21. * 3. Neither the name of the University nor the names of its contributors
  22. * may be used to endorse or promote products derived from this software
  23. * without specific prior written permission.
  24. *
  25. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35. * SUCH DAMAGE.
  36. *
  37. * @(#)ufs_disksubr.c 8.5 (Berkeley) 1/21/94
  38. */
  39. #include <sys/param.h>
  40. #include <sys/systm.h>
  41. #include <sys/kernel.h>
  42. #include <sys/malloc.h>
  43. #include <sys/fcntl.h>
  44. #include <sys/buf.h>
  45. #include <sys/stat.h>
  46. #include <sys/syslog.h>
  47. #include <sys/device.h>
  48. #include <sys/time.h>
  49. #include <sys/disklabel.h>
  50. #include <sys/conf.h>
  51. #include <sys/lock.h>
  52. #include <sys/disk.h>
  53. #include <sys/reboot.h>
  54. #include <sys/dkio.h>
  55. #include <sys/vnode.h>
  56. #include <sys/task.h>
  57. #include <sys/socket.h>
  58. #include <sys/socketvar.h>
  59. #include <net/if.h>
  60. #include <dev/rndvar.h>
  61. #include <dev/cons.h>
  62. #ifdef GPT
  63. #include <lib/libz/zlib.h>
  64. #endif
  65. #include "softraid.h"
  66. #ifdef DEBUG
  67. #define DPRINTF(x...) printf(x)
  68. #else
  69. #define DPRINTF(x...)
  70. #endif
  71. /*
  72. * A global list of all disks attached to the system. May grow or
  73. * shrink over time.
  74. */
  75. struct disklist_head disklist; /* TAILQ_HEAD */
  76. int disk_count; /* number of drives in global disklist */
  77. int disk_change; /* set if a disk has been attached/detached
  78. * since last we looked at this variable. This
  79. * is reset by hw_sysctl()
  80. */
  81. u_char bootduid[8]; /* DUID of boot disk. */
  82. u_char rootduid[8]; /* DUID of root disk. */
  83. /* softraid callback, do not use! */
  84. void (*softraid_disk_attach)(struct disk *, int);
  85. void sr_map_root(void);
  86. struct disk_attach_task {
  87. struct task task;
  88. struct disk *dk;
  89. };
  90. void disk_attach_callback(void *);
  91. /*
  92. * Compute checksum for disk label.
  93. */
  94. u_int
  95. dkcksum(struct disklabel *lp)
  96. {
  97. u_int16_t *start, *end;
  98. u_int16_t sum = 0;
  99. start = (u_int16_t *)lp;
  100. end = (u_int16_t *)&lp->d_partitions[lp->d_npartitions];
  101. while (start < end)
  102. sum ^= *start++;
  103. return (sum);
  104. }
  105. int
  106. initdisklabel(struct disklabel *lp)
  107. {
  108. int i;
  109. /* minimal requirements for archetypal disk label */
  110. if (lp->d_secsize < DEV_BSIZE)
  111. lp->d_secsize = DEV_BSIZE;
  112. if (DL_GETDSIZE(lp) == 0)
  113. DL_SETDSIZE(lp, MAXDISKSIZE);
  114. if (lp->d_secpercyl == 0)
  115. return (ERANGE);
  116. lp->d_npartitions = MAXPARTITIONS;
  117. for (i = 0; i < RAW_PART; i++) {
  118. DL_SETPSIZE(&lp->d_partitions[i], 0);
  119. DL_SETPOFFSET(&lp->d_partitions[i], 0);
  120. }
  121. if (DL_GETPSIZE(&lp->d_partitions[RAW_PART]) == 0)
  122. DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp));
  123. DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0);
  124. DL_SETBSTART(lp, 0);
  125. DL_SETBEND(lp, DL_GETDSIZE(lp));
  126. lp->d_version = 1;
  127. lp->d_bbsize = 8192;
  128. lp->d_sbsize = 64*1024; /* XXX ? */
  129. return (0);
  130. }
  131. /*
  132. * Check an incoming block to make sure it is a disklabel, convert it to
  133. * a newer version if needed, etc etc.
  134. */
  135. int
  136. checkdisklabel(void *rlp, struct disklabel *lp, u_int64_t boundstart,
  137. u_int64_t boundend)
  138. {
  139. struct disklabel *dlp = rlp;
  140. struct __partitionv0 *v0pp;
  141. struct partition *pp;
  142. u_int64_t disksize;
  143. int error = 0;
  144. int i;
  145. if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC)
  146. error = ENOENT; /* no disk label */
  147. else if (dlp->d_npartitions > MAXPARTITIONS)
  148. error = E2BIG; /* too many partitions */
  149. else if (dlp->d_secpercyl == 0)
  150. error = EINVAL; /* invalid label */
  151. else if (dlp->d_secsize == 0)
  152. error = ENOSPC; /* disk too small */
  153. else if (dkcksum(dlp) != 0)
  154. error = EINVAL; /* incorrect checksum */
  155. if (error) {
  156. u_int16_t *start, *end, sum = 0;
  157. /* If it is byte-swapped, attempt to convert it */
  158. if (swap32(dlp->d_magic) != DISKMAGIC ||
  159. swap32(dlp->d_magic2) != DISKMAGIC ||
  160. swap16(dlp->d_npartitions) > MAXPARTITIONS)
  161. return (error);
  162. /*
  163. * Need a byte-swap aware dkcksum variant
  164. * inlined, because dkcksum uses a sub-field
  165. */
  166. start = (u_int16_t *)dlp;
  167. end = (u_int16_t *)&dlp->d_partitions[
  168. swap16(dlp->d_npartitions)];
  169. while (start < end)
  170. sum ^= *start++;
  171. if (sum != 0)
  172. return (error);
  173. dlp->d_magic = swap32(dlp->d_magic);
  174. dlp->d_type = swap16(dlp->d_type);
  175. dlp->d_subtype = swap16(dlp->d_subtype);
  176. /* d_typename and d_packname are strings */
  177. dlp->d_secsize = swap32(dlp->d_secsize);
  178. dlp->d_nsectors = swap32(dlp->d_nsectors);
  179. dlp->d_ntracks = swap32(dlp->d_ntracks);
  180. dlp->d_ncylinders = swap32(dlp->d_ncylinders);
  181. dlp->d_secpercyl = swap32(dlp->d_secpercyl);
  182. dlp->d_secperunit = swap32(dlp->d_secperunit);
  183. /* d_uid is a string */
  184. dlp->d_acylinders = swap32(dlp->d_acylinders);
  185. dlp->d_flags = swap32(dlp->d_flags);
  186. for (i = 0; i < NDDATA; i++)
  187. dlp->d_drivedata[i] = swap32(dlp->d_drivedata[i]);
  188. dlp->d_secperunith = swap16(dlp->d_secperunith);
  189. dlp->d_version = swap16(dlp->d_version);
  190. for (i = 0; i < NSPARE; i++)
  191. dlp->d_spare[i] = swap32(dlp->d_spare[i]);
  192. dlp->d_magic2 = swap32(dlp->d_magic2);
  193. dlp->d_npartitions = swap16(dlp->d_npartitions);
  194. dlp->d_bbsize = swap32(dlp->d_bbsize);
  195. dlp->d_sbsize = swap32(dlp->d_sbsize);
  196. for (i = 0; i < MAXPARTITIONS; i++) {
  197. pp = &dlp->d_partitions[i];
  198. pp->p_size = swap32(pp->p_size);
  199. pp->p_offset = swap32(pp->p_offset);
  200. if (dlp->d_version == 0) {
  201. v0pp = (struct __partitionv0 *)pp;
  202. v0pp->p_fsize = swap32(v0pp->p_fsize);
  203. } else {
  204. pp->p_offseth = swap16(pp->p_offseth);
  205. pp->p_sizeh = swap16(pp->p_sizeh);
  206. }
  207. pp->p_cpg = swap16(pp->p_cpg);
  208. }
  209. dlp->d_checksum = 0;
  210. dlp->d_checksum = dkcksum(dlp);
  211. error = 0;
  212. }
  213. /* XXX should verify lots of other fields and whine a lot */
  214. /* Initial passed in lp contains the real disk size. */
  215. disksize = DL_GETDSIZE(lp);
  216. if (lp != dlp)
  217. *lp = *dlp;
  218. if (lp->d_version == 0) {
  219. lp->d_version = 1;
  220. lp->d_secperunith = 0;
  221. v0pp = (struct __partitionv0 *)lp->d_partitions;
  222. pp = lp->d_partitions;
  223. for (i = 0; i < lp->d_npartitions; i++, pp++, v0pp++) {
  224. pp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(v0pp->
  225. p_fsize, v0pp->p_frag);
  226. pp->p_offseth = 0;
  227. pp->p_sizeh = 0;
  228. }
  229. }
  230. #ifdef DEBUG
  231. if (DL_GETDSIZE(lp) != disksize)
  232. printf("on-disk disklabel has incorrect disksize (%llu)\n",
  233. DL_GETDSIZE(lp));
  234. if (DL_GETPSIZE(&lp->d_partitions[RAW_PART]) != disksize)
  235. printf("on-disk disklabel RAW_PART has incorrect size (%llu)\n",
  236. DL_GETPSIZE(&lp->d_partitions[RAW_PART]));
  237. if (DL_GETPOFFSET(&lp->d_partitions[RAW_PART]) != 0)
  238. printf("on-disk disklabel RAW_PART offset != 0 (%llu)\n",
  239. DL_GETPOFFSET(&lp->d_partitions[RAW_PART]));
  240. #endif
  241. DL_SETDSIZE(lp, disksize);
  242. DL_SETPSIZE(&lp->d_partitions[RAW_PART], disksize);
  243. DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0);
  244. DL_SETBSTART(lp, boundstart);
  245. DL_SETBEND(lp, boundend < DL_GETDSIZE(lp) ? boundend : DL_GETDSIZE(lp));
  246. lp->d_checksum = 0;
  247. lp->d_checksum = dkcksum(lp);
  248. return (0);
  249. }
  250. /*
  251. * If dos partition table requested, attempt to load it and
  252. * find disklabel inside a DOS partition. Return buffer
  253. * for use in signalling errors if requested.
  254. *
  255. * We would like to check if each MBR has a valid BOOT_MAGIC, but
  256. * we cannot because it doesn't always exist. So.. we assume the
  257. * MBR is valid.
  258. */
  259. int
  260. readdoslabel(struct buf *bp, void (*strat)(struct buf *),
  261. struct disklabel *lp, daddr_t *partoffp, int spoofonly)
  262. {
  263. u_int64_t dospartoff = 0, dospartend = DL_GETBEND(lp);
  264. int i, ourpart = -1, wander = 1, n = 0, loop = 0, offset;
  265. struct dos_partition dp[NDOSPART], *dp2;
  266. daddr_t part_blkno = DOSBBSECTOR;
  267. u_int32_t extoff = 0;
  268. int error;
  269. if (lp->d_secpercyl == 0)
  270. return (EINVAL); /* invalid label */
  271. if (lp->d_secsize == 0)
  272. return (ENOSPC); /* disk too small */
  273. /* do DOS partitions in the process of getting disklabel? */
  274. /*
  275. * Read dos partition table, follow extended partitions.
  276. * Map the partitions to disklabel entries i-p
  277. */
  278. while (wander && loop < DOS_MAXEBR) {
  279. loop++;
  280. wander = 0;
  281. if (part_blkno < extoff)
  282. part_blkno = extoff;
  283. /* read MBR/EBR */
  284. bp->b_blkno = DL_SECTOBLK(lp, part_blkno);
  285. bp->b_bcount = lp->d_secsize;
  286. bp->b_error = 0; /* B_ERROR and b_error may have stale data. */
  287. CLR(bp->b_flags, B_READ | B_WRITE | B_DONE | B_ERROR);
  288. SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
  289. (*strat)(bp);
  290. error = biowait(bp);
  291. if (error) {
  292. /*wrong*/ if (partoffp)
  293. /*wrong*/ *partoffp = -1;
  294. return (error);
  295. }
  296. bcopy(bp->b_data + DOSPARTOFF, dp, sizeof(dp));
  297. if (n == 0 && part_blkno == DOSBBSECTOR) {
  298. u_int16_t mbrtest;
  299. /* Check the end of sector marker. */
  300. mbrtest = ((bp->b_data[510] << 8) & 0xff00) |
  301. (bp->b_data[511] & 0xff);
  302. if (mbrtest != 0x55aa)
  303. goto notmbr;
  304. }
  305. if (ourpart == -1) {
  306. /* Search for our MBR partition */
  307. for (dp2=dp, i=0; i < NDOSPART && ourpart == -1;
  308. i++, dp2++)
  309. if (letoh32(dp2->dp_size) &&
  310. dp2->dp_typ == DOSPTYP_OPENBSD)
  311. ourpart = i;
  312. if (ourpart == -1)
  313. goto donot;
  314. /*
  315. * This is our MBR partition. need sector
  316. * address for SCSI/IDE, cylinder for
  317. * ESDI/ST506/RLL
  318. */
  319. dp2 = &dp[ourpart];
  320. dospartoff = letoh32(dp2->dp_start) + part_blkno;
  321. dospartend = dospartoff + letoh32(dp2->dp_size);
  322. /*
  323. * Record the OpenBSD partition's placement (in
  324. * 512-byte blocks!) for the caller. No need to
  325. * finish spoofing.
  326. */
  327. if (partoffp) {
  328. *partoffp = DL_SECTOBLK(lp, dospartoff);
  329. return (0);
  330. }
  331. if (lp->d_ntracks == 0)
  332. lp->d_ntracks = dp2->dp_ehd + 1;
  333. if (lp->d_nsectors == 0)
  334. lp->d_nsectors = DPSECT(dp2->dp_esect);
  335. if (lp->d_secpercyl == 0)
  336. lp->d_secpercyl = lp->d_ntracks *
  337. lp->d_nsectors;
  338. }
  339. donot:
  340. /*
  341. * In case the disklabel read below fails, we want to
  342. * provide a fake label in i-p.
  343. */
  344. for (dp2=dp, i=0; i < NDOSPART; i++, dp2++) {
  345. struct partition *pp;
  346. u_int8_t fstype;
  347. if (dp2->dp_typ == DOSPTYP_OPENBSD ||
  348. dp2->dp_typ == DOSPTYP_EFI)
  349. continue;
  350. if (letoh32(dp2->dp_size) > DL_GETDSIZE(lp))
  351. continue;
  352. if (letoh32(dp2->dp_start) > DL_GETDSIZE(lp))
  353. continue;
  354. if (letoh32(dp2->dp_size) == 0)
  355. continue;
  356. switch (dp2->dp_typ) {
  357. case DOSPTYP_UNUSED:
  358. fstype = FS_UNUSED;
  359. break;
  360. case DOSPTYP_LINUX:
  361. fstype = FS_EXT2FS;
  362. break;
  363. case DOSPTYP_NTFS:
  364. fstype = FS_NTFS;
  365. break;
  366. case DOSPTYP_EFISYS:
  367. case DOSPTYP_FAT12:
  368. case DOSPTYP_FAT16S:
  369. case DOSPTYP_FAT16B:
  370. case DOSPTYP_FAT16L:
  371. case DOSPTYP_FAT32:
  372. case DOSPTYP_FAT32L:
  373. fstype = FS_MSDOS;
  374. break;
  375. case DOSPTYP_EXTEND:
  376. case DOSPTYP_EXTENDL:
  377. part_blkno = letoh32(dp2->dp_start) + extoff;
  378. if (!extoff) {
  379. extoff = letoh32(dp2->dp_start);
  380. part_blkno = 0;
  381. }
  382. wander = 1;
  383. continue;
  384. break;
  385. default:
  386. fstype = FS_OTHER;
  387. break;
  388. }
  389. /*
  390. * Don't set fstype/offset/size when just looking for
  391. * the offset of the OpenBSD partition. It would
  392. * invalidate the disklabel checksum!
  393. *
  394. * Don't try to spoof more than 8 partitions, i.e.
  395. * 'i' -'p'.
  396. */
  397. if (partoffp || n >= 8)
  398. continue;
  399. pp = &lp->d_partitions[8+n];
  400. n++;
  401. pp->p_fstype = fstype;
  402. if (letoh32(dp2->dp_start))
  403. DL_SETPOFFSET(pp,
  404. letoh32(dp2->dp_start) + part_blkno);
  405. DL_SETPSIZE(pp, letoh32(dp2->dp_size));
  406. }
  407. }
  408. notmbr:
  409. if (partoffp == NULL)
  410. /* Must not modify *lp when partoffp is set. */
  411. lp->d_npartitions = MAXPARTITIONS;
  412. if (n == 0 && part_blkno == DOSBBSECTOR && ourpart == -1) {
  413. u_int16_t fattest;
  414. /* Check for a valid initial jmp instruction. */
  415. switch ((u_int8_t)bp->b_data[0]) {
  416. case 0xeb:
  417. /*
  418. * Two-byte jmp instruction. The 2nd byte is the number
  419. * of bytes to jmp and the 3rd byte must be a NOP.
  420. */
  421. if ((u_int8_t)bp->b_data[2] != 0x90)
  422. goto notfat;
  423. break;
  424. case 0xe9:
  425. /*
  426. * Three-byte jmp instruction. The next two bytes are a
  427. * little-endian 16 bit value.
  428. */
  429. break;
  430. default:
  431. goto notfat;
  432. break;
  433. }
  434. /* Check for a valid bytes per sector value. */
  435. fattest = ((bp->b_data[12] << 8) & 0xff00) |
  436. (bp->b_data[11] & 0xff);
  437. if (fattest < 512 || fattest > 4096 || (fattest % 512 != 0))
  438. goto notfat;
  439. if (partoffp)
  440. return (ENXIO); /* No place for disklabel on FAT! */
  441. DL_SETPSIZE(&lp->d_partitions['i' - 'a'],
  442. DL_GETPSIZE(&lp->d_partitions[RAW_PART]));
  443. DL_SETPOFFSET(&lp->d_partitions['i' - 'a'], 0);
  444. lp->d_partitions['i' - 'a'].p_fstype = FS_MSDOS;
  445. spoofonly = 1; /* No disklabel to read from disk. */
  446. }
  447. notfat:
  448. /* record the OpenBSD partition's placement for the caller */
  449. if (partoffp)
  450. *partoffp = DL_SECTOBLK(lp, dospartoff);
  451. else {
  452. DL_SETBSTART(lp, dospartoff);
  453. DL_SETBEND(lp, (dospartend < DL_GETDSIZE(lp)) ? dospartend :
  454. DL_GETDSIZE(lp));
  455. }
  456. /* don't read the on-disk label if we are in spoofed-only mode */
  457. if (spoofonly)
  458. return (0);
  459. bp->b_blkno = DL_BLKTOSEC(lp, DL_SECTOBLK(lp, dospartoff) +
  460. DOS_LABELSECTOR) * DL_BLKSPERSEC(lp);
  461. offset = DL_BLKOFFSET(lp, DL_SECTOBLK(lp, dospartoff) +
  462. DOS_LABELSECTOR);
  463. bp->b_bcount = lp->d_secsize;
  464. bp->b_error = 0; /* B_ERROR and b_error may have stale data. */
  465. CLR(bp->b_flags, B_READ | B_WRITE | B_DONE | B_ERROR);
  466. SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
  467. (*strat)(bp);
  468. if (biowait(bp))
  469. return (bp->b_error);
  470. error = checkdisklabel(bp->b_data + offset, lp,
  471. DL_GETBSTART((struct disklabel*)(bp->b_data+offset)),
  472. DL_GETBEND((struct disklabel *)(bp->b_data+offset)));
  473. return (error);
  474. }
  475. #ifdef GPT
  476. int gpt_chk_hdr(struct gpt_header *);
  477. int gpt_chk_parts(struct gpt_header *, struct gpt_partition *);
  478. int get_fstype(struct uuid *);
  479. int
  480. gpt_chk_hdr(struct gpt_header *gh)
  481. {
  482. u_int32_t orig_gh_csum = gh->gh_csum;
  483. gh->gh_csum = 0;
  484. gh->gh_csum = crc32(0, (unsigned char *)gh, gh->gh_size);
  485. if (orig_gh_csum != gh->gh_csum)
  486. return (EINVAL);
  487. return 0;
  488. }
  489. int
  490. gpt_chk_parts(struct gpt_header *gh, struct gpt_partition *gp)
  491. {
  492. u_int32_t checksum;
  493. checksum = crc32(0, (unsigned char *)gp,
  494. gh->gh_part_num * gh->gh_part_size);
  495. if (checksum != gh->gh_part_csum)
  496. return (EINVAL);
  497. return 0;
  498. }
  499. int
  500. get_fstype(struct uuid *uuid_part)
  501. {
  502. static int init = 0;
  503. static struct uuid uuid_openbsd, uuid_msdos, uuid_chromefs,
  504. uuid_linux, uuid_hfs, uuid_unused;
  505. static const uint8_t gpt_uuid_openbsd[] = GPT_UUID_OPENBSD;
  506. static const uint8_t gpt_uuid_msdos[] = GPT_UUID_MSDOS;
  507. static const uint8_t gpt_uuid_chromerootfs[] = GPT_UUID_CHROMEROOTFS;
  508. static const uint8_t gpt_uuid_linux[] = GPT_UUID_LINUX;
  509. static const uint8_t gpt_uuid_hfs[] = GPT_UUID_APPLE_HFS;
  510. static const uint8_t gpt_uuid_unused[] = GPT_UUID_UNUSED;
  511. if (init == 0) {
  512. uuid_dec_be(gpt_uuid_openbsd, &uuid_openbsd);
  513. uuid_dec_be(gpt_uuid_msdos, &uuid_msdos);
  514. uuid_dec_be(gpt_uuid_chromerootfs, &uuid_chromefs);
  515. uuid_dec_be(gpt_uuid_linux, &uuid_linux);
  516. uuid_dec_be(gpt_uuid_hfs, &uuid_hfs);
  517. uuid_dec_be(gpt_uuid_unused, &uuid_unused);
  518. init = 1;
  519. }
  520. if (!memcmp(uuid_part, &uuid_unused, sizeof(struct uuid)))
  521. return FS_UNUSED;
  522. else if (!memcmp(uuid_part, &uuid_openbsd, sizeof(struct uuid)))
  523. return FS_BSDFFS;
  524. else if (!memcmp(uuid_part, &uuid_msdos, sizeof(struct uuid)))
  525. return FS_MSDOS;
  526. else if (!memcmp(uuid_part, &uuid_chromefs, sizeof(struct uuid)))
  527. return FS_EXT2FS;
  528. else if (!memcmp(uuid_part, &uuid_linux, sizeof(struct uuid)))
  529. return FS_EXT2FS;
  530. else if (!memcmp(uuid_part, &uuid_hfs, sizeof(struct uuid)))
  531. return FS_HFS;
  532. else
  533. return FS_OTHER;
  534. }
  535. /*
  536. * If gpt partition table requested, attempt to load it and
  537. * find disklabel inside a GPT partition. Return buffer
  538. * for use in signalling errors if requested.
  539. *
  540. * XXX: readgptlabel() is based on readdoslabel(), so they should be merged
  541. */
  542. int
  543. readgptlabel(struct buf *bp, void (*strat)(struct buf *),
  544. struct disklabel *lp, daddr_t *partoffp, int spoofonly)
  545. {
  546. struct gpt_header gh;
  547. struct gpt_partition *gp, *gp_tmp;
  548. size_t gpsz;
  549. struct uuid uuid_part, uuid_openbsd;
  550. struct partition *pp;
  551. daddr_t part_blkno;
  552. u_int64_t gptpartoff = 0, gptpartend = DL_GETBEND(lp);
  553. int i, altheader = 0, error, n=0, ourpart = -1, offset;
  554. static const u_int8_t gpt_uuid_openbsd[] = GPT_UUID_OPENBSD;
  555. u_int8_t fstype;
  556. uuid_dec_be(gpt_uuid_openbsd, &uuid_openbsd);
  557. if (lp->d_secpercyl == 0)
  558. return (EINVAL); /* invalid label */
  559. if (lp->d_secsize == 0)
  560. return (ENOSPC); /* disk too small */
  561. /*
  562. * XXX: We should not trust the primary header and instead
  563. * use the last LBA of the disk, as defined in the standard.
  564. */
  565. for (part_blkno = GPTSECTOR; ; part_blkno = gh.gh_lba_alt,
  566. altheader = 1) {
  567. uint32_t ghsize;
  568. uint32_t ghpartsize;
  569. uint32_t ghpartnum;
  570. /* read header record */
  571. bp->b_blkno = DL_BLKTOSEC(lp, part_blkno) * DL_BLKSPERSEC(lp);
  572. offset = DL_BLKOFFSET(lp, part_blkno);
  573. bp->b_bcount = lp->d_secsize;
  574. bp->b_error = 0; /* B_ERROR and b_error may have stale data. */
  575. CLR(bp->b_flags, B_READ | B_WRITE | B_DONE | B_ERROR);
  576. SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
  577. (*strat)(bp);
  578. error = biowait(bp);
  579. if (error) {
  580. DPRINTF("error reading from disk\n");
  581. /*wrong*/ if (partoffp)
  582. /*wrong*/ *partoffp = -1;
  583. return (error);
  584. }
  585. bcopy(bp->b_data + offset, &gh, sizeof(gh));
  586. ghsize = letoh32(gh.gh_size);
  587. ghpartsize = letoh32(gh.gh_part_size);
  588. ghpartnum = letoh32(gh.gh_part_num);
  589. if (letoh64(gh.gh_sig) != GPTSIGNATURE)
  590. return (EINVAL);
  591. /* we only support version 1.0 */
  592. if (letoh32(gh.gh_rev) != GPTREVISION)
  593. return (EINVAL);
  594. if (gpt_chk_hdr(&gh)) {
  595. /* header broken, using alternate header */
  596. if (altheader) {
  597. DPRINTF("alternate header also broken\n");
  598. return (EINVAL);
  599. }
  600. if (gh.gh_lba_alt >= DL_GETDSIZE(lp)) {
  601. DPRINTF("alternate header's position is "
  602. "bogous\n");
  603. return (EINVAL);
  604. }
  605. continue;
  606. }
  607. /*
  608. * Header size must be greater than or equal to 92 and less
  609. * than or equal to the logical block size.
  610. */
  611. if (ghsize < GPTMINHDRSIZE || ghsize > DEV_BSIZE)
  612. return (EINVAL);
  613. if (letoh64(gh.gh_lba_start) >= DL_GETDSIZE(lp) ||
  614. letoh64(gh.gh_lba_end) >= DL_GETDSIZE(lp) ||
  615. letoh64(gh.gh_part_lba) >= DL_GETDSIZE(lp))
  616. return (EINVAL);
  617. /*
  618. * Size per partition entry shall be 128*(2**n) with n >= 0.
  619. * We don't support partition entries larger than block size.
  620. */
  621. if (ghpartsize % GPTMINPARTSIZE
  622. || ghpartsize > DEV_BSIZE
  623. || GPT_PARTSPERSEC(&gh) == 0) {
  624. DPRINTF("invalid partition size\n");
  625. return (EINVAL);
  626. }
  627. /* XXX: we don't support multiples of GPTMINPARTSIZE yet */
  628. if (letoh32(gh.gh_part_size) != GPTMINPARTSIZE) {
  629. DPRINTF("partition sizes larger than %d bytes are not "
  630. "supported", GPTMINPARTSIZE);
  631. return (EINVAL);
  632. }
  633. /* read GPT partition entry array */
  634. gp = mallocarray(ghpartnum, sizeof(struct gpt_partition), M_DEVBUF, M_NOWAIT|M_ZERO);
  635. if (gp == NULL)
  636. return (ENOMEM);
  637. gpsz = ghpartnum * sizeof(struct gpt_partition);
  638. /*
  639. * XXX: Fails if # of partition entries is no multiple of
  640. * GPT_PARTSPERSEC(&gh)
  641. */
  642. for (i = 0; i < ghpartnum / GPT_PARTSPERSEC(&gh);
  643. i++) {
  644. part_blkno = letoh64(gh.gh_part_lba) + i;
  645. /* read partition record */
  646. bp->b_blkno = DL_BLKTOSEC(lp, part_blkno) *
  647. DL_BLKSPERSEC(lp);
  648. offset = DL_BLKOFFSET(lp, part_blkno);
  649. bp->b_bcount = lp->d_secsize;
  650. /* B_ERROR and b_error may have stale data. */
  651. bp->b_error = 0;
  652. CLR(bp->b_flags, B_READ | B_WRITE | B_DONE | B_ERROR);
  653. SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
  654. (*strat)(bp);
  655. error = biowait(bp);
  656. if (error) {
  657. /*wrong*/ if (partoffp)
  658. /*wrong*/ *partoffp = -1;
  659. free(gp, M_DEVBUF, gpsz);
  660. return (error);
  661. }
  662. bcopy(bp->b_data + offset, gp +
  663. i * GPT_PARTSPERSEC(&gh), GPT_PARTSPERSEC(&gh) *
  664. sizeof(struct gpt_partition));
  665. }
  666. if (gpt_chk_parts(&gh, gp)) {
  667. DPRINTF("partition entries broken, using alternate "
  668. "header\n");
  669. free(gp, M_DEVBUF, gpsz);
  670. if (altheader) {
  671. DPRINTF("alternate partition entries are also "
  672. "broken\n");
  673. return (EINVAL);
  674. }
  675. continue;
  676. }
  677. break;
  678. }
  679. /* find OpenBSD partition */
  680. for (gp_tmp = gp, i = 0; i < letoh32(gh.gh_part_num) && ourpart == -1;
  681. gp_tmp++, i++) {
  682. if (letoh64(gp_tmp->gp_lba_start) > letoh64(gp_tmp->gp_lba_end)
  683. || letoh64(gp_tmp->gp_lba_start) < letoh64(gh.gh_lba_start)
  684. || letoh64(gp_tmp->gp_lba_end) > letoh64(gh.gh_lba_end))
  685. continue; /* entry invalid */
  686. uuid_dec_le(&gp_tmp->gp_type, &uuid_part);
  687. if (!memcmp(&uuid_part, &uuid_openbsd, sizeof(struct uuid))) {
  688. ourpart = i; /* found it */
  689. }
  690. /*
  691. * In case the disklabel read below fails, we want to
  692. * provide a fake label in i-p.
  693. */
  694. fstype = get_fstype(&uuid_part);
  695. /*
  696. * Don't set fstype/offset/size when just looking for
  697. * the offset of the OpenBSD partition. It would
  698. * invalidate the disklabel checksum!
  699. *
  700. * Don't try to spoof more than 8 partitions, i.e.
  701. * 'i' -'p'.
  702. */
  703. if (partoffp || n >= 8)
  704. continue;
  705. pp = &lp->d_partitions[8+n];
  706. n++;
  707. pp->p_fstype = fstype;
  708. DL_SETPOFFSET(pp, letoh64(gp_tmp->gp_lba_start));
  709. DL_SETPSIZE(pp, letoh64(gp_tmp->gp_lba_end)
  710. - letoh64(gp_tmp->gp_lba_start) + 1);
  711. }
  712. if (ourpart != -1) {
  713. /* found our OpenBSD partition, so use it */
  714. gp_tmp = &gp[ourpart];
  715. gptpartoff = letoh64(gp_tmp->gp_lba_start);
  716. gptpartend = letoh64(gp_tmp->gp_lba_end) + 1;
  717. } else
  718. spoofonly = 1; /* No disklabel to read from disk. */
  719. if (!partoffp)
  720. /* Must not modify *lp when partoffp is set. */
  721. lp->d_npartitions = MAXPARTITIONS;
  722. free(gp, M_DEVBUF, gpsz);
  723. /* record the OpenBSD partition's placement for the caller */
  724. if (partoffp)
  725. *partoffp = DL_SECTOBLK(lp, gptpartoff);
  726. else {
  727. DL_SETBSTART(lp, gptpartoff);
  728. DL_SETBEND(lp, (gptpartend < DL_GETDSIZE(lp)) ? gptpartend :
  729. DL_GETDSIZE(lp));
  730. }
  731. /* don't read the on-disk label if we are in spoofed-only mode */
  732. if (spoofonly)
  733. return (0);
  734. bp->b_blkno = DL_BLKTOSEC(lp, DL_SECTOBLK(lp, gptpartoff) +
  735. DOS_LABELSECTOR) * DL_BLKSPERSEC(lp);
  736. offset = DL_BLKOFFSET(lp, DL_SECTOBLK(lp, gptpartoff) +
  737. DOS_LABELSECTOR);
  738. bp->b_bcount = lp->d_secsize;
  739. bp->b_error = 0; /* B_ERROR and b_error may have stale data. */
  740. CLR(bp->b_flags, B_READ | B_WRITE | B_DONE | B_ERROR);
  741. SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
  742. (*strat)(bp);
  743. if (biowait(bp))
  744. return (bp->b_error);
  745. error = checkdisklabel(bp->b_data + offset, lp,
  746. DL_GETBSTART((struct disklabel*)(bp->b_data+offset)),
  747. DL_GETBEND((struct disklabel *)(bp->b_data+offset)));
  748. return (error);
  749. }
  750. #endif
  751. /*
  752. * Check new disk label for sensibility before setting it.
  753. */
  754. int
  755. setdisklabel(struct disklabel *olp, struct disklabel *nlp, u_int openmask)
  756. {
  757. struct partition *opp, *npp;
  758. struct disk *dk;
  759. u_int64_t uid;
  760. int i;
  761. /* sanity clause */
  762. if (nlp->d_secpercyl == 0 || nlp->d_secsize == 0 ||
  763. (nlp->d_secsize % DEV_BSIZE) != 0)
  764. return (EINVAL);
  765. /* special case to allow disklabel to be invalidated */
  766. if (nlp->d_magic == 0xffffffff) {
  767. *olp = *nlp;
  768. return (0);
  769. }
  770. if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC ||
  771. dkcksum(nlp) != 0)
  772. return (EINVAL);
  773. /* XXX missing check if other dos partitions will be overwritten */
  774. for (i = 0; i < MAXPARTITIONS; i++) {
  775. opp = &olp->d_partitions[i];
  776. npp = &nlp->d_partitions[i];
  777. if ((openmask & (1 << i)) &&
  778. (DL_GETPOFFSET(npp) != DL_GETPOFFSET(opp) ||
  779. DL_GETPSIZE(npp) < DL_GETPSIZE(opp)))
  780. return (EBUSY);
  781. /*
  782. * Copy internally-set partition information
  783. * if new label doesn't include it. XXX
  784. */
  785. if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) {
  786. npp->p_fragblock = opp->p_fragblock;
  787. npp->p_cpg = opp->p_cpg;
  788. }
  789. }
  790. /* Generate a UID if the disklabel does not already have one. */
  791. uid = 0;
  792. if (memcmp(nlp->d_uid, &uid, sizeof(nlp->d_uid)) == 0) {
  793. do {
  794. arc4random_buf(nlp->d_uid, sizeof(nlp->d_uid));
  795. TAILQ_FOREACH(dk, &disklist, dk_link)
  796. if (dk->dk_label && memcmp(dk->dk_label->d_uid,
  797. nlp->d_uid, sizeof(nlp->d_uid)) == 0)
  798. break;
  799. } while (dk != NULL &&
  800. memcmp(nlp->d_uid, &uid, sizeof(nlp->d_uid)) == 0);
  801. }
  802. nlp->d_checksum = 0;
  803. nlp->d_checksum = dkcksum(nlp);
  804. *olp = *nlp;
  805. disk_change = 1;
  806. return (0);
  807. }
  808. /*
  809. * Determine the size of the transfer, and make sure it is within the
  810. * boundaries of the partition. Adjust transfer if needed, and signal errors or
  811. * early completion.
  812. */
  813. int
  814. bounds_check_with_label(struct buf *bp, struct disklabel *lp)
  815. {
  816. struct partition *p = &lp->d_partitions[DISKPART(bp->b_dev)];
  817. daddr_t partblocks, sz;
  818. /* Avoid division by zero, negative offsets, and negative sizes. */
  819. if (lp->d_secpercyl == 0 || bp->b_blkno < 0 || bp->b_bcount < 0)
  820. goto bad;
  821. /* Ensure transfer is a whole number of aligned sectors. */
  822. if ((bp->b_blkno % DL_BLKSPERSEC(lp)) != 0 ||
  823. (bp->b_bcount % lp->d_secsize) != 0)
  824. goto bad;
  825. /* Ensure transfer starts within partition boundary. */
  826. partblocks = DL_SECTOBLK(lp, DL_GETPSIZE(p));
  827. if (bp->b_blkno > partblocks)
  828. goto bad;
  829. /* If exactly at end of partition or null transfer, return EOF. */
  830. if (bp->b_blkno == partblocks || bp->b_bcount == 0)
  831. goto done;
  832. /* Truncate request if it exceeds past the end of the partition. */
  833. sz = bp->b_bcount >> DEV_BSHIFT;
  834. if (sz > partblocks - bp->b_blkno) {
  835. sz = partblocks - bp->b_blkno;
  836. bp->b_bcount = sz << DEV_BSHIFT;
  837. }
  838. return (0);
  839. bad:
  840. bp->b_error = EINVAL;
  841. bp->b_flags |= B_ERROR;
  842. done:
  843. bp->b_resid = bp->b_bcount;
  844. return (-1);
  845. }
  846. /*
  847. * Disk error is the preface to plaintive error messages
  848. * about failing disk transfers. It prints messages of the form
  849. hp0g: hard error reading fsbn 12345 of 12344-12347 (hp0 bn %d cn %d tn %d sn %d)
  850. * if the offset of the error in the transfer and a disk label
  851. * are both available. blkdone should be -1 if the position of the error
  852. * is unknown; the disklabel pointer may be null from drivers that have not
  853. * been converted to use them. The message is printed with printf
  854. * if pri is LOG_PRINTF, otherwise it uses log at the specified priority.
  855. * The message should be completed (with at least a newline) with printf
  856. * or addlog, respectively. There is no trailing space.
  857. */
  858. void
  859. diskerr(struct buf *bp, char *dname, char *what, int pri, int blkdone,
  860. struct disklabel *lp)
  861. {
  862. int unit = DISKUNIT(bp->b_dev), part = DISKPART(bp->b_dev);
  863. int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2)));
  864. char partname = 'a' + part;
  865. daddr_t sn;
  866. if (pri != LOG_PRINTF) {
  867. log(pri, "%s", "");
  868. pr = addlog;
  869. } else
  870. pr = printf;
  871. (*pr)("%s%d%c: %s %sing fsbn ", dname, unit, partname, what,
  872. bp->b_flags & B_READ ? "read" : "writ");
  873. sn = bp->b_blkno;
  874. if (bp->b_bcount <= DEV_BSIZE)
  875. (*pr)("%lld", (long long)sn);
  876. else {
  877. if (blkdone >= 0) {
  878. sn += blkdone;
  879. (*pr)("%lld of ", (long long)sn);
  880. }
  881. (*pr)("%lld-%lld", (long long)bp->b_blkno,
  882. (long long)(bp->b_blkno + (bp->b_bcount - 1) / DEV_BSIZE));
  883. }
  884. if (lp && (blkdone >= 0 || bp->b_bcount <= lp->d_secsize)) {
  885. sn += DL_SECTOBLK(lp, DL_GETPOFFSET(&lp->d_partitions[part]));
  886. (*pr)(" (%s%d bn %lld; cn %lld", dname, unit, (long long)sn,
  887. (long long)(sn / DL_SECTOBLK(lp, lp->d_secpercyl)));
  888. sn %= DL_SECTOBLK(lp, lp->d_secpercyl);
  889. (*pr)(" tn %lld sn %lld)",
  890. (long long)(sn / DL_SECTOBLK(lp, lp->d_nsectors)),
  891. (long long)(sn % DL_SECTOBLK(lp, lp->d_nsectors)));
  892. }
  893. }
  894. /*
  895. * Initialize the disklist. Called by main() before autoconfiguration.
  896. */
  897. void
  898. disk_init(void)
  899. {
  900. TAILQ_INIT(&disklist);
  901. disk_count = disk_change = 0;
  902. }
  903. int
  904. disk_construct(struct disk *diskp)
  905. {
  906. rw_init(&diskp->dk_lock, "dklk");
  907. mtx_init(&diskp->dk_mtx, IPL_BIO);
  908. diskp->dk_flags |= DKF_CONSTRUCTED;
  909. return (0);
  910. }
  911. /*
  912. * Attach a disk.
  913. */
  914. void
  915. disk_attach(struct device *dv, struct disk *diskp)
  916. {
  917. int majdev;
  918. if (!ISSET(diskp->dk_flags, DKF_CONSTRUCTED))
  919. disk_construct(diskp);
  920. /*
  921. * Allocate and initialize the disklabel structures. Note that
  922. * it's not safe to sleep here, since we're probably going to be
  923. * called during autoconfiguration.
  924. */
  925. diskp->dk_label = malloc(sizeof(struct disklabel), M_DEVBUF,
  926. M_NOWAIT|M_ZERO);
  927. if (diskp->dk_label == NULL)
  928. panic("disk_attach: can't allocate storage for disklabel");
  929. /*
  930. * Set the attached timestamp.
  931. */
  932. microuptime(&diskp->dk_attachtime);
  933. /*
  934. * Link into the disklist.
  935. */
  936. TAILQ_INSERT_TAIL(&disklist, diskp, dk_link);
  937. ++disk_count;
  938. disk_change = 1;
  939. /*
  940. * Store device structure and number for later use.
  941. */
  942. diskp->dk_device = dv;
  943. diskp->dk_devno = NODEV;
  944. if (dv != NULL) {
  945. majdev = findblkmajor(dv);
  946. if (majdev >= 0)
  947. diskp->dk_devno =
  948. MAKEDISKDEV(majdev, dv->dv_unit, RAW_PART);
  949. if (diskp->dk_devno != NODEV) {
  950. struct disk_attach_task *dat;
  951. dat = malloc(sizeof(*dat), M_TEMP, M_WAITOK);
  952. /* XXX: Assumes dk is part of the device softc. */
  953. device_ref(dv);
  954. dat->dk = diskp;
  955. task_set(&dat->task, disk_attach_callback, dat);
  956. task_add(systq, &dat->task);
  957. }
  958. }
  959. if (softraid_disk_attach)
  960. softraid_disk_attach(diskp, 1);
  961. }
  962. void
  963. disk_attach_callback(void *xdat)
  964. {
  965. struct disk_attach_task *dat = xdat;
  966. struct disk *dk = dat->dk;
  967. char errbuf[100];
  968. struct disklabel dl;
  969. dev_t dev;
  970. free(dat, M_TEMP, sizeof(*dat));
  971. if (dk->dk_flags & (DKF_OPENED | DKF_NOLABELREAD))
  972. goto done;
  973. /* Read disklabel. */
  974. dev = dk->dk_devno;
  975. if (disk_readlabel(&dl, dk->dk_devno, errbuf, sizeof(errbuf)) == NULL) {
  976. add_timer_randomness(dl.d_checksum);
  977. dk->dk_flags |= DKF_LABELVALID;
  978. }
  979. done:
  980. dk->dk_flags |= DKF_OPENED;
  981. device_unref(dk->dk_device);
  982. wakeup(dk);
  983. }
  984. /*
  985. * Detach a disk.
  986. */
  987. void
  988. disk_detach(struct disk *diskp)
  989. {
  990. if (softraid_disk_attach)
  991. softraid_disk_attach(diskp, -1);
  992. /*
  993. * Free the space used by the disklabel structures.
  994. */
  995. free(diskp->dk_label, M_DEVBUF, sizeof(*diskp->dk_label));
  996. /*
  997. * Remove from the disklist.
  998. */
  999. TAILQ_REMOVE(&disklist, diskp, dk_link);
  1000. disk_change = 1;
  1001. if (--disk_count < 0)
  1002. panic("disk_detach: disk_count < 0");
  1003. }
  1004. int
  1005. disk_openpart(struct disk *dk, int part, int fmt, int haslabel)
  1006. {
  1007. KASSERT(part >= 0 && part < MAXPARTITIONS);
  1008. /* Unless opening the raw partition, check that the partition exists. */
  1009. if (part != RAW_PART && (!haslabel ||
  1010. part >= dk->dk_label->d_npartitions ||
  1011. dk->dk_label->d_partitions[part].p_fstype == FS_UNUSED))
  1012. return (ENXIO);
  1013. /* Ensure the partition doesn't get changed under our feet. */
  1014. switch (fmt) {
  1015. case S_IFCHR:
  1016. dk->dk_copenmask |= (1 << part);
  1017. break;
  1018. case S_IFBLK:
  1019. dk->dk_bopenmask |= (1 << part);
  1020. break;
  1021. }
  1022. dk->dk_openmask = dk->dk_copenmask | dk->dk_bopenmask;
  1023. return (0);
  1024. }
  1025. void
  1026. disk_closepart(struct disk *dk, int part, int fmt)
  1027. {
  1028. KASSERT(part >= 0 && part < MAXPARTITIONS);
  1029. switch (fmt) {
  1030. case S_IFCHR:
  1031. dk->dk_copenmask &= ~(1 << part);
  1032. break;
  1033. case S_IFBLK:
  1034. dk->dk_bopenmask &= ~(1 << part);
  1035. break;
  1036. }
  1037. dk->dk_openmask = dk->dk_copenmask | dk->dk_bopenmask;
  1038. }
  1039. void
  1040. disk_gone(int (*open)(dev_t, int, int, struct proc *), int unit)
  1041. {
  1042. int bmaj, cmaj, mn;
  1043. /* Locate the lowest minor number to be detached. */
  1044. mn = DISKMINOR(unit, 0);
  1045. for (bmaj = 0; bmaj < nblkdev; bmaj++)
  1046. if (bdevsw[bmaj].d_open == open)
  1047. vdevgone(bmaj, mn, mn + MAXPARTITIONS - 1, VBLK);
  1048. for (cmaj = 0; cmaj < nchrdev; cmaj++)
  1049. if (cdevsw[cmaj].d_open == open)
  1050. vdevgone(cmaj, mn, mn + MAXPARTITIONS - 1, VCHR);
  1051. }
  1052. /*
  1053. * Increment a disk's busy counter. If the counter is going from
  1054. * 0 to 1, set the timestamp.
  1055. */
  1056. void
  1057. disk_busy(struct disk *diskp)
  1058. {
  1059. /*
  1060. * XXX We'd like to use something as accurate as microtime(),
  1061. * but that doesn't depend on the system TOD clock.
  1062. */
  1063. mtx_enter(&diskp->dk_mtx);
  1064. if (diskp->dk_busy++ == 0)
  1065. microuptime(&diskp->dk_timestamp);
  1066. mtx_leave(&diskp->dk_mtx);
  1067. }
  1068. /*
  1069. * Decrement a disk's busy counter, increment the byte count, total busy
  1070. * time, and reset the timestamp.
  1071. */
  1072. void
  1073. disk_unbusy(struct disk *diskp, long bcount, int read)
  1074. {
  1075. struct timeval dv_time, diff_time;
  1076. mtx_enter(&diskp->dk_mtx);
  1077. if (diskp->dk_busy-- == 0)
  1078. printf("disk_unbusy: %s: dk_busy < 0\n", diskp->dk_name);
  1079. microuptime(&dv_time);
  1080. timersub(&dv_time, &diskp->dk_timestamp, &diff_time);
  1081. timeradd(&diskp->dk_time, &diff_time, &diskp->dk_time);
  1082. diskp->dk_timestamp = dv_time;
  1083. if (bcount > 0) {
  1084. if (read) {
  1085. diskp->dk_rbytes += bcount;
  1086. diskp->dk_rxfer++;
  1087. } else {
  1088. diskp->dk_wbytes += bcount;
  1089. diskp->dk_wxfer++;
  1090. }
  1091. } else
  1092. diskp->dk_seek++;
  1093. mtx_leave(&diskp->dk_mtx);
  1094. add_disk_randomness(bcount ^ diff_time.tv_usec);
  1095. }
  1096. int
  1097. disk_lock(struct disk *dk)
  1098. {
  1099. return (rw_enter(&dk->dk_lock, RW_WRITE|RW_INTR));
  1100. }
  1101. void
  1102. disk_lock_nointr(struct disk *dk)
  1103. {
  1104. rw_enter_write(&dk->dk_lock);
  1105. }
  1106. void
  1107. disk_unlock(struct disk *dk)
  1108. {
  1109. rw_exit_write(&dk->dk_lock);
  1110. }
  1111. int
  1112. dk_mountroot(void)
  1113. {
  1114. char errbuf[100];
  1115. int part = DISKPART(rootdev);
  1116. int (*mountrootfn)(void);
  1117. struct disklabel dl;
  1118. char *error;
  1119. error = disk_readlabel(&dl, rootdev, errbuf, sizeof(errbuf));
  1120. if (error)
  1121. panic("%s", error);
  1122. if (DL_GETPSIZE(&dl.d_partitions[part]) == 0)
  1123. panic("root filesystem has size 0");
  1124. switch (dl.d_partitions[part].p_fstype) {
  1125. #ifdef EXT2FS
  1126. case FS_EXT2FS:
  1127. {
  1128. extern int ext2fs_mountroot(void);
  1129. mountrootfn = ext2fs_mountroot;
  1130. }
  1131. break;
  1132. #endif
  1133. #ifdef FFS
  1134. case FS_BSDFFS:
  1135. {
  1136. extern int ffs_mountroot(void);
  1137. mountrootfn = ffs_mountroot;
  1138. }
  1139. break;
  1140. #endif
  1141. #ifdef CD9660
  1142. case FS_ISO9660:
  1143. {
  1144. extern int cd9660_mountroot(void);
  1145. mountrootfn = cd9660_mountroot;
  1146. }
  1147. break;
  1148. #endif
  1149. default:
  1150. #ifdef FFS
  1151. {
  1152. extern int ffs_mountroot(void);
  1153. printf("filesystem type %d not known.. assuming ffs\n",
  1154. dl.d_partitions[part].p_fstype);
  1155. mountrootfn = ffs_mountroot;
  1156. }
  1157. #else
  1158. panic("disk 0x%x filesystem type %d not known",
  1159. rootdev, dl.d_partitions[part].p_fstype);
  1160. #endif
  1161. }
  1162. return (*mountrootfn)();
  1163. }
  1164. struct device *
  1165. getdisk(char *str, int len, int defpart, dev_t *devp)
  1166. {
  1167. struct device *dv;
  1168. if ((dv = parsedisk(str, len, defpart, devp)) == NULL) {
  1169. printf("use one of: exit");
  1170. TAILQ_FOREACH(dv, &alldevs, dv_list) {
  1171. if (dv->dv_class == DV_DISK)
  1172. printf(" %s[a-p]", dv->dv_xname);
  1173. #if defined(NFSCLIENT)
  1174. if (dv->dv_class == DV_IFNET)
  1175. printf(" %s", dv->dv_xname);
  1176. #endif
  1177. }
  1178. printf("\n");
  1179. }
  1180. return (dv);
  1181. }
  1182. struct device *
  1183. parsedisk(char *str, int len, int defpart, dev_t *devp)
  1184. {
  1185. struct device *dv;
  1186. int majdev, part = defpart;
  1187. char c;
  1188. if (len == 0)
  1189. return (NULL);
  1190. c = str[len-1];
  1191. if (c >= 'a' && (c - 'a') < MAXPARTITIONS) {
  1192. part = c - 'a';
  1193. len -= 1;
  1194. }
  1195. TAILQ_FOREACH(dv, &alldevs, dv_list) {
  1196. if (dv->dv_class == DV_DISK &&
  1197. strncmp(str, dv->dv_xname, len) == 0 &&
  1198. dv->dv_xname[len] == '\0') {
  1199. majdev = findblkmajor(dv);
  1200. if (majdev < 0)
  1201. return NULL;
  1202. *devp = MAKEDISKDEV(majdev, dv->dv_unit, part);
  1203. break;
  1204. }
  1205. #if defined(NFSCLIENT)
  1206. if (dv->dv_class == DV_IFNET &&
  1207. strncmp(str, dv->dv_xname, len) == 0 &&
  1208. dv->dv_xname[len] == '\0') {
  1209. *devp = NODEV;
  1210. break;
  1211. }
  1212. #endif
  1213. }
  1214. return (dv);
  1215. }
  1216. void
  1217. setroot(struct device *bootdv, int part, int exitflags)
  1218. {
  1219. int majdev, unit, len, s, slept = 0;
  1220. struct swdevt *swp;
  1221. struct device *rootdv, *dv;
  1222. dev_t nrootdev, nswapdev = NODEV, temp = NODEV;
  1223. struct ifnet *ifp = NULL;
  1224. struct disk *dk;
  1225. u_char duid[8];
  1226. char buf[128];
  1227. #if defined(NFSCLIENT)
  1228. extern char *nfsbootdevname;
  1229. #endif
  1230. /* Ensure that all disk attach callbacks have completed. */
  1231. do {
  1232. TAILQ_FOREACH(dk, &disklist, dk_link) {
  1233. if (dk->dk_devno != NODEV &&
  1234. (dk->dk_flags & DKF_OPENED) == 0) {
  1235. tsleep(dk, 0, "dkopen", hz);
  1236. slept++;
  1237. break;
  1238. }
  1239. }
  1240. } while (dk != NULL && slept < 5);
  1241. if (slept == 5) {
  1242. printf("disklabels not read:");
  1243. TAILQ_FOREACH(dk, &disklist, dk_link)
  1244. if (dk->dk_devno != NODEV &&
  1245. (dk->dk_flags & DKF_OPENED) == 0)
  1246. printf(" %s", dk->dk_name);
  1247. printf("\n");
  1248. }
  1249. /* Locate DUID for boot disk if not already provided. */
  1250. memset(duid, 0, sizeof(duid));
  1251. if (memcmp(bootduid, duid, sizeof(bootduid)) == 0) {
  1252. TAILQ_FOREACH(dk, &disklist, dk_link)
  1253. if (dk->dk_device == bootdv)
  1254. break;
  1255. if (dk && (dk->dk_flags & DKF_LABELVALID))
  1256. bcopy(dk->dk_label->d_uid, bootduid, sizeof(bootduid));
  1257. }
  1258. bcopy(bootduid, rootduid, sizeof(rootduid));
  1259. #if NSOFTRAID > 0
  1260. sr_map_root();
  1261. #endif
  1262. /*
  1263. * If `swap generic' and we couldn't determine boot device,
  1264. * ask the user.
  1265. */
  1266. dk = NULL;
  1267. if (mountroot == NULL && bootdv == NULL)
  1268. boothowto |= RB_ASKNAME;
  1269. if (boothowto & RB_ASKNAME) {
  1270. while (1) {
  1271. printf("root device");
  1272. if (bootdv != NULL) {
  1273. printf(" (default %s", bootdv->dv_xname);
  1274. if (bootdv->dv_class == DV_DISK)
  1275. printf("%c", 'a' + part);
  1276. printf(")");
  1277. }
  1278. printf(": ");
  1279. s = splhigh();
  1280. cnpollc(1);
  1281. len = getsn(buf, sizeof(buf));
  1282. cnpollc(0);
  1283. splx(s);
  1284. if (strcmp(buf, "exit") == 0)
  1285. reboot(exitflags);
  1286. if (len == 0 && bootdv != NULL) {
  1287. strlcpy(buf, bootdv->dv_xname, sizeof buf);
  1288. len = strlen(buf);
  1289. }
  1290. if (len > 0 && buf[len - 1] == '*') {
  1291. buf[--len] = '\0';
  1292. dv = getdisk(buf, len, part, &nrootdev);
  1293. if (dv != NULL) {
  1294. rootdv = dv;
  1295. nswapdev = nrootdev;
  1296. goto gotswap;
  1297. }
  1298. }
  1299. dv = getdisk(buf, len, part, &nrootdev);
  1300. if (dv != NULL) {
  1301. rootdv = dv;
  1302. break;
  1303. }
  1304. }
  1305. if (rootdv->dv_class == DV_IFNET)
  1306. goto gotswap;
  1307. /* try to build swap device out of new root device */
  1308. while (1) {
  1309. printf("swap device");
  1310. if (rootdv != NULL)
  1311. printf(" (default %s%s)", rootdv->dv_xname,
  1312. rootdv->dv_class == DV_DISK ? "b" : "");
  1313. printf(": ");
  1314. s = splhigh();
  1315. cnpollc(1);
  1316. len = getsn(buf, sizeof(buf));
  1317. cnpollc(0);
  1318. splx(s);
  1319. if (strcmp(buf, "exit") == 0)
  1320. reboot(exitflags);
  1321. if (len == 0 && rootdv != NULL) {
  1322. switch (rootdv->dv_class) {
  1323. case DV_IFNET:
  1324. nswapdev = NODEV;
  1325. break;
  1326. case DV_DISK:
  1327. nswapdev = MAKEDISKDEV(major(nrootdev),
  1328. DISKUNIT(nrootdev), 1);
  1329. if (nswapdev == nrootdev)
  1330. continue;
  1331. break;
  1332. default:
  1333. break;
  1334. }
  1335. break;
  1336. }
  1337. dv = getdisk(buf, len, 1, &nswapdev);
  1338. if (dv) {
  1339. if (dv->dv_class == DV_IFNET)
  1340. nswapdev = NODEV;
  1341. if (nswapdev == nrootdev)
  1342. continue;
  1343. break;
  1344. }
  1345. }
  1346. gotswap:
  1347. rootdev = nrootdev;
  1348. dumpdev = nswapdev;
  1349. swdevt[0].sw_dev = nswapdev;
  1350. swdevt[1].sw_dev = NODEV;
  1351. #if defined(NFSCLIENT)
  1352. } else if (mountroot == nfs_mountroot) {
  1353. rootdv = bootdv;
  1354. rootdev = dumpdev = swapdev = NODEV;
  1355. #endif
  1356. } else if (mountroot == NULL && rootdev == NODEV) {
  1357. /*
  1358. * `swap generic'
  1359. */
  1360. rootdv = bootdv;
  1361. if (bootdv->dv_class == DV_DISK) {
  1362. memset(&duid, 0, sizeof(duid));
  1363. if (memcmp(rootduid, &duid, sizeof(rootduid)) != 0) {
  1364. TAILQ_FOREACH(dk, &disklist, dk_link)
  1365. if ((dk->dk_flags & DKF_LABELVALID) &&
  1366. dk->dk_label && memcmp(dk->dk_label->d_uid,
  1367. &rootduid, sizeof(rootduid)) == 0)
  1368. break;
  1369. if (dk == NULL)
  1370. panic("root device (%02hx%02hx%02hx%02hx"
  1371. "%02hx%02hx%02hx%02hx) not found",
  1372. rootduid[0], rootduid[1], rootduid[2],
  1373. rootduid[3], rootduid[4], rootduid[5],
  1374. rootduid[6], rootduid[7]);
  1375. rootdv = dk->dk_device;
  1376. }
  1377. }
  1378. majdev = findblkmajor(rootdv);
  1379. if (majdev >= 0) {
  1380. /*
  1381. * Root and swap are on the disk.
  1382. * Assume swap is on partition b.
  1383. */
  1384. rootdev = MAKEDISKDEV(majdev, rootdv->dv_unit, part);
  1385. nswapdev = MAKEDISKDEV(majdev, rootdv->dv_unit, 1);
  1386. } else {
  1387. /*
  1388. * Root and swap are on a net.
  1389. */
  1390. nswapdev = NODEV;
  1391. }
  1392. dumpdev = nswapdev;
  1393. swdevt[0].sw_dev = nswapdev;
  1394. /* swdevt[1].sw_dev = NODEV; */
  1395. } else {
  1396. /* Completely pre-configured, but we want rootdv .. */
  1397. majdev = major(rootdev);
  1398. if (findblkname(majdev) == NULL)
  1399. return;
  1400. unit = DISKUNIT(rootdev);
  1401. part = DISKPART(rootdev);
  1402. snprintf(buf, sizeof buf, "%s%d%c",
  1403. findblkname(majdev), unit, 'a' + part);
  1404. rootdv = parsedisk(buf, strlen(buf), 0, &nrootdev);
  1405. if (rootdv == NULL)
  1406. panic("root device (%s) not found", buf);
  1407. }
  1408. if (rootdv && rootdv == bootdv && rootdv->dv_class == DV_IFNET)
  1409. ifp = ifunit(rootdv->dv_xname);
  1410. else if (bootdv && bootdv->dv_class == DV_IFNET)
  1411. ifp = ifunit(bootdv->dv_xname);
  1412. if (ifp)
  1413. if_addgroup(ifp, "netboot");
  1414. switch (rootdv->dv_class) {
  1415. #if defined(NFSCLIENT)
  1416. case DV_IFNET:
  1417. mountroot = nfs_mountroot;
  1418. nfsbootdevname = rootdv->dv_xname;
  1419. return;
  1420. #endif
  1421. case DV_DISK:
  1422. mountroot = dk_mountroot;
  1423. part = DISKPART(rootdev);
  1424. break;
  1425. default:
  1426. printf("can't figure root, hope your kernel is right\n");
  1427. return;
  1428. }
  1429. printf("root on %s%c", rootdv->dv_xname, 'a' + part);
  1430. if (dk && dk->dk_device == rootdv)
  1431. printf(" (%02hx%02hx%02hx%02hx%02hx%02hx%02hx%02hx.%c)",
  1432. rootduid[0], rootduid[1], rootduid[2], rootduid[3],
  1433. rootduid[4], rootduid[5], rootduid[6], rootduid[7],
  1434. 'a' + part);
  1435. /*
  1436. * Make the swap partition on the root drive the primary swap.
  1437. */
  1438. for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
  1439. if (major(rootdev) == major(swp->sw_dev) &&
  1440. DISKUNIT(rootdev) == DISKUNIT(swp->sw_dev)) {
  1441. temp = swdevt[0].sw_dev;
  1442. swdevt[0].sw_dev = swp->sw_dev;
  1443. swp->sw_dev = temp;
  1444. break;
  1445. }
  1446. }
  1447. if (swp->sw_dev != NODEV) {
  1448. /*
  1449. * If dumpdev was the same as the old primary swap device,
  1450. * move it to the new primary swap device.
  1451. */
  1452. if (temp == dumpdev)
  1453. dumpdev = swdevt[0].sw_dev;
  1454. }
  1455. if (swdevt[0].sw_dev != NODEV)
  1456. printf(" swap on %s%d%c", findblkname(major(swdevt[0].sw_dev)),
  1457. DISKUNIT(swdevt[0].sw_dev),
  1458. 'a' + DISKPART(swdevt[0].sw_dev));
  1459. if (dumpdev != NODEV)
  1460. printf(" dump on %s%d%c", findblkname(major(dumpdev)),
  1461. DISKUNIT(dumpdev), 'a' + DISKPART(dumpdev));
  1462. printf("\n");
  1463. }
  1464. extern struct nam2blk nam2blk[];
  1465. int
  1466. findblkmajor(struct device *dv)
  1467. {
  1468. char buf[16], *p;
  1469. int i;
  1470. if (strlcpy(buf, dv->dv_xname, sizeof buf) >= sizeof buf)
  1471. return (-1);
  1472. for (p = buf; *p; p++)
  1473. if (*p >= '0' && *p <= '9')
  1474. *p = '\0';
  1475. for (i = 0; nam2blk[i].name; i++)
  1476. if (!strcmp(buf, nam2blk[i].name))
  1477. return (nam2blk[i].maj);
  1478. return (-1);
  1479. }
  1480. char *
  1481. findblkname(int maj)
  1482. {
  1483. int i;
  1484. for (i = 0; nam2blk[i].name; i++)
  1485. if (nam2blk[i].maj == maj)
  1486. return (nam2blk[i].name);
  1487. return (NULL);
  1488. }
  1489. char *
  1490. disk_readlabel(struct disklabel *dl, dev_t dev, char *errbuf, size_t errsize)
  1491. {
  1492. struct vnode *vn;
  1493. dev_t chrdev, rawdev;
  1494. int error;
  1495. chrdev = blktochr(dev);
  1496. rawdev = MAKEDISKDEV(major(chrdev), DISKUNIT(chrdev), RAW_PART);
  1497. #ifdef DEBUG
  1498. printf("dev=0x%x chrdev=0x%x rawdev=0x%x\n", dev, chrdev, rawdev);
  1499. #endif
  1500. if (cdevvp(rawdev, &vn)) {
  1501. snprintf(errbuf, errsize,
  1502. "cannot obtain vnode for 0x%x/0x%x", dev, rawdev);
  1503. return (errbuf);
  1504. }
  1505. error = VOP_OPEN(vn, FREAD, NOCRED, curproc);
  1506. if (error) {
  1507. snprintf(errbuf, errsize,
  1508. "cannot open disk, 0x%x/0x%x, error %d",
  1509. dev, rawdev, error);
  1510. goto done;
  1511. }
  1512. error = VOP_IOCTL(vn, DIOCGDINFO, (caddr_t)dl, FREAD, NOCRED, curproc);
  1513. if (error) {
  1514. snprintf(errbuf, errsize,
  1515. "cannot read disk label, 0x%x/0x%x, error %d",
  1516. dev, rawdev, error);
  1517. }
  1518. done:
  1519. VOP_CLOSE(vn, FREAD, NOCRED, curproc);
  1520. vput(vn);
  1521. if (error)
  1522. return (errbuf);
  1523. return (NULL);
  1524. }
  1525. int
  1526. disk_map(char *path, char *mappath, int size, int flags)
  1527. {
  1528. struct disk *dk, *mdk;
  1529. u_char uid[8];
  1530. char c, part;
  1531. int i;
  1532. /*
  1533. * Attempt to map a request for a disklabel UID to the correct device.
  1534. * We should be supplied with a disklabel UID which has the following
  1535. * format:
  1536. *
  1537. * [disklabel uid] . [partition]
  1538. *
  1539. * Alternatively, if the DM_OPENPART flag is set the disklabel UID can
  1540. * based passed on its own.
  1541. */
  1542. if (strchr(path, '/') != NULL)
  1543. return -1;
  1544. /* Verify that the device name is properly formed. */
  1545. if (!((strlen(path) == 16 && (flags & DM_OPENPART)) ||
  1546. (strlen(path) == 18 && path[16] == '.')))
  1547. return -1;
  1548. /* Get partition. */
  1549. if (flags & DM_OPENPART)
  1550. part = 'a' + RAW_PART;
  1551. else
  1552. part = path[17];
  1553. if (part < 'a' || part >= 'a' + MAXPARTITIONS)
  1554. return -1;
  1555. /* Derive label UID. */
  1556. memset(uid, 0, sizeof(uid));
  1557. for (i = 0; i < 16; i++) {
  1558. c = path[i];
  1559. if (c >= '0' && c <= '9')
  1560. c -= '0';
  1561. else if (c >= 'a' && c <= 'f')
  1562. c -= ('a' - 10);
  1563. else
  1564. return -1;
  1565. uid[i / 2] <<= 4;
  1566. uid[i / 2] |= c & 0xf;
  1567. }
  1568. mdk = NULL;
  1569. TAILQ_FOREACH(dk, &disklist, dk_link) {
  1570. if ((dk->dk_flags & DKF_LABELVALID) && dk->dk_label &&
  1571. memcmp(dk->dk_label->d_uid, uid,
  1572. sizeof(dk->dk_label->d_uid)) == 0) {
  1573. /* Fail if there are duplicate UIDs! */
  1574. if (mdk != NULL)
  1575. return -1;
  1576. mdk = dk;
  1577. }
  1578. }
  1579. if (mdk == NULL || mdk->dk_name == NULL)
  1580. return -1;
  1581. snprintf(mappath, size, "/dev/%s%s%c",
  1582. (flags & DM_OPENBLCK) ? "" : "r", mdk->dk_name, part);
  1583. return 0;
  1584. }
  1585. /*
  1586. * Lookup a disk device and verify that it has completed attaching.
  1587. */
  1588. struct device *
  1589. disk_lookup(struct cfdriver *cd, int unit)
  1590. {
  1591. struct device *dv;
  1592. struct disk *dk;
  1593. dv = device_lookup(cd, unit);
  1594. if (dv == NULL)
  1595. return (NULL);
  1596. TAILQ_FOREACH(dk, &disklist, dk_link)
  1597. if (dk->dk_device == dv)
  1598. break;
  1599. if (dk == NULL) {
  1600. device_unref(dv);
  1601. return (NULL);
  1602. }
  1603. return (dv);
  1604. }