1*3e58d19eSkrw /* $OpenBSD: softraid_i386.c,v 1.4 2020/12/09 18:10:18 krw Exp $ */
265f4a3c7Sjsing
365f4a3c7Sjsing /*
465f4a3c7Sjsing * Copyright (c) 2012 Joel Sing <jsing@openbsd.org>
565f4a3c7Sjsing *
665f4a3c7Sjsing * Permission to use, copy, modify, and distribute this software for any
765f4a3c7Sjsing * purpose with or without fee is hereby granted, provided that the above
865f4a3c7Sjsing * copyright notice and this permission notice appear in all copies.
965f4a3c7Sjsing *
1065f4a3c7Sjsing * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1165f4a3c7Sjsing * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1265f4a3c7Sjsing * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1365f4a3c7Sjsing * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1465f4a3c7Sjsing * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1565f4a3c7Sjsing * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1665f4a3c7Sjsing * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1765f4a3c7Sjsing */
1865f4a3c7Sjsing
1965f4a3c7Sjsing #include <sys/param.h>
2065f4a3c7Sjsing #include <sys/queue.h>
2165f4a3c7Sjsing #include <sys/disklabel.h>
2265f4a3c7Sjsing #include <sys/reboot.h>
2365f4a3c7Sjsing
2465f4a3c7Sjsing #include <dev/biovar.h>
2565f4a3c7Sjsing #include <dev/softraidvar.h>
2665f4a3c7Sjsing
2765f4a3c7Sjsing #include <lib/libsa/aes_xts.h>
28a211a09cSjsing #include <lib/libsa/softraid.h>
2965f4a3c7Sjsing
3065f4a3c7Sjsing #include "libsa.h"
3165f4a3c7Sjsing #include "disk.h"
3265f4a3c7Sjsing #include "softraid_i386.h"
3365f4a3c7Sjsing
3465f4a3c7Sjsing void
srprobe_meta_opt_load(struct sr_metadata * sm,struct sr_meta_opt_head * som)3565f4a3c7Sjsing srprobe_meta_opt_load(struct sr_metadata *sm, struct sr_meta_opt_head *som)
3665f4a3c7Sjsing {
3765f4a3c7Sjsing struct sr_meta_opt_hdr *omh;
3865f4a3c7Sjsing struct sr_meta_opt_item *omi;
3965f4a3c7Sjsing #if 0
4065f4a3c7Sjsing u_int8_t checksum[MD5_DIGEST_LENGTH];
4165f4a3c7Sjsing #endif
4265f4a3c7Sjsing int i;
4365f4a3c7Sjsing
4465f4a3c7Sjsing /* Process optional metadata. */
4565f4a3c7Sjsing omh = (struct sr_meta_opt_hdr *)((u_int8_t *)(sm + 1) +
4665f4a3c7Sjsing sizeof(struct sr_meta_chunk) * sm->ssdi.ssd_chunk_no);
4765f4a3c7Sjsing for (i = 0; i < sm->ssdi.ssd_opt_no; i++) {
4865f4a3c7Sjsing
4965f4a3c7Sjsing #ifdef BIOS_DEBUG
5065f4a3c7Sjsing printf("Found optional metadata of type %u, length %u\n",
5165f4a3c7Sjsing omh->som_type, omh->som_length);
5265f4a3c7Sjsing #endif
5365f4a3c7Sjsing
5465f4a3c7Sjsing /* Unsupported old fixed length optional metadata. */
5565f4a3c7Sjsing if (omh->som_length == 0) {
5665f4a3c7Sjsing omh = (struct sr_meta_opt_hdr *)((void *)omh +
5765f4a3c7Sjsing SR_OLD_META_OPT_SIZE);
5865f4a3c7Sjsing continue;
5965f4a3c7Sjsing }
6065f4a3c7Sjsing
6165f4a3c7Sjsing /* Load variable length optional metadata. */
6265f4a3c7Sjsing omi = alloc(sizeof(struct sr_meta_opt_item));
6365f4a3c7Sjsing bzero(omi, sizeof(struct sr_meta_opt_item));
6465f4a3c7Sjsing SLIST_INSERT_HEAD(som, omi, omi_link);
6565f4a3c7Sjsing omi->omi_som = alloc(omh->som_length);
6665f4a3c7Sjsing bzero(omi->omi_som, omh->som_length);
6765f4a3c7Sjsing bcopy(omh, omi->omi_som, omh->som_length);
6865f4a3c7Sjsing
6965f4a3c7Sjsing #if 0
7065f4a3c7Sjsing /* XXX - Validate checksum. */
7165f4a3c7Sjsing bcopy(&omi->omi_som->som_checksum, &checksum,
7265f4a3c7Sjsing MD5_DIGEST_LENGTH);
7365f4a3c7Sjsing bzero(&omi->omi_som->som_checksum, MD5_DIGEST_LENGTH);
7465f4a3c7Sjsing sr_checksum(sc, omi->omi_som,
7565f4a3c7Sjsing &omi->omi_som->som_checksum, omh->som_length);
7665f4a3c7Sjsing if (bcmp(&checksum, &omi->omi_som->som_checksum,
7765f4a3c7Sjsing sizeof(checksum)))
7865f4a3c7Sjsing panic("%s: invalid optional metadata checksum",
7965f4a3c7Sjsing DEVNAME(sc));
8065f4a3c7Sjsing #endif
8165f4a3c7Sjsing
8265f4a3c7Sjsing omh = (struct sr_meta_opt_hdr *)((void *)omh +
8365f4a3c7Sjsing omh->som_length);
8465f4a3c7Sjsing }
8565f4a3c7Sjsing }
8665f4a3c7Sjsing
8765f4a3c7Sjsing void
srprobe_keydisk_load(struct sr_metadata * sm)8865f4a3c7Sjsing srprobe_keydisk_load(struct sr_metadata *sm)
8965f4a3c7Sjsing {
9065f4a3c7Sjsing struct sr_meta_opt_hdr *omh;
9165f4a3c7Sjsing struct sr_meta_keydisk *skm;
9265f4a3c7Sjsing struct sr_boot_keydisk *kd;
9365f4a3c7Sjsing int i;
9465f4a3c7Sjsing
9565f4a3c7Sjsing /* Process optional metadata. */
9665f4a3c7Sjsing omh = (struct sr_meta_opt_hdr *)((u_int8_t *)(sm + 1) +
9765f4a3c7Sjsing sizeof(struct sr_meta_chunk) * sm->ssdi.ssd_chunk_no);
9865f4a3c7Sjsing for (i = 0; i < sm->ssdi.ssd_opt_no; i++) {
9965f4a3c7Sjsing
10065f4a3c7Sjsing /* Unsupported old fixed length optional metadata. */
10165f4a3c7Sjsing if (omh->som_length == 0) {
10265f4a3c7Sjsing omh = (struct sr_meta_opt_hdr *)((void *)omh +
10365f4a3c7Sjsing SR_OLD_META_OPT_SIZE);
10465f4a3c7Sjsing continue;
10565f4a3c7Sjsing }
10665f4a3c7Sjsing
10765f4a3c7Sjsing if (omh->som_type != SR_OPT_KEYDISK) {
10865f4a3c7Sjsing omh = (struct sr_meta_opt_hdr *)((void *)omh +
10965f4a3c7Sjsing omh->som_length);
11065f4a3c7Sjsing continue;
11165f4a3c7Sjsing }
11265f4a3c7Sjsing
11365f4a3c7Sjsing kd = alloc(sizeof(struct sr_boot_keydisk));
11465f4a3c7Sjsing bcopy(&sm->ssdi.ssd_uuid, &kd->kd_uuid, sizeof(kd->kd_uuid));
11565f4a3c7Sjsing skm = (struct sr_meta_keydisk*)omh;
11665f4a3c7Sjsing bcopy(&skm->skm_maskkey, &kd->kd_key, sizeof(kd->kd_key));
11765f4a3c7Sjsing SLIST_INSERT_HEAD(&sr_keydisks, kd, kd_link);
11865f4a3c7Sjsing }
11965f4a3c7Sjsing }
12065f4a3c7Sjsing
12165f4a3c7Sjsing void
srprobe(void)12265f4a3c7Sjsing srprobe(void)
12365f4a3c7Sjsing {
12465f4a3c7Sjsing struct sr_boot_volume *bv, *bv1, *bv2;
12565f4a3c7Sjsing struct sr_boot_chunk *bc, *bc1, *bc2;
12665f4a3c7Sjsing struct sr_meta_chunk *mc;
12765f4a3c7Sjsing struct sr_metadata *md;
12865f4a3c7Sjsing struct diskinfo *dip;
12965f4a3c7Sjsing struct partition *pp;
13065f4a3c7Sjsing int i, error, volno;
13165f4a3c7Sjsing dev_t bsd_dev;
13265f4a3c7Sjsing daddr_t off;
13365f4a3c7Sjsing
13465f4a3c7Sjsing /* Probe for softraid volumes. */
13565f4a3c7Sjsing SLIST_INIT(&sr_volumes);
13665f4a3c7Sjsing SLIST_INIT(&sr_keydisks);
13765f4a3c7Sjsing
13865f4a3c7Sjsing md = alloc(SR_META_SIZE * DEV_BSIZE);
13965f4a3c7Sjsing
14065f4a3c7Sjsing TAILQ_FOREACH(dip, &disklist, list) {
14165f4a3c7Sjsing
14265f4a3c7Sjsing /* Only check hard disks, skip those with I/O errors. */
14365f4a3c7Sjsing if ((dip->bios_info.bios_number & 0x80) == 0 ||
14465f4a3c7Sjsing (dip->bios_info.flags & BDI_INVALID))
14565f4a3c7Sjsing continue;
14665f4a3c7Sjsing
14765f4a3c7Sjsing /* Make sure disklabel has been read. */
14865f4a3c7Sjsing if ((dip->bios_info.flags & (BDI_BADLABEL|BDI_GOODLABEL)) == 0)
14965f4a3c7Sjsing continue;
15065f4a3c7Sjsing
15165f4a3c7Sjsing for (i = 0; i < MAXPARTITIONS; i++) {
15265f4a3c7Sjsing
15365f4a3c7Sjsing pp = &dip->disklabel.d_partitions[i];
15465f4a3c7Sjsing if (pp->p_fstype != FS_RAID || pp->p_size == 0)
15565f4a3c7Sjsing continue;
15665f4a3c7Sjsing
15765f4a3c7Sjsing /* Read softraid metadata. */
15865f4a3c7Sjsing bzero(md, SR_META_SIZE * DEV_BSIZE);
15965f4a3c7Sjsing off = DL_SECTOBLK(&dip->disklabel, DL_GETPOFFSET(pp));
16065f4a3c7Sjsing off += SR_META_OFFSET;
16165f4a3c7Sjsing error = dip->diskio(F_READ, dip, off, SR_META_SIZE, md);
16265f4a3c7Sjsing if (error)
16365f4a3c7Sjsing continue;
16465f4a3c7Sjsing
16565f4a3c7Sjsing /* Is this valid softraid metadata? */
16665f4a3c7Sjsing if (md->ssdi.ssd_magic != SR_MAGIC)
16765f4a3c7Sjsing continue;
16865f4a3c7Sjsing
16965f4a3c7Sjsing /* XXX - validate checksum. */
17065f4a3c7Sjsing
17165f4a3c7Sjsing /* Handle key disks separately... */
17265f4a3c7Sjsing if (md->ssdi.ssd_level == SR_KEYDISK_LEVEL) {
17365f4a3c7Sjsing srprobe_keydisk_load(md);
17465f4a3c7Sjsing continue;
17565f4a3c7Sjsing }
17665f4a3c7Sjsing
17765f4a3c7Sjsing /* Locate chunk-specific metadata for this chunk. */
17865f4a3c7Sjsing mc = (struct sr_meta_chunk *)(md + 1);
17965f4a3c7Sjsing mc += md->ssdi.ssd_chunk_id;
18065f4a3c7Sjsing
18165f4a3c7Sjsing bc = alloc(sizeof(struct sr_boot_chunk));
18265f4a3c7Sjsing bc->sbc_diskinfo = dip;
18365f4a3c7Sjsing bc->sbc_disk = dip->bios_info.bios_number;
18465f4a3c7Sjsing bc->sbc_part = 'a' + i;
18565f4a3c7Sjsing
18665f4a3c7Sjsing bsd_dev = dip->bios_info.bsd_dev;
18765f4a3c7Sjsing bc->sbc_mm = MAKEBOOTDEV(B_TYPE(bsd_dev),
18865f4a3c7Sjsing B_ADAPTOR(bsd_dev), B_CONTROLLER(bsd_dev),
18965f4a3c7Sjsing B_UNIT(bsd_dev), bc->sbc_part - 'a');
19065f4a3c7Sjsing
19165f4a3c7Sjsing bc->sbc_chunk_id = md->ssdi.ssd_chunk_id;
19265f4a3c7Sjsing bc->sbc_ondisk = md->ssd_ondisk;
19365f4a3c7Sjsing bc->sbc_state = mc->scm_status;
19465f4a3c7Sjsing
19565f4a3c7Sjsing SLIST_FOREACH(bv, &sr_volumes, sbv_link) {
19665f4a3c7Sjsing if (bcmp(&md->ssdi.ssd_uuid, &bv->sbv_uuid,
19765f4a3c7Sjsing sizeof(md->ssdi.ssd_uuid)) == 0)
19865f4a3c7Sjsing break;
19965f4a3c7Sjsing }
20065f4a3c7Sjsing
20165f4a3c7Sjsing if (bv == NULL) {
20265f4a3c7Sjsing bv = alloc(sizeof(struct sr_boot_volume));
20365f4a3c7Sjsing bzero(bv, sizeof(struct sr_boot_volume));
20465f4a3c7Sjsing bv->sbv_level = md->ssdi.ssd_level;
20565f4a3c7Sjsing bv->sbv_volid = md->ssdi.ssd_volid;
20665f4a3c7Sjsing bv->sbv_chunk_no = md->ssdi.ssd_chunk_no;
20765f4a3c7Sjsing bv->sbv_flags = md->ssdi.ssd_vol_flags;
20865f4a3c7Sjsing bv->sbv_size = md->ssdi.ssd_size;
20965f4a3c7Sjsing bv->sbv_data_blkno = md->ssd_data_blkno;
21065f4a3c7Sjsing bcopy(&md->ssdi.ssd_uuid, &bv->sbv_uuid,
21165f4a3c7Sjsing sizeof(md->ssdi.ssd_uuid));
21265f4a3c7Sjsing SLIST_INIT(&bv->sbv_chunks);
21365f4a3c7Sjsing SLIST_INIT(&bv->sbv_meta_opt);
21465f4a3c7Sjsing
21565f4a3c7Sjsing /* Load optional metadata for this volume. */
21665f4a3c7Sjsing srprobe_meta_opt_load(md, &bv->sbv_meta_opt);
21765f4a3c7Sjsing
21865f4a3c7Sjsing /* Maintain volume order. */
21965f4a3c7Sjsing bv2 = NULL;
22065f4a3c7Sjsing SLIST_FOREACH(bv1, &sr_volumes, sbv_link) {
22165f4a3c7Sjsing if (bv1->sbv_volid > bv->sbv_volid)
22265f4a3c7Sjsing break;
22365f4a3c7Sjsing bv2 = bv1;
22465f4a3c7Sjsing }
22565f4a3c7Sjsing if (bv2 == NULL)
22665f4a3c7Sjsing SLIST_INSERT_HEAD(&sr_volumes, bv,
22765f4a3c7Sjsing sbv_link);
22865f4a3c7Sjsing else
22965f4a3c7Sjsing SLIST_INSERT_AFTER(bv2, bv, sbv_link);
23065f4a3c7Sjsing }
23165f4a3c7Sjsing
23265f4a3c7Sjsing /* Maintain chunk order. */
23365f4a3c7Sjsing bc2 = NULL;
23465f4a3c7Sjsing SLIST_FOREACH(bc1, &bv->sbv_chunks, sbc_link) {
23565f4a3c7Sjsing if (bc1->sbc_chunk_id > bc->sbc_chunk_id)
23665f4a3c7Sjsing break;
23765f4a3c7Sjsing bc2 = bc1;
23865f4a3c7Sjsing }
23965f4a3c7Sjsing if (bc2 == NULL)
24065f4a3c7Sjsing SLIST_INSERT_HEAD(&bv->sbv_chunks,
24165f4a3c7Sjsing bc, sbc_link);
24265f4a3c7Sjsing else
24365f4a3c7Sjsing SLIST_INSERT_AFTER(bc2, bc, sbc_link);
24465f4a3c7Sjsing
24565f4a3c7Sjsing bv->sbv_chunks_found++;
24665f4a3c7Sjsing }
24765f4a3c7Sjsing }
24865f4a3c7Sjsing
24965f4a3c7Sjsing /*
25065f4a3c7Sjsing * Assemble RAID volumes.
25165f4a3c7Sjsing */
25265f4a3c7Sjsing volno = 0;
25365f4a3c7Sjsing SLIST_FOREACH(bv, &sr_volumes, sbv_link) {
25465f4a3c7Sjsing
25565f4a3c7Sjsing /* Skip if this is a hotspare "volume". */
25665f4a3c7Sjsing if (bv->sbv_level == SR_HOTSPARE_LEVEL &&
25765f4a3c7Sjsing bv->sbv_chunk_no == 1)
25865f4a3c7Sjsing continue;
25965f4a3c7Sjsing
26065f4a3c7Sjsing /* Determine current ondisk version. */
26165f4a3c7Sjsing bv->sbv_ondisk = 0;
26265f4a3c7Sjsing SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link) {
26365f4a3c7Sjsing if (bc->sbc_ondisk > bv->sbv_ondisk)
26465f4a3c7Sjsing bv->sbv_ondisk = bc->sbc_ondisk;
26565f4a3c7Sjsing }
26665f4a3c7Sjsing SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link) {
26765f4a3c7Sjsing if (bc->sbc_ondisk != bv->sbv_ondisk)
26865f4a3c7Sjsing bc->sbc_state = BIOC_SDOFFLINE;
26965f4a3c7Sjsing }
27065f4a3c7Sjsing
27165f4a3c7Sjsing /* XXX - Check for duplicate chunks. */
27265f4a3c7Sjsing
27365f4a3c7Sjsing /*
27465f4a3c7Sjsing * Validate that volume has sufficient chunks for
27565f4a3c7Sjsing * read-only access.
27665f4a3c7Sjsing *
27765f4a3c7Sjsing * XXX - check chunk states.
27865f4a3c7Sjsing */
27965f4a3c7Sjsing bv->sbv_state = BIOC_SVOFFLINE;
28065f4a3c7Sjsing switch (bv->sbv_level) {
28165f4a3c7Sjsing case 0:
28265f4a3c7Sjsing case 'C':
28365f4a3c7Sjsing case 'c':
28465f4a3c7Sjsing if (bv->sbv_chunk_no == bv->sbv_chunks_found)
28565f4a3c7Sjsing bv->sbv_state = BIOC_SVONLINE;
28665f4a3c7Sjsing break;
28765f4a3c7Sjsing
28865f4a3c7Sjsing case 1:
28965f4a3c7Sjsing if (bv->sbv_chunk_no == bv->sbv_chunks_found)
29065f4a3c7Sjsing bv->sbv_state = BIOC_SVONLINE;
29165f4a3c7Sjsing else if (bv->sbv_chunks_found > 0)
29265f4a3c7Sjsing bv->sbv_state = BIOC_SVDEGRADED;
29365f4a3c7Sjsing break;
29465f4a3c7Sjsing }
29565f4a3c7Sjsing
29665f4a3c7Sjsing bv->sbv_unit = volno++;
29765f4a3c7Sjsing if (bv->sbv_state != BIOC_SVOFFLINE)
29865f4a3c7Sjsing printf(" sr%d%s", bv->sbv_unit,
29965f4a3c7Sjsing bv->sbv_flags & BIOC_SCBOOTABLE ? "*" : "");
30065f4a3c7Sjsing }
30165f4a3c7Sjsing
30265f4a3c7Sjsing explicit_bzero(md, SR_META_SIZE * DEV_BSIZE);
303bac5600aSfcambus free(md, SR_META_SIZE * DEV_BSIZE);
30465f4a3c7Sjsing }
30565f4a3c7Sjsing
30665f4a3c7Sjsing int
sr_strategy(struct sr_boot_volume * bv,int rw,daddr_t blk,size_t size,void * buf,size_t * rsize)307*3e58d19eSkrw sr_strategy(struct sr_boot_volume *bv, int rw, daddr_t blk, size_t size,
30865f4a3c7Sjsing void *buf, size_t *rsize)
30965f4a3c7Sjsing {
31065f4a3c7Sjsing struct diskinfo *sr_dip, *dip;
31165f4a3c7Sjsing struct sr_boot_chunk *bc;
31265f4a3c7Sjsing struct aes_xts_ctx ctx;
31365f4a3c7Sjsing size_t i, j, nsect;
31465f4a3c7Sjsing daddr_t blkno;
31565f4a3c7Sjsing u_char iv[8];
31665f4a3c7Sjsing u_char *bp;
31765f4a3c7Sjsing int err;
31865f4a3c7Sjsing
31965f4a3c7Sjsing /* We only support read-only softraid. */
32065f4a3c7Sjsing if (rw != F_READ)
32165f4a3c7Sjsing return ENOTSUP;
32265f4a3c7Sjsing
32365f4a3c7Sjsing /* Partition offset within softraid volume. */
32465f4a3c7Sjsing sr_dip = (struct diskinfo *)bv->sbv_diskinfo;
32565f4a3c7Sjsing blk += sr_dip->disklabel.d_partitions[bv->sbv_part - 'a'].p_offset;
32665f4a3c7Sjsing
32765f4a3c7Sjsing if (bv->sbv_level == 0) {
32865f4a3c7Sjsing return ENOTSUP;
32965f4a3c7Sjsing } else if (bv->sbv_level == 1) {
33065f4a3c7Sjsing
33165f4a3c7Sjsing /* Select first online chunk. */
33265f4a3c7Sjsing SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link)
33365f4a3c7Sjsing if (bc->sbc_state == BIOC_SDONLINE)
33465f4a3c7Sjsing break;
33565f4a3c7Sjsing if (bc == NULL)
33665f4a3c7Sjsing return EIO;
33765f4a3c7Sjsing
33865f4a3c7Sjsing dip = (struct diskinfo *)bc->sbc_diskinfo;
33965f4a3c7Sjsing dip->bsddev = bc->sbc_mm;
34065f4a3c7Sjsing blk += bv->sbv_data_blkno;
34165f4a3c7Sjsing
34265f4a3c7Sjsing /* XXX - If I/O failed we should try another chunk... */
34365f4a3c7Sjsing return dip->strategy(dip, rw, blk, size, buf, rsize);
34465f4a3c7Sjsing
34565f4a3c7Sjsing } else if (bv->sbv_level == 'C') {
34665f4a3c7Sjsing
34765f4a3c7Sjsing /* Select first online chunk. */
34865f4a3c7Sjsing SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link)
34965f4a3c7Sjsing if (bc->sbc_state == BIOC_SDONLINE)
35065f4a3c7Sjsing break;
35165f4a3c7Sjsing if (bc == NULL)
35265f4a3c7Sjsing return EIO;
35365f4a3c7Sjsing
35465f4a3c7Sjsing dip = (struct diskinfo *)bc->sbc_diskinfo;
35565f4a3c7Sjsing dip->bsddev = bc->sbc_mm;
35665f4a3c7Sjsing
35765f4a3c7Sjsing /* XXX - select correct key. */
35865f4a3c7Sjsing aes_xts_setkey(&ctx, (u_char *)bv->sbv_keys, 64);
35965f4a3c7Sjsing
36065f4a3c7Sjsing nsect = (size + DEV_BSIZE - 1) / DEV_BSIZE;
36165f4a3c7Sjsing for (i = 0; i < nsect; i++) {
36265f4a3c7Sjsing blkno = blk + i;
36365f4a3c7Sjsing bp = ((u_char *)buf) + i * DEV_BSIZE;
36465f4a3c7Sjsing err = dip->strategy(dip, rw, bv->sbv_data_blkno + blkno,
36565f4a3c7Sjsing DEV_BSIZE, bp, NULL);
36665f4a3c7Sjsing if (err != 0)
36765f4a3c7Sjsing return err;
36865f4a3c7Sjsing
36965f4a3c7Sjsing bcopy(&blkno, iv, sizeof(blkno));
37065f4a3c7Sjsing aes_xts_reinit(&ctx, iv);
37165f4a3c7Sjsing for (j = 0; j < DEV_BSIZE; j += AES_XTS_BLOCKSIZE)
37265f4a3c7Sjsing aes_xts_decrypt(&ctx, bp + j);
37365f4a3c7Sjsing }
37465f4a3c7Sjsing if (rsize != NULL)
37565f4a3c7Sjsing *rsize = nsect * DEV_BSIZE;
37665f4a3c7Sjsing
37765f4a3c7Sjsing return err;
37865f4a3c7Sjsing
37965f4a3c7Sjsing } else
38065f4a3c7Sjsing return ENOTSUP;
38165f4a3c7Sjsing }
38265f4a3c7Sjsing
38365f4a3c7Sjsing const char *
sr_getdisklabel(struct sr_boot_volume * bv,struct disklabel * label)38465f4a3c7Sjsing sr_getdisklabel(struct sr_boot_volume *bv, struct disklabel *label)
38565f4a3c7Sjsing {
38665f4a3c7Sjsing struct dos_partition *dp;
38765f4a3c7Sjsing struct dos_mbr mbr;
38865f4a3c7Sjsing u_int start = 0;
38965f4a3c7Sjsing char buf[DEV_BSIZE];
39065f4a3c7Sjsing int i;
39165f4a3c7Sjsing
39265f4a3c7Sjsing /* Check for MBR to determine partition offset. */
39365f4a3c7Sjsing bzero(&mbr, sizeof(mbr));
39465f4a3c7Sjsing sr_strategy(bv, F_READ, DOSBBSECTOR, sizeof(mbr), &mbr, NULL);
39565f4a3c7Sjsing if (mbr.dmbr_sign == DOSMBR_SIGNATURE) {
39665f4a3c7Sjsing
39765f4a3c7Sjsing /* Search for OpenBSD partition */
39865f4a3c7Sjsing for (i = 0; i < NDOSPART; i++) {
39965f4a3c7Sjsing dp = &mbr.dmbr_parts[i];
40065f4a3c7Sjsing if (!dp->dp_size)
40165f4a3c7Sjsing continue;
40265f4a3c7Sjsing if (dp->dp_typ == DOSPTYP_OPENBSD) {
40365f4a3c7Sjsing start = dp->dp_start;
40465f4a3c7Sjsing break;
40565f4a3c7Sjsing }
40665f4a3c7Sjsing }
40765f4a3c7Sjsing }
40865f4a3c7Sjsing
40965f4a3c7Sjsing /* Read the disklabel. */
41065f4a3c7Sjsing sr_strategy(bv, F_READ, start + DOS_LABELSECTOR,
41165f4a3c7Sjsing sizeof(struct disklabel), buf, NULL);
41265f4a3c7Sjsing
41365f4a3c7Sjsing #ifdef BIOS_DEBUG
41465f4a3c7Sjsing printf("sr_getdisklabel: magic %lx\n",
41565f4a3c7Sjsing ((struct disklabel *)buf)->d_magic);
41665f4a3c7Sjsing for (i = 0; i < MAXPARTITIONS; i++)
41765f4a3c7Sjsing printf("part %c: type = %d, size = %d, offset = %d\n", 'a' + i,
41865f4a3c7Sjsing (int)((struct disklabel *)buf)->d_partitions[i].p_fstype,
41965f4a3c7Sjsing (int)((struct disklabel *)buf)->d_partitions[i].p_size,
42065f4a3c7Sjsing (int)((struct disklabel *)buf)->d_partitions[i].p_offset);
42165f4a3c7Sjsing #endif
42265f4a3c7Sjsing
42365f4a3c7Sjsing /* Fill in disklabel */
42465f4a3c7Sjsing return (getdisklabel(buf, label));
42565f4a3c7Sjsing }
426