[Syslinux-patches] HDT merge

Pierre-Alexandre Meyer pierre at mouraf.org
Tue Aug 4 21:50:18 PDT 2009


So, I wanted to send the "few" pending patches I had locally for review
but the diffstat is bigger than expected:

  60 files changed, 4318 insertions(+), 922 deletions(-)

  11.9% com32/gplinclude/disk/
  34.5% com32/gpllib/disk/
   6.5% com32/gpllib/dmi/
   5.1% com32/gpllib/
  35.2% com32/hdt/
   6.5% com32/

Did some testing with the CLI on HP2530p, DELL E6400 and in Qemu.
Noticed some glitches with the menu that I'll fix later.

The area I am still not sure about is the partitioning functions:

   com32/gpllib/disk/msdos.c

especially the code that iterates through extended partitions (I coded
that inspired by the wikipedia article...).

hpa already gave some feedback:

  * some sanity checks make it break for disks > 1TB (?)
  * char* ebr should be const char* (why?)
  * callback should be typedef (always thought typedefs were 3vi7?)
  * change the interface of read_sectors to be more like the read() syscall

Will address those after this first pass, so I get at least the logic
right.

URL:

http://git.zytor.com/?p=users/pam/hdt-pierre.git;a=shortlog;h=refs/heads/for-erwan

File for reference:

/* ----------------------------------------------------------------------- *
 *
 *   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 <stdlib.h>
#include <disk/geom.h>
#include <disk/partition.h>
#include <disk/read.h>

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(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 partition
 * @callback:		Callback to execute
 * @error:		Buffer for I/O errors
 * @nb_part_seen:	Number of partitions found on the disk so far
 **/
static void process_extended_partition(struct driveinfo *drive_info,
				       int partition_offset,
				       void *callback(struct driveinfo *, struct part_entry *, int, int),
				       int *error, int nb_part_seen)
{
	/* The ebr is located at the first sector of the extended partition */
	char* ebr = read_sectors(drive_info, partition_offset, 1, error);

	/* If something bad during the read happens, we can't do much: bail out */
	if (*error)
		return;

	/* Check msdos magic signature */
	if (!msdos_magic_present(ebr))
		return;

	struct part_entry *ptab = (struct part_entry *)(ebr + PARTITION_TABLES_OFFSET);

	for (int i = 0; i < 4; i++) {
		if (!is_extended_partition(&ptab[i])) {
			/*
			 * This EBR partition table entry points to the
			 * logical partition associated to that EBR
			 */
			int logical_partition_start = partition_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],
				 logical_partition_start,
				 nb_part_seen);
		} else
			process_extended_partition(drive_info,
						   partition_offset + ptab[i].start_lba,
						   callback,
						   error, nb_part_seen);
	}
}

/**
 * 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
 * @error:	Return the error code (I/O), if needed
 **/
static void process_mbr(struct driveinfo *drive_info, struct part_entry *ptab,
		        void *callback(struct driveinfo *, struct part_entry *, int, int),
		        int *error)
{
	for (int i = 0; i < 4; i++) {
		if (*error)
			return;

		if (ptab[i].start_sect > 0) {
			if (is_extended_partition(&ptab[i])) {
				callback(drive_info,
					 &ptab[i],
					 ptab[i].start_lba,
					 i+1);
				process_extended_partition(drive_info, ptab[i].start_lba, callback, error, 4);
			} else
				callback(drive_info,
					 &ptab[i],
					 ptab[i].start_lba,
					 i+1);
		}
	}
}

/**
 * parse_partition_table - execute a callback for each partition entry
 * @d:		driveinfo struct describing the drive
 * @callback:	Callback to execute
 * @error:	Return the error code (I/O), if needed
 *
 * 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, void *callback, int *error)
{
	char *mbr = read_mbr(d->disk, error);
	if (!mbr)
		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);
		process_mbr(d, ptab, callback, error);
		if (*error)
			return -1;
		else
			return 0;
	}
}

-- 
Pierre-Alexandre Meyer



More information about the Syslinux-patches mailing list