Drop BeRTOS SD and FAT modules
[rmslog.git] / FAT16 / partition.c
1
2 /*
3  * Copyright (c) 2006-2009 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. Use this in case you want to open the whole device
60  *                  as a single partition (e.g. for "super floppy" use).
61  * \returns 0 on failure, a partition descriptor on success.
62  * \see partition_close
63  */
64 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)
65 {
66     struct partition_struct* new_partition = 0;
67     uint8_t buffer[0x10];
68
69     if(!device_read || !device_read_interval || index >= 4)
70         return 0;
71
72     if(index >= 0)
73     {
74         /* read specified partition table index */
75         if(!device_read(0x01be + index * 0x10, buffer, sizeof(buffer)))
76             return 0;
77
78         /* abort on empty partition entry */
79         if(buffer[4] == 0x00)
80             return 0;
81     }
82
83     /* allocate partition descriptor */
84 #if USE_DYNAMIC_MEMORY
85     new_partition = malloc(sizeof(*new_partition));
86     if(!new_partition)
87         return 0;
88 #else
89     new_partition = partition_handles;
90     uint8_t i;
91     for(i = 0; i < PARTITION_COUNT; ++i)
92     {
93         if(new_partition->type == PARTITION_TYPE_FREE)
94             break;
95
96         ++new_partition;
97     }
98     if(i >= PARTITION_COUNT)
99         return 0;
100 #endif
101
102     memset(new_partition, 0, sizeof(*new_partition));
103
104     /* fill partition descriptor */
105     new_partition->device_read = device_read;
106     new_partition->device_read_interval = device_read_interval;
107     new_partition->device_write = device_write;
108     new_partition->device_write_interval = device_write_interval;
109
110     if(index >= 0)
111     {
112         new_partition->type = buffer[4];
113         new_partition->offset = ((uint32_t) buffer[8]) |
114                                 ((uint32_t) buffer[9] << 8) |
115                                 ((uint32_t) buffer[10] << 16) |
116                                 ((uint32_t) buffer[11] << 24);
117         new_partition->length = ((uint32_t) buffer[12]) |
118                                 ((uint32_t) buffer[13] << 8) |
119                                 ((uint32_t) buffer[14] << 16) |
120                                 ((uint32_t) buffer[15] << 24);
121     }
122     else
123     {
124         new_partition->type = 0xff;
125     }
126
127     return new_partition;
128 }
129
130 /**
131  * Closes a partition.
132  *
133  * This function destroys a partition descriptor which was
134  * previously obtained from a call to partition_open().
135  * When this function returns, the given descriptor will be
136  * invalid.
137  *
138  * \param[in] partition The partition descriptor to destroy.
139  * \returns 0 on failure, 1 on success.
140  * \see partition_open
141  */
142 uint8_t partition_close(struct partition_struct* partition)
143 {
144     if(!partition)
145         return 0;
146
147     /* destroy partition descriptor */
148 #if USE_DYNAMIC_MEMORY
149     free(partition);
150 #else
151     partition->type = PARTITION_TYPE_FREE;
152 #endif
153
154     return 1;
155 }
156
157 /**
158  * @}
159  */
160