From 12e4b1c978975d8cb6f3e13f20b1dbb136166b41 Mon Sep 17 00:00:00 2001 From: Sebastian Schmelzer Date: Mon, 14 Mar 2011 17:51:16 +0100 Subject: initial commit --- .../syslinux-4.03/com32/gpllib/disk/msdos.c | 162 +++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 contrib/syslinux/syslinux-4.03/com32/gpllib/disk/msdos.c (limited to 'contrib/syslinux/syslinux-4.03/com32/gpllib/disk/msdos.c') diff --git a/contrib/syslinux/syslinux-4.03/com32/gpllib/disk/msdos.c b/contrib/syslinux/syslinux-4.03/com32/gpllib/disk/msdos.c new file mode 100644 index 0000000..affec43 --- /dev/null +++ b/contrib/syslinux/syslinux-4.03/com32/gpllib/disk/msdos.c @@ -0,0 +1,162 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#include + +#include +#include +#include +#include +#include + +static inline int is_extended_partition(struct part_entry *ptab) +{ + return (ptab->ostype == 0x05 || + ptab->ostype == 0x0f || ptab->ostype == 0x85); +} + +static inline int msdos_magic_present(const char *ptab) +{ + return (*(uint16_t *) (ptab + 0x1fe) == 0xaa55); +} + +/** + * process_extended_partition - execute a callback for each partition contained listed in an ebr + * @drive_info: driveinfo struct describing the drive + * @partition_offset: Absolute start (lba) of the extended partition + * @ebr_offset: Relative start (lba) of the current ebr processed within + * the extended partition + * @callback: Callback to execute + * @error: Buffer for I/O errors + * @nb_part_seen: Number of partitions found on the disk so far + **/ +static int process_extended_partition(struct driveinfo *drive_info, + const int partition_offset, + const int ebr_offset, + p_callback callback, int nb_part_seen) +{ + int status = 0; + /* The ebr is located at the first sector of the extended partition */ + char *ebr = malloc(SECTOR * sizeof(char)); + + if (read_sectors(drive_info, ebr, partition_offset + ebr_offset, 1) == -1) + goto abort; + + /* Check msdos magic signature */ + if (!msdos_magic_present(ebr)) + goto abort; + + struct part_entry *ptab = + (struct part_entry *)(ebr + PARTITION_TABLES_OFFSET); + + for (int i = 0; i < 4; i++) { + if (status == -1) + goto abort; + + if (!is_extended_partition(&ptab[i])) { + /* + * This EBR partition table entry points to the + * logical partition associated to that EBR + */ + int logical_partition_start = ebr_offset + ptab[i].start_lba; + + /* Last EBR in the extended partition? */ + if (!logical_partition_start) + continue; + + /* + * Check for garbage: + * 3rd and 4th entries in an EBR should be zero + * Some (malformed) partitioning software still add some + * data partitions there. + */ + if (ptab[i].start_lba <= 0 || ptab[i].length <= 0) + continue; + + nb_part_seen++; + callback(drive_info, + &ptab[i], + partition_offset + logical_partition_start, nb_part_seen); + } else + status = process_extended_partition(drive_info, + partition_offset, + ptab[i].start_lba, + callback, nb_part_seen); + } + + free(ebr); + return 0; + +abort: + free(ebr); + return -1; +} + +/** + * process_mbr - execute a callback for each partition contained in an {m,e}br + * @drive_info: driveinfo struct describing the drive + * @ptab: Pointer to the partition table + * @callback: Callback to execute + **/ +static int process_mbr(struct driveinfo *drive_info, struct part_entry *ptab, + p_callback callback) +{ + int status = 0; + + for (int i = 0; i < 4; i++) { + if (status == -1) + return -1; + + if (ptab[i].start_sect > 0) { + if (is_extended_partition(&ptab[i])) { + callback(drive_info, &ptab[i], ptab[i].start_lba, i + 1); + status = + process_extended_partition(drive_info, ptab[i].start_lba, 0, + callback, 4); + } else + callback(drive_info, &ptab[i], ptab[i].start_lba, i + 1); + } + } + + return 0; +} + +/** + * parse_partition_table - execute a callback for each partition entry + * @d: driveinfo struct describing the drive + * @callback: Callback to execute + * + * The signature of the callback should be the following: + * + * void callback(struct driveinfo *drive_info, + * struct part_entry *ptab, + * int offset_root, + * int nb_part_seen) + **/ +int parse_partition_table(struct driveinfo *d, p_callback callback) +{ + char *mbr = malloc(SECTOR * sizeof(char)); + + if (read_mbr(d->disk, mbr) == -1) + return -1; + else { + /* Check msdos magic signature */ + if (!msdos_magic_present(mbr)) + return -1; + + struct part_entry *ptab = + (struct part_entry *)(mbr + PARTITION_TABLES_OFFSET); + return process_mbr(d, ptab, callback); + } +} -- cgit v1.2.3-55-g7522