« Return to Thread: [patch] Support for partition table in LBA48 bios

[patch] Support for partition table in LBA48 bios

by Torne Wuff-2 :: Rate this Message:

Reply to Author | View in Thread

Attached is a patch to 2.4.32 to support reading the on-disk partition
table used by newer versions of oz_paulb's LBA48 patch for the Microsoft
xbox kernel. This allows using an xbox disk on which the standard
partitions have been resized/moved, or which contains more partitions
after hda55/56 (F/G).

I am currently running my box with root on hda57 (partition 8) and swap
on hda58 (partition 9) and this works very nicely, enabling me to have
my linux FS natively formatted without giving up the F/G drives used by
homebrew software.

Technical/stylistic commentary is invited. I realise implementation of
this has been discussed in the past on this list, and that it raised
discussion of legal issues, but since I couldn't find a previous
implementation, here's one for anyone who'd find this a useful feature.
It would be nice to see this in the main tree but I realise this is
contentious, so hey.

Making the assumptions the xbox partitioning code currently does can
easily result in data loss on a box whose hard disk is not partitioned
in the 'ordinary' way (linux overwriting fatx or vice versa) - I'd
consider this a reason to include it if nothing else ;)

--
Torne Wuff
torne@...
low in saturated fats, high in protein

Index: linux-2.4.32-xbox-r1/fs/partitions/xbox.c
===================================================================
--- linux-2.4.32-xbox-r1.orig/fs/partitions/xbox.c
+++ linux-2.4.32-xbox-r1/fs/partitions/xbox.c
@@ -26,7 +26,7 @@
 
 /*
  * The offset for numbering xbox partitions:
- * We create hdX50->56
+ * We create hdX50->56 (or higher if a partition table is found in sector 0)
  */
 #define XBOX_PARTITION_OFFSET 50
 
@@ -51,6 +51,26 @@
 
 #define XBOX_SECTOR_MAGIC (3L)
 
+#define XBOX_PARTITION_IN_USE 0x80000000
+
+typedef struct
+{
+ char name[16];
+ u32  flags;
+ u32  start;
+ u32  size;
+ u32  reserved;
+} xbox_partition_entry;
+
+
+typedef struct
+{
+ char                 magic[16];
+ char                 reserved[32];
+ xbox_partition_entry partitions[14];
+} xbox_partition_table;
+
+
 static int
 xbox_sig_string_match( struct block_device *bdev,
  unsigned long at_sector,
@@ -101,6 +121,33 @@ xbox_drive_detect(struct block_device *b
  (xbox_sig_string_match(bdev,XBOX_SECTOR_STORE ,"FATX"))) {
  return 1; //success
  }
+
+ return 0; // no xbox drive
+}
+
+static inline int
+xbox_ptbl_detect(struct block_device *bdev)
+{
+ /**
+ * check for "BRFR" magic number, then for "****PARTINFO****" at
+ * start of zeroth sector. This intentionally doesn't check for
+ * FATX signatures at the expected system and store locations
+ * as it's possible for these partitions to have been moved.
+ */
+ if (xbox_sig_string_match(bdev,XBOX_SECTOR_MAGIC,"BRFR")) {
+ Sector sect;
+ int retv;
+ xbox_partition_table *table;
+
+ table = (xbox_partition_table*)read_dev_sector(bdev, XBOX_SECTOR_CONFIG, §);
+
+ if (!table) return 0;
+
+ if (strncmp(table->magic, "****PARTINFO****", 16) == 0) retv = 1; else retv = 0;
+
+ put_dev_sector(sect);
+ return retv;
+ }
 
  return 0; // no xbox drive
 }
@@ -118,8 +165,32 @@ int xbox_partition(struct gendisk *hd, s
  return 0;
  }
 
- if (xbox_drive_detect(bdev)) {
- num_sectors = (blk_size[hd->major][first_part_minor-1] << 1);
+ num_sectors = (blk_size[hd->major][first_part_minor-1] << 1);
+
+ if (xbox_ptbl_detect(bdev)) {
+ Sector sect;
+ xbox_partition_table *table;
+
+ table = (xbox_partition_table*)read_dev_sector(bdev, XBOX_SECTOR_CONFIG, §);
+
+ if (!table) return 0;
+
+ int i;
+ for (i=0; i<14; i++) {
+ xbox_partition_entry *part = &table->partitions[i];
+ if (part->flags & XBOX_PARTITION_IN_USE) {
+ if (part->start >= num_sectors)
+ printk("xbox_partition: partition %d starts off the end of the disk, at sector %d, skipping\n", i, part->start);
+ else if (part->start + part->size > num_sectors)
+ printk("xbox_partition: partition %d extends past the end of the disk, to sector %d, skipping\n", i, part->start + part->size - 1);
+ else
+ add_gd_partition(hd,minor+i,part->start,part->size);
+ }
+ }
+
+ put_dev_sector(sect);
+ return 1;
+ } else if (xbox_drive_detect(bdev)) {
  add_gd_partition(hd,minor++,XBOX_SECTOR_STORE ,XBOX_SECTORS_STORE );
  add_gd_partition(hd,minor++,XBOX_SECTOR_SYSTEM,XBOX_SECTORS_SYSTEM);
  add_gd_partition(hd,minor++,XBOX_SECTOR_CACHE1,XBOX_SECTORS_CACHE1);
@@ -136,6 +207,7 @@ int xbox_partition(struct gendisk *hd, s
  /* Just a large F on this system - to end of drive*/
  else add_gd_partition(hd,minor++,XBOX_SECTOR_EXTEND_F, num_sectors-XBOX_SECTOR_EXTEND_F);
  }
+ return 0; // this will ensure other partition schemes are tried
  } else {
  //not an xbox drive
  return 0;
Index: linux-2.4.32-xbox-r1/fs/partitions/check.c
===================================================================
--- linux-2.4.32-xbox-r1.orig/fs/partitions/check.c
+++ linux-2.4.32-xbox-r1/fs/partitions/check.c
@@ -42,6 +42,14 @@ extern int *blk_size[];
 int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
 
 static int (*check_part[])(struct gendisk *hd, struct block_device *bdev, unsigned long first_sect, int first_minor) = {
+#ifdef CONFIG_XBOX_PARTITION
+/* do this first; if the drive is Xbox-formatted, add partitions 50+
+ * and then go ahead and look for other schemes - this way, an Xbox
+ * HD can have 2 partitioning systems: the implicit Xbox one (50+)
+ * and the explicit one (1+)
+ */
+ xbox_partition,
+#endif
 #ifdef CONFIG_ACORN_PARTITION
  acorn_partition,
 #endif
@@ -270,12 +278,6 @@ static void check_partition(struct gendi
 
  printk(" unknown partition table\n");
 setup_devfs:
-/* if the drive is Xbox-formatted, add partitions 50+ to the existing
-   partitions - this way, an Xbox HD can have 2 partitioning systems
-   systems: the implicit Xbox one (50+) and the explicit one (1+) */
-#ifdef CONFIG_XBOX_PARTITION
-        xbox_partition(hd, bdev, first_sector, first_part_minor);
-#endif
  invalidate_bdev(bdev, 1);
  truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
  bdput(bdev);

 « Return to Thread: [patch] Support for partition table in LBA48 bios