function old new delta nowarn 1 - -1 listing 1 - -1 dos_compatible_flag 1 - -1 warn_cylinders 44 42 -2 open_list_and_close 364 362 -2 fdisk_fatal 41 38 -3 verify 1053 1049 -4 user_sectors 4 - -4 user_heads 4 - -4 user_cylinders 4 - -4 pt_sectors 4 - -4 pt_heads 4 - -4 kern_sectors 4 - -4 kern_heads 4 - -4 ext_index 4 - -4 total_number_of_sectors 8 - -8 extended_offset 8 - -8 create_doslabel 129 120 -9 write_table 225 211 -14 delete_partition 445 431 -14 set_partition 476 459 -17 list_disk_geometry 247 229 -18 unable_to_write 19 - -19 add_partition 2515 2486 -29 get_boot 1709 1636 -73 fdisk_main 2812 2679 -133 ------------------------------------------------------------------------------ (add/remove: 0/14 grow/shrink: 0/12 up/down: 0/-388) Total: -388 bytes text data bss dec hex filename 804634 611 6852 812097 c6441 busybox_old 804298 610 6804 811712 c62c0 busybox_unstripped
		
			
				
	
	
		
			887 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			887 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#if ENABLE_FEATURE_SGI_LABEL
 | 
						|
 | 
						|
#define SGI_DEBUG 0
 | 
						|
 | 
						|
/*
 | 
						|
 * Copyright (C) Andreas Neuper, Sep 1998.
 | 
						|
 *      This file may be modified and redistributed under
 | 
						|
 *      the terms of the GNU Public License.
 | 
						|
 */
 | 
						|
 | 
						|
#define SGI_VOLHDR      0x00
 | 
						|
/* 1 and 2 were used for drive types no longer supported by SGI */
 | 
						|
#define SGI_SWAP        0x03
 | 
						|
/* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
 | 
						|
#define SGI_VOLUME      0x06
 | 
						|
#define SGI_EFS         0x07
 | 
						|
#define SGI_LVOL        0x08
 | 
						|
#define SGI_RLVOL       0x09
 | 
						|
#define SGI_XFS         0x0a
 | 
						|
#define SGI_XFSLOG      0x0b
 | 
						|
#define SGI_XLV         0x0c
 | 
						|
#define SGI_XVM         0x0d
 | 
						|
#define SGI_ENTIRE_DISK SGI_VOLUME
 | 
						|
 | 
						|
struct device_parameter { /* 48 bytes */
 | 
						|
	unsigned char  skew;
 | 
						|
	unsigned char  gap1;
 | 
						|
	unsigned char  gap2;
 | 
						|
	unsigned char  sparecyl;
 | 
						|
	unsigned short pcylcount;
 | 
						|
	unsigned short head_vol0;
 | 
						|
	unsigned short ntrks;   /* tracks in cyl 0 or vol 0 */
 | 
						|
	unsigned char  cmd_tag_queue_depth;
 | 
						|
	unsigned char  unused0;
 | 
						|
	unsigned short unused1;
 | 
						|
	unsigned short nsect;   /* sectors/tracks in cyl 0 or vol 0 */
 | 
						|
	unsigned short bytes;
 | 
						|
	unsigned short ilfact;
 | 
						|
	unsigned int   flags;           /* controller flags */
 | 
						|
	unsigned int   datarate;
 | 
						|
	unsigned int   retries_on_error;
 | 
						|
	unsigned int   ms_per_word;
 | 
						|
	unsigned short xylogics_gap1;
 | 
						|
	unsigned short xylogics_syncdelay;
 | 
						|
	unsigned short xylogics_readdelay;
 | 
						|
	unsigned short xylogics_gap2;
 | 
						|
	unsigned short xylogics_readgate;
 | 
						|
	unsigned short xylogics_writecont;
 | 
						|
};
 | 
						|
 | 
						|
/*
 | 
						|
 * controller flags
 | 
						|
 */
 | 
						|
#define SECTOR_SLIP     0x01
 | 
						|
#define SECTOR_FWD      0x02
 | 
						|
#define TRACK_FWD       0x04
 | 
						|
#define TRACK_MULTIVOL  0x08
 | 
						|
#define IGNORE_ERRORS   0x10
 | 
						|
#define RESEEK          0x20
 | 
						|
#define ENABLE_CMDTAGQ  0x40
 | 
						|
 | 
						|
typedef struct {
 | 
						|
	unsigned int   magic;            /* expect SGI_LABEL_MAGIC */
 | 
						|
	unsigned short boot_part;        /* active boot partition */
 | 
						|
	unsigned short swap_part;        /* active swap partition */
 | 
						|
	unsigned char  boot_file[16];    /* name of the bootfile */
 | 
						|
	struct device_parameter devparam;       /*  1 * 48 bytes */
 | 
						|
	struct volume_directory {               /* 15 * 16 bytes */
 | 
						|
		unsigned char vol_file_name[8]; /* a character array */
 | 
						|
		unsigned int  vol_file_start;   /* number of logical block */
 | 
						|
		unsigned int  vol_file_size;    /* number of bytes */
 | 
						|
	} directory[15];
 | 
						|
	struct sgi_partinfo {                  /* 16 * 12 bytes */
 | 
						|
		unsigned int num_sectors;       /* number of blocks */
 | 
						|
		unsigned int start_sector;      /* must be cylinder aligned */
 | 
						|
		unsigned int id;
 | 
						|
	} partitions[16];
 | 
						|
	unsigned int   csum;
 | 
						|
	unsigned int   fillbytes;
 | 
						|
} sgi_partition;
 | 
						|
 | 
						|
typedef struct {
 | 
						|
	unsigned int   magic;           /* looks like a magic number */
 | 
						|
	unsigned int   a2;
 | 
						|
	unsigned int   a3;
 | 
						|
	unsigned int   a4;
 | 
						|
	unsigned int   b1;
 | 
						|
	unsigned short b2;
 | 
						|
	unsigned short b3;
 | 
						|
	unsigned int   c[16];
 | 
						|
	unsigned short d[3];
 | 
						|
	unsigned char  scsi_string[50];
 | 
						|
	unsigned char  serial[137];
 | 
						|
	unsigned short check1816;
 | 
						|
	unsigned char  installer[225];
 | 
						|
} sgiinfo;
 | 
						|
 | 
						|
#define SGI_LABEL_MAGIC         0x0be5a941
 | 
						|
#define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
 | 
						|
#define SGI_INFO_MAGIC          0x00072959
 | 
						|
#define SGI_INFO_MAGIC_SWAPPED  0x59290700
 | 
						|
 | 
						|
#define SGI_SSWAP16(x) (sgi_other_endian ? fdisk_swap16(x) : (uint16_t)(x))
 | 
						|
#define SGI_SSWAP32(x) (sgi_other_endian ? fdisk_swap32(x) : (uint32_t)(x))
 | 
						|
 | 
						|
#define sgilabel ((sgi_partition *)MBRbuffer)
 | 
						|
#define sgiparam (sgilabel->devparam)
 | 
						|
 | 
						|
/*
 | 
						|
 *
 | 
						|
 * fdisksgilabel.c
 | 
						|
 *
 | 
						|
 * Copyright (C) Andreas Neuper, Sep 1998.
 | 
						|
 *      This file may be modified and redistributed under
 | 
						|
 *      the terms of the GNU Public License.
 | 
						|
 *
 | 
						|
 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
 | 
						|
 *      Internationalization
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
static smallint sgi_other_endian; /* bool */
 | 
						|
static smallint sgi_volumes = 1; /* max 15 */
 | 
						|
 | 
						|
/*
 | 
						|
 * only dealing with free blocks here
 | 
						|
 */
 | 
						|
 | 
						|
typedef struct {
 | 
						|
	unsigned int first;
 | 
						|
	unsigned int last;
 | 
						|
} freeblocks;
 | 
						|
static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
 | 
						|
 | 
						|
static void
 | 
						|
setfreelist(int i, unsigned int f, unsigned int l)
 | 
						|
{
 | 
						|
	freelist[i].first = f;
 | 
						|
	freelist[i].last = l;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
add2freelist(unsigned int f, unsigned int l)
 | 
						|
{
 | 
						|
	int i;
 | 
						|
	for (i = 0; i < 17; i++)
 | 
						|
		if (freelist[i].last == 0)
 | 
						|
			break;
 | 
						|
	setfreelist(i, f, l);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
clearfreelist(void)
 | 
						|
{
 | 
						|
	int i;
 | 
						|
 | 
						|
	for (i = 0; i < 17; i++)
 | 
						|
		setfreelist(i, 0, 0);
 | 
						|
}
 | 
						|
 | 
						|
static unsigned int
 | 
						|
isinfreelist(unsigned int b)
 | 
						|
{
 | 
						|
	int i;
 | 
						|
 | 
						|
	for (i = 0; i < 17; i++)
 | 
						|
		if (freelist[i].first <= b && freelist[i].last >= b)
 | 
						|
			return freelist[i].last;
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
	/* return last vacant block of this stride (never 0). */
 | 
						|
	/* the '>=' is not quite correct, but simplifies the code */
 | 
						|
/*
 | 
						|
 * end of free blocks section
 | 
						|
 */
 | 
						|
 | 
						|
static const char *const sgi_sys_types[] = {
 | 
						|
/* SGI_VOLHDR   */	"\x00" "SGI volhdr"  ,
 | 
						|
/* 0x01         */	"\x01" "SGI trkrepl" ,
 | 
						|
/* 0x02         */	"\x02" "SGI secrepl" ,
 | 
						|
/* SGI_SWAP     */	"\x03" "SGI raw"     ,
 | 
						|
/* 0x04         */	"\x04" "SGI bsd"     ,
 | 
						|
/* 0x05         */	"\x05" "SGI sysv"    ,
 | 
						|
/* SGI_ENTIRE_DISK  */	"\x06" "SGI volume"  ,
 | 
						|
/* SGI_EFS      */	"\x07" "SGI efs"     ,
 | 
						|
/* 0x08         */	"\x08" "SGI lvol"    ,
 | 
						|
/* 0x09         */	"\x09" "SGI rlvol"   ,
 | 
						|
/* SGI_XFS      */	"\x0a" "SGI xfs"     ,
 | 
						|
/* SGI_XFSLOG   */	"\x0b" "SGI xfslog"  ,
 | 
						|
/* SGI_XLV      */	"\x0c" "SGI xlv"     ,
 | 
						|
/* SGI_XVM      */	"\x0d" "SGI xvm"     ,
 | 
						|
/* LINUX_SWAP   */	"\x82" "Linux swap"  ,
 | 
						|
/* LINUX_NATIVE */	"\x83" "Linux native",
 | 
						|
/* LINUX_LVM    */	"\x8d" "Linux LVM"   ,
 | 
						|
/* LINUX_RAID   */	"\xfd" "Linux RAID"  ,
 | 
						|
			NULL
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
sgi_get_nsect(void)
 | 
						|
{
 | 
						|
	return SGI_SSWAP16(sgilabel->devparam.nsect);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
sgi_get_ntrks(void)
 | 
						|
{
 | 
						|
	return SGI_SSWAP16(sgilabel->devparam.ntrks);
 | 
						|
}
 | 
						|
 | 
						|
static unsigned int
 | 
						|
two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */)
 | 
						|
{
 | 
						|
	int i = 0;
 | 
						|
	unsigned int sum = 0;
 | 
						|
 | 
						|
	size /= sizeof(unsigned int);
 | 
						|
	for (i = 0; i < size; i++)
 | 
						|
		sum -= SGI_SSWAP32(base[i]);
 | 
						|
	return sum;
 | 
						|
}
 | 
						|
 | 
						|
void BUG_bad_sgi_partition_size(void);
 | 
						|
 | 
						|
static int
 | 
						|
check_sgi_label(void)
 | 
						|
{
 | 
						|
	if (sizeof(sgi_partition) > 512) {
 | 
						|
		/* According to MIPS Computer Systems, Inc the label
 | 
						|
		 * must not contain more than 512 bytes */
 | 
						|
		BUG_bad_sgi_partition_size();
 | 
						|
	}
 | 
						|
 | 
						|
	if (sgilabel->magic != SGI_LABEL_MAGIC
 | 
						|
	 && sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED
 | 
						|
	) {
 | 
						|
		current_label_type = LABEL_DOS;
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
 | 
						|
	/*
 | 
						|
	 * test for correct checksum
 | 
						|
	 */
 | 
						|
	if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
 | 
						|
				sizeof(*sgilabel))) {
 | 
						|
		printf("Detected sgi disklabel with wrong checksum\n");
 | 
						|
	}
 | 
						|
	update_units();
 | 
						|
	current_label_type = LABEL_SGI;
 | 
						|
	g_partitions = 16;
 | 
						|
	sgi_volumes = 15;
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static unsigned int
 | 
						|
sgi_get_start_sector(int i)
 | 
						|
{
 | 
						|
	return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
 | 
						|
}
 | 
						|
 | 
						|
static unsigned int
 | 
						|
sgi_get_num_sectors(int i)
 | 
						|
{
 | 
						|
	return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
sgi_get_sysid(int i)
 | 
						|
{
 | 
						|
	return SGI_SSWAP32(sgilabel->partitions[i].id);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
sgi_get_bootpartition(void)
 | 
						|
{
 | 
						|
	return SGI_SSWAP16(sgilabel->boot_part);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
sgi_get_swappartition(void)
 | 
						|
{
 | 
						|
	return SGI_SSWAP16(sgilabel->swap_part);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
sgi_list_table(int xtra)
 | 
						|
{
 | 
						|
	int i, w, wd;
 | 
						|
	int kpi = 0;                /* kernel partition ID */
 | 
						|
 | 
						|
	if (xtra) {
 | 
						|
		printf("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
 | 
						|
			"%d cylinders, %d physical cylinders\n"
 | 
						|
			"%d extra sects/cyl, interleave %d:1\n"
 | 
						|
			"%s\n"
 | 
						|
			"Units = %s of %d * 512 bytes\n\n",
 | 
						|
			disk_device, g_heads, g_sectors, g_cylinders,
 | 
						|
			SGI_SSWAP16(sgiparam.pcylcount),
 | 
						|
			SGI_SSWAP16(sgiparam.sparecyl),
 | 
						|
			SGI_SSWAP16(sgiparam.ilfact),
 | 
						|
			(char *)sgilabel,
 | 
						|
			str_units(PLURAL), units_per_sector);
 | 
						|
	} else {
 | 
						|
		printf("\nDisk %s (SGI disk label): "
 | 
						|
			"%d heads, %d sectors, %d cylinders\n"
 | 
						|
			"Units = %s of %d * 512 bytes\n\n",
 | 
						|
			disk_device, g_heads, g_sectors, g_cylinders,
 | 
						|
			str_units(PLURAL), units_per_sector );
 | 
						|
	}
 | 
						|
 | 
						|
	w = strlen(disk_device);
 | 
						|
	wd = sizeof("Device") - 1;
 | 
						|
	if (w < wd)
 | 
						|
	w = wd;
 | 
						|
 | 
						|
	printf("----- partitions -----\n"
 | 
						|
		"Pt# %*s  Info     Start       End   Sectors  Id  System\n",
 | 
						|
		w + 2, "Device");
 | 
						|
	for (i = 0; i < g_partitions; i++) {
 | 
						|
		if (sgi_get_num_sectors(i) || SGI_DEBUG) {
 | 
						|
			uint32_t start = sgi_get_start_sector(i);
 | 
						|
			uint32_t len = sgi_get_num_sectors(i);
 | 
						|
			kpi++;              /* only count nonempty partitions */
 | 
						|
			printf(
 | 
						|
			"%2d: %s %4s %9ld %9ld %9ld  %2x  %s\n",
 | 
						|
/* fdisk part number */	i+1,
 | 
						|
/* device */            partname(disk_device, kpi, w+3),
 | 
						|
/* flags */             (sgi_get_swappartition() == i) ? "swap" :
 | 
						|
/* flags */             (sgi_get_bootpartition() == i) ? "boot" : "    ",
 | 
						|
/* start */             (long) scround(start),
 | 
						|
/* end */               (long) scround(start+len)-1,
 | 
						|
/* no odd flag on end */(long) len,
 | 
						|
/* type id */           sgi_get_sysid(i),
 | 
						|
/* type name */         partition_type(sgi_get_sysid(i)));
 | 
						|
		}
 | 
						|
	}
 | 
						|
	printf("----- Bootinfo -----\nBootfile: %s\n"
 | 
						|
		"----- Directory Entries -----\n",
 | 
						|
		sgilabel->boot_file);
 | 
						|
	for (i = 0; i < sgi_volumes; i++) {
 | 
						|
		if (sgilabel->directory[i].vol_file_size) {
 | 
						|
			uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
 | 
						|
			uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
 | 
						|
			unsigned char *name = sgilabel->directory[i].vol_file_name;
 | 
						|
 | 
						|
			printf("%2d: %-10s sector%5u size%8u\n",
 | 
						|
				i, (char*)name, (unsigned int) start, (unsigned int) len);
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
sgi_set_bootpartition(int i)
 | 
						|
{
 | 
						|
	sgilabel->boot_part = SGI_SSWAP16(((short)i));
 | 
						|
}
 | 
						|
 | 
						|
static unsigned int
 | 
						|
sgi_get_lastblock(void)
 | 
						|
{
 | 
						|
	return g_heads * g_sectors * g_cylinders;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
sgi_set_swappartition(int i)
 | 
						|
{
 | 
						|
	sgilabel->swap_part = SGI_SSWAP16(((short)i));
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
sgi_check_bootfile(const char* aFile)
 | 
						|
{
 | 
						|
	if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
 | 
						|
		printf("\nInvalid Bootfile!\n"
 | 
						|
			"\tThe bootfile must be an absolute non-zero pathname,\n"
 | 
						|
			"\te.g. \"/unix\" or \"/unix.save\".\n");
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
	if (strlen(aFile) > 16) {
 | 
						|
		printf("\nName of Bootfile too long (>16 bytes)\n");
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
	if (aFile[0] != '/') {
 | 
						|
		printf("\nBootfile must have a fully qualified pathname\n");
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
	if (strncmp(aFile, (char*)sgilabel->boot_file, 16)) {
 | 
						|
		printf("\nBe aware, that the bootfile is not checked for existence.\n"
 | 
						|
			 "\tSGI's default is \"/unix\" and for backup \"/unix.save\".\n");
 | 
						|
		/* filename is correct and did change */
 | 
						|
		return 1;
 | 
						|
	}
 | 
						|
	return 0;   /* filename did not change */
 | 
						|
}
 | 
						|
 | 
						|
static const char *
 | 
						|
sgi_get_bootfile(void)
 | 
						|
{
 | 
						|
	return (char*)sgilabel->boot_file;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
sgi_set_bootfile(const char* aFile)
 | 
						|
{
 | 
						|
	int i = 0;
 | 
						|
 | 
						|
	if (sgi_check_bootfile(aFile)) {
 | 
						|
		while (i < 16) {
 | 
						|
			if ((aFile[i] != '\n')  /* in principle caught again by next line */
 | 
						|
			 && (strlen(aFile) > i))
 | 
						|
				sgilabel->boot_file[i] = aFile[i];
 | 
						|
			else
 | 
						|
				sgilabel->boot_file[i] = 0;
 | 
						|
			i++;
 | 
						|
		}
 | 
						|
		printf("\n\tBootfile is changed to \"%s\"\n", sgilabel->boot_file);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
create_sgiinfo(void)
 | 
						|
{
 | 
						|
	/* I keep SGI's habit to write the sgilabel to the second block */
 | 
						|
	sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
 | 
						|
	sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
 | 
						|
	strncpy((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8);
 | 
						|
}
 | 
						|
 | 
						|
static sgiinfo *fill_sgiinfo(void);
 | 
						|
 | 
						|
static void
 | 
						|
sgi_write_table(void)
 | 
						|
{
 | 
						|
	sgilabel->csum = 0;
 | 
						|
	sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
 | 
						|
			(unsigned int*)sgilabel, sizeof(*sgilabel)));
 | 
						|
	assert(two_s_complement_32bit_sum(
 | 
						|
		(unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
 | 
						|
 | 
						|
	write_sector(0, sgilabel);
 | 
						|
	if (!strncmp((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
 | 
						|
		/*
 | 
						|
		 * keep this habit of first writing the "sgilabel".
 | 
						|
		 * I never tested whether it works without (AN 981002).
 | 
						|
		 */
 | 
						|
		sgiinfo *info = fill_sgiinfo();
 | 
						|
		int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
 | 
						|
		write_sector(infostartblock, info);
 | 
						|
		free(info);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
compare_start(int *x, int *y)
 | 
						|
{
 | 
						|
	/*
 | 
						|
	 * sort according to start sectors
 | 
						|
	 * and prefers largest partition:
 | 
						|
	 * entry zero is entire disk entry
 | 
						|
	 */
 | 
						|
	unsigned int i = *x;
 | 
						|
	unsigned int j = *y;
 | 
						|
	unsigned int a = sgi_get_start_sector(i);
 | 
						|
	unsigned int b = sgi_get_start_sector(j);
 | 
						|
	unsigned int c = sgi_get_num_sectors(i);
 | 
						|
	unsigned int d = sgi_get_num_sectors(j);
 | 
						|
 | 
						|
	if (a == b)
 | 
						|
		return (d > c) ? 1 : (d == c) ? 0 : -1;
 | 
						|
	return (a > b) ? 1 : -1;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
verify_sgi(int verbose)
 | 
						|
{
 | 
						|
	int Index[16];      /* list of valid partitions */
 | 
						|
	int sortcount = 0;  /* number of used partitions, i.e. non-zero lengths */
 | 
						|
	int entire = 0, i = 0;
 | 
						|
	unsigned int start = 0;
 | 
						|
	long long gap = 0;      /* count unused blocks */
 | 
						|
	unsigned int lastblock = sgi_get_lastblock();
 | 
						|
 | 
						|
	clearfreelist();
 | 
						|
	for (i = 0; i < 16; i++) {
 | 
						|
		if (sgi_get_num_sectors(i) != 0) {
 | 
						|
			Index[sortcount++] = i;
 | 
						|
			if (sgi_get_sysid(i) == SGI_ENTIRE_DISK) {
 | 
						|
				if (entire++ == 1) {
 | 
						|
					if (verbose)
 | 
						|
						printf("More than one entire disk entry present\n");
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if (sortcount == 0) {
 | 
						|
		if (verbose)
 | 
						|
			printf("No partitions defined\n");
 | 
						|
		return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
 | 
						|
	}
 | 
						|
	qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
 | 
						|
	if (sgi_get_sysid(Index[0]) == SGI_ENTIRE_DISK) {
 | 
						|
		if ((Index[0] != 10) && verbose)
 | 
						|
			printf("IRIX likes when Partition 11 covers the entire disk\n");
 | 
						|
		if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
 | 
						|
			printf("The entire disk partition should start "
 | 
						|
				"at block 0,\n"
 | 
						|
				"not at diskblock %d\n",
 | 
						|
				sgi_get_start_sector(Index[0]));
 | 
						|
		if (SGI_DEBUG)      /* I do not understand how some disks fulfil it */
 | 
						|
			if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
 | 
						|
				printf("The entire disk partition is only %d diskblock large,\n"
 | 
						|
					"but the disk is %d diskblocks long\n",
 | 
						|
					sgi_get_num_sectors(Index[0]), lastblock);
 | 
						|
			lastblock = sgi_get_num_sectors(Index[0]);
 | 
						|
	} else {
 | 
						|
		if (verbose)
 | 
						|
			printf("One Partition (#11) should cover the entire disk\n");
 | 
						|
		if (SGI_DEBUG > 2)
 | 
						|
			printf("sysid=%d\tpartition=%d\n",
 | 
						|
				sgi_get_sysid(Index[0]), Index[0]+1);
 | 
						|
	}
 | 
						|
	for (i = 1, start = 0; i < sortcount; i++) {
 | 
						|
		int cylsize = sgi_get_nsect() * sgi_get_ntrks();
 | 
						|
 | 
						|
		if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
 | 
						|
			if (SGI_DEBUG)      /* I do not understand how some disks fulfil it */
 | 
						|
				if (verbose)
 | 
						|
					printf("Partition %d does not start on cylinder boundary\n",
 | 
						|
						Index[i]+1);
 | 
						|
		}
 | 
						|
		if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
 | 
						|
			if (SGI_DEBUG)      /* I do not understand how some disks fulfil it */
 | 
						|
				if (verbose)
 | 
						|
					printf("Partition %d does not end on cylinder boundary\n",
 | 
						|
						Index[i]+1);
 | 
						|
		}
 | 
						|
		/* We cannot handle several "entire disk" entries. */
 | 
						|
		if (sgi_get_sysid(Index[i]) == SGI_ENTIRE_DISK) continue;
 | 
						|
		if (start > sgi_get_start_sector(Index[i])) {
 | 
						|
			if (verbose)
 | 
						|
				printf("Partitions %d and %d overlap by %d sectors\n",
 | 
						|
					Index[i-1]+1, Index[i]+1,
 | 
						|
					start - sgi_get_start_sector(Index[i]));
 | 
						|
			if (gap > 0) gap = -gap;
 | 
						|
			if (gap == 0) gap = -1;
 | 
						|
		}
 | 
						|
		if (start < sgi_get_start_sector(Index[i])) {
 | 
						|
			if (verbose)
 | 
						|
				printf("Unused gap of %8u sectors - sectors %8u-%8u\n",
 | 
						|
					sgi_get_start_sector(Index[i]) - start,
 | 
						|
					start, sgi_get_start_sector(Index[i])-1);
 | 
						|
			gap += sgi_get_start_sector(Index[i]) - start;
 | 
						|
			add2freelist(start, sgi_get_start_sector(Index[i]));
 | 
						|
		}
 | 
						|
		start = sgi_get_start_sector(Index[i])
 | 
						|
			   + sgi_get_num_sectors(Index[i]);
 | 
						|
		if (SGI_DEBUG > 1) {
 | 
						|
			if (verbose)
 | 
						|
				printf("%2d:%12d\t%12d\t%12d\n", Index[i],
 | 
						|
					sgi_get_start_sector(Index[i]),
 | 
						|
					sgi_get_num_sectors(Index[i]),
 | 
						|
					sgi_get_sysid(Index[i]));
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if (start < lastblock) {
 | 
						|
		if (verbose)
 | 
						|
			printf("Unused gap of %8u sectors - sectors %8u-%8u\n",
 | 
						|
				lastblock - start, start, lastblock-1);
 | 
						|
		gap += lastblock - start;
 | 
						|
		add2freelist(start, lastblock);
 | 
						|
	}
 | 
						|
	/*
 | 
						|
	 * Done with arithmetics
 | 
						|
	 * Go for details now
 | 
						|
	 */
 | 
						|
	if (verbose) {
 | 
						|
		if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
 | 
						|
			printf("\nThe boot partition does not exist\n");
 | 
						|
		}
 | 
						|
		if (!sgi_get_num_sectors(sgi_get_swappartition())) {
 | 
						|
			printf("\nThe swap partition does not exist\n");
 | 
						|
		} else {
 | 
						|
			if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
 | 
						|
			 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
 | 
						|
				printf("\nThe swap partition has no swap type\n");
 | 
						|
		}
 | 
						|
		if (sgi_check_bootfile("/unix"))
 | 
						|
			printf("\tYou have chosen an unusual boot file name\n");
 | 
						|
	}
 | 
						|
	return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
sgi_gaps(void)
 | 
						|
{
 | 
						|
	/*
 | 
						|
	 * returned value is:
 | 
						|
	 *  = 0 : disk is properly filled to the rim
 | 
						|
	 *  < 0 : there is an overlap
 | 
						|
	 *  > 0 : there is still some vacant space
 | 
						|
	 */
 | 
						|
	return verify_sgi(0);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
sgi_change_sysid(int i, int sys)
 | 
						|
{
 | 
						|
	if (sgi_get_num_sectors(i) == 0) { /* caught already before, ... */
 | 
						|
		printf("Sorry you may change the Tag of non-empty partitions\n");
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if ((sys != SGI_ENTIRE_DISK) && (sys != SGI_VOLHDR)
 | 
						|
	 && (sgi_get_start_sector(i) < 1)
 | 
						|
	) {
 | 
						|
		read_maybe_empty(
 | 
						|
			"It is highly recommended that the partition at offset 0\n"
 | 
						|
			"is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
 | 
						|
			"retrieve from its directory standalone tools like sash and fx.\n"
 | 
						|
			"Only the \"SGI volume\" entire disk section may violate this.\n"
 | 
						|
			"Type YES if you are sure about tagging this partition differently.\n");
 | 
						|
		if (strcmp(line_ptr, "YES\n") != 0)
 | 
						|
			return;
 | 
						|
	}
 | 
						|
	sgilabel->partitions[i].id = SGI_SSWAP32(sys);
 | 
						|
}
 | 
						|
 | 
						|
/* returns partition index of first entry marked as entire disk */
 | 
						|
static int
 | 
						|
sgi_entire(void)
 | 
						|
{
 | 
						|
	int i;
 | 
						|
 | 
						|
	for (i = 0; i < 16; i++)
 | 
						|
		if (sgi_get_sysid(i) == SGI_VOLUME)
 | 
						|
			return i;
 | 
						|
	return -1;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
sgi_set_partition(int i, unsigned int start, unsigned int length, int sys)
 | 
						|
{
 | 
						|
	sgilabel->partitions[i].id = SGI_SSWAP32(sys);
 | 
						|
	sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
 | 
						|
	sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
 | 
						|
	set_changed(i);
 | 
						|
	if (sgi_gaps() < 0)     /* rebuild freelist */
 | 
						|
		printf("Partition overlap detected\n");
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
sgi_set_entire(void)
 | 
						|
{
 | 
						|
	int n;
 | 
						|
 | 
						|
	for (n = 10; n < g_partitions; n++) {
 | 
						|
		if (!sgi_get_num_sectors(n) ) {
 | 
						|
			sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
sgi_set_volhdr(void)
 | 
						|
{
 | 
						|
	int n;
 | 
						|
 | 
						|
	for (n = 8; n < g_partitions; n++) {
 | 
						|
	if (!sgi_get_num_sectors(n)) {
 | 
						|
		/*
 | 
						|
		 * 5 cylinders is an arbitrary value I like
 | 
						|
		 * IRIX 5.3 stored files in the volume header
 | 
						|
		 * (like sash, symmon, fx, ide) with ca. 3200
 | 
						|
		 * sectors.
 | 
						|
		 */
 | 
						|
		if (g_heads * g_sectors * 5 < sgi_get_lastblock())
 | 
						|
			sgi_set_partition(n, 0, g_heads * g_sectors * 5, SGI_VOLHDR);
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
sgi_delete_partition(int i)
 | 
						|
{
 | 
						|
	sgi_set_partition(i, 0, 0, 0);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
sgi_add_partition(int n, int sys)
 | 
						|
{
 | 
						|
	char mesg[256];
 | 
						|
	unsigned int first = 0, last = 0;
 | 
						|
 | 
						|
	if (n == 10) {
 | 
						|
		sys = SGI_VOLUME;
 | 
						|
	} else if (n == 8) {
 | 
						|
		sys = 0;
 | 
						|
	}
 | 
						|
	if (sgi_get_num_sectors(n)) {
 | 
						|
		printf(msg_part_already_defined, n + 1);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if ((sgi_entire() == -1) && (sys != SGI_VOLUME)) {
 | 
						|
		printf("Attempting to generate entire disk entry automatically\n");
 | 
						|
		sgi_set_entire();
 | 
						|
		sgi_set_volhdr();
 | 
						|
	}
 | 
						|
	if ((sgi_gaps() == 0) && (sys != SGI_VOLUME)) {
 | 
						|
		printf("The entire disk is already covered with partitions\n");
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if (sgi_gaps() < 0) {
 | 
						|
		printf("You got a partition overlap on the disk. Fix it first!\n");
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR));
 | 
						|
	while (1) {
 | 
						|
		if (sys == SGI_VOLUME) {
 | 
						|
			last = sgi_get_lastblock();
 | 
						|
			first = read_int(0, 0, last-1, 0, mesg);
 | 
						|
			if (first != 0) {
 | 
						|
				printf("It is highly recommended that eleventh partition\n"
 | 
						|
						"covers the entire disk and is of type 'SGI volume'\n");
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			first = freelist[0].first;
 | 
						|
			last  = freelist[0].last;
 | 
						|
			first = read_int(scround(first), scround(first), scround(last)-1,
 | 
						|
				0, mesg);
 | 
						|
		}
 | 
						|
		if (display_in_cyl_units)
 | 
						|
			first *= units_per_sector;
 | 
						|
		else
 | 
						|
			first = first; /* align to cylinder if you know how ... */
 | 
						|
		if (!last )
 | 
						|
			last = isinfreelist(first);
 | 
						|
		if (last != 0)
 | 
						|
			break;
 | 
						|
		printf("You will get a partition overlap on the disk. "
 | 
						|
				"Fix it first!\n");
 | 
						|
	}
 | 
						|
	snprintf(mesg, sizeof(mesg), " Last %s", str_units(SINGULAR));
 | 
						|
	last = read_int(scround(first), scround(last)-1, scround(last)-1,
 | 
						|
			scround(first), mesg)+1;
 | 
						|
	if (display_in_cyl_units)
 | 
						|
		last *= units_per_sector;
 | 
						|
	else
 | 
						|
		last = last; /* align to cylinder if You know how ... */
 | 
						|
	if ( (sys == SGI_VOLUME) && (first != 0 || last != sgi_get_lastblock() ) )
 | 
						|
		printf("It is highly recommended that eleventh partition\n"
 | 
						|
			"covers the entire disk and is of type 'SGI volume'\n");
 | 
						|
	sgi_set_partition(n, first, last-first, sys);
 | 
						|
}
 | 
						|
 | 
						|
#if ENABLE_FEATURE_FDISK_ADVANCED
 | 
						|
static void
 | 
						|
create_sgilabel(void)
 | 
						|
{
 | 
						|
	struct hd_geometry geometry;
 | 
						|
	struct {
 | 
						|
		unsigned int start;
 | 
						|
		unsigned int nsect;
 | 
						|
		int sysid;
 | 
						|
	} old[4];
 | 
						|
	int i = 0;
 | 
						|
	long longsectors;               /* the number of sectors on the device */
 | 
						|
	int res;                        /* the result from the ioctl */
 | 
						|
	int sec_fac;                    /* the sector factor */
 | 
						|
 | 
						|
	sec_fac = sector_size / 512;    /* determine the sector factor */
 | 
						|
 | 
						|
	printf(msg_building_new_label, "SGI disklabel");
 | 
						|
 | 
						|
	sgi_other_endian = BB_LITTLE_ENDIAN;
 | 
						|
	res = ioctl(dev_fd, BLKGETSIZE, &longsectors);
 | 
						|
	if (!ioctl(dev_fd, HDIO_GETGEO, &geometry)) {
 | 
						|
		g_heads = geometry.heads;
 | 
						|
		g_sectors = geometry.sectors;
 | 
						|
		if (res == 0) {
 | 
						|
			/* the get device size ioctl was successful */
 | 
						|
			g_cylinders = longsectors / (g_heads * g_sectors);
 | 
						|
			g_cylinders /= sec_fac;
 | 
						|
		} else {
 | 
						|
			/* otherwise print error and use truncated version */
 | 
						|
			g_cylinders = geometry.cylinders;
 | 
						|
			printf(
 | 
						|
"Warning: BLKGETSIZE ioctl failed on %s.  Using geometry cylinder value of %d.\n"
 | 
						|
"This value may be truncated for devices > 33.8 GB.\n", disk_device, g_cylinders);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	for (i = 0; i < 4; i++) {
 | 
						|
		old[i].sysid = 0;
 | 
						|
		if (valid_part_table_flag(MBRbuffer)) {
 | 
						|
			if (get_part_table(i)->sys_ind) {
 | 
						|
				old[i].sysid = get_part_table(i)->sys_ind;
 | 
						|
				old[i].start = get_start_sect(get_part_table(i));
 | 
						|
				old[i].nsect = get_nr_sects(get_part_table(i));
 | 
						|
				printf("Trying to keep parameters of partition %d\n", i);
 | 
						|
				if (SGI_DEBUG)
 | 
						|
					printf("ID=%02x\tSTART=%d\tLENGTH=%d\n",
 | 
						|
				old[i].sysid, old[i].start, old[i].nsect);
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	memset(MBRbuffer, 0, sizeof(MBRbuffer));
 | 
						|
	/* fields with '//' are already zeroed out by memset above */
 | 
						|
 | 
						|
	sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
 | 
						|
	//sgilabel->boot_part = SGI_SSWAP16(0);
 | 
						|
	sgilabel->swap_part = SGI_SSWAP16(1);
 | 
						|
 | 
						|
	//memset(sgilabel->boot_file, 0, 16);
 | 
						|
	strcpy((char*)sgilabel->boot_file, "/unix"); /* sizeof(sgilabel->boot_file) == 16 > 6 */
 | 
						|
 | 
						|
	//sgilabel->devparam.skew                     = (0);
 | 
						|
	//sgilabel->devparam.gap1                     = (0);
 | 
						|
	//sgilabel->devparam.gap2                     = (0);
 | 
						|
	//sgilabel->devparam.sparecyl                 = (0);
 | 
						|
	sgilabel->devparam.pcylcount                = SGI_SSWAP16(geometry.cylinders);
 | 
						|
	//sgilabel->devparam.head_vol0                = SGI_SSWAP16(0);
 | 
						|
	/* tracks/cylinder (heads) */
 | 
						|
	sgilabel->devparam.ntrks                    = SGI_SSWAP16(geometry.heads);
 | 
						|
	//sgilabel->devparam.cmd_tag_queue_depth      = (0);
 | 
						|
	//sgilabel->devparam.unused0                  = (0);
 | 
						|
	//sgilabel->devparam.unused1                  = SGI_SSWAP16(0);
 | 
						|
	/* sectors/track */
 | 
						|
	sgilabel->devparam.nsect                    = SGI_SSWAP16(geometry.sectors);
 | 
						|
	sgilabel->devparam.bytes                    = SGI_SSWAP16(512);
 | 
						|
	sgilabel->devparam.ilfact                   = SGI_SSWAP16(1);
 | 
						|
	sgilabel->devparam.flags                    = SGI_SSWAP32(TRACK_FWD|
 | 
						|
							IGNORE_ERRORS|RESEEK);
 | 
						|
	//sgilabel->devparam.datarate                 = SGI_SSWAP32(0);
 | 
						|
	sgilabel->devparam.retries_on_error         = SGI_SSWAP32(1);
 | 
						|
	//sgilabel->devparam.ms_per_word              = SGI_SSWAP32(0);
 | 
						|
	//sgilabel->devparam.xylogics_gap1            = SGI_SSWAP16(0);
 | 
						|
	//sgilabel->devparam.xylogics_syncdelay       = SGI_SSWAP16(0);
 | 
						|
	//sgilabel->devparam.xylogics_readdelay       = SGI_SSWAP16(0);
 | 
						|
	//sgilabel->devparam.xylogics_gap2            = SGI_SSWAP16(0);
 | 
						|
	//sgilabel->devparam.xylogics_readgate        = SGI_SSWAP16(0);
 | 
						|
	//sgilabel->devparam.xylogics_writecont       = SGI_SSWAP16(0);
 | 
						|
	//memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
 | 
						|
	//memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partinfo)*16 );
 | 
						|
	current_label_type = LABEL_SGI;
 | 
						|
	g_partitions = 16;
 | 
						|
	sgi_volumes = 15;
 | 
						|
	sgi_set_entire();
 | 
						|
	sgi_set_volhdr();
 | 
						|
	for (i = 0; i < 4; i++) {
 | 
						|
		if (old[i].sysid) {
 | 
						|
			sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
sgi_set_xcyl(void)
 | 
						|
{
 | 
						|
	/* do nothing in the beginning */
 | 
						|
}
 | 
						|
#endif /* FEATURE_FDISK_ADVANCED */
 | 
						|
 | 
						|
/* _____________________________________________________________
 | 
						|
 */
 | 
						|
 | 
						|
static sgiinfo *
 | 
						|
fill_sgiinfo(void)
 | 
						|
{
 | 
						|
	sgiinfo *info = xzalloc(sizeof(sgiinfo));
 | 
						|
 | 
						|
	info->magic = SGI_SSWAP32(SGI_INFO_MAGIC);
 | 
						|
	info->b1 = SGI_SSWAP32(-1);
 | 
						|
	info->b2 = SGI_SSWAP16(-1);
 | 
						|
	info->b3 = SGI_SSWAP16(1);
 | 
						|
	/* You may want to replace this string !!!!!!! */
 | 
						|
	strcpy( (char*)info->scsi_string, "IBM OEM 0662S12         3 30" );
 | 
						|
	strcpy( (char*)info->serial, "0000" );
 | 
						|
	info->check1816 = SGI_SSWAP16(18*256 +16 );
 | 
						|
	strcpy( (char*)info->installer, "Sfx version 5.3, Oct 18, 1994" );
 | 
						|
	return info;
 | 
						|
}
 | 
						|
#endif /* SGI_LABEL */
 |