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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [hfsplus/] [wrapper.c] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  linux/fs/hfsplus/wrapper.c
3
 *
4
 * Copyright (C) 2001
5
 * Brad Boyer (flar@allandria.com)
6
 * (C) 2003 Ardis Technologies <roman@ardistech.com>
7
 *
8
 * Handling of HFS wrappers around HFS+ volumes
9
 */
10
 
11
#include <linux/fs.h>
12
#include <linux/blkdev.h>
13
#include <linux/version.h>
14
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
15
#include <linux/buffer_head.h>
16
#endif
17
#include <asm/unaligned.h>
18
 
19
#include "hfsplus_fs.h"
20
#include "hfsplus_raw.h"
21
 
22
struct hfsplus_wd {
23
        u32 ablk_size;
24
        u16 ablk_start;
25
        u16 embed_start;
26
        u16 embed_count;
27
};
28
 
29
static int hfsplus_read_mdb(unsigned char *bufptr, struct hfsplus_wd *wd)
30
{
31
        u32 extent;
32
        u16 attrib;
33
 
34
        if (be16_to_cpu(*(u16 *)(bufptr + HFSP_WRAPOFF_EMBEDSIG)) != HFSPLUS_VOLHEAD_SIG)
35
                return 0;
36
 
37
        attrib = be16_to_cpu(*(u16 *)(bufptr + HFSP_WRAPOFF_ATTRIB));
38
        if (!(attrib & HFSP_WRAP_ATTRIB_SLOCK) ||
39
           !(attrib & HFSP_WRAP_ATTRIB_SPARED))
40
                return 0;
41
 
42
        wd->ablk_size = be32_to_cpu(*(u32 *)(bufptr + HFSP_WRAPOFF_ABLKSIZE));
43
        if (wd->ablk_size < HFSPLUS_SECTOR_SIZE)
44
                return 0;
45
        if (wd->ablk_size % HFSPLUS_SECTOR_SIZE)
46
                return 0;
47
        wd->ablk_start = be16_to_cpu(*(u16 *)(bufptr + HFSP_WRAPOFF_ABLKSTART));
48
 
49
        extent = be32_to_cpu(get_unaligned((u32 *)(bufptr + HFSP_WRAPOFF_EMBEDEXT)));
50
        wd->embed_start = (extent >> 16) & 0xFFFF;
51
        wd->embed_count = extent & 0xFFFF;
52
 
53
        return 1;
54
}
55
 
56
/* Find the volume header and fill in some minimum bits in superblock */
57
/* Takes in super block, returns true if good data read */
58
int hfsplus_read_wrapper(struct super_block *sb)
59
{
60
        struct buffer_head *bh;
61
        struct hfsplus_vh *vhdr;
62
        char *bufptr;
63
        unsigned long block, offset, vhsect;
64
        struct hfsplus_wd wd;
65
        u32 blocksize, blockoffset;
66
        u16 sig;
67
 
68
        blocksize = sb_min_blocksize(sb, HFSPLUS_SECTOR_SIZE);
69
        if (!blocksize) {
70
                printk("HFS+-fs: unable to configure block size\n");
71
                return -EINVAL;
72
        }
73
 
74
        block = (HFSPLUS_VOLHEAD_SECTOR * HFSPLUS_SECTOR_SIZE) / blocksize;
75
        offset = (HFSPLUS_VOLHEAD_SECTOR * HFSPLUS_SECTOR_SIZE) % blocksize;
76
 
77
        bh = sb_bread(sb, block);
78
        if (!bh) {
79
                printk("HFS+-fs: unable to read VHDR or MDB\n");
80
                return -EIO;
81
        }
82
 
83
        bufptr = bh->b_data + offset;
84
        sig = be16_to_cpu(*(u16 *)(bufptr + HFSP_WRAPOFF_SIG));
85
        if (sig == HFSP_WRAP_MAGIC) {
86
                if (!hfsplus_read_mdb(bufptr, &wd))
87
                        goto error;
88
                vhsect = (wd.ablk_start + wd.embed_start * (wd.ablk_size >> 9))
89
                        + HFSPLUS_VOLHEAD_SECTOR;
90
                block = (vhsect * HFSPLUS_SECTOR_SIZE) / blocksize;
91
                offset = (vhsect * HFSPLUS_SECTOR_SIZE) % blocksize;
92
                brelse(bh);
93
                bh = sb_bread(sb, block);
94
                if (!bh) {
95
                        printk("HFS+-fs: unable to read VHDR\n");
96
                        return -EIO;
97
                }
98
                HFSPLUS_SB(sb).sect_count = wd.embed_count * (wd.ablk_size >> 9);
99
        } else {
100
                wd.ablk_start = 0;
101
                wd.ablk_size = blocksize;
102
                wd.embed_start = 0;
103
                HFSPLUS_SB(sb).sect_count = sb->s_bdev->bd_inode->i_size >> 9;
104
        }
105
        vhdr = (struct hfsplus_vh *)(bh->b_data + offset);
106
        if (be16_to_cpu(vhdr->signature) != HFSPLUS_VOLHEAD_SIG)
107
                goto error;
108
        blocksize = be32_to_cpu(vhdr->blocksize);
109
        brelse(bh);
110
 
111
        /* block size must be at least as large as a sector
112
         * and a multiple of 2
113
         */
114
        if (blocksize < HFSPLUS_SECTOR_SIZE ||
115
            ((blocksize - 1) & blocksize))
116
                return -EINVAL;
117
 
118
        /* block offset must be a multiple of the block size */
119
        blockoffset = wd.ablk_start + wd.embed_start * (wd.ablk_size >> 9);
120
        if (blockoffset % (blocksize / HFSPLUS_SECTOR_SIZE)) {
121
                printk("HFS+-fs: embedded blocks not aligned with wrapper\n");
122
                return -EINVAL;
123
        }
124
        blockoffset /= blocksize / HFSPLUS_SECTOR_SIZE;
125
        HFSPLUS_SB(sb).blockoffset = blockoffset;
126
 
127
        if (sb_set_blocksize(sb, blocksize) != blocksize)
128
                return -EINVAL;
129
 
130
        block = blockoffset + HFSPLUS_VOLHEAD_SECTOR /
131
                (blocksize / HFSPLUS_SECTOR_SIZE);
132
        offset = (HFSPLUS_VOLHEAD_SECTOR * HFSPLUS_SECTOR_SIZE) % blocksize;
133
        bh = sb_bread(sb, block);
134
        if (!bh) {
135
                printk("HFS+-fs: unable to read VHDR or MDB\n");
136
                return -EIO;
137
        }
138
        vhdr = (struct hfsplus_vh *)(bh->b_data + offset);
139
        /* should still be the same... */
140
        if (be16_to_cpu(vhdr->signature) != HFSPLUS_VOLHEAD_SIG)
141
                goto error;
142
        HFSPLUS_SB(sb).s_vhbh = bh;
143
        HFSPLUS_SB(sb).s_vhdr = vhdr;
144
 
145
        return 0;
146
 error:
147
        brelse(bh);
148
        return -EINVAL;
149
}

powered by: WebSVN 2.1.0

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