2 * Copyright 2003-2013, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
12 #include <boot/partitions.h>
13 #include <boot/platform.h>
17 #include "Directory.h"
23 # define TRACE(x) dprintf x
33 Volume::Volume(boot::Partition
*partition
)
37 fDevice
= open_node(partition
, O_RDONLY
);
41 if (read_pos(fDevice
, 512, &fSuperBlock
, sizeof(disk_super_block
)) < B_OK
)
44 if (!IsValidSuperBlock()) {
45 #ifndef BFS_LITTLE_ENDIAN_ONLY
46 // try block 0 again (can only happen on the big endian BFS)
47 if (read_pos(fDevice
, 0, &fSuperBlock
, sizeof(disk_super_block
)) < B_OK
)
50 if (!IsValidSuperBlock())
57 TRACE(("bfs: we do have a valid superblock (name = %s)!\n", fSuperBlock
.name
));
59 fRootNode
= new(nothrow
) BFS::Directory(*this, Root());
60 if (fRootNode
== NULL
)
63 if (fRootNode
->InitCheck() < B_OK
) {
64 TRACE(("bfs: init check for root node failed\n"));
84 return fRootNode
!= NULL
? B_OK
: B_ERROR
;
89 Volume::IsValidSuperBlock()
91 if (fSuperBlock
.Magic1() != (int32
)SUPER_BLOCK_MAGIC1
92 || fSuperBlock
.Magic2() != (int32
)SUPER_BLOCK_MAGIC2
93 || fSuperBlock
.Magic3() != (int32
)SUPER_BLOCK_MAGIC3
94 || (int32
)fSuperBlock
.block_size
!= fSuperBlock
.inode_size
95 || fSuperBlock
.ByteOrder() != SUPER_BLOCK_FS_LENDIAN
96 || (1UL << fSuperBlock
.BlockShift()) != fSuperBlock
.BlockSize()
97 || fSuperBlock
.AllocationGroups() < 1
98 || fSuperBlock
.AllocationGroupShift() < 1
99 || fSuperBlock
.BlocksPerAllocationGroup() < 1
100 || fSuperBlock
.NumBlocks() < 10
101 || fSuperBlock
.AllocationGroups() != divide_roundup(fSuperBlock
.NumBlocks(), 1L << fSuperBlock
.AllocationGroupShift()))
109 Volume::ValidateBlockRun(block_run run
)
111 if (run
.AllocationGroup() < 0 || run
.AllocationGroup() > (int32
)AllocationGroups()
112 || run
.Start() > (1UL << AllocationGroupShift())
114 || uint32(run
.Length() + run
.Start()) > (1UL << AllocationGroupShift())) {
115 dprintf("bfs: invalid run(%" B_PRId32
",%d,%d)\n",
116 run
.AllocationGroup(), run
.Start(), run
.Length());
124 Volume::ToBlockRun(off_t block
) const
127 run
.allocation_group
= HOST_ENDIAN_TO_BFS_INT32(block
>> fSuperBlock
.AllocationGroupShift());
128 run
.start
= HOST_ENDIAN_TO_BFS_INT16(block
& ~((1LL << fSuperBlock
.AllocationGroupShift()) - 1));
129 run
.length
= HOST_ENDIAN_TO_BFS_INT16(1);
138 bfs_identify_file_system(boot::Partition
*partition
)
140 Volume
volume(partition
);
142 return volume
.InitCheck() < B_OK
? 0 : 0.8;
147 bfs_get_file_system(boot::Partition
*partition
, ::Directory
**_root
)
149 Volume
*volume
= new(nothrow
) Volume(partition
);
153 if (volume
->InitCheck() < B_OK
) {
158 *_root
= volume
->RootNode();
163 file_system_module_info gBFSFileSystemModule
= {
164 "file_systems/bfs/v1",
166 bfs_identify_file_system
,