/* Sun style partitioning */
#include <fcntl.h>
#include <unistd.h>
#include "balkan.h"
#include "byteswap.h"
struct singlePartitionTable {
unsigned char info[128]; /* Informative text string */
unsigned char spare0[14];
struct sun_info {
unsigned char spare1;
unsigned char id;
unsigned char spare2;
unsigned char flags;
} infos[8];
unsigned char spare1[246]; /* Boot information etc. */
unsigned short rspeed; /* Disk rotational speed */
unsigned short pcylcount; /* Physical cylinder count */
unsigned short sparecyl; /* extra sects per cylinder */
unsigned char spare2[4]; /* More magic... */
unsigned short ilfact; /* Interleave factor */
unsigned short ncyl; /* Data cylinder count */
unsigned short nacyl; /* Alt. cylinder count */
unsigned short ntrks; /* Tracks per cylinder */
unsigned short nsect; /* Sectors per track */
unsigned char spare3[4]; /* Even more magic... */
struct sun_partition {
unsigned int start_cylinder;
unsigned int num_sectors;
} parts[8];
unsigned short magic; /* Magic number */
unsigned short csum; /* Label xor'd checksum */
};
#define SUN_LABEL_MAGIC 0xDABE
#define SECTOR_SIZE 512
#define WHOLE_DISK 5
#define UFS_SUPER_MAGIC 0x00011954
long long llseek(int fd, long long offset, int whence);
int sunpReadTable(int fd, struct partitionTable * table) {
struct singlePartitionTable singleTable;
int i, rc, magic;
unsigned short *p, csum;
table->maxNumPartitions = 8;
for (i = 0; i < table->maxNumPartitions; i++)
table->parts[i].type = -1;
table->sectorSize = SECTOR_SIZE;
if (lseek(fd, 0, SEEK_SET) < 0)
return BALKAN_ERROR_ERRNO;
if (read(fd, &singleTable, sizeof(singleTable)) != sizeof(singleTable))
return BALKAN_ERROR_ERRNO;
if (be16_to_cpu(singleTable.magic) != SUN_LABEL_MAGIC)
return BALKAN_ERROR_BADMAGIC;
for (p = (unsigned short *)&singleTable, csum = 0;
p < (unsigned short *)(&singleTable+1);)
csum ^= *p++;
if (csum)
return BALKAN_ERROR_BADMAGIC;
for (i = 0; i < 8; i++) {
if (!singleTable.parts[i].num_sectors) continue;
table->parts[i].startSector =
be32_to_cpu(singleTable.parts[i].start_cylinder) *
be16_to_cpu(singleTable.nsect) *
be16_to_cpu(singleTable.ntrks);
table->parts[i].size =
be32_to_cpu(singleTable.parts[i].num_sectors);
table->parts[i].type = singleTable.infos[i].id;
}
for (i = 0; i < 8; i++) {
if (table->parts[i].type == -1) continue;
switch (table->parts[i].type) {
case 0x83:
table->parts[i].type = BALKAN_PART_EXT2;
break;
case 0x82:
table->parts[i].type = BALKAN_PART_SWAP;
break;
default:
if (table->parts[i].type != WHOLE_DISK &&
llseek(fd, (8192 + 0x55c + SECTOR_SIZE *
(unsigned long long)table->parts[i].startSector),
SEEK_SET) >= 0 &&
read(fd, &magic, 4) == 4 &&
(magic == UFS_SUPER_MAGIC ||
swab32(magic) == UFS_SUPER_MAGIC))
table->parts[i].type = BALKAN_PART_UFS;
else
table->parts[i].type = BALKAN_PART_OTHER;
break;
}
}
return 0;
}
#ifdef STANDALONE_TEST
void main() {
int fd;
int i;
struct partitionTable table;
fd = open("/dev/hda", O_RDONLY);
printf("rc= %d\n", sunpReadTable(fd, &table));
for (i = 0; i < table.maxNumPartitions; i++) {
if (table.parts[i].type == -1) continue;
printf("%d: %x %d\n", i, table.parts[i].type, table.parts[i].size);
}
}
#endif