CODE
+#define XBOX_CONFIG_START 0x00000000L
+#define XBOX_CACHE1_START 0x00000400L
+#define XBOX_CACHE2_START 0x00177400L
+#define XBOX_CACHE3_START 0x002EE400L
+#define XBOX_SYSTEM_START 0x00465400L
+#define XBOX_DATA_START 0x0055F400L
+#define XBOX_EXTEND_F_START 0x00EE8AB0L
+#define XBOX_EXTEND_G_START 0x0FFFFFFFL
+
+#define XBOX_CONFIG_SIZE (XBOX_CACHE1_START - XBOX_CONFIG_START)
+#define XBOX_CACHE1_SIZE (XBOX_CACHE2_START - XBOX_CACHE1_START)
+#define XBOX_CACHE2_SIZE (XBOX_CACHE3_START - XBOX_CACHE2_START)
+#define XBOX_CACHE3_SIZE (XBOX_SYSTEM_START - XBOX_CACHE3_START)
+#define XBOX_SYSTEM_SIZE (XBOX_DATA_START - XBOX_SYSTEM_START)
+#define XBOX_DATA_SIZE (XBOX_EXTEND_F_START - XBOX_DATA_START)
+#define XBOX_EXTEND_F_SIZE (XBOX_EXTEND_G_START - XBOX_EXTEND_F_START)
+
+#define XBOX_MAGIC_SECT 3L
+#define XBOX_PARTITION_IN_USE 0x80000000
+#define XBOX_DEV_MINOR_START 50
+
+#define XBOX_EXT_PART_NKP06 1
+#define XBOX_EXT_PART_NKP67 2
+
+
+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_ext_partition_type = 0;
+
+static int __init xbox_setup_ext_partition(char *str)
+{
+ int val;
+ if (get_option(&str,&val) == 1) {
+ xbox_ext_partition_type = val;
+ }
+
+ return 1;
+}
+
+__setup("xboxpartition=", xbox_setup_ext_partition);
+
+
+static int xbox_check_magic(struct block_device *bdev, sector_t at_sect,
+ char *magic)
+{
+ Sector sect;
+ char *data;
+ int ret;
+
+ data = read_dev_sector(bdev, at_sect, §);
+ if (!data)
+ return -1;
+
+ /* Ick! */
+ ret = (*(u32*)data == *(u32*)magic) ? 1 : 0;
+ put_dev_sector(sect);
+
+ return ret;
+}
+
+static inline int xbox_drive_detect(struct block_device *bdev)
+{
+ /**
+ * "BRFR" is apparently the magic number in the config area
+ * the others are just paranoid checks to assure the expected
+ * "FATX" tags for the other xbox partitions
+ *
+ * the odds against a non-xbox drive having random data to match is
+ * astronomical...but it's possible I guess...you should only include
+ * this check if you actually *have* an xbox drive...since it has to
+ * be detected first
+ *
+ * @see check.c
+ */
+ return (xbox_check_magic(bdev, XBOX_MAGIC_SECT, "BRFR") &&
+ xbox_check_magic(bdev, XBOX_SYSTEM_START, "FATX") &&
+ xbox_check_magic(bdev, XBOX_DATA_START, "FATX")) ?
+ 0 : -ENODEV;
+}
+
+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_check_magic(bdev,XBOX_MAGIC_SECT,"BRFR")) {
+ Sector sect;
+ int retv;
+ xbox_partition_table *table;
+
+ table = (xbox_partition_table*)read_dev_sector(bdev, XBOX_CONFIG_START, §);
+
+ 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
+}
+
+int xbox_partition(struct parsed_partitions *state, struct block_device *bdev)
+{
+ sector_t disk_size = bdev->bd_disk->capacity;
+
+ if (xbox_ext_partition_type == 0 && xbox_ptbl_detect(bdev)) {
+ int i;
+ Sector sect;
+ xbox_partition_table *table = (xbox_partition_table*)read_dev_sector(bdev,
+ XBOX_CONFIG_START, §);
+
+ if (!table) return 0;
+
+ printk(" [xbox_partition]");
+
+ for (i=0; i<14; i++) {
+ xbox_partition_entry *part = &table->partitions;
+ if (part->flags & XBOX_PARTITION_IN_USE) {
+ if (part->start >= disk_size)
+ 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 > disk_size)
+ printk("xbox_partition: partition %d extends past the end of the disk, to sector %d, skipping\n", i, part->start + part->size - 1);
+ else
+ put_partition(state, XBOX_DEV_MINOR_START+i+bdev->bd_disk->first_minor,
+ part->start, part->size);
+ }
+ }
+
+ put_dev_sector(sect);
+ return 1;
+ } else {
+ int err = xbox_drive_detect(bdev);
+ if (err)
+ return err;
+
+ printk(" [xbox]");
+ int slot = XBOX_DEV_MINOR_START + bdev->bd_disk->first_minor;
+ put_partition(state, slot++, XBOX_DATA_START, XBOX_DATA_SIZE);
+ put_partition(state, slot++, XBOX_SYSTEM_START, XBOX_SYSTEM_SIZE);
+ put_partition(state, slot++, XBOX_CACHE1_START, XBOX_CACHE1_SIZE);
+ put_partition(state, slot++, XBOX_CACHE2_START, XBOX_CACHE2_SIZE);
+ put_partition(state, slot++, XBOX_CACHE3_START, XBOX_CACHE3_SIZE);
+
+ if (disk_size <= XBOX_EXTEND_F_START)
+ goto out; /* no extended partitions */
+
+ /* Support for fixed size 'extended partitions' */
+ if (XBOX_EXTEND_G_START < disk_size) {
+ /* use NKPatcher67 style F and G drive */
+ if ( xbox_ext_partition_type == XBOX_EXT_PART_NKP67 ) {
+ /* There's an F and G on this system - F only goes to the LBA28 boundary */
+ put_partition(state, slot++, XBOX_EXTEND_F_START,
+ XBOX_EXTEND_F_SIZE);
+ /* G goes to end of drive */
+ put_partition(state, slot++, XBOX_EXTEND_G_START,
+ disk_size - XBOX_EXTEND_G_START);
+ } else {
+ /* use NKPatcher06 style F drive */
+ put_partition(state, slot++, XBOX_EXTEND_F_START,
+ disk_size - XBOX_EXTEND_F_START);
+ }
+ } else {
+ /* Just a large F on this system - to end of drive*/
+ put_partition(state, slot++, XBOX_EXTEND_F_START,
+ disk_size - XBOX_EXTEND_F_START);
+ }
+ }
+