mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-09 04:21:49 +08:00
68ed285428
Since we require C11 now, we can assume many headers exist, and clean up all of the conditional includes. It's not like any of this code actually accounted for the headers not existing, just whether we could include them. The strings.h cleanup is a little nuanced: it isn't in C11, but every use of it in the codebase will include strings.h only if string.h doesn't exist. Since we now assume the C11 string.h exists, we'll never include strings.h, so we can delete it.
397 lines
11 KiB
C
397 lines
11 KiB
C
/* This file is part of the program psim.
|
|
|
|
Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
#ifndef _PK_DISKLABEL_C_
|
|
#define _PK_DISKLABEL_C_
|
|
|
|
#ifndef STATIC_INLINE_PK_DISKLABEL
|
|
#define STATIC_INLINE_PK_DISKLABEL STATIC_INLINE
|
|
#endif
|
|
|
|
#include "device_table.h"
|
|
|
|
#include "pk.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
/* PACKAGE
|
|
|
|
disk-label - all knowing disk I/O package
|
|
|
|
DESCRIPTION
|
|
|
|
The disk-label package provides a generic interface to disk
|
|
devices. It uses the arguments specified when an instance is being
|
|
created to determine if the raw disk, a partition, or a file within
|
|
a partition should be opened.
|
|
|
|
An instance create call to disk-label could result, for instance,
|
|
in the opening of a DOS file system contained within a dos
|
|
partition contained within a physical disk.
|
|
|
|
*/
|
|
|
|
/* taken from bfd/ppcboot.c by Michael Meissner */
|
|
|
|
/* PPCbug location structure */
|
|
typedef struct ppcboot_location {
|
|
unsigned8 ind;
|
|
unsigned8 head;
|
|
unsigned8 sector;
|
|
unsigned8 cylinder;
|
|
} ppcboot_location_t;
|
|
|
|
/* PPCbug partition table layout */
|
|
typedef struct ppcboot_partition {
|
|
ppcboot_location_t partition_begin; /* partition begin */
|
|
ppcboot_location_t partition_end; /* partition end */
|
|
unsigned8 sector_begin[4]; /* 32-bit start RBA (zero-based), little endian */
|
|
unsigned8 sector_length[4]; /* 32-bit RBA count (one-based), little endian */
|
|
} ppcboot_partition_t;
|
|
|
|
#if 0
|
|
/* PPCbug boot layout. */
|
|
typedef struct ppcboot_hdr {
|
|
unsigned8 pc_compatibility[446]; /* x86 instruction field */
|
|
ppcboot_partition_t partition[4]; /* partition information */
|
|
unsigned8 signature[2]; /* 0x55 and 0xaa */
|
|
unsigned8 entry_offset[4]; /* entry point offset, little endian */
|
|
unsigned8 length[4]; /* load image length, little endian */
|
|
unsigned8 flags; /* flag field */
|
|
unsigned8 os_id; /* OS_ID */
|
|
char partition_name[32]; /* partition name */
|
|
unsigned8 reserved1[470]; /* reserved */
|
|
} ppcboot_hdr_t;
|
|
#endif
|
|
|
|
|
|
typedef struct _disklabel {
|
|
device_instance *parent;
|
|
device_instance *raw_disk;
|
|
unsigned_word pos;
|
|
unsigned_word sector_begin;
|
|
unsigned_word sector_length;
|
|
} disklabel;
|
|
|
|
|
|
static unsigned_word
|
|
sector2uw(unsigned8 s[4])
|
|
{
|
|
return ((s[3] << 24)
|
|
+ (s[2] << 16)
|
|
+ (s[1] << 8)
|
|
+ (s[0] << 0));
|
|
}
|
|
|
|
|
|
static void
|
|
disklabel_delete(device_instance *instance)
|
|
{
|
|
disklabel *label = device_instance_data(instance);
|
|
device_instance_delete(label->raw_disk);
|
|
free(label);
|
|
}
|
|
|
|
|
|
static int
|
|
disklabel_read(device_instance *instance,
|
|
void *buf,
|
|
unsigned_word len)
|
|
{
|
|
disklabel *label = device_instance_data(instance);
|
|
int nr_read;
|
|
if (label->pos + len > label->sector_length)
|
|
len = label->sector_length - label->pos;
|
|
if (device_instance_seek(label->raw_disk, 0,
|
|
label->sector_begin + label->pos) < 0)
|
|
return -1;
|
|
nr_read = device_instance_read(label->raw_disk, buf, len);
|
|
if (nr_read > 0)
|
|
label->pos += nr_read;
|
|
return nr_read;
|
|
}
|
|
|
|
static int
|
|
disklabel_write(device_instance *instance,
|
|
const void *buf,
|
|
unsigned_word len)
|
|
{
|
|
disklabel *label = device_instance_data(instance);
|
|
int nr_written;
|
|
if (label->pos + len > label->sector_length)
|
|
len = label->sector_length - label->pos;
|
|
if (device_instance_seek(label->raw_disk, 0,
|
|
label->sector_begin + label->pos) < 0)
|
|
return -1;
|
|
nr_written = device_instance_write(label->raw_disk, buf, len);
|
|
if (nr_written > 0)
|
|
label->pos += nr_written;
|
|
return nr_written;
|
|
}
|
|
|
|
static int
|
|
disklabel_seek(device_instance *instance,
|
|
unsigned_word pos_hi,
|
|
unsigned_word pos_lo)
|
|
{
|
|
disklabel *label = device_instance_data(instance);
|
|
if (pos_lo >= label->sector_length || pos_hi != 0)
|
|
return -1;
|
|
label->pos = pos_lo;
|
|
return 0;
|
|
}
|
|
|
|
|
|
static const device_instance_callbacks package_disklabel_callbacks = {
|
|
disklabel_delete,
|
|
disklabel_read,
|
|
disklabel_write,
|
|
disklabel_seek,
|
|
};
|
|
|
|
/* Reconize different types of boot block */
|
|
|
|
static int
|
|
block0_is_bpb(const unsigned8 block[])
|
|
{
|
|
const char ebdic_ibma[] = { 0xc9, 0xc2, 0xd4, 0xc1 };
|
|
/* ref PowerPC Microprocessor CHRP bindings 1.2b - page 47 */
|
|
/* can't start with IBMA */
|
|
if (memcmp(block, ebdic_ibma, sizeof(ebdic_ibma)) == 0)
|
|
return 0;
|
|
/* must have LE 0xAA55 signature at offset 510 */
|
|
if (block[511] != 0xAA && block[510] != 0x55)
|
|
return 0;
|
|
/* valid 16 bit LE bytes per sector - 256, 512, 1024 */
|
|
if (block[11] != 0
|
|
|| (block[12] != 1 && block[12] != 2 && block[12] != 4))
|
|
return 0;
|
|
/* nr fats is 1 or 2 */
|
|
if (block[16] != 1 && block[16] != 2)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
|
|
/* Verify that the device contains an ISO-9660 File system */
|
|
|
|
static int
|
|
is_iso9660(device_instance *raw_disk)
|
|
{
|
|
/* ref PowerPC Microprocessor CHRP bindings 1.2b - page 47 */
|
|
unsigned8 block[512];
|
|
if (device_instance_seek(raw_disk, 0, 512 * 64) < 0)
|
|
return 0;
|
|
if (device_instance_read(raw_disk, block, sizeof(block)) != sizeof(block))
|
|
return 0;
|
|
if (block[0] == 0x01
|
|
&& block[1] == 'C'
|
|
&& block[2] == 'D'
|
|
&& block[3] == '0'
|
|
&& block[4] == '0'
|
|
&& block[5] == '1')
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Verify that the disk block contains a valid DOS partition table.
|
|
While we're at it have a look around for active partitions etc.
|
|
|
|
Return 0: invalid
|
|
Return 1..4: valid, value returned is the first active partition
|
|
Return -1: no active partition */
|
|
|
|
static int
|
|
block0_is_fdisk(const unsigned8 block[])
|
|
{
|
|
const int partition_type_fields[] = { 0, 0x1c2, 0x1d2, 0x1e2, 0x1f2 };
|
|
const int partition_active_fields[] = { 0, 0x1be, 0x1ce, 0x1de, 0xee };
|
|
int partition;
|
|
int active = -1;
|
|
/* ref PowerPC Microprocessor CHRP bindings 1.2b - page 47 */
|
|
/* must have LE 0xAA55 signature at offset 510 */
|
|
if (block[511/*0x1ff*/] != 0xAA && block[510/*0x1fe*/] != 0x55)
|
|
return 0;
|
|
/* must contain valid partition types */
|
|
for (partition = 1; partition <= 4 && active != 0; partition++) {
|
|
int partition_type = block[partition_type_fields[partition]];
|
|
int is_active = block[partition_active_fields[partition]] == 0x80;
|
|
const char *type;
|
|
switch (partition_type) {
|
|
case 0x00:
|
|
type = "UNUSED";
|
|
break;
|
|
case 0x01:
|
|
type = "FAT 12 File system";
|
|
break;
|
|
case 0x04:
|
|
type = "FAT 16 File system";
|
|
break;
|
|
case 0x05:
|
|
case 0x06:
|
|
type = "rejected - extended/chained partition not supported";
|
|
active = 0;
|
|
break;
|
|
case 0x41:
|
|
type = "Single program image";
|
|
break;
|
|
case 0x82:
|
|
type = "Solaris?";
|
|
break;
|
|
case 0x96:
|
|
type = "ISO 9660 File system";
|
|
break;
|
|
default:
|
|
type = "rejected - unknown type";
|
|
active = 0;
|
|
break;
|
|
}
|
|
PTRACE(disklabel, ("partition %d of type 0x%02x - %s%s\n",
|
|
partition,
|
|
partition_type,
|
|
type,
|
|
is_active && active != 0 ? " (active)" : ""));
|
|
if (partition_type != 0 && is_active && active < 0)
|
|
active = partition;
|
|
}
|
|
return active;
|
|
}
|
|
|
|
|
|
/* Verify that block0 corresponds to a MAC disk */
|
|
|
|
static int
|
|
block0_is_mac_disk(const unsigned8 block[])
|
|
{
|
|
/* ref PowerPC Microprocessor CHRP bindings 1.2b - page 47 */
|
|
/* signature - BEx4552 at offset 0 */
|
|
if (block[0] != 0x45 || block[1] != 0x52)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
|
|
/* Open a logical disk/file */
|
|
|
|
device_instance *
|
|
pk_disklabel_create_instance(device_instance *raw_disk,
|
|
const char *args)
|
|
{
|
|
int partition;
|
|
char *filename;
|
|
|
|
/* parse the arguments */
|
|
if (args == NULL) {
|
|
partition = 0;
|
|
filename = NULL;
|
|
}
|
|
else {
|
|
partition = strtoul((char*)args, &filename, 0);
|
|
if (filename == args)
|
|
partition = -1; /* not specified */
|
|
if (*filename == ',')
|
|
filename++;
|
|
if (*filename == '\0')
|
|
filename = NULL; /* easier */
|
|
}
|
|
|
|
if (partition == 0) {
|
|
/* select the raw disk */
|
|
return raw_disk;
|
|
}
|
|
else {
|
|
unsigned8 boot_block[512];
|
|
/* get the boot block for examination */
|
|
if (device_instance_seek(raw_disk, 0, 0) < 0)
|
|
device_error(device_instance_device(raw_disk),
|
|
"Problem seeking on raw disk");
|
|
if (device_instance_read(raw_disk, &boot_block, sizeof(boot_block))
|
|
!= sizeof(boot_block))
|
|
device_error(device_instance_device(raw_disk), "Problem reading boot block");
|
|
|
|
if (partition < 0) {
|
|
/* select the active partition */
|
|
if (block0_is_bpb(boot_block)) {
|
|
device_error(device_instance_device(raw_disk), "Unimplemented active BPB");
|
|
}
|
|
else if (block0_is_fdisk(boot_block)) {
|
|
int active = block0_is_fdisk(boot_block);
|
|
device_error(device_instance_device(raw_disk), "Unimplemented active FDISK (%d)",
|
|
active);
|
|
}
|
|
else if (is_iso9660(raw_disk)) {
|
|
device_error(device_instance_device(raw_disk), "Unimplemented active ISO9660");
|
|
}
|
|
else if (block0_is_mac_disk(boot_block)) {
|
|
device_error(device_instance_device(raw_disk), "Unimplemented active MAC DISK");
|
|
}
|
|
else {
|
|
device_error(device_instance_device(raw_disk), "Unreconized bootblock");
|
|
}
|
|
}
|
|
else {
|
|
/* select the specified disk partition */
|
|
if (block0_is_bpb(boot_block)) {
|
|
device_error(device_instance_device(raw_disk), "Unimplemented BPB");
|
|
}
|
|
else if (block0_is_fdisk(boot_block)) {
|
|
/* return an instance */
|
|
ppcboot_partition_t *partition_table = (ppcboot_partition_t*) &boot_block[446];
|
|
ppcboot_partition_t *partition_entry;
|
|
disklabel *label;
|
|
if (partition > 4)
|
|
device_error(device_instance_device(raw_disk),
|
|
"Only FDISK partitions 1..4 supported");
|
|
partition_entry = &partition_table[partition - 1];
|
|
label = ZALLOC(disklabel);
|
|
label->raw_disk = raw_disk;
|
|
label->pos = 0;
|
|
label->sector_begin = 512 * sector2uw(partition_entry->sector_begin);
|
|
label->sector_length = 512 * sector2uw(partition_entry->sector_length);
|
|
PTRACE(disklabel, ("partition %ld, sector-begin %ld, length %ld\n",
|
|
(long)partition,
|
|
(long)label->sector_begin,
|
|
(long)label->sector_length));
|
|
if (filename != NULL)
|
|
device_error(device_instance_device(raw_disk),
|
|
"FDISK file names not yet supported");
|
|
return device_create_instance_from(NULL, raw_disk,
|
|
label,
|
|
NULL, args,
|
|
&package_disklabel_callbacks);
|
|
}
|
|
else if (block0_is_mac_disk(boot_block)) {
|
|
device_error(device_instance_device(raw_disk), "Unimplemented MAC DISK");
|
|
}
|
|
else {
|
|
device_error(device_instance_device(raw_disk),
|
|
"Unreconized bootblock");
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
#endif /* _PK_DISKLABEL_C_ */
|
|
|