summaryrefslogtreecommitdiff
path: root/trunk/users/metalab/GCode_Interpreter_SD/partition.cpp
blob: d5997e782b6d2020080b46f88ef59d1071579578 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160

/*
 * Copyright (c) 2006-2008 by Roland Riegel <feedback@roland-riegel.de>
 *
 * This file is free software; you can redistribute it and/or modify
 * it under the terms of either the GNU General Public License version 2
 * or the GNU Lesser General Public License version 2.1, both as
 * published by the Free Software Foundation.
 */

#include "partition.h"
#include "partition_config.h"
#include "sd-reader_config.h"

#include <string.h>

#if USE_DYNAMIC_MEMORY
    #include <stdlib.h>
#endif

/**
 * \addtogroup partition Partition table support
 *
 * Support for reading partition tables and access to partitions.
 *
 * @{
 */
/**
 * \file
 * Partition table implementation (license: GPLv2 or LGPLv2.1)
 *
 * \author Roland Riegel
 */

/**
 * \addtogroup partition_config Configuration of partition table support
 * Preprocessor defines to configure the partition support.
 */

#if !USE_DYNAMIC_MEMORY
static struct partition_struct partition_handles[PARTITION_COUNT];
#endif

/**
 * Opens a partition.
 *
 * Opens a partition by its index number and returns a partition
 * handle which describes the opened partition.
 *
 * \note This function does not support extended partitions.
 *
 * \param[in] device_read A function pointer which is used to read from the disk.
 * \param[in] device_read_interval A function pointer which is used to read in constant intervals from the disk.
 * \param[in] device_write A function pointer which is used to write to the disk.
 * \param[in] device_write_interval A function pointer which is used to write a data stream to disk.
 * \param[in] index The index of the partition which should be opened, range 0 to 3.
 *                  A negative value is allowed as well. In this case, the partition opened is
 *                  not checked for existance, begins at offset zero, has a length of zero
 *                  and is of an unknown type. Use this in case you want to open the whole device
 *                  as a single partition (e.g. for "super floppy" use).
 * \returns 0 on failure, a partition descriptor on success.
 * \see partition_close
 */
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)
{
    struct partition_struct* new_partition = 0;
    uint8_t buffer[0x10];

    if(!device_read || !device_read_interval || index >= 4)
        return 0;

    if(index >= 0)
    {
        /* read specified partition table index */
        if(!device_read(0x01be + index * 0x10, buffer, sizeof(buffer)))
            return 0;

        /* abort on empty partition entry */
        if(buffer[4] == 0x00)
            return 0;
    }

    /* allocate partition descriptor */
#if USE_DYNAMIC_MEMORY
    new_partition = malloc(sizeof(*new_partition));
    if(!new_partition)
        return 0;
#else
    new_partition = partition_handles;
    uint8_t i;
    for(i = 0; i < PARTITION_COUNT; ++i)
    {
        if(new_partition->type == PARTITION_TYPE_FREE)
            break;

        ++new_partition;
    }
    if(i >= PARTITION_COUNT)
        return 0;
#endif

    memset(new_partition, 0, sizeof(*new_partition));

    /* fill partition descriptor */
    new_partition->device_read = device_read;
    new_partition->device_read_interval = device_read_interval;
    new_partition->device_write = device_write;
    new_partition->device_write_interval = device_write_interval;

    if(index >= 0)
    {
        new_partition->type = buffer[4];
        new_partition->offset = ((uint32_t) buffer[8]) |
                                ((uint32_t) buffer[9] << 8) |
                                ((uint32_t) buffer[10] << 16) |
                                ((uint32_t) buffer[11] << 24);
        new_partition->length = ((uint32_t) buffer[12]) |
                                ((uint32_t) buffer[13] << 8) |
                                ((uint32_t) buffer[14] << 16) |
                                ((uint32_t) buffer[15] << 24);
    }
    else
    {
        new_partition->type = 0xff;
    }

    return new_partition;
}

/**
 * Closes a partition.
 *
 * This function destroys a partition descriptor which was
 * previously obtained from a call to partition_open().
 * When this function returns, the given descriptor will be
 * invalid.
 *
 * \param[in] partition The partition descriptor to destroy.
 * \returns 0 on failure, 1 on success.
 * \see partition_open
 */
uint8_t partition_close(struct partition_struct* partition)
{
    if(!partition)
        return 0;

    /* destroy partition descriptor */
#if USE_DYNAMIC_MEMORY
    free(partition);
#else
    partition->type = PARTITION_TYPE_FREE;
#endif

    return 1;
}

/**
 * @}
 */