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