| 1144 | kaklik | 1 |  | 
      
        |  |  | 2 | /* | 
      
        |  |  | 3 |  * Copyright (c) 2006-2007 by Roland Riegel <feedback@roland-riegel.de> | 
      
        |  |  | 4 |  * | 
      
        |  |  | 5 |  * This file is free software; you can redistribute it and/or modify | 
      
        |  |  | 6 |  * it under the terms of either the GNU General Public License version 2 | 
      
        |  |  | 7 |  * or the GNU Lesser General Public License version 2.1, both as | 
      
        |  |  | 8 |  * published by the Free Software Foundation. | 
      
        |  |  | 9 |  */ | 
      
        |  |  | 10 |  | 
      
        |  |  | 11 | #include "partition.h" | 
      
        |  |  | 12 | #include "partition_config.h" | 
      
        |  |  | 13 | #include "sd-reader_config.h" | 
      
        |  |  | 14 |  | 
      
        |  |  | 15 | #include <string.h> | 
      
        |  |  | 16 |  | 
      
        |  |  | 17 | #if USE_DYNAMIC_MEMORY | 
      
        |  |  | 18 |     #include <stdlib.h> | 
      
        |  |  | 19 | #endif | 
      
        |  |  | 20 |  | 
      
        |  |  | 21 | /** | 
      
        |  |  | 22 |  * \addtogroup partition Partition table support | 
      
        |  |  | 23 |  * | 
      
        |  |  | 24 |  * Support for reading partition tables and access to partitions. | 
      
        |  |  | 25 |  * | 
      
        |  |  | 26 |  * @{ | 
      
        |  |  | 27 |  */ | 
      
        |  |  | 28 | /** | 
      
        |  |  | 29 |  * \file | 
      
        |  |  | 30 |  * Partition table implementation (license: GPLv2 or LGPLv2.1) | 
      
        |  |  | 31 |  * | 
      
        |  |  | 32 |  * \author Roland Riegel | 
      
        |  |  | 33 |  */ | 
      
        |  |  | 34 |  | 
      
        |  |  | 35 | /** | 
      
        |  |  | 36 |  * \addtogroup partition_config Configuration of partition table support | 
      
        |  |  | 37 |  * Preprocessor defines to configure the partition support. | 
      
        |  |  | 38 |  */ | 
      
        |  |  | 39 |  | 
      
        |  |  | 40 | #if !USE_DYNAMIC_MEMORY | 
      
        |  |  | 41 | static struct partition_struct partition_handles[PARTITION_COUNT]; | 
      
        |  |  | 42 | #endif | 
      
        |  |  | 43 |  | 
      
        |  |  | 44 | /** | 
      
        |  |  | 45 |  * Opens a partition. | 
      
        |  |  | 46 |  * | 
      
        |  |  | 47 |  * Opens a partition by its index number and returns a partition | 
      
        |  |  | 48 |  * handle which describes the opened partition. | 
      
        |  |  | 49 |  * | 
      
        |  |  | 50 |  * \note This function does not support extended partitions. | 
      
        |  |  | 51 |  * | 
      
        |  |  | 52 |  * \param[in] device_read A function pointer which is used to read from the disk. | 
      
        |  |  | 53 |  * \param[in] device_read_interval A function pointer which is used to read in constant intervals from the disk. | 
      
        |  |  | 54 |  * \param[in] device_write A function pointer which is used to write to the disk. | 
      
        |  |  | 55 |  * \param[in] device_write_interval A function pointer which is used to write a data stream to disk. | 
      
        |  |  | 56 |  * \param[in] index The index of the partition which should be opened, range 0 to 3. | 
      
        |  |  | 57 |  *                  A negative value is allowed as well. In this case, the partition opened is | 
      
        |  |  | 58 |  *                  not checked for existance, begins at offset zero, has a length of zero | 
      
        |  |  | 59 |  *                  and is of an unknown type. | 
      
        |  |  | 60 |  * \returns 0 on failure, a partition descriptor on success. | 
      
        |  |  | 61 |  * \see partition_close | 
      
        |  |  | 62 |  */ | 
      
        |  |  | 63 | struct partition_struct* partition_open(device_read_t device_read, device_read_interval_t device_read_interval, device_write_t device_write, device_write_interval_t device_write_interval, int8_t index) | 
      
        |  |  | 64 | { | 
      
        |  |  | 65 |     struct partition_struct* new_partition = 0; | 
      
        |  |  | 66 |     uint8_t buffer[0x10]; | 
      
        |  |  | 67 |  | 
      
        |  |  | 68 |     if(!device_read || !device_read_interval || index >= 4) | 
      
        |  |  | 69 |         return 0; | 
      
        |  |  | 70 |  | 
      
        |  |  | 71 |     if(index >= 0) | 
      
        |  |  | 72 |     { | 
      
        |  |  | 73 |         /* read specified partition table index */ | 
      
        |  |  | 74 |         if(!device_read(0x01be + index * 0x10, buffer, sizeof(buffer))) | 
      
        |  |  | 75 |             return 0; | 
      
        |  |  | 76 |  | 
      
        |  |  | 77 |         /* abort on empty partition entry */ | 
      
        |  |  | 78 |         if(buffer[4] == 0x00) | 
      
        |  |  | 79 |             return 0; | 
      
        |  |  | 80 |     } | 
      
        |  |  | 81 |  | 
      
        |  |  | 82 |     /* allocate partition descriptor */ | 
      
        |  |  | 83 | #if USE_DYNAMIC_MEMORY | 
      
        |  |  | 84 |     new_partition = malloc(sizeof(*new_partition)); | 
      
        |  |  | 85 |     if(!new_partition) | 
      
        |  |  | 86 |         return 0; | 
      
        |  |  | 87 | #else | 
      
        |  |  | 88 |     new_partition = partition_handles; | 
      
        |  |  | 89 |     uint8_t i; | 
      
        |  |  | 90 |     for(i = 0; i < PARTITION_COUNT; ++i) | 
      
        |  |  | 91 |     { | 
      
        |  |  | 92 |         if(new_partition->type == PARTITION_TYPE_FREE) | 
      
        |  |  | 93 |             break; | 
      
        |  |  | 94 |  | 
      
        |  |  | 95 |         ++new_partition; | 
      
        |  |  | 96 |     } | 
      
        |  |  | 97 |     if(i >= PARTITION_COUNT) | 
      
        |  |  | 98 |         return 0; | 
      
        |  |  | 99 | #endif | 
      
        |  |  | 100 |  | 
      
        |  |  | 101 |     memset(new_partition, 0, sizeof(*new_partition)); | 
      
        |  |  | 102 |  | 
      
        |  |  | 103 |     /* fill partition descriptor */ | 
      
        |  |  | 104 |     new_partition->device_read = device_read; | 
      
        |  |  | 105 |     new_partition->device_read_interval = device_read_interval; | 
      
        |  |  | 106 |     new_partition->device_write = device_write; | 
      
        |  |  | 107 |     new_partition->device_write_interval = device_write_interval; | 
      
        |  |  | 108 |  | 
      
        |  |  | 109 |     if(index >= 0) | 
      
        |  |  | 110 |     { | 
      
        |  |  | 111 |         new_partition->type = buffer[4]; | 
      
        |  |  | 112 |         new_partition->offset = ((uint32_t) buffer[8]) | | 
      
        |  |  | 113 |                                 ((uint32_t) buffer[9] << 8) | | 
      
        |  |  | 114 |                                 ((uint32_t) buffer[10] << 16) | | 
      
        |  |  | 115 |                                 ((uint32_t) buffer[11] << 24); | 
      
        |  |  | 116 |         new_partition->length = ((uint32_t) buffer[12]) | | 
      
        |  |  | 117 |                                 ((uint32_t) buffer[13] << 8) | | 
      
        |  |  | 118 |                                 ((uint32_t) buffer[14] << 16) | | 
      
        |  |  | 119 |                                 ((uint32_t) buffer[15] << 24); | 
      
        |  |  | 120 |     } | 
      
        |  |  | 121 |     else | 
      
        |  |  | 122 |     { | 
      
        |  |  | 123 |         new_partition->type = 0xff; | 
      
        |  |  | 124 |     } | 
      
        |  |  | 125 |  | 
      
        |  |  | 126 |     return new_partition; | 
      
        |  |  | 127 | } | 
      
        |  |  | 128 |  | 
      
        |  |  | 129 | /** | 
      
        |  |  | 130 |  * Closes a partition. | 
      
        |  |  | 131 |  * | 
      
        |  |  | 132 |  * This function destroys a partition descriptor which was | 
      
        |  |  | 133 |  * previously obtained from a call to partition_open(). | 
      
        |  |  | 134 |  * When this function returns, the given descriptor will be | 
      
        |  |  | 135 |  * invalid. | 
      
        |  |  | 136 |  * | 
      
        |  |  | 137 |  * \param[in] partition The partition descriptor to destroy. | 
      
        |  |  | 138 |  * \returns 0 on failure, 1 on success. | 
      
        |  |  | 139 |  * \see partition_open | 
      
        |  |  | 140 |  */ | 
      
        |  |  | 141 | uint8_t partition_close(struct partition_struct* partition) | 
      
        |  |  | 142 | { | 
      
        |  |  | 143 |     if(!partition) | 
      
        |  |  | 144 |         return 0; | 
      
        |  |  | 145 |  | 
      
        |  |  | 146 |     /* destroy partition descriptor */ | 
      
        |  |  | 147 | #if USE_DYNAMIC_MEMORY | 
      
        |  |  | 148 |     free(partition); | 
      
        |  |  | 149 | #else | 
      
        |  |  | 150 |     partition->type = PARTITION_TYPE_FREE; | 
      
        |  |  | 151 | #endif | 
      
        |  |  | 152 |  | 
      
        |  |  | 153 |     return 1; | 
      
        |  |  | 154 | } | 
      
        |  |  | 155 |  | 
      
        |  |  | 156 | /** | 
      
        |  |  | 157 |  * @} | 
      
        |  |  | 158 |  */ | 
      
        |  |  | 159 |  |