diff options
| -rw-r--r-- | Documentation/ldm.txt | 21 | ||||
| -rw-r--r-- | MAINTAINERS | 6 | ||||
| -rw-r--r-- | fs/partitions/Kconfig | 12 | ||||
| -rw-r--r-- | fs/partitions/ldm.c | 206 | ||||
| -rw-r--r-- | fs/partitions/ldm.h | 6 |
5 files changed, 144 insertions, 107 deletions
diff --git a/Documentation/ldm.txt b/Documentation/ldm.txt index e266e11c19a3..718085bc9f1a 100644 --- a/Documentation/ldm.txt +++ b/Documentation/ldm.txt | |||
| @@ -2,10 +2,13 @@ | |||
| 2 | LDM - Logical Disk Manager (Dynamic Disks) | 2 | LDM - Logical Disk Manager (Dynamic Disks) |
| 3 | ------------------------------------------ | 3 | ------------------------------------------ |
| 4 | 4 | ||
| 5 | Originally Written by FlatCap - Richard Russon <ldm@flatcap.org>. | ||
| 6 | Last Updated by Anton Altaparmakov on 30 March 2007 for Windows Vista. | ||
| 7 | |||
| 5 | Overview | 8 | Overview |
| 6 | -------- | 9 | -------- |
| 7 | 10 | ||
| 8 | Windows 2000 and XP use a new partitioning scheme. It is a complete | 11 | Windows 2000, XP, and Vista use a new partitioning scheme. It is a complete |
| 9 | replacement for the MSDOS style partitions. It stores its information in a | 12 | replacement for the MSDOS style partitions. It stores its information in a |
| 10 | 1MiB journalled database at the end of the physical disk. The size of | 13 | 1MiB journalled database at the end of the physical disk. The size of |
| 11 | partitions is limited only by disk space. The maximum number of partitions is | 14 | partitions is limited only by disk space. The maximum number of partitions is |
| @@ -23,7 +26,11 @@ Once the LDM driver has divided up the disk, you can use the MD driver to | |||
| 23 | assemble any multi-partition volumes, e.g. Stripes, RAID5. | 26 | assemble any multi-partition volumes, e.g. Stripes, RAID5. |
| 24 | 27 | ||
| 25 | To prevent legacy applications from repartitioning the disk, the LDM creates a | 28 | To prevent legacy applications from repartitioning the disk, the LDM creates a |
| 26 | dummy MSDOS partition containing one disk-sized partition. | 29 | dummy MSDOS partition containing one disk-sized partition. This is what is |
| 30 | supported with the Linux LDM driver. | ||
| 31 | |||
| 32 | A newer approach that has been implemented with Vista is to put LDM on top of a | ||
| 33 | GPT label disk. This is not supported by the Linux LDM driver yet. | ||
| 27 | 34 | ||
| 28 | 35 | ||
| 29 | Example | 36 | Example |
| @@ -88,13 +95,13 @@ and cannot boot from a Dynamic Disk. | |||
| 88 | More Documentation | 95 | More Documentation |
| 89 | ------------------ | 96 | ------------------ |
| 90 | 97 | ||
| 91 | There is an Overview of the LDM online together with complete Technical | 98 | There is an Overview of the LDM together with complete Technical Documentation. |
| 92 | Documentation. It can also be downloaded in html. | 99 | It is available for download. |
| 93 | 100 | ||
| 94 | http://linux-ntfs.sourceforge.net/ldm/index.html | 101 | http://www.linux-ntfs.org/content/view/19/37/ |
| 95 | http://linux-ntfs.sourceforge.net/downloads.html | ||
| 96 | 102 | ||
| 97 | If you have any LDM questions that aren't answered on the website, email me. | 103 | If you have any LDM questions that aren't answered in the documentation, email |
| 104 | me. | ||
| 98 | 105 | ||
| 99 | Cheers, | 106 | Cheers, |
| 100 | FlatCap - Richard Russon | 107 | FlatCap - Richard Russon |
diff --git a/MAINTAINERS b/MAINTAINERS index 4c3277cb925e..22ab4019972b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -2231,11 +2231,11 @@ M: khali@linux-fr.org | |||
| 2231 | L: lm-sensors@lm-sensors.org | 2231 | L: lm-sensors@lm-sensors.org |
| 2232 | S: Maintained | 2232 | S: Maintained |
| 2233 | 2233 | ||
| 2234 | LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP Dynamic Disks) | 2234 | LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP/Vista Dynamic Disks) |
| 2235 | P: Richard Russon (FlatCap) | 2235 | P: Richard Russon (FlatCap) |
| 2236 | M: ldm@flatcap.org | 2236 | M: ldm@flatcap.org |
| 2237 | L: ldm-devel@lists.sourceforge.net | 2237 | L: linux-ntfs-dev@lists.sourceforge.net |
| 2238 | W: http://ldm.sourceforge.net | 2238 | W: http://www.linux-ntfs.org/content/view/19/37/ |
| 2239 | S: Maintained | 2239 | S: Maintained |
| 2240 | 2240 | ||
| 2241 | LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI) | 2241 | LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI) |
diff --git a/fs/partitions/Kconfig b/fs/partitions/Kconfig index 7638a1c42a7d..a99acd8de353 100644 --- a/fs/partitions/Kconfig +++ b/fs/partitions/Kconfig | |||
| @@ -166,8 +166,12 @@ config LDM_PARTITION | |||
| 166 | depends on PARTITION_ADVANCED | 166 | depends on PARTITION_ADVANCED |
| 167 | ---help--- | 167 | ---help--- |
| 168 | Say Y here if you would like to use hard disks under Linux which | 168 | Say Y here if you would like to use hard disks under Linux which |
| 169 | were partitioned using Windows 2000's or XP's Logical Disk Manager. | 169 | were partitioned using Windows 2000's/XP's or Vista's Logical Disk |
| 170 | They are also known as "Dynamic Disks". | 170 | Manager. They are also known as "Dynamic Disks". |
| 171 | |||
| 172 | Note this driver only supports Dynamic Disks with a protective MBR | ||
| 173 | label, i.e. DOS partition table. It does not support GPT labelled | ||
| 174 | Dynamic Disks yet as can be created with Vista. | ||
| 171 | 175 | ||
| 172 | Windows 2000 introduced the concept of Dynamic Disks to get around | 176 | Windows 2000 introduced the concept of Dynamic Disks to get around |
| 173 | the limitations of the PC's partitioning scheme. The Logical Disk | 177 | the limitations of the PC's partitioning scheme. The Logical Disk |
| @@ -175,8 +179,8 @@ config LDM_PARTITION | |||
| 175 | mirrored, striped or RAID volumes, all without the need for | 179 | mirrored, striped or RAID volumes, all without the need for |
| 176 | rebooting. | 180 | rebooting. |
| 177 | 181 | ||
| 178 | Normal partitions are now called Basic Disks under Windows 2000 and | 182 | Normal partitions are now called Basic Disks under Windows 2000, XP, |
| 179 | XP. | 183 | and Vista. |
| 180 | 184 | ||
| 181 | For a fuller description read <file:Documentation/ldm.txt>. | 185 | For a fuller description read <file:Documentation/ldm.txt>. |
| 182 | 186 | ||
diff --git a/fs/partitions/ldm.c b/fs/partitions/ldm.c index 1a60926a4ccd..c387812537d7 100644 --- a/fs/partitions/ldm.c +++ b/fs/partitions/ldm.c | |||
| @@ -2,10 +2,10 @@ | |||
| 2 | * ldm - Support for Windows Logical Disk Manager (Dynamic Disks) | 2 | * ldm - Support for Windows Logical Disk Manager (Dynamic Disks) |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org> | 4 | * Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org> |
| 5 | * Copyright (c) 2001-2004 Anton Altaparmakov | 5 | * Copyright (c) 2001-2007 Anton Altaparmakov |
| 6 | * Copyright (C) 2001,2002 Jakob Kemi <jakob.kemi@telia.com> | 6 | * Copyright (C) 2001,2002 Jakob Kemi <jakob.kemi@telia.com> |
| 7 | * | 7 | * |
| 8 | * Documentation is available at http://linux-ntfs.sf.net/ldm | 8 | * Documentation is available at http://www.linux-ntfs.org/content/view/19/37/ |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify it under | 10 | * This program is free software; you can redistribute it and/or modify it under |
| 11 | * the terms of the GNU General Public License as published by the Free Software | 11 | * the terms of the GNU General Public License as published by the Free Software |
| @@ -62,7 +62,6 @@ static void _ldm_printk (const char *level, const char *function, | |||
| 62 | printk ("%s%s(): %s\n", level, function, buf); | 62 | printk ("%s%s(): %s\n", level, function, buf); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | |||
| 66 | /** | 65 | /** |
| 67 | * ldm_parse_hexbyte - Convert a ASCII hex number to a byte | 66 | * ldm_parse_hexbyte - Convert a ASCII hex number to a byte |
| 68 | * @src: Pointer to at least 2 characters to convert. | 67 | * @src: Pointer to at least 2 characters to convert. |
| @@ -118,7 +117,6 @@ static bool ldm_parse_guid (const u8 *src, u8 *dest) | |||
| 118 | return true; | 117 | return true; |
| 119 | } | 118 | } |
| 120 | 119 | ||
| 121 | |||
| 122 | /** | 120 | /** |
| 123 | * ldm_parse_privhead - Read the LDM Database PRIVHEAD structure | 121 | * ldm_parse_privhead - Read the LDM Database PRIVHEAD structure |
| 124 | * @data: Raw database PRIVHEAD structure loaded from the device | 122 | * @data: Raw database PRIVHEAD structure loaded from the device |
| @@ -130,46 +128,48 @@ static bool ldm_parse_guid (const u8 *src, u8 *dest) | |||
| 130 | * Return: 'true' @ph contains the PRIVHEAD data | 128 | * Return: 'true' @ph contains the PRIVHEAD data |
| 131 | * 'false' @ph contents are undefined | 129 | * 'false' @ph contents are undefined |
| 132 | */ | 130 | */ |
| 133 | static bool ldm_parse_privhead (const u8 *data, struct privhead *ph) | 131 | static bool ldm_parse_privhead(const u8 *data, struct privhead *ph) |
| 134 | { | 132 | { |
| 135 | BUG_ON (!data || !ph); | 133 | bool is_vista = false; |
| 136 | 134 | ||
| 137 | if (MAGIC_PRIVHEAD != BE64 (data)) { | 135 | BUG_ON(!data || !ph); |
| 138 | ldm_error ("Cannot find PRIVHEAD structure. LDM database is" | 136 | if (MAGIC_PRIVHEAD != BE64(data)) { |
| 137 | ldm_error("Cannot find PRIVHEAD structure. LDM database is" | ||
| 139 | " corrupt. Aborting."); | 138 | " corrupt. Aborting."); |
| 140 | return false; | 139 | return false; |
| 141 | } | 140 | } |
| 142 | 141 | ph->ver_major = BE16(data + 0x000C); | |
| 143 | ph->ver_major = BE16 (data + 0x000C); | 142 | ph->ver_minor = BE16(data + 0x000E); |
| 144 | ph->ver_minor = BE16 (data + 0x000E); | 143 | ph->logical_disk_start = BE64(data + 0x011B); |
| 145 | ph->logical_disk_start = BE64 (data + 0x011B); | 144 | ph->logical_disk_size = BE64(data + 0x0123); |
| 146 | ph->logical_disk_size = BE64 (data + 0x0123); | 145 | ph->config_start = BE64(data + 0x012B); |
| 147 | ph->config_start = BE64 (data + 0x012B); | 146 | ph->config_size = BE64(data + 0x0133); |
| 148 | ph->config_size = BE64 (data + 0x0133); | 147 | /* Version 2.11 is Win2k/XP and version 2.12 is Vista. */ |
| 149 | 148 | if (ph->ver_major == 2 && ph->ver_minor == 12) | |
| 150 | if ((ph->ver_major != 2) || (ph->ver_minor != 11)) { | 149 | is_vista = true; |
| 151 | ldm_error ("Expected PRIVHEAD version %d.%d, got %d.%d." | 150 | if (!is_vista && (ph->ver_major != 2 || ph->ver_minor != 11)) { |
| 152 | " Aborting.", 2, 11, ph->ver_major, ph->ver_minor); | 151 | ldm_error("Expected PRIVHEAD version 2.11 or 2.12, got %d.%d." |
| 152 | " Aborting.", ph->ver_major, ph->ver_minor); | ||
| 153 | return false; | 153 | return false; |
| 154 | } | 154 | } |
| 155 | ldm_debug("PRIVHEAD version %d.%d (Windows %s).", ph->ver_major, | ||
| 156 | ph->ver_minor, is_vista ? "Vista" : "2000/XP"); | ||
| 155 | if (ph->config_size != LDM_DB_SIZE) { /* 1 MiB in sectors. */ | 157 | if (ph->config_size != LDM_DB_SIZE) { /* 1 MiB in sectors. */ |
| 156 | /* Warn the user and continue, carefully */ | 158 | /* Warn the user and continue, carefully. */ |
| 157 | ldm_info ("Database is normally %u bytes, it claims to " | 159 | ldm_info("Database is normally %u bytes, it claims to " |
| 158 | "be %llu bytes.", LDM_DB_SIZE, | 160 | "be %llu bytes.", LDM_DB_SIZE, |
| 159 | (unsigned long long)ph->config_size ); | 161 | udunsigned long long)ph->config_size); |
| 160 | } | 162 | } |
| 161 | if ((ph->logical_disk_size == 0) || | 163 | if ((ph->logical_disk_size == 0) || (ph->logical_disk_start + |
| 162 | (ph->logical_disk_start + ph->logical_disk_size > ph->config_start)) { | 164 | ph->logical_disk_size > ph->config_start)) { |
| 163 | ldm_error ("PRIVHEAD disk size doesn't match real disk size"); | 165 | ldm_error("PRIVHEAD disk size doesn't match real disk size"); |
| 164 | return false; | 166 | return false; |
| 165 | } | 167 | } |
| 166 | 168 | if (!ldm_parse_guid(data + 0x0030, ph->disk_id)) { | |
| 167 | if (!ldm_parse_guid (data + 0x0030, ph->disk_id)) { | 169 | ldm_error("PRIVHEAD contains an invalid GUID."); |
| 168 | ldm_error ("PRIVHEAD contains an invalid GUID."); | ||
| 169 | return false; | 170 | return false; |
| 170 | } | 171 | } |
| 171 | 172 | ldm_debug("Parsed PRIVHEAD successfully."); | |
| 172 | ldm_debug ("Parsed PRIVHEAD successfully."); | ||
| 173 | return true; | 173 | return true; |
| 174 | } | 174 | } |
| 175 | 175 | ||
| @@ -409,7 +409,7 @@ out: | |||
| 409 | * Return: 'true' @toc1 contains validated TOCBLOCK info | 409 | * Return: 'true' @toc1 contains validated TOCBLOCK info |
| 410 | * 'false' @toc1 contents are undefined | 410 | * 'false' @toc1 contents are undefined |
| 411 | */ | 411 | */ |
| 412 | static bool ldm_validate_tocblocks (struct block_device *bdev, | 412 | static bool ldm_validate_tocblocks(struct block_device *bdev, |
| 413 | unsigned long base, struct ldmdb *ldb) | 413 | unsigned long base, struct ldmdb *ldb) |
| 414 | { | 414 | { |
| 415 | static const int off[4] = { OFF_TOCB1, OFF_TOCB2, OFF_TOCB3, OFF_TOCB4}; | 415 | static const int off[4] = { OFF_TOCB1, OFF_TOCB2, OFF_TOCB3, OFF_TOCB4}; |
| @@ -417,54 +417,57 @@ static bool ldm_validate_tocblocks (struct block_device *bdev, | |||
| 417 | struct privhead *ph; | 417 | struct privhead *ph; |
| 418 | Sector sect; | 418 | Sector sect; |
| 419 | u8 *data; | 419 | u8 *data; |
| 420 | int i, nr_tbs; | ||
| 420 | bool result = false; | 421 | bool result = false; |
| 421 | int i; | ||
| 422 | 422 | ||
| 423 | BUG_ON (!bdev || !ldb); | 423 | BUG_ON(!bdev || !ldb); |
| 424 | 424 | ph = &ldb->ph; | |
| 425 | ph = &ldb->ph; | ||
| 426 | tb[0] = &ldb->toc; | 425 | tb[0] = &ldb->toc; |
| 427 | tb[1] = kmalloc (sizeof (*tb[1]), GFP_KERNEL); | 426 | tb[1] = kmalloc(sizeof(*tb[1]) * 3, GFP_KERNEL); |
| 428 | tb[2] = kmalloc (sizeof (*tb[2]), GFP_KERNEL); | 427 | if (!tb[1]) { |
| 429 | tb[3] = kmalloc (sizeof (*tb[3]), GFP_KERNEL); | 428 | ldm_crit("Out of memory."); |
| 430 | if (!tb[1] || !tb[2] || !tb[3]) { | 429 | goto err; |
| 431 | ldm_crit ("Out of memory."); | ||
| 432 | goto out; | ||
| 433 | } | 430 | } |
| 434 | 431 | tb[2] = (struct tocblock*)((u8*)tb[1] + sizeof(*tb[1])); | |
| 435 | for (i = 0; i < 4; i++) /* Read and parse all four toc's. */ | 432 | tb[3] = (struct tocblock*)((u8*)tb[2] + sizeof(*tb[2])); |
| 436 | { | 433 | /* |
| 437 | data = read_dev_sector (bdev, base + off[i], §); | 434 | * Try to read and parse all four TOCBLOCKs. |
| 435 | * | ||
| 436 | * Windows Vista LDM v2.12 does not always have all four TOCBLOCKs so | ||
| 437 | * skip any that fail as long as we get at least one valid TOCBLOCK. | ||
| 438 | */ | ||
| 439 | for (nr_tbs = i = 0; i < 4; i++) { | ||
| 440 | data = read_dev_sector(bdev, base + off[i], §); | ||
| 438 | if (!data) { | 441 | if (!data) { |
| 439 | ldm_crit ("Disk read failed."); | 442 | ldm_error("Disk read failed for TOCBLOCK %d.", i); |
| 440 | goto out; | 443 | continue; |
| 441 | } | 444 | } |
| 442 | result = ldm_parse_tocblock (data, tb[i]); | 445 | if (ldm_parse_tocblock(data, tb[nr_tbs])) |
| 443 | put_dev_sector (sect); | 446 | nr_tbs++; |
| 444 | if (!result) | 447 | put_dev_sector(sect); |
| 445 | goto out; /* Already logged */ | ||
| 446 | } | 448 | } |
| 447 | 449 | if (!nr_tbs) { | |
| 448 | /* Range check the toc against a privhead. */ | 450 | ldm_crit("Failed to find a valid TOCBLOCK."); |
| 451 | goto err; | ||
| 452 | } | ||
| 453 | /* Range check the TOCBLOCK against a privhead. */ | ||
| 449 | if (((tb[0]->bitmap1_start + tb[0]->bitmap1_size) > ph->config_size) || | 454 | if (((tb[0]->bitmap1_start + tb[0]->bitmap1_size) > ph->config_size) || |
| 450 | ((tb[0]->bitmap2_start + tb[0]->bitmap2_size) > ph->config_size)) { | 455 | ((tb[0]->bitmap2_start + tb[0]->bitmap2_size) > |
| 451 | ldm_crit ("The bitmaps are out of range. Giving up."); | 456 | ph->config_size)) { |
| 452 | goto out; | 457 | ldm_crit("The bitmaps are out of range. Giving up."); |
| 458 | goto err; | ||
| 453 | } | 459 | } |
| 454 | 460 | /* Compare all loaded TOCBLOCKs. */ | |
| 455 | if (!ldm_compare_tocblocks (tb[0], tb[1]) || /* Compare all tocs. */ | 461 | for (i = 1; i < nr_tbs; i++) { |
| 456 | !ldm_compare_tocblocks (tb[0], tb[2]) || | 462 | if (!ldm_compare_tocblocks(tb[0], tb[i])) { |
| 457 | !ldm_compare_tocblocks (tb[0], tb[3])) { | 463 | ldm_crit("TOCBLOCKs 0 and %d do not match.", i); |
| 458 | ldm_crit ("The TOCBLOCKs don't match."); | 464 | goto err; |
| 459 | goto out; | 465 | } |
| 460 | } | 466 | } |
| 461 | 467 | ldm_debug("Validated %d TOCBLOCKs successfully.", nr_tbs); | |
| 462 | ldm_debug ("Validated TOCBLOCKs successfully."); | ||
| 463 | result = true; | 468 | result = true; |
| 464 | out: | 469 | err: |
| 465 | kfree (tb[1]); | 470 | kfree(tb[1]); |
| 466 | kfree (tb[2]); | ||
| 467 | kfree (tb[3]); | ||
| 468 | return result; | 471 | return result; |
| 469 | } | 472 | } |
| 470 | 473 | ||
| @@ -566,7 +569,7 @@ static bool ldm_validate_partition_table (struct block_device *bdev) | |||
| 566 | 569 | ||
| 567 | p = (struct partition*)(data + 0x01BE); | 570 | p = (struct partition*)(data + 0x01BE); |
| 568 | for (i = 0; i < 4; i++, p++) | 571 | for (i = 0; i < 4; i++, p++) |
| 569 | if (SYS_IND (p) == WIN2K_DYNAMIC_PARTITION) { | 572 | if (SYS_IND (p) == LDM_PARTITION) { |
| 570 | result = true; | 573 | result = true; |
| 571 | break; | 574 | break; |
| 572 | } | 575 | } |
| @@ -975,44 +978,68 @@ static bool ldm_parse_dsk4 (const u8 *buffer, int buflen, struct vblk *vb) | |||
| 975 | * Return: 'true' @vb contains a Partition VBLK | 978 | * Return: 'true' @vb contains a Partition VBLK |
| 976 | * 'false' @vb contents are not defined | 979 | * 'false' @vb contents are not defined |
| 977 | */ | 980 | */ |
| 978 | static bool ldm_parse_prt3 (const u8 *buffer, int buflen, struct vblk *vb) | 981 | static bool ldm_parse_prt3(const u8 *buffer, int buflen, struct vblk *vb) |
| 979 | { | 982 | { |
| 980 | int r_objid, r_name, r_size, r_parent, r_diskid, r_index, len; | 983 | int r_objid, r_name, r_size, r_parent, r_diskid, r_index, len; |
| 981 | struct vblk_part *part; | 984 | struct vblk_part *part; |
| 982 | 985 | ||
| 983 | BUG_ON (!buffer || !vb); | 986 | BUG_ON(!buffer || !vb); |
| 984 | 987 | r_objid = ldm_relative(buffer, buflen, 0x18, 0); | |
| 985 | r_objid = ldm_relative (buffer, buflen, 0x18, 0); | 988 | if (r_objid < 0) { |
| 986 | r_name = ldm_relative (buffer, buflen, 0x18, r_objid); | 989 | ldm_error("r_objid %d < 0", r_objid); |
| 987 | r_size = ldm_relative (buffer, buflen, 0x34, r_name); | 990 | return false; |
| 988 | r_parent = ldm_relative (buffer, buflen, 0x34, r_size); | 991 | } |
| 989 | r_diskid = ldm_relative (buffer, buflen, 0x34, r_parent); | 992 | r_name = ldm_relative(buffer, buflen, 0x18, r_objid); |
| 990 | 993 | if (r_name < 0) { | |
| 994 | ldm_error("r_name %d < 0", r_name); | ||
| 995 | return false; | ||
| 996 | } | ||
| 997 | r_size = ldm_relative(buffer, buflen, 0x34, r_name); | ||
| 998 | if (r_size < 0) { | ||
| 999 | ldm_error("r_size %d < 0", r_size); | ||
| 1000 | return false; | ||
| 1001 | } | ||
| 1002 | r_parent = ldm_relative(buffer, buflen, 0x34, r_size); | ||
| 1003 | if (r_parent < 0) { | ||
| 1004 | ldm_error("r_parent %d < 0", r_parent); | ||
| 1005 | return false; | ||
| 1006 | } | ||
| 1007 | r_diskid = ldm_relative(buffer, buflen, 0x34, r_parent); | ||
| 1008 | if (r_diskid < 0) { | ||
| 1009 | ldm_error("r_diskid %d < 0", r_diskid); | ||
| 1010 | return false; | ||
| 1011 | } | ||
| 991 | if (buffer[0x12] & VBLK_FLAG_PART_INDEX) { | 1012 | if (buffer[0x12] & VBLK_FLAG_PART_INDEX) { |
| 992 | r_index = ldm_relative (buffer, buflen, 0x34, r_diskid); | 1013 | r_index = ldm_relative(buffer, buflen, 0x34, r_diskid); |
| 1014 | if (r_index < 0) { | ||
| 1015 | ldm_error("r_index %d < 0", r_index); | ||
| 1016 | return false; | ||
| 1017 | } | ||
| 993 | len = r_index; | 1018 | len = r_index; |
| 994 | } else { | 1019 | } else { |
| 995 | r_index = 0; | 1020 | r_index = 0; |
| 996 | len = r_diskid; | 1021 | len = r_diskid; |
| 997 | } | 1022 | } |
| 998 | if (len < 0) | 1023 | if (len < 0) { |
| 1024 | ldm_error("len %d < 0", len); | ||
| 999 | return false; | 1025 | return false; |
| 1000 | 1026 | } | |
| 1001 | len += VBLK_SIZE_PRT3; | 1027 | len += VBLK_SIZE_PRT3; |
| 1002 | if (len != BE32 (buffer + 0x14)) | 1028 | if (len > BE32(buffer + 0x14)) { |
| 1029 | ldm_error("len %d > BE32(buffer + 0x14) %d", len, | ||
| 1030 | BE32(buffer + 0x14)); | ||
| 1003 | return false; | 1031 | return false; |
| 1004 | 1032 | } | |
| 1005 | part = &vb->vblk.part; | 1033 | part = &vb->vblk.part; |
| 1006 | part->start = BE64 (buffer + 0x24 + r_name); | 1034 | part->start = BE64(buffer + 0x24 + r_name); |
| 1007 | part->volume_offset = BE64 (buffer + 0x2C + r_name); | 1035 | part->volume_offset = BE64(buffer + 0x2C + r_name); |
| 1008 | part->size = ldm_get_vnum (buffer + 0x34 + r_name); | 1036 | part->size = ldm_get_vnum(buffer + 0x34 + r_name); |
| 1009 | part->parent_id = ldm_get_vnum (buffer + 0x34 + r_size); | 1037 | part->parent_id = ldm_get_vnum(buffer + 0x34 + r_size); |
| 1010 | part->disk_id = ldm_get_vnum (buffer + 0x34 + r_parent); | 1038 | part->disk_id = ldm_get_vnum(buffer + 0x34 + r_parent); |
| 1011 | if (vb->flags & VBLK_FLAG_PART_INDEX) | 1039 | if (vb->flags & VBLK_FLAG_PART_INDEX) |
| 1012 | part->partnum = buffer[0x35 + r_diskid]; | 1040 | part->partnum = buffer[0x35 + r_diskid]; |
| 1013 | else | 1041 | else |
| 1014 | part->partnum = 0; | 1042 | part->partnum = 0; |
| 1015 | |||
| 1016 | return true; | 1043 | return true; |
| 1017 | } | 1044 | } |
| 1018 | 1045 | ||
| @@ -1475,4 +1502,3 @@ out: | |||
| 1475 | kfree (ldb); | 1502 | kfree (ldb); |
| 1476 | return result; | 1503 | return result; |
| 1477 | } | 1504 | } |
| 1478 | |||
diff --git a/fs/partitions/ldm.h b/fs/partitions/ldm.h index 6e8d7952b8b5..d2e6a3046939 100644 --- a/fs/partitions/ldm.h +++ b/fs/partitions/ldm.h | |||
| @@ -2,10 +2,10 @@ | |||
| 2 | * ldm - Part of the Linux-NTFS project. | 2 | * ldm - Part of the Linux-NTFS project. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org> | 4 | * Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org> |
| 5 | * Copyright (C) 2001 Anton Altaparmakov <aia21@cantab.net> | 5 | * Copyright (c) 2001-2007 Anton Altaparmakov |
| 6 | * Copyright (C) 2001,2002 Jakob Kemi <jakob.kemi@telia.com> | 6 | * Copyright (C) 2001,2002 Jakob Kemi <jakob.kemi@telia.com> |
| 7 | * | 7 | * |
| 8 | * Documentation is available at http://linux-ntfs.sf.net/ldm | 8 | * Documentation is available at http://www.linux-ntfs.org/content/view/19/37/ |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify it | 10 | * This program is free software; you can redistribute it and/or modify it |
| 11 | * under the terms of the GNU General Public License as published by the Free | 11 | * under the terms of the GNU General Public License as published by the Free |
| @@ -93,7 +93,7 @@ struct parsed_partitions; | |||
| 93 | 93 | ||
| 94 | #define OFF_VMDB 17 /* List of partitions. */ | 94 | #define OFF_VMDB 17 /* List of partitions. */ |
| 95 | 95 | ||
| 96 | #define WIN2K_DYNAMIC_PARTITION 0x42 /* Formerly SFS (Landis). */ | 96 | #define LDM_PARTITION 0x42 /* Formerly SFS (Landis). */ |
| 97 | 97 | ||
| 98 | #define TOC_BITMAP1 "config" /* Names of the two defined */ | 98 | #define TOC_BITMAP1 "config" /* Names of the two defined */ |
| 99 | #define TOC_BITMAP2 "log" /* bitmaps in the TOCBLOCK. */ | 99 | #define TOC_BITMAP2 "log" /* bitmaps in the TOCBLOCK. */ |
