/* * Find and convert from a DEC label to BSD */ boolean_t rz_dec_label( target_info_t *tgt, struct disklabel *label, io_req_t ior) { /* here look for a DEC label */ register scsi_dec_label_t *part; char *data; int i, dev_bsize = tgt->block_size; ior->io_count = dev_bsize; ior->io_op = IO_READ; tgt->ior = ior; scdisk_read( tgt, DEC_LABEL_BYTE_OFFSET/dev_bsize, ior); iowait(ior); data = (char *)ior->io_data; part = (scsi_dec_label_t*)&data[DEC_LABEL_BYTE_OFFSET%dev_bsize]; if (part->magic == DEC_LABEL_MAGIC) { if (scsi_debug) printf("{Using DEC label}"); for (i = 0; i < 8; i++) { label->d_partitions[i].p_size = part->partitions[i].n_sectors; label->d_partitions[i].p_offset = part->partitions[i].offset; } return TRUE; } return FALSE; }
/* Write back a label to the disk */ scsi_ret_t scdisk_writelabel( target_info_t *tgt) { io_req_t ior; char *data; struct disklabel *label; io_return_t error; io_req_alloc(ior); #ifdef MACH_KERNEL data = (char *) kalloc(tgt->block_size); #else /*MACH_KERNEL*/ data = (char *)ior->io_data; #endif /*MACH_KERNEL*/ ior->io_next = 0; ior->io_prev = 0; ior->io_data = data; ior->io_count = tgt->block_size; ior->io_op = IO_READ; ior->io_error = 0; if (grab_it(tgt, ior) != D_SUCCESS) { error = D_ALREADY_OPEN; goto ret; } scdisk_read( tgt, LABELSECTOR, ior); iowait(ior); if (error = ior->io_error) goto ret; label = (struct disklabel *) &data[LABELOFFSET % tgt->block_size]; *label = tgt->dev_info.disk.l; ior->io_next = 0; ior->io_prev = 0; ior->io_data = data; ior->io_count = tgt->block_size; ior->io_op = IO_WRITE; ior->io_error = 0; tgt->ior = ior; /*?*/ while (grab_it(tgt, ior) != D_SUCCESS) ; /* ahem */ scdisk_write( tgt, LABELSECTOR, ior); iowait(ior); error = ior->io_error; ret: #ifdef MACH_KERNEL kfree((vm_offset_t) data, tgt->block_size); #endif io_req_free(ior); return error; }
boolean_t rz_bios_bsd_label( target_info_t *tgt, struct disklabel *label, io_req_t ior, struct bios_partition_info *ospart) { struct disklabel *dlp; int dev_bsize = tgt->block_size; int i; extern int allow_bsd_label; ior->io_count = dev_bsize; ior->io_op = IO_READ; tgt->ior = ior; scdisk_read( tgt, (ospart->offset + LBLLOC) * 512 / dev_bsize, ior); iowait(ior); dlp = (struct disklabel *)ior->io_data; if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { if (OS == BSDOS) { printf("NO BSD LABEL!!\n"); } return FALSE; } printf("BSD LABEL "); LABEL_DEBUG(2,print_bsd_label(dlp, "dk:")); /* * here's where we dump label */ if (allow_bsd_label == 0) return FALSE; i = label->d_secperunit; *label = *dlp; label->d_secperunit = i; /* * The disklabel program should insure the invariant below * when it writes a label. But it does not seem to. */ label->d_partitions[MAXPARTITIONS].p_size = -1; label->d_partitions[MAXPARTITIONS].p_offset = 0; label->d_checksum = dkcksum(label); tgt->dev_info.disk.labeloffset = 0; tgt->dev_info.disk.labelsector = (ospart->offset + LBLLOC) * 512 / dev_bsize; LABEL_DEBUG(0x20,print_bsd_label(dlp, " ")); return TRUE; }
/* * Find and convert from a Omron label to BSD */ boolean_t rz_omron_label( target_info_t *tgt, struct disklabel *label, io_req_t ior) { /* here look for an Omron label */ register scsi_omron_label_t *part; char *data; int i, dev_bsize = tgt->block_size; ior->io_count = dev_bsize; ior->io_op = IO_READ; tgt->ior = ior; scdisk_read( tgt, OMRON_LABEL_BYTE_OFFSET/dev_bsize, ior); iowait(ior); data = (char *)ior->io_data; part = (scsi_omron_label_t*)&data[OMRON_LABEL_BYTE_OFFSET%dev_bsize]; if (part->magic == OMRON_LABEL_MAGIC) { if (scsi_debug) printf("{Using OMRON label}"); for (i = 0; i < 8; i++) { label->d_partitions[i].p_size = part->partitions[i].n_sectors; label->d_partitions[i].p_offset = part->partitions[i].offset; } bcopy(part->packname, label->d_packname, 16); label->d_ncylinders = part->ncyl; label->d_acylinders = part->acyl; label->d_ntracks = part->nhead; label->d_nsectors = part->nsect; /* Many disks have this wrong, therefore.. */ #if 0 label->d_secperunit = part->maxblk; #else label->d_secperunit = label->d_ncylinders * label->d_ntracks * label->d_nsectors; #endif return TRUE; } return FALSE; }
/* * Find and convert from an HPUX label to BSD */ boolean_t read_hpux_label( target_info_t *tgt, struct disklabel *label, io_req_t ior) { struct lif_header *l_header; struct lif_label *l_label; struct disklabel *dlp; vm_offset_t data; boolean_t rc = FALSE; if (kmem_alloc(kernel_map, (vm_offset_t *)&data, DEV_BSIZE) != KERN_SUCCESS) { printf("cant read LIF header\n"); return(FALSE); } if (label->d_secperunit == 0) label->d_secperunit = 0x1fffffff; label->d_npartitions = 1; if (label->d_partitions[0].p_size == 0) label->d_partitions[0].p_size = 0x1fffffff; label->d_partitions[0].p_offset = 0; ior->io_count = DEV_BSIZE; ior->io_op = IO_READ; ior->io_data = (char *)data; tgt->ior = ior; scdisk_read( tgt, LIF_HEADER_OFF/tgt->block_size, ior); iowait(ior); l_header = (struct lif_header*)ior->io_data; if (l_header->magic != LIF_MAGIC) { printf("cant find LIF_HEADER block\n"); rc = FALSE; goto out; } if (!IS_OSF1_DISK(l_header)) { ior->io_count = DEV_BSIZE; ior->io_op = IO_READ; tgt->ior = ior; scdisk_read( tgt, LIF_LABEL_OFF/tgt->block_size, ior); iowait(ior); if (!convert_lif_to_osf1((struct lif_label*)ior->io_data, label)) { printf("No FS detected in LIF block\n"); rc = FALSE; goto out; } else rc = TRUE; } else { ior->io_count = DEV_BSIZE; ior->io_op = IO_READ; tgt->ior = ior; scdisk_read( tgt, LABELSECTOR, ior); iowait(ior); for (dlp = (struct disklabel *)ior->io_data; dlp <= (struct disklabel *)(ior->io_data +DEV_BSIZE-sizeof(*dlp)); dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { continue; } else if (dlp->d_npartitions > MAXPARTITIONS || dkcksum(dlp) != 0) { printf("disk label corrupted\n"); rc = FALSE; goto out; } else { rc = TRUE; *label = *dlp; break; } } if (rc == FALSE) printf("no disk label\n"); } out: if (data) (void) kmem_free(kernel_map, data, DEV_BSIZE); return rc; }
boolean_t rz_bios_label( target_info_t *tgt, struct disklabel *label, io_req_t ior) { /* here look for a BIOS label */ char *data; int i, dev_bsize = tgt->block_size; scsi_bios_label_t part; ior->io_count = dev_bsize; ior->io_op = IO_READ; tgt->ior = ior; scdisk_read( tgt, BIOS_LABEL_BYTE_OFFSET/dev_bsize, ior); iowait(ior); data = (char *)ior->io_data; /* * It's safer to just copy the data here and not worry about * scdisk_read's down the line will clobber the buffer. */ part = *(scsi_bios_label_t*)&data[BIOS_LABEL_BYTE_OFFSET%dev_bsize]; if (((scsi_bios_label_t*)&data[BIOS_LABEL_BYTE_OFFSET%dev_bsize])->magic == BIOS_LABEL_MAGIC) { struct bios_partition_info *bpart, *ospart = (struct bios_partition_info *)0; if (scsi_debug) printf("{Using BIOS label}"); for (i = 0; i < 4; i++) { bpart = &(((struct bios_partition_info *)part.partitions)[i]); LABEL_DEBUG(1,print_dos_partition(i, bpart)); label->d_partitions[i].p_size = bpart->n_sectors; label->d_partitions[i].p_offset = bpart->offset; if (bpart->systid == UNIXOS || bpart->systid == BSDOS) { if (ospart != 0) { if (bpart->bootid == BIOS_BOOTABLE) ospart = bpart; } else ospart = bpart; } } tgt->dev_info.disk.l.d_partitions[MAXPARTITIONS].p_offset= 0; tgt->dev_info.disk.l.d_partitions[MAXPARTITIONS].p_size = -1; if (ospart == 0) return FALSE; OS = ospart->systid; if (OS == UNIXOS) printf("sd%d: MACH OS ", tgt->target_id); if (OS == BSDOS) printf("sd%d: XXXBSD OS ", tgt->target_id); if (rz_bios_bsd_label(tgt, label, ior, ospart)) return TRUE; #ifdef AT386 /* this goes away real fast */ if (!grab_bob_label(tgt, label, ior, ((struct bios_partition_info *)part.partitions))) return FALSE; /* take default setup of "a" and "c" */ #else label->d_npartitions = 4; #endif label->d_bbsize = BIOS_BOOT0_SIZE; return TRUE; } return FALSE; }