1*82357f6dSdsl /* $NetBSD: read.c,v 1.4 2009/03/14 21:04:06 dsl Exp $ */
23f496a25Sleo
33f496a25Sleo /*
43f496a25Sleo * Copyright (c) 1999 The NetBSD Foundation, Inc.
53f496a25Sleo * All rights reserved.
63f496a25Sleo *
73f496a25Sleo * This code is derived from software contributed to The NetBSD Foundation
83f496a25Sleo * by Julian Coleman, Waldi Ravens and Leo Weppelman.
93f496a25Sleo *
103f496a25Sleo * Redistribution and use in source and binary forms, with or without
113f496a25Sleo * modification, are permitted provided that the following conditions
123f496a25Sleo * are met:
133f496a25Sleo * 1. Redistributions of source code must retain the above copyright
143f496a25Sleo * notice, this list of conditions and the following disclaimer.
153f496a25Sleo * 2. Redistributions in binary form must reproduce the above copyright
163f496a25Sleo * notice, this list of conditions and the following disclaimer in the
173f496a25Sleo * documentation and/or other materials provided with the distribution.
183f496a25Sleo *
193f496a25Sleo * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
203f496a25Sleo * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
213f496a25Sleo * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
223f496a25Sleo * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
233f496a25Sleo * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
243f496a25Sleo * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
253f496a25Sleo * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
263f496a25Sleo * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
273f496a25Sleo * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
283f496a25Sleo * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
293f496a25Sleo * POSSIBILITY OF SUCH DAMAGE.
303f496a25Sleo */
313f496a25Sleo
323f496a25Sleo #include "privahdi.h"
333f496a25Sleo #include <fcntl.h>
34b2b6b2d9Sjdc #ifdef DEBUG
35b2b6b2d9Sjdc #include <stdio.h>
36b2b6b2d9Sjdc #endif
373f496a25Sleo #include <stdlib.h>
383f496a25Sleo #include <strings.h>
393f496a25Sleo #include <unistd.h>
403f496a25Sleo #include <sys/dkio.h>
413f496a25Sleo #include <sys/ioctl.h>
423f496a25Sleo
433f496a25Sleo /*
443f496a25Sleo * Read AHDI partitions from disk.
453f496a25Sleo */
463f496a25Sleo int
ahdi_readlabel(struct ahdi_ptable * ptable,char * diskname,int flags)47*82357f6dSdsl ahdi_readlabel (struct ahdi_ptable *ptable, char *diskname, int flags)
483f496a25Sleo {
493f496a25Sleo int fd, rv;
503f496a25Sleo struct disklabel *dl;
513f496a25Sleo
523f496a25Sleo if (!(fd = openraw (diskname, O_RDONLY)))
533f496a25Sleo return (-1);
543f496a25Sleo
553f496a25Sleo if ((dl = read_dl (fd)) == NULL) {
563f496a25Sleo close (fd);
573f496a25Sleo return (-1);
583f496a25Sleo }
593f496a25Sleo
603f496a25Sleo if (dl->d_secsize != AHDI_BSIZE) {
613f496a25Sleo close (fd);
623f496a25Sleo return (-2);
633f496a25Sleo }
643f496a25Sleo
653f496a25Sleo if ((rv = check_magic(fd, LABELSECTOR, flags)) < 0) {
663f496a25Sleo close (fd);
673f496a25Sleo return (rv);
683f496a25Sleo }
693f496a25Sleo
703f496a25Sleo bzero ((void *) ptable, sizeof (struct ahdi_ptable));
713f496a25Sleo
723f496a25Sleo if ((rv = read_rsec (fd, ptable, AHDI_BBLOCK, AHDI_BBLOCK, flags))
733f496a25Sleo < 0) {
743f496a25Sleo close (fd);
753f496a25Sleo return (rv);
763f496a25Sleo }
773f496a25Sleo
783f496a25Sleo if (dl->d_secperunit != ptable->secperunit) {
793f496a25Sleo if (flags & AHDI_IGN_SPU)
803f496a25Sleo ptable->secperunit = dl->d_secperunit;
813f496a25Sleo else {
823f496a25Sleo close (fd);
833f496a25Sleo return (-6);
843f496a25Sleo }
853f496a25Sleo }
863f496a25Sleo
873f496a25Sleo ptable->nsectors = dl->d_nsectors;
883f496a25Sleo ptable->ntracks = dl->d_ntracks;
893f496a25Sleo ptable->ncylinders = dl->d_ncylinders;
903f496a25Sleo ptable->secpercyl = dl->d_secpercyl;
913f496a25Sleo
923f496a25Sleo assign_letters (ptable);
933f496a25Sleo
943f496a25Sleo close (fd);
953f496a25Sleo return (1);
963f496a25Sleo }
973f496a25Sleo
983f496a25Sleo /*
993f496a25Sleo * Read AHDI partitions from root sector/auxillary root sector.
1003f496a25Sleo */
1013f496a25Sleo int
read_rsec(int fd,struct ahdi_ptable * ptable,u_int rsec,u_int esec,int flags)102*82357f6dSdsl read_rsec (int fd, struct ahdi_ptable *ptable, u_int rsec, u_int esec, int flags)
1033f496a25Sleo {
1043f496a25Sleo struct ahdi_part *part, *end;
1053f496a25Sleo struct ahdi_root *root;
1063f496a25Sleo u_int16_t cksum, newcksum;
1073f496a25Sleo int rv;
1083f496a25Sleo
1093f496a25Sleo if ((root = disk_read (fd, rsec, 1)) == NULL) {
1103f496a25Sleo return (-1);
1113f496a25Sleo }
1123f496a25Sleo
1133f496a25Sleo if (rsec == AHDI_BBLOCK) {
1143f496a25Sleo end = &root->ar_parts[AHDI_MAXRPD];
1153f496a25Sleo if (root->ar_checksum) {
1163f496a25Sleo cksum = root->ar_checksum;
1173f496a25Sleo root->ar_checksum = 0;
1183f496a25Sleo newcksum = ahdi_cksum (root);
1193f496a25Sleo if ((cksum != newcksum) && !(flags & AHDI_IGN_CKSUM)) {
1203f496a25Sleo free (root);
1213f496a25Sleo return (-4);
1223f496a25Sleo }
1233f496a25Sleo }
1243f496a25Sleo ptable->secperunit=root->ar_hdsize;
1253f496a25Sleo } else
1263f496a25Sleo end = &root->ar_parts[AHDI_MAXARPD];
1273f496a25Sleo for (part = root->ar_parts; part < end; ++part) {
1283f496a25Sleo #ifdef DEBUG
1293f496a25Sleo printf ("Found partitions at sector %u:\n", rsec);
1303f496a25Sleo printf (" flags : %02x\n", part->ap_flg);
1313f496a25Sleo printf (" id : %c%c%c\n", part->ap_id[0], part->ap_id[1],
1323f496a25Sleo part->ap_id[2]);
1333f496a25Sleo printf (" start : %u\n", part->ap_st);
1343f496a25Sleo printf (" size : %u\n", part->ap_size);
1353f496a25Sleo #endif
1363f496a25Sleo if (!(part->ap_flg & 0x01)) {
1373f496a25Sleo if ((part->ap_id[0] || part->ap_id[1] ||
1383f496a25Sleo part->ap_id[2]) && (flags & AHDI_IGN_EXISTS))
1393f496a25Sleo part->ap_flg &= 0x01;
1403f496a25Sleo else
1413f496a25Sleo continue;
1423f496a25Sleo }
1433f496a25Sleo
1443f496a25Sleo if (AHDI_MKPID (part->ap_id[0], part->ap_id[1],
1453f496a25Sleo part->ap_id[2]) == AHDI_PID_XGM) {
1463f496a25Sleo u_int offs = part->ap_st + esec;
1473f496a25Sleo if ((rv = read_rsec (fd, ptable, offs,
1483f496a25Sleo esec == AHDI_BBLOCK ? offs : esec, flags)) < 0) {
1493f496a25Sleo free (root);
1503f496a25Sleo return (rv);
1513f496a25Sleo }
1523f496a25Sleo } else {
1533f496a25Sleo /* Attempt to check for junk values */
1543f496a25Sleo if (((part->ap_st + rsec) > ptable->secperunit ||
1553f496a25Sleo (part->ap_st + rsec + part->ap_size -1) >
1563f496a25Sleo ptable->secperunit)) {
1573f496a25Sleo if (flags & AHDI_IGN_EXT) {
1583f496a25Sleo /* Fake previous partition */
1593f496a25Sleo ptable->parts[ptable->nparts].id[0] =
1603f496a25Sleo part->ap_id[0];
1613f496a25Sleo ptable->parts[ptable->nparts].id[1] =
1623f496a25Sleo part->ap_id[1];
1633f496a25Sleo ptable->parts[ptable->nparts].id[2] =
1643f496a25Sleo part->ap_id[2];
1653f496a25Sleo } else {
1663f496a25Sleo free (root);
1673f496a25Sleo return (-5);
1683f496a25Sleo }
1693f496a25Sleo }
1703f496a25Sleo ptable->parts[ptable->nparts].flag = part->ap_flg;
1713f496a25Sleo ptable->parts[ptable->nparts].id[0] = part->ap_id[0];
1723f496a25Sleo ptable->parts[ptable->nparts].id[1] = part->ap_id[1];
1733f496a25Sleo ptable->parts[ptable->nparts].id[2] = part->ap_id[2];
1743f496a25Sleo ptable->parts[ptable->nparts].root = rsec;
1753f496a25Sleo ptable->parts[ptable->nparts].start =
1763f496a25Sleo part->ap_st + rsec;
1773f496a25Sleo ptable->parts[ptable->nparts].size = part->ap_size;
1783f496a25Sleo ptable->nparts++;
1793f496a25Sleo }
1803f496a25Sleo }
1813f496a25Sleo free (root);
1823f496a25Sleo if (ptable->nparts || FORCE_AHDI)
1833f496a25Sleo return (1);
1843f496a25Sleo else
1853f496a25Sleo return (-3);
1863f496a25Sleo }
1873f496a25Sleo
1883f496a25Sleo /*
1893f496a25Sleo * Read a sector from the disk.
1903f496a25Sleo */
1913f496a25Sleo void *
disk_read(fd,start,count)1923f496a25Sleo disk_read (fd, start, count)
1933f496a25Sleo int fd;
1943f496a25Sleo u_int start,
1953f496a25Sleo count;
1963f496a25Sleo {
1973f496a25Sleo void *buffer;
1983f496a25Sleo off_t offset;
1993f496a25Sleo size_t size;
2003f496a25Sleo
2013f496a25Sleo
2023f496a25Sleo size = count * DEV_BSIZE;
2033f496a25Sleo offset = start * DEV_BSIZE;
2043f496a25Sleo
2053f496a25Sleo if ((buffer = malloc (size)) == NULL)
2063f496a25Sleo return (NULL);
2073f496a25Sleo
2083f496a25Sleo if (lseek (fd, offset, SEEK_SET) != offset) {
2093f496a25Sleo free (buffer);
2103f496a25Sleo return (NULL);
2113f496a25Sleo }
2123f496a25Sleo if (read (fd, buffer, size) != size) {
2133f496a25Sleo free (buffer);
2143f496a25Sleo return (NULL);
2153f496a25Sleo }
2163f496a25Sleo return (buffer);
2173f496a25Sleo }
2183f496a25Sleo
2193f496a25Sleo /*
2203f496a25Sleo * Assign NetBSD drive letters to partitions
2213f496a25Sleo */
2223f496a25Sleo void
assign_letters(struct ahdi_ptable * ptable)223*82357f6dSdsl assign_letters (struct ahdi_ptable *ptable)
2243f496a25Sleo {
2253f496a25Sleo int i, have_root, pno;
2263f496a25Sleo u_int32_t pid;
2273f496a25Sleo
2283f496a25Sleo #define ROOT_PART 0
2293f496a25Sleo
2303f496a25Sleo have_root = 0;
2313f496a25Sleo pno = 0;
2323f496a25Sleo
2333f496a25Sleo for (i = 0; i < ptable->nparts; i++) {
2343f496a25Sleo while (pno == ROOT_PART || pno == SWAP_PART || pno == RAW_PART)
2353f496a25Sleo pno++;
2363f496a25Sleo pid = AHDI_MKPID (ptable->parts[i].id[0],
2373f496a25Sleo ptable->parts[i].id[1], ptable->parts[i].id[2]);
2383f496a25Sleo if (!have_root && pid == AHDI_PID_NBD) {
2393f496a25Sleo ptable->parts[i].letter = ROOT_PART;
2403f496a25Sleo have_root = 1;
2413f496a25Sleo } else if (pid == AHDI_PID_SWP)
2423f496a25Sleo ptable->parts[i].letter = SWAP_PART;
2433f496a25Sleo else {
2443f496a25Sleo ptable->parts[i].letter = pno;
2453f496a25Sleo pno++;
2463f496a25Sleo }
2473f496a25Sleo }
2483f496a25Sleo }
2493f496a25Sleo
2503f496a25Sleo /*
2513f496a25Sleo * Read disklabel for disk.
2523f496a25Sleo */
2533f496a25Sleo struct disklabel *
read_dl(int fd)254*82357f6dSdsl read_dl (int fd)
2553f496a25Sleo {
2563f496a25Sleo struct disklabel *dl;
2573f496a25Sleo
2583f496a25Sleo if ((dl = malloc (sizeof (struct disklabel))) == NULL) {
2593f496a25Sleo return (NULL);
2603f496a25Sleo }
2613f496a25Sleo
2623f496a25Sleo if (ioctl (fd, DIOCGDINFO, dl) < 0) {
2633f496a25Sleo free (dl);
2643f496a25Sleo return (NULL);
2653f496a25Sleo }
2663f496a25Sleo return (dl);
2673f496a25Sleo }
268