OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [fs/] [udf/] [misc.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * misc.c
3
 *
4
 * PURPOSE
5
 *      Miscellaneous routines for the OSTA-UDF(tm) filesystem.
6
 *
7
 * COPYRIGHT
8
 *      This file is distributed under the terms of the GNU General Public
9
 *      License (GPL). Copies of the GPL can be obtained from:
10
 *              ftp://prep.ai.mit.edu/pub/gnu/GPL
11
 *      Each contributing author retains all rights to their own work.
12
 *
13
 *  (C) 1998 Dave Boynton
14
 *  (C) 1998-2004 Ben Fennema
15
 *  (C) 1999-2000 Stelias Computing Inc
16
 *
17
 * HISTORY
18
 *
19
 *  04/19/99 blf  partial support for reading/writing specific EA's
20
 */
21
 
22
#include "udfdecl.h"
23
 
24
#include <linux/fs.h>
25
#include <linux/string.h>
26
#include <linux/udf_fs.h>
27
#include <linux/buffer_head.h>
28
 
29
#include "udf_i.h"
30
#include "udf_sb.h"
31
 
32
struct buffer_head *udf_tgetblk(struct super_block *sb, int block)
33
{
34
        if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV))
35
                return sb_getblk(sb, udf_fixed_to_variable(block));
36
        else
37
                return sb_getblk(sb, block);
38
}
39
 
40
struct buffer_head *udf_tread(struct super_block *sb, int block)
41
{
42
        if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV))
43
                return sb_bread(sb, udf_fixed_to_variable(block));
44
        else
45
                return sb_bread(sb, block);
46
}
47
 
48
struct genericFormat *udf_add_extendedattr(struct inode *inode, uint32_t size,
49
                                           uint32_t type, uint8_t loc)
50
{
51
        uint8_t *ea = NULL, *ad = NULL;
52
        int offset;
53
        uint16_t crclen;
54
        int i;
55
 
56
        ea = UDF_I_DATA(inode);
57
        if (UDF_I_LENEATTR(inode)) {
58
                ad = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
59
        } else {
60
                ad = ea;
61
                size += sizeof(struct extendedAttrHeaderDesc);
62
        }
63
 
64
        offset = inode->i_sb->s_blocksize - udf_file_entry_alloc_offset(inode) -
65
                UDF_I_LENALLOC(inode);
66
 
67
        /* TODO - Check for FreeEASpace */
68
 
69
        if (loc & 0x01 && offset >= size) {
70
                struct extendedAttrHeaderDesc *eahd;
71
                eahd = (struct extendedAttrHeaderDesc *)ea;
72
 
73
                if (UDF_I_LENALLOC(inode)) {
74
                        memmove(&ad[size], ad, UDF_I_LENALLOC(inode));
75
                }
76
 
77
                if (UDF_I_LENEATTR(inode)) {
78
                        /* check checksum/crc */
79
                        if (le16_to_cpu(eahd->descTag.tagIdent) != TAG_IDENT_EAHD ||
80
                            le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum) {
81
                                return NULL;
82
                        }
83
                } else {
84
                        size -= sizeof(struct extendedAttrHeaderDesc);
85
                        UDF_I_LENEATTR(inode) += sizeof(struct extendedAttrHeaderDesc);
86
                        eahd->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EAHD);
87
                        if (UDF_SB_UDFREV(inode->i_sb) >= 0x0200)
88
                                eahd->descTag.descVersion = cpu_to_le16(3);
89
                        else
90
                                eahd->descTag.descVersion = cpu_to_le16(2);
91
                        eahd->descTag.tagSerialNum = cpu_to_le16(UDF_SB_SERIALNUM(inode->i_sb));
92
                        eahd->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);
93
                        eahd->impAttrLocation = cpu_to_le32(0xFFFFFFFF);
94
                        eahd->appAttrLocation = cpu_to_le32(0xFFFFFFFF);
95
                }
96
 
97
                offset = UDF_I_LENEATTR(inode);
98
                if (type < 2048) {
99
                        if (le32_to_cpu(eahd->appAttrLocation) < UDF_I_LENEATTR(inode)) {
100
                                uint32_t aal = le32_to_cpu(eahd->appAttrLocation);
101
                                memmove(&ea[offset - aal + size],
102
                                        &ea[aal], offset - aal);
103
                                offset -= aal;
104
                                eahd->appAttrLocation = cpu_to_le32(aal + size);
105
                        }
106
                        if (le32_to_cpu(eahd->impAttrLocation) < UDF_I_LENEATTR(inode)) {
107
                                uint32_t ial = le32_to_cpu(eahd->impAttrLocation);
108
                                memmove(&ea[offset - ial + size],
109
                                        &ea[ial], offset - ial);
110
                                offset -= ial;
111
                                eahd->impAttrLocation = cpu_to_le32(ial + size);
112
                        }
113
                } else if (type < 65536) {
114
                        if (le32_to_cpu(eahd->appAttrLocation) < UDF_I_LENEATTR(inode)) {
115
                                uint32_t aal = le32_to_cpu(eahd->appAttrLocation);
116
                                memmove(&ea[offset - aal + size],
117
                                        &ea[aal], offset - aal);
118
                                offset -= aal;
119
                                eahd->appAttrLocation = cpu_to_le32(aal + size);
120
                        }
121
                }
122
                /* rewrite CRC + checksum of eahd */
123
                crclen = sizeof(struct extendedAttrHeaderDesc) - sizeof(tag);
124
                eahd->descTag.descCRCLength = cpu_to_le16(crclen);
125
                eahd->descTag.descCRC = cpu_to_le16(udf_crc((char *)eahd +
126
                                                            sizeof(tag), crclen, 0));
127
                eahd->descTag.tagChecksum = 0;
128
                for (i = 0; i < 16; i++)
129
                        if (i != 4)
130
                                eahd->descTag.tagChecksum += ((uint8_t *)&(eahd->descTag))[i];
131
                UDF_I_LENEATTR(inode) += size;
132
                return (struct genericFormat *)&ea[offset];
133
        }
134
        if (loc & 0x02) {
135
        }
136
 
137
        return NULL;
138
}
139
 
140
struct genericFormat *udf_get_extendedattr(struct inode *inode, uint32_t type,
141
                                           uint8_t subtype)
142
{
143
        struct genericFormat *gaf;
144
        uint8_t *ea = NULL;
145
        uint32_t offset;
146
 
147
        ea = UDF_I_DATA(inode);
148
 
149
        if (UDF_I_LENEATTR(inode)) {
150
                struct extendedAttrHeaderDesc *eahd;
151
                eahd = (struct extendedAttrHeaderDesc *)ea;
152
 
153
                /* check checksum/crc */
154
                if (le16_to_cpu(eahd->descTag.tagIdent) != TAG_IDENT_EAHD ||
155
                    le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum) {
156
                        return NULL;
157
                }
158
 
159
                if (type < 2048)
160
                        offset = sizeof(struct extendedAttrHeaderDesc);
161
                else if (type < 65536)
162
                        offset = le32_to_cpu(eahd->impAttrLocation);
163
                else
164
                        offset = le32_to_cpu(eahd->appAttrLocation);
165
 
166
                while (offset < UDF_I_LENEATTR(inode)) {
167
                        gaf = (struct genericFormat *)&ea[offset];
168
                        if (le32_to_cpu(gaf->attrType) == type && gaf->attrSubtype == subtype)
169
                                return gaf;
170
                        else
171
                                offset += le32_to_cpu(gaf->attrLength);
172
                }
173
        }
174
 
175
        return NULL;
176
}
177
 
178
/*
179
 * udf_read_tagged
180
 *
181
 * PURPOSE
182
 *      Read the first block of a tagged descriptor.
183
 *
184
 * HISTORY
185
 *      July 1, 1997 - Andrew E. Mileski
186
 *      Written, tested, and released.
187
 */
188
struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
189
                                    uint32_t location, uint16_t * ident)
190
{
191
        tag *tag_p;
192
        struct buffer_head *bh = NULL;
193
        register uint8_t checksum;
194
        register int i;
195
 
196
        /* Read the block */
197
        if (block == 0xFFFFFFFF)
198
                return NULL;
199
 
200
        bh = udf_tread(sb, block + UDF_SB_SESSION(sb));
201
        if (!bh) {
202
                udf_debug("block=%d, location=%d: read failed\n",
203
                          block + UDF_SB_SESSION(sb), location);
204
                return NULL;
205
        }
206
 
207
        tag_p = (tag *)(bh->b_data);
208
 
209
        *ident = le16_to_cpu(tag_p->tagIdent);
210
 
211
        if (location != le32_to_cpu(tag_p->tagLocation)) {
212
                udf_debug("location mismatch block %u, tag %u != %u\n",
213
                          block + UDF_SB_SESSION(sb), le32_to_cpu(tag_p->tagLocation), location);
214
                goto error_out;
215
        }
216
 
217
        /* Verify the tag checksum */
218
        checksum = 0U;
219
        for (i = 0; i < 4; i++)
220
                checksum += (uint8_t)(bh->b_data[i]);
221
        for (i = 5; i < 16; i++)
222
                checksum += (uint8_t)(bh->b_data[i]);
223
        if (checksum != tag_p->tagChecksum) {
224
                printk(KERN_ERR "udf: tag checksum failed block %d\n", block);
225
                goto error_out;
226
        }
227
 
228
        /* Verify the tag version */
229
        if (le16_to_cpu(tag_p->descVersion) != 0x0002U &&
230
            le16_to_cpu(tag_p->descVersion) != 0x0003U) {
231
                udf_debug("tag version 0x%04x != 0x0002 || 0x0003 block %d\n",
232
                          le16_to_cpu(tag_p->descVersion), block);
233
                goto error_out;
234
        }
235
 
236
        /* Verify the descriptor CRC */
237
        if (le16_to_cpu(tag_p->descCRCLength) + sizeof(tag) > sb->s_blocksize ||
238
            le16_to_cpu(tag_p->descCRC) == udf_crc(bh->b_data + sizeof(tag),
239
                                                   le16_to_cpu(tag_p->descCRCLength), 0)) {
240
                return bh;
241
        }
242
        udf_debug("Crc failure block %d: crc = %d, crclen = %d\n",
243
                  block + UDF_SB_SESSION(sb), le16_to_cpu(tag_p->descCRC),
244
                  le16_to_cpu(tag_p->descCRCLength));
245
 
246
error_out:
247
        brelse(bh);
248
        return NULL;
249
}
250
 
251
struct buffer_head *udf_read_ptagged(struct super_block *sb, kernel_lb_addr loc,
252
                                     uint32_t offset, uint16_t * ident)
253
{
254
        return udf_read_tagged(sb, udf_get_lb_pblock(sb, loc, offset),
255
                               loc.logicalBlockNum + offset, ident);
256
}
257
 
258
void udf_update_tag(char *data, int length)
259
{
260
        tag *tptr = (tag *)data;
261
        int i;
262
 
263
        length -= sizeof(tag);
264
 
265
        tptr->tagChecksum = 0;
266
        tptr->descCRCLength = cpu_to_le16(length);
267
        tptr->descCRC = cpu_to_le16(udf_crc(data + sizeof(tag), length, 0));
268
 
269
        for (i = 0; i < 16; i++)
270
                if (i != 4)
271
                        tptr->tagChecksum += (uint8_t)(data[i]);
272
}
273
 
274
void udf_new_tag(char *data, uint16_t ident, uint16_t version, uint16_t snum,
275
                 uint32_t loc, int length)
276
{
277
        tag *tptr = (tag *)data;
278
        tptr->tagIdent = cpu_to_le16(ident);
279
        tptr->descVersion = cpu_to_le16(version);
280
        tptr->tagSerialNum = cpu_to_le16(snum);
281
        tptr->tagLocation = cpu_to_le32(loc);
282
        udf_update_tag(data, length);
283
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.