ldm.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:33k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * ldm - Part of the Linux-NTFS project.
  3.  *
  4.  * Copyright (C) 2001 Richard Russon <ldm@flatcap.org>
  5.  * Copyright (C) 2001 Anton Altaparmakov <antona@users.sf.net> (AIA)
  6.  *
  7.  * Documentation is available at http://linux-ntfs.sf.net/ldm
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify it
  10.  * under the terms of the GNU General Public License as published by the Free
  11.  * Software Foundation; either version 2 of the License, or (at your option)
  12.  * any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program (in the main directory of the Linux-NTFS source
  21.  * in the file COPYING); if not, write to the Free Software Foundation,
  22.  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  23.  *
  24.  * 28/10/2001 - Added sorting of ldm partitions. (AIA)
  25.  */
  26. #include <linux/types.h>
  27. #include <asm/unaligned.h>
  28. #include <asm/byteorder.h>
  29. #include <linux/genhd.h>
  30. #include <linux/blkdev.h>
  31. #include <linux/slab.h>
  32. #include "check.h"
  33. #include "ldm.h"
  34. #include "msdos.h"
  35. #if 0 /* Fool kernel-doc since it doesn't do macros yet. */
  36. /**
  37.  * ldm_debug - output an error message if debugging was enabled at compile time
  38.  * @f: a printf format string containing the message
  39.  * @...: the variables to substitute into @f
  40.  *
  41.  * ldm_debug() writes a DEBUG level message to the syslog but only if the
  42.  * driver was compiled with debug enabled. Otherwise, the call turns into a NOP.
  43.  */
  44. static void ldm_debug(const char *f, ...);
  45. #endif
  46. #ifdef CONFIG_LDM_DEBUG
  47. #define ldm_debug(f, a...)
  48. {
  49. printk(LDM_DEBUG " DEBUG (%s, %d): %s: ",
  50. __FILE__, __LINE__, __FUNCTION__);
  51. printk(f, ##a);
  52. }
  53. #else /* !CONFIG_LDM_DEBUG */
  54. #define ldm_debug(f, a...) do {} while (0)
  55. #endif /* !CONFIG_LDM_DEBUG */
  56. /* Necessary forward declarations. */
  57. static int create_partition(struct gendisk *, int, int, int);
  58. static int parse_privhead(const u8 *, struct privhead *);
  59. static u64 get_vnum(const u8 *, int *);
  60. static int get_vstr(const u8 *, u8 *, const int);
  61. /**
  62.  * parse_vblk_part - parse a LDM database vblk partition record
  63.  * @buffer: vblk partition record loaded from the LDM database
  64.  * @buf_size: size of @buffer in bytes
  65.  * @vb: in memory vblk structure to return parsed information in
  66.  *
  67.  * This parses the LDM database vblk record of type VBLK_PART, i.e. a partition
  68.  * record, supplied in @buffer and sets up the in memory vblk structure @vb
  69.  * with the obtained information.
  70.  *
  71.  * Return 1 on success and -1 on error, in which case @vb is undefined.
  72.  */
  73. static int parse_vblk_part(const u8 *buffer, const int buf_size,
  74. struct vblk *vb)
  75. {
  76. int err, rel_objid, rel_name, rel_size, rel_parent;
  77. if (0x34 >= buf_size)
  78. return -1;
  79. /* Calculate relative offsets. */
  80. rel_objid  = 1 + buffer[0x18];
  81. if (0x18 + rel_objid >= buf_size)
  82. return -1;
  83. rel_name   = 1 + buffer[0x18 + rel_objid] + rel_objid;
  84. if (0x34 + rel_name >= buf_size)
  85. return -1;
  86. rel_size   = 1 + buffer[0x34 + rel_name] + rel_name;
  87. if (0x34 + rel_size >= buf_size)
  88. return -1;
  89. rel_parent = 1 + buffer[0x34 + rel_size] + rel_size;
  90. if (0x34 + rel_parent >= buf_size)
  91. return -1;
  92. /* Setup @vb. */
  93. vb->vblk_type    = VBLK_PART;
  94. vb->obj_id       = get_vnum(buffer + 0x18, &err);
  95. if (err || 0x34 + rel_parent + buffer[0x34 + rel_parent] >= buf_size)
  96. return -1;
  97. vb->disk_id      = get_vnum(buffer + 0x34 + rel_parent, &err);
  98. if (err || 0x24 + rel_name + 8 > buf_size)
  99. return -1;
  100. vb->start_sector = BE64(buffer + 0x24 + rel_name);
  101. if (0x34 + rel_name + buffer[0x34 + rel_name] >= buf_size)
  102. return -1;
  103. vb->num_sectors  = get_vnum(buffer + 0x34 + rel_name, &err);
  104. if (err || 0x18 + rel_objid + buffer[0x18 + rel_objid] >= buf_size)
  105. return -1;
  106. err = get_vstr(buffer + 0x18 + rel_objid, vb->name, sizeof(vb->name));
  107. if (err == -1)
  108. return err;
  109. ldm_debug("Parsed Partition VBLK successfully.n");
  110. return 1;
  111. }
  112. /**
  113.  * parse_vblk - parse a LDM database vblk record
  114.  * @buffer: vblk record loaded from the LDM database
  115.  * @buf_size: size of @buffer in bytes
  116.  * @vb: in memory vblk structure to return parsed information in
  117.  *
  118.  * This parses the LDM database vblk record supplied in @buffer and sets up
  119.  * the in memory vblk structure @vb with the obtained information.
  120.  *
  121.  * Return 1 on success, 0 if successful but record not in use, and -1 on error.
  122.  * If the return value is 0 or -1, @vb is undefined.
  123.  *
  124.  * NOTE: Currently the only record type we handle is VBLK_PART, i.e. records
  125.  * describing a partition. For all others, we just set @vb->vblk_type to 0 and
  126.  * return success. This of course means that if @vb->vblk_type is zero, all
  127.  * other fields in @vb are undefined.
  128.  */
  129. static int parse_vblk(const u8 *buffer, const int buf_size, struct vblk *vb)
  130. {
  131. int err = 1;
  132. if (buf_size < 0x14)
  133. return -1;
  134. if (MAGIC_VBLK != BE32(buffer)) {
  135. printk(LDM_CRIT "Cannot find VBLK, database may be corrupt.n");
  136. return -1;
  137. }
  138. if ((BE16(buffer + 0x0E) == 0) ||       /* Record is not in use. */
  139.     (BE16(buffer + 0x0C) != 0))         /* Part 2 of an ext. record */
  140. return 0;
  141. /* FIXME: What about extended VBLKs? */
  142. switch (buffer[0x13]) {
  143. case VBLK_PART:
  144. err = parse_vblk_part(buffer, buf_size, vb);
  145. break;
  146. default:
  147. vb->vblk_type = 0;
  148. }
  149. if (err != -1)
  150. ldm_debug("Parsed VBLK successfully.n");
  151. return err;
  152. }
  153. /**
  154.  * add_partition_to_list - insert partition into a partition list
  155.  * @pl: sorted list of partitions
  156.  * @hd: gendisk structure to which the data partition belongs
  157.  * @disk_minor: minor number of the disk device
  158.  * @start: first sector within the disk device
  159.  * @size: number of sectors on the partition device
  160.  *
  161.  * This sanity checks the partition specified by @start and @size against the
  162.  * device specified by @hd and inserts the partition into the sorted partition
  163.  * list @pl if the checks pass.
  164.  *
  165.  * On success return 1, otherwise return -1.
  166.  *
  167.  * TODO: Add sanity check for overlapping partitions. (AIA)
  168.  */ 
  169. static int add_partition_to_list(struct list_head *pl, const struct gendisk *hd,
  170. const int disk_minor, const unsigned long start,
  171. const unsigned long size)
  172. {
  173. struct ldm_part *lp, *lptmp;
  174. struct list_head *tmp;
  175. if (!hd->part)
  176. return -1;
  177. if ((start < 1) || ((start + size) > hd->part[disk_minor].nr_sects)) {
  178. printk(LDM_CRIT "LDM partition exceeds physical disk. "
  179. "Skipping.n");
  180. return -1;
  181. }
  182. lp = (struct ldm_part*)kmalloc(sizeof(struct ldm_part), GFP_KERNEL);
  183. if (!lp) {
  184. printk(LDM_CRIT "Not enough memory! Aborting LDM partition "
  185. "parsing.n");
  186. return -2;
  187. }
  188. INIT_LIST_HEAD(&lp->part_list);
  189. lp->start = start;
  190. lp->size = size;
  191. list_for_each(tmp, pl) {
  192. lptmp = list_entry(tmp, struct ldm_part, part_list);
  193. if (start > lptmp->start)
  194. continue;
  195. if (start < lptmp->start)
  196. break;
  197. printk(LDM_CRIT "Duplicate LDM partition entry! Skipping.n");
  198. kfree(lp);
  199. return -1;
  200. }
  201. list_add_tail(&lp->part_list, tmp);
  202. ldm_debug("Added LDM partition successfully.n");
  203. return 1;
  204. }
  205. /**
  206.  * create_data_partitions - create the data partition devices
  207.  * @hd: gendisk structure in which to create the data partitions
  208.  * @first_sector: first sector within the disk device
  209.  * @first_part_minor: first minor number of data partition devices
  210.  * @dev: partition device holding the LDM database
  211.  * @vm: in memory vmdb structure of @dev
  212.  * @ph: in memory privhead structure of the disk device
  213.  * @dk: in memory ldmdisk structure of the disk device
  214.  *
  215.  * The database contains ALL the partitions for ALL the disks, so we need to
  216.  * filter out this specific disk. Using the disk's object id, we can find all
  217.  * the partitions in the database that belong to this disk.
  218.  *
  219.  * For each found partition, we create a corresponding partition device starting
  220.  * with minor number @first_part_minor. But we do this in such a way that we
  221.  * actually sort the partitions in order of on-disk position. Any invalid
  222.  * partitions are completely ignored/skipped (an error is output but that's
  223.  * all).
  224.  *
  225.  * Return 1 on success and -1 on error.
  226.  */
  227. static int create_data_partitions(struct gendisk *hd,
  228. const unsigned long first_sector, int first_part_minor,
  229. struct block_device *bdev, const struct vmdb *vm,
  230. const struct privhead *ph, const struct ldmdisk *dk,
  231. unsigned long base)
  232. {
  233. Sector sect;
  234. unsigned char *data;
  235. struct vblk *vb;
  236. LIST_HEAD(pl); /* Sorted list of partitions. */
  237. struct ldm_part *lp;
  238. struct list_head *tmp;
  239. int vblk;
  240. int vsize; /* VBLK size. */
  241. int perbuf; /* VBLKs per buffer. */
  242. int buffer, lastbuf, lastofs, err, disk_minor;
  243. vb = (struct vblk*)kmalloc(sizeof(struct vblk), GFP_KERNEL);
  244. if (!vb)
  245. goto no_mem;
  246. vsize   = vm->vblk_size;
  247. if (vsize < 1 || vsize > 512)
  248. goto err_out;
  249. perbuf  = 512 / vsize;
  250. if (perbuf < 1 || 512 % vsize)
  251. goto err_out;
  252. /* 512 == VMDB size */
  253. lastbuf = vm->last_vblk_seq / perbuf - 1;
  254. lastofs = vm->last_vblk_seq % perbuf;
  255. if (lastofs)
  256. lastbuf++;
  257. if (OFF_VBLK * LDM_BLOCKSIZE + vm->last_vblk_seq * vsize >
  258. ph->config_size * 512)
  259. goto err_out;
  260. /*
  261.  * Get the minor number of the parent device so we can check we don't
  262.  * go beyond the end of the device.
  263.  */
  264. disk_minor = (first_part_minor >> hd->minor_shift) << hd->minor_shift;
  265. for (buffer = 0; buffer < lastbuf; buffer++) {
  266. data = read_dev_sector(bdev, base + 2*OFF_VBLK + buffer, &sect);
  267. if (!data)
  268. goto read_err;
  269. for (vblk = 0; vblk < perbuf; vblk++) {
  270. u8 *block;
  271. if (lastofs && buffer == lastbuf - 1 && vblk >= lastofs)
  272. break;
  273. block = data + vsize * vblk;
  274. if (block + vsize > data + 512)
  275. goto brelse_out;
  276. if (parse_vblk(block, vsize, vb) != 1)
  277. continue;
  278. if (vb->vblk_type != VBLK_PART)
  279. continue;
  280. if (dk->obj_id != vb->disk_id)
  281. continue;
  282. /* Ignore invalid partition errors. */
  283. if (add_partition_to_list(&pl, hd, disk_minor,
  284. first_sector + vb->start_sector +
  285. ph->logical_disk_start,
  286. vb->num_sectors) < -1)
  287. goto brelse_out;
  288. }
  289. put_dev_sector(sect);
  290. }
  291. err = 1;
  292. out:
  293. /* Finally create the nicely sorted data partitions. */
  294. printk(" <");
  295. list_for_each(tmp, &pl) {
  296. lp = list_entry(tmp, struct ldm_part, part_list);
  297. add_gd_partition(hd, first_part_minor++, lp->start, lp->size);
  298. }
  299. printk(" >n");
  300. if (!list_empty(&pl)) {
  301. struct list_head *tmp2;
  302. /* Cleanup the partition list which is now superfluous. */
  303. list_for_each_safe(tmp, tmp2, &pl) {
  304. lp = list_entry(tmp, struct ldm_part, part_list);
  305. list_del(tmp);
  306. kfree(lp);
  307. }
  308. }
  309. kfree(vb);
  310. return err;
  311. brelse_out:
  312. put_dev_sector(sect);
  313. goto err_out;
  314. no_mem:
  315. printk(LDM_CRIT "Not enough memory to allocate required buffers.n");
  316. goto err_out;
  317. read_err:
  318. printk(LDM_CRIT "Disk read failed in create_partitions.n");
  319. err_out:
  320. err = -1;
  321. goto out;
  322. }
  323. /**
  324.  * get_vnum - convert a variable-width, big endian number, to cpu u64 one
  325.  * @block: pointer to the variable-width number to convert
  326.  * @err: address of an integer into which to return the error code.
  327.  *
  328.  * This converts a variable-width, big endian number into a 64-bit, CPU format
  329.  * number and returns the result with err set to 0. If an error occurs return 0
  330.  * with err set to -1.
  331.  *
  332.  * The first byte of a variable-width number is the size of the number in bytes.
  333.  */
  334. static u64 get_vnum(const u8 *block, int *err)
  335. {
  336. u64 tmp = 0ULL;
  337. u8 length = *block++;
  338. if (length && length <= 8) {
  339. while (length--)
  340. tmp = (tmp << 8) | *block++;
  341. *err = 0;
  342. } else {
  343. printk(LDM_ERR "Illegal length in get_vnum(): %d.n", length);
  344. *err = 1;
  345. }
  346. return tmp;
  347. }
  348. /**
  349.  * get_vstr - convert a counted, non-null-terminated ASCII string to C-style one
  350.  * @block: string to convert
  351.  * @buffer: output buffer
  352.  * @buflen: size of output buffer
  353.  *
  354.  * This converts @block, a counted, non-null-terminated ASCII string, into a
  355.  * C-style, null-terminated, ASCII string and returns this in @buffer. The
  356.  * maximum number of characters converted is given by @buflen.
  357.  *
  358.  * The first bytes of a counted string stores the length of the string in bytes.
  359.  *
  360.  * Return the number of characters written to @buffer, not including the
  361.  * terminating null character, on success, and -1 on error, in which case
  362.  * @buffer is not defined.
  363.  */
  364. static int get_vstr(const u8 *block, u8 *buffer, const int buflen)
  365. {
  366. int length = block[0];
  367. if (length < 1)
  368. return -1;
  369. if (length >= buflen) {
  370. printk(LDM_ERR "String too long for buffer in get_vstr(): "
  371. "(%d/%d). Truncating.n", length, buflen);
  372. length = buflen - 1;
  373. }
  374. memcpy(buffer, block + 1, length);
  375. buffer[length] = (u8)'';
  376. return length;
  377. }
  378. /**
  379.  * get_disk_objid - obtain the object id for the device we are working on
  380.  * @dev: partition device holding the LDM database
  381.  * @vm: in memory vmdb structure of the LDM database
  382.  * @ph: in memory privhead structure of the device we are working on
  383.  * @dk: in memory ldmdisk structure to return information into
  384.  *
  385.  * This obtains the object id for the device we are working on as defined by
  386.  * the private header @ph. The obtained object id, together with the disk's
  387.  * GUID from @ph are returned in the ldmdisk structure pointed to by @dk.
  388.  *
  389.  * A Disk has two Ids. The main one is a GUID in string format. The second,
  390.  * used internally for cross-referencing, is a small, sequentially allocated,
  391.  * number. The PRIVHEAD, just after the partition table, tells us the disk's
  392.  * GUID. To find the disk's object id, we have to look through the database.
  393.  *
  394.  * Return 1 on success and -1 on error, in which case @dk is undefined.
  395.  */
  396. static int get_disk_objid(struct block_device *bdev, const struct vmdb *vm,
  397. const struct privhead *ph, struct ldmdisk *dk,
  398. unsigned long base)
  399. {
  400. Sector sect;
  401. unsigned char *data;
  402. u8 *disk_id;
  403. int vblk;
  404. int vsize; /* VBLK size. */
  405. int perbuf; /* VBLKs per buffer. */
  406. int buffer, lastbuf, lastofs, err;
  407. disk_id = (u8*)kmalloc(DISK_ID_SIZE, GFP_KERNEL);
  408. if (!disk_id)
  409. goto no_mem;
  410. vsize   = vm->vblk_size;
  411. if (vsize < 1 || vsize > 512)
  412. goto err_out;
  413. perbuf  = 512 / vsize;
  414. if (perbuf < 1 || 512 % vsize)
  415. goto err_out;
  416. /* 512 == VMDB size */
  417. lastbuf = vm->last_vblk_seq / perbuf - 1;
  418. lastofs = vm->last_vblk_seq % perbuf;
  419. if (lastofs)
  420. lastbuf++;
  421. if (OFF_VBLK * LDM_BLOCKSIZE + vm->last_vblk_seq * vsize >
  422. ph->config_size * 512)
  423. goto err_out;
  424. for (buffer = 0; buffer < lastbuf; buffer++) {
  425. data = read_dev_sector(bdev, base + 2*OFF_VBLK + buffer, &sect);
  426. if (!data)
  427. goto read_err;
  428. for (vblk = 0; vblk < perbuf; vblk++) {
  429. int rel_objid, rel_name, delta;
  430. u8 *block;
  431. if (lastofs && buffer == lastbuf - 1 && vblk >= lastofs)
  432. break;
  433. block = data + vblk * vsize;
  434. delta = vblk * vsize + 0x18;
  435. if (delta >= 512)
  436. goto brelse_out;
  437. if (block[0x0D] != 0) /* Extended VBLK, ignore */
  438. continue;
  439. if ((block[0x13] != VBLK_DSK1) &&
  440.     (block[0x13] != VBLK_DSK2))
  441. continue;
  442. /* Calculate relative offsets. */
  443. rel_objid = 1 + block[0x18];
  444. if (delta + rel_objid >= 512)
  445. goto brelse_out;
  446. rel_name  = 1 + block[0x18 + rel_objid] + rel_objid;
  447. if (delta + rel_name >= 512 ||
  448.     delta + rel_name + block[0x18 + rel_name] >= 512)
  449. goto brelse_out;
  450. err = get_vstr(block + 0x18 + rel_name, disk_id,
  451. DISK_ID_SIZE);
  452. if (err == -1)
  453. goto brelse_out;
  454. if (!strncmp(disk_id, ph->disk_id, DISK_ID_SIZE)) {
  455. dk->obj_id = get_vnum(block + 0x18, &err);
  456. put_dev_sector(sect);
  457. if (err)
  458. goto out;
  459. strncpy(dk->disk_id, ph->disk_id,
  460. sizeof(dk->disk_id));
  461. dk->disk_id[sizeof(dk->disk_id) - 1] = (u8)'';
  462. err = 1;
  463. goto out;
  464. }
  465. }
  466. put_dev_sector(sect);
  467. }
  468. err = -1;
  469. out:
  470. kfree(disk_id);
  471. return err;
  472. brelse_out:
  473. put_dev_sector(sect);
  474. goto err_out;
  475. no_mem:
  476. printk(LDM_CRIT "Not enough memory to allocate required buffers.n");
  477. goto err_out;
  478. read_err:
  479. printk(LDM_CRIT "Disk read failed in get_disk_objid.n");
  480. err_out:
  481. err = -1;
  482. goto out;
  483. }
  484. /**
  485.  * parse_vmdb - parse the LDM database vmdb structure
  486.  * @buffer: LDM database vmdb structure loaded from the device
  487.  * @vm: in memory vmdb structure to return parsed information in
  488.  *
  489.  * This parses the LDM database vmdb structure supplied in @buffer and sets up
  490.  * the in memory vmdb structure @vm with the obtained information.
  491.  *
  492.  * Return 1 on success and -1 on error, in which case @vm is undefined.
  493.  *
  494.  * NOTE: The *_start, *_size and *_seq values returned in @vm have not been
  495.  * checked for validity, so make sure to check them when using them.
  496.  */
  497. static int parse_vmdb(const u8 *buffer, struct vmdb *vm)
  498. {
  499. if (MAGIC_VMDB != BE32(buffer)) {
  500. printk(LDM_CRIT "Cannot find VMDB, database may be corrupt.n");
  501. return -1;
  502. }
  503. vm->ver_major = BE16(buffer + 0x12);
  504. vm->ver_minor = BE16(buffer + 0x14);
  505. if ((vm->ver_major != 4) || (vm->ver_minor != 10)) {
  506. printk(LDM_ERR "Expected VMDB version %d.%d, got %d.%d. "
  507. "Aborting.n", 4, 10, vm->ver_major,
  508. vm->ver_minor);
  509. return -1;
  510. }
  511. vm->vblk_size   = BE32(buffer + 0x08);
  512. vm->vblk_offset   = BE32(buffer + 0x0C);
  513. vm->last_vblk_seq = BE32(buffer + 0x04);
  514. ldm_debug("Parsed VMDB successfully.n");
  515. return 1;
  516. }
  517. /**
  518.  * validate_vmdb - validate the vmdb
  519.  * @dev: partition device holding the LDM database
  520.  * @vm: in memory vmdb in which to return information
  521.  *
  522.  * Find the vmdb of the LDM database stored on @dev and return the parsed
  523.  * information into @vm.
  524.  *
  525.  * Return 1 on success and -1 on error, in which case @vm is undefined.
  526.  */
  527. static int validate_vmdb(struct block_device *bdev, struct vmdb *vm, unsigned long base)
  528. {
  529. Sector sect;
  530. unsigned char *data;
  531. int ret;
  532. data = read_dev_sector(bdev, base + OFF_VMDB * 2 + 1, &sect);
  533. if (!data) {
  534. printk(LDM_CRIT "Disk read failed in validate_vmdb.n");
  535. return -1;
  536. }
  537. ret = parse_vmdb(data, vm);
  538. put_dev_sector(sect);
  539. return ret;
  540. }
  541. /**
  542.  * compare_tocblocks - compare two tables of contents
  543.  * @toc1: first toc
  544.  * @toc2: second toc
  545.  *
  546.  * This compares the two tables of contents @toc1 and @toc2.
  547.  *
  548.  * Return 1 if @toc1 and @toc2 are equal and -1 otherwise.
  549.  */
  550. static int compare_tocblocks(const struct tocblock *toc1,
  551. const struct tocblock *toc2)
  552. {
  553. if ((toc1->bitmap1_start == toc2->bitmap1_start) &&
  554.     (toc1->bitmap1_size  == toc2->bitmap1_size) &&
  555.     (toc1->bitmap2_start == toc2->bitmap2_start) &&
  556.     (toc1->bitmap2_size  == toc2->bitmap2_size) &&
  557.     !strncmp(toc1->bitmap1_name, toc2->bitmap1_name,
  558. sizeof(toc1->bitmap1_name)) &&
  559.     !strncmp(toc1->bitmap2_name, toc2->bitmap2_name,
  560. sizeof(toc1->bitmap2_name)))
  561. return 1;
  562. return -1;
  563. }
  564. /**
  565.  * parse_tocblock - parse the LDM database table of contents structure
  566.  * @buffer: LDM database toc structure loaded from the device
  567.  * @toc: in memory toc structure to return parsed information in
  568.  *
  569.  * This parses the LDM database table of contents structure supplied in @buffer
  570.  * and sets up the in memory table of contents structure @toc with the obtained
  571.  * information.
  572.  *
  573.  * Return 1 on success and -1 on error, in which case @toc is undefined.
  574.  *
  575.  * FIXME: The *_start and *_size values returned in @toc are not been checked
  576.  * for validity but as we don't use the actual values for anything other than
  577.  * comparing between the toc and its backups, the values are not important.
  578.  */
  579. static int parse_tocblock(const u8 *buffer, struct tocblock *toc)
  580. {
  581. if (MAGIC_TOCBLOCK != BE64(buffer)) {
  582. printk(LDM_CRIT "Cannot find TOCBLOCK, database may be "
  583. "corrupt.n");
  584. return -1;
  585. }
  586. strncpy(toc->bitmap1_name, buffer + 0x24, sizeof(toc->bitmap1_name));
  587. toc->bitmap1_name[sizeof(toc->bitmap1_name) - 1] = (u8)'';
  588. toc->bitmap1_start = BE64(buffer + 0x2E);
  589. toc->bitmap1_size  = BE64(buffer + 0x36);
  590. /*toc->bitmap1_flags = BE64(buffer + 0x3E);*/
  591. if (strncmp(toc->bitmap1_name, TOC_BITMAP1,
  592. sizeof(toc->bitmap1_name)) != 0) {
  593. printk(LDM_CRIT "TOCBLOCK's first bitmap should be %s, but is "
  594. "%s.n", TOC_BITMAP1, toc->bitmap1_name);
  595. return -1;
  596. }
  597. strncpy(toc->bitmap2_name, buffer + 0x46, sizeof(toc->bitmap2_name));
  598. toc->bitmap2_name[sizeof(toc->bitmap2_name) - 1] = (u8)'';
  599. toc->bitmap2_start = BE64(buffer + 0x50);
  600. toc->bitmap2_size  = BE64(buffer + 0x58);
  601. /*toc->bitmap2_flags = BE64(buffer + 0x60);*/
  602. if (strncmp(toc->bitmap2_name, TOC_BITMAP2,
  603. sizeof(toc->bitmap2_name)) != 0) {
  604. printk(LDM_CRIT "TOCBLOCK's second bitmap should be %s, but is "
  605. "%s.n", TOC_BITMAP2, toc->bitmap2_name);
  606. return -1;
  607. }
  608. ldm_debug("Parsed TOCBLOCK successfully.n");
  609. return 1;
  610. }
  611. /**
  612.  * validate_tocblocks - validate the table of contents and its backups
  613.  * @dev: partition device holding the LDM database
  614.  * @toc1: in memory table of contents in which to return information
  615.  *
  616.  * Find and compare the four tables of contents of the LDM database stored on
  617.  * @dev and return the parsed information into @toc1.
  618.  *
  619.  * Return 1 on success and -1 on error, in which case @toc1 is undefined.
  620.  */
  621. static int validate_tocblocks(struct block_device *bdev,
  622. struct tocblock *toc1,
  623. unsigned long base)
  624. {
  625. Sector sect;
  626. unsigned char *data;
  627. struct tocblock *toc2 = NULL, *toc3 = NULL, *toc4 = NULL;
  628. int err;
  629. toc2 = (struct tocblock*)kmalloc(sizeof(*toc2), GFP_KERNEL);
  630. if (!toc2)
  631. goto no_mem;
  632. toc3 = (struct tocblock*)kmalloc(sizeof(*toc3), GFP_KERNEL);
  633. if (!toc3)
  634. goto no_mem;
  635. toc4 = (struct tocblock*)kmalloc(sizeof(*toc4), GFP_KERNEL);
  636. if (!toc4)
  637. goto no_mem;
  638. /* Read and parse first toc. */
  639. data = read_dev_sector(bdev, base + OFF_TOCBLOCK1 * 2 + 1, &sect);
  640. if (!data) {
  641. printk(LDM_CRIT "Disk read 1 failed in validate_tocblocks.n");
  642. goto err_out;
  643. }
  644. err = parse_tocblock(data, toc1);
  645. put_dev_sector(sect);
  646. if (err != 1)
  647. goto out;
  648. /* Read and parse second toc. */
  649. data = read_dev_sector(bdev, base + OFF_TOCBLOCK2 * 2, &sect);
  650. if (!data) {
  651. printk(LDM_CRIT "Disk read 2 failed in validate_tocblocks.n");
  652. goto err_out;
  653. }
  654. err = parse_tocblock(data, toc2);
  655. put_dev_sector(sect);
  656. if (err != 1)
  657. goto out;
  658. /* Read and parse third toc. */
  659. data = read_dev_sector(bdev, base + OFF_TOCBLOCK3 * 2 + 1, &sect);
  660. if (!data) {
  661. printk(LDM_CRIT "Disk read 3 failed in validate_tocblocks.n");
  662. goto err_out;
  663. }
  664. err = parse_tocblock(data, toc3);
  665. put_dev_sector(sect);
  666. if (err != 1)
  667. goto out;
  668. /* Read and parse fourth toc. */
  669. data = read_dev_sector(bdev, base + OFF_TOCBLOCK4 * 2, &sect);
  670. if (!data) {
  671. printk(LDM_CRIT "Disk read 4 failed in validate_tocblocks.n");
  672. goto err_out;
  673. }
  674. err = parse_tocblock(data, toc4);
  675. put_dev_sector(sect);
  676. if (err != 1)
  677. goto out;
  678. /* Compare all tocs. */
  679. err = compare_tocblocks(toc1, toc2);
  680. if (err != 1) {
  681. printk(LDM_CRIT "First and second TOCBLOCKs don't match.n");
  682. goto out;
  683. }
  684. err = compare_tocblocks(toc3, toc4);
  685. if (err != 1) {
  686. printk(LDM_CRIT "Third and fourth TOCBLOCKs don't match.n");
  687. goto out;
  688. }
  689. err = compare_tocblocks(toc1, toc3);
  690. if (err != 1)
  691. printk(LDM_CRIT "First and third TOCBLOCKs don't match.n");
  692. else
  693. ldm_debug("Validated TOCBLOCKs successfully.n");
  694. out:
  695. kfree(toc2);
  696. kfree(toc3);
  697. kfree(toc4);
  698. return err;
  699. no_mem:
  700. printk(LDM_CRIT "Not enough memory to allocate required buffers.n");
  701. err_out:
  702. err = -1;
  703. goto out;
  704. }
  705. /**
  706.  * compare_privheads - compare two privheads
  707.  * @ph1: first privhead
  708.  * @ph2: second privhead
  709.  *
  710.  * This compares the two privheads @ph1 and @ph2.
  711.  *
  712.  * Return 1 if @ph1 and @ph2 are equal and -1 otherwise.
  713.  */
  714. static int compare_privheads(const struct privhead *ph1,
  715. const struct privhead *ph2)
  716. {
  717. if ((ph1->ver_major == ph2->ver_major)  &&
  718.     (ph1->ver_minor == ph2->ver_minor)  &&
  719.     (ph1->logical_disk_start == ph2->logical_disk_start) &&
  720.     (ph1->logical_disk_size  == ph2->logical_disk_size)  &&
  721.     (ph1->config_start == ph2->config_start)  &&
  722.     (ph1->config_size  == ph2->config_size)  &&
  723.     !strncmp(ph1->disk_id, ph2->disk_id, sizeof(ph1->disk_id)))
  724. return 1;
  725. return -1;
  726. }
  727. /**
  728.  * validate_privheads - compare the privhead backups to the first one
  729.  * @dev: partition device holding the LDM database
  730.  * @ph1: first privhead which we have already validated before
  731.  *
  732.  * We already have one privhead from the beginning of the disk.
  733.  * Now we compare the two other copies for safety.
  734.  *
  735.  * Return 1 on succes and -1 on error.
  736.  */
  737. static int validate_privheads(struct block_device *bdev,
  738.       const struct privhead *ph1,
  739.       unsigned long base)
  740. {
  741. Sector sect;
  742. unsigned char *data;
  743. struct privhead *ph2 = NULL, *ph3 = NULL;
  744. int err;
  745. ph2 = (struct privhead*)kmalloc(sizeof(*ph2), GFP_KERNEL);
  746. if (!ph2)
  747. goto no_mem;
  748. ph3 = (struct privhead*)kmalloc(sizeof(*ph3), GFP_KERNEL);
  749. if (!ph3)
  750. goto no_mem;
  751. data = read_dev_sector(bdev, base + OFF_PRIVHEAD2 * 2, &sect);
  752. if (!data) {
  753. printk(LDM_CRIT "Disk read 1 failed in validate_privheads.n");
  754. goto err_out;
  755. }
  756. err = parse_privhead(data, ph2);
  757. put_dev_sector(sect);
  758. if (err != 1)
  759. goto out;
  760. data = read_dev_sector(bdev, base + OFF_PRIVHEAD3 * 2 + 1, &sect);
  761. if (!data) {
  762. printk(LDM_CRIT "Disk read 2 failed in validate_privheads.n");
  763. goto err_out;
  764. }
  765. err = parse_privhead(data, ph3);
  766. put_dev_sector(sect);
  767. if (err != 1)
  768. goto out;
  769. err = compare_privheads(ph1, ph2);
  770. if (err != 1) {
  771. printk(LDM_CRIT "First and second PRIVHEADs don't match.n");
  772. goto out;
  773. }
  774. err = compare_privheads(ph1, ph3);
  775. if (err != 1)
  776. printk(LDM_CRIT "First and third PRIVHEADs don't match.n");
  777. else
  778. /* We _could_ have checked more. */
  779. ldm_debug("Validated PRIVHEADs successfully.n");
  780. out:
  781. kfree(ph2);
  782. kfree(ph3);
  783. return err;
  784. no_mem:
  785. printk(LDM_CRIT "Not enough memory to allocate required buffers.n");
  786. err_out:
  787. err = -1;
  788. goto out;
  789. }
  790. /**
  791.  * create_partition - validate input and create a kernel partition device
  792.  * @hd: gendisk structure in which to create partition
  793.  * @minor: minor number for device to create
  794.  * @start: starting offset of the partition into the parent device
  795.  * @size: size of the partition
  796.  *
  797.  * This validates the range, then puts an entry into the kernel's partition
  798.  * table.
  799.  *
  800.  * @start and @size are numbers of sectors.
  801.  *
  802.  * Return 1 on succes and -1 on error.
  803.  */
  804. static int create_partition(struct gendisk *hd, const int minor,
  805. const int start, const int size)
  806. {
  807. int disk_minor;
  808. if (!hd->part)
  809. return -1;
  810. /*
  811.  * Get the minor number of the parent device so we can check we don't
  812.  * go beyond the end of the device.
  813.  */
  814. disk_minor = (minor >> hd->minor_shift) << hd->minor_shift;
  815. if ((start < 1) || ((start + size) > hd->part[disk_minor].nr_sects)) {
  816. printk(LDM_CRIT "LDM Partition exceeds physical disk. "
  817. "Aborting.n");
  818. return -1;
  819. }
  820. add_gd_partition(hd, minor, start, size);
  821. ldm_debug("Created partition successfully.n");
  822. return 1;
  823. }
  824. /**
  825.  * parse_privhead - parse the LDM database PRIVHEAD structure
  826.  * @buffer: LDM database privhead structure loaded from the device
  827.  * @ph: in memory privhead structure to return parsed information in
  828.  *
  829.  * This parses the LDM database PRIVHEAD structure supplied in @buffer and
  830.  * sets up the in memory privhead structure @ph with the obtained information.
  831.  *
  832.  * Return 1 on succes and -1 on error, in which case @ph is undefined.
  833.  */
  834. static int parse_privhead(const u8 *buffer, struct privhead *ph)
  835. {
  836. if (MAGIC_PRIVHEAD != BE64(buffer)) {
  837. printk(LDM_ERR "Cannot find PRIVHEAD structure. LDM database "
  838. "is corrupt. Aborting.n");
  839. return -1;
  840. }
  841. ph->ver_major = BE16(buffer + 0x000C);
  842. ph->ver_minor = BE16(buffer + 0x000E);
  843. if ((ph->ver_major != 2) || (ph->ver_minor != 11)) {
  844. printk(LDM_ERR "Expected PRIVHEAD version %d.%d, got %d.%d. "
  845. "Aborting.n", 2, 11, ph->ver_major,
  846. ph->ver_minor);
  847. return -1;
  848. }
  849. ph->config_start = BE64(buffer + 0x012B);
  850. ph->config_size  = BE64(buffer + 0x0133);
  851. if (ph->config_size != LDM_DB_SIZE) { /* 1 MiB in sectors. */
  852. printk(LDM_ERR "Database should be %u bytes, claims to be %Lu "
  853. "bytes. Aborting.n", LDM_DB_SIZE,
  854. ph->config_size);
  855. return -1;
  856. }
  857. ph->logical_disk_start = BE64(buffer + 0x011B);
  858. ph->logical_disk_size  = BE64(buffer + 0x0123);
  859. if (!ph->logical_disk_size ||
  860.     ph->logical_disk_start + ph->logical_disk_size > ph->config_start)
  861. return -1;
  862. memcpy(ph->disk_id, buffer + 0x0030, sizeof(ph->disk_id));
  863. ldm_debug("Parsed PRIVHEAD successfully.n");
  864. return 1;
  865. }
  866. /**
  867.  * create_db_partition - create a dedicated partition for our database
  868.  * @hd: gendisk structure in which to create partition
  869.  * @dev: device of which to create partition
  870.  * @ph: @dev's LDM database private header
  871.  *
  872.  * Find the primary private header, locate the LDM database, then create a
  873.  * partition to wrap it.
  874.  *
  875.  * Return 1 on succes, 0 if device is not a dynamic disk and -1 on error.
  876.  */
  877. static int create_db_partition(struct gendisk *hd, struct block_device *bdev,
  878. const unsigned long first_sector, const int first_part_minor,
  879. struct privhead *ph)
  880. {
  881. Sector sect;
  882. unsigned char *data;
  883. int err;
  884. data = read_dev_sector(bdev, OFF_PRIVHEAD1*2, &sect);
  885. if (!data) {
  886. printk(LDM_CRIT __FUNCTION__ "(): Device read failed.n");
  887. return -1;
  888. }
  889. if (BE64(data) != MAGIC_PRIVHEAD) {
  890. ldm_debug("Cannot find PRIVHEAD structure. Not a dynamic disk "
  891. "or corrupt LDM database.n");
  892. return 0;
  893. }
  894. err = parse_privhead(data, ph);
  895. if (err == 1)
  896. err = create_partition(hd, first_part_minor, first_sector +
  897. ph->config_start, ph->config_size);
  898. put_dev_sector(sect);
  899. return err;
  900. }
  901. /**
  902.  * validate_patition_table - check whether @dev is a dynamic disk
  903.  * @dev: device to test
  904.  *
  905.  * Check whether @dev is a dynamic disk by looking for an MS-DOS-style partition
  906.  * table with one or more entries of type 0x42 (the former Secure File System
  907.  * (Landis) partition type, now recycled by Microsoft for dynamic disks) in it.
  908.  * If this succeeds we assume we have a dynamic disk, and not otherwise.
  909.  *
  910.  * Return 1 if @dev is a dynamic disk, 0 if not and -1 on error.
  911.  */
  912. static int validate_partition_table(struct block_device *bdev)
  913. {
  914. Sector sect;
  915. unsigned char *data;
  916. struct partition *p;
  917. int i, nr_sfs;
  918. data = read_dev_sector(bdev, 0, &sect);
  919. if (!data)
  920. return -1;
  921. if (*(u16*)(data + 0x01FE) != cpu_to_le16(MSDOS_LABEL_MAGIC)) {
  922. ldm_debug("No MS-DOS partition found.n");
  923. goto no_msdos_partition;
  924. }
  925. nr_sfs = 0;
  926. p = (struct partition*)(data + 0x01BE);
  927. for (i = 0; i < 4; i++) {
  928. if (!SYS_IND(p+i) || SYS_IND(p+i) == WIN2K_EXTENDED_PARTITION)
  929. continue;
  930. if (SYS_IND(p+i) == WIN2K_DYNAMIC_PARTITION) {
  931. nr_sfs++;
  932. continue;
  933. }
  934. goto not_dynamic_disk;
  935. }
  936. if (!nr_sfs)
  937. goto not_dynamic_disk;
  938. ldm_debug("Parsed partition table successfully.n");
  939. put_dev_sector(sect);
  940. return 1;
  941. not_dynamic_disk:
  942. // ldm_debug("Found basic MS-DOS partition, not a dynamic disk.n");
  943. no_msdos_partition:
  944. put_dev_sector(sect);
  945. return 0;
  946. }
  947. /**
  948.  * ldm_partition - find out whether a device is a dynamic disk and handle it
  949.  * @hd: gendisk structure in which to return the handled disk
  950.  * @dev: device we need to look at
  951.  * @first_sector: first sector within the device
  952.  * @first_part_minor: first minor number of partitions for the device
  953.  *
  954.  * Description:
  955.  *
  956.  * This determines whether the device @dev is a dynamic disk and if so creates
  957.  * the partitions necessary in the gendisk structure pointed to by @hd.
  958.  *
  959.  * We create a dummy device 1, which contains the LDM database, we skip
  960.  * devices 2-4 and then create each partition described by the LDM database
  961.  * in sequence as devices 5 and following. For example, if the device is hda,
  962.  * we would have: hda1: LDM database, hda2-4: nothing, hda5-following: the
  963.  * actual data containing partitions.
  964.  *
  965.  * Return values:
  966.  *
  967.  *  1 if @dev is a dynamic disk and we handled it,
  968.  *  0 if @dev is not a dynamic disk,
  969.  * -1 if an error occured.
  970.  */
  971. int ldm_partition(struct gendisk *hd, struct block_device *bdev,
  972. unsigned long first_sector, int first_part_minor)
  973. {
  974. struct privhead *ph  = NULL;
  975. struct tocblock *toc = NULL;
  976. struct vmdb     *vm  = NULL;
  977. struct ldmdisk  *dk  = NULL;
  978. unsigned long db_first;
  979. int err;
  980. if (!hd)
  981. return 0;
  982. /* Check the partition table. */
  983. err = validate_partition_table(bdev);
  984. if (err != 1)
  985. return err;
  986. if (!(ph = (struct privhead*)kmalloc(sizeof(*ph), GFP_KERNEL)))
  987. goto no_mem;
  988. /* Create the LDM database device. */
  989. err = create_db_partition(hd, bdev, first_sector, first_part_minor, ph);
  990. if (err != 1)
  991. goto out;
  992. db_first = hd->part[first_part_minor].start_sect;
  993. /* Check the backup privheads. */
  994. err = validate_privheads(bdev, ph, db_first);
  995. if (err != 1)
  996. goto out;
  997. /* Check the table of contents and its backups. */
  998. if (!(toc = (struct tocblock*)kmalloc(sizeof(*toc), GFP_KERNEL)))
  999. goto no_mem;
  1000. err = validate_tocblocks(bdev, toc, db_first);
  1001. if (err != 1)
  1002. goto out;
  1003. /* Check the vmdb. */
  1004. if (!(vm = (struct vmdb*)kmalloc(sizeof(*vm), GFP_KERNEL)))
  1005. goto no_mem;
  1006. err = validate_vmdb(bdev, vm, db_first);
  1007. if (err != 1)
  1008. goto out;
  1009. /* Find the object id for @dev in the LDM database. */
  1010. if (!(dk = (struct ldmdisk*)kmalloc(sizeof(*dk), GFP_KERNEL)))
  1011. goto no_mem;
  1012. err = get_disk_objid(bdev, vm, ph, dk, db_first);
  1013. if (err != 1)
  1014. goto out;
  1015. /* Finally, create the data partition devices. */
  1016. err = create_data_partitions(hd, first_sector, first_part_minor +
  1017. LDM_FIRST_PART_OFFSET, bdev, vm, ph, dk, db_first);
  1018. if (err == 1)
  1019. ldm_debug("Parsed LDM database successfully.n");
  1020. out:
  1021. kfree(ph);
  1022. kfree(toc);
  1023. kfree(vm);
  1024. kfree(dk);
  1025. return err;
  1026. no_mem:
  1027. printk(LDM_CRIT "Not enough memory to allocate required buffers.n");
  1028. err = -1;
  1029. goto out;
  1030. }