Started to implement the real BFS module for the boot loader.

Currently, it only recognizes a BFS disk, and will print out its name
(and that code is now endian-aware as well).
More to come, though :-)


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4637 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2003-09-12 01:22:40 +00:00
parent b796791788
commit c966bfdab7
5 changed files with 320 additions and 5 deletions
@@ -0,0 +1,100 @@
/*
** Copyright 2003, Axel Dörfler, [email protected]. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
#include "Directory.h"
#include "Volume.h"
namespace BFS {
Directory::Directory(Volume &volume, block_run run)
:
fVolume(volume)
{
}
Directory::~Directory()
{
}
status_t
Directory::InitCheck()
{
return B_ERROR;
}
status_t
Directory::Open(void **_cookie, int mode)
{
return B_ERROR;
}
status_t
Directory::Close(void *cookie)
{
return B_ERROR;
}
Node *
Directory::Lookup(const char *name, bool traverseLinks)
{
return NULL;
}
status_t
Directory::GetNextNode(void *cookie, Node **_node)
{
return B_ERROR;
}
status_t
Directory::Rewind(void *cookie)
{
return B_ERROR;
}
// #pragma mark -
status_t
bfs_inode::InitCheck(Volume *volume)
{
if (Flags() & INODE_NOT_READY) {
// the other fields may not yet contain valid values
return B_BUSY;
}
if (Magic1() != INODE_MAGIC1
|| !(Flags() & INODE_IN_USE)
|| inode_num.Length() != 1
// matches inode size?
|| (uint32)InodeSize() != volume->InodeSize()
// parent resides on disk?
|| parent.AllocationGroup() > int32(volume->AllocationGroups())
|| parent.AllocationGroup() < 0
|| parent.Start() > (1L << volume->AllocationGroupShift())
|| parent.Length() != 1
// attributes, too?
|| attributes.AllocationGroup() > int32(volume->AllocationGroups())
|| attributes.AllocationGroup() < 0
|| attributes.Start() > (1L << volume->AllocationGroupShift()))
return B_BAD_DATA;
// ToDo: Add some tests to check the integrity of the other stuff here,
// especially for the data_stream!
return B_OK;
}
} // namespace BFS
@@ -0,0 +1,38 @@
/*
** Copyright 2003, Axel Dörfler, [email protected]. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
#ifndef DIRECTORY_H
#define DIRECTORY_H
#include <boot/vfs.h>
#include "Volume.h"
namespace BFS {
class Directory : public ::Directory {
public:
Directory(BFS::Volume &volume, block_run run);
virtual ~Directory();
status_t InitCheck();
virtual status_t Open(void **_cookie, int mode);
virtual status_t Close(void *cookie);
virtual Node *Lookup(const char *name, bool traverseLinks);
virtual status_t GetNextNode(void *cookie, Node **_node);
virtual status_t Rewind(void *cookie);
private:
Volume &fVolume;
bfs_inode fNode;
};
} // namespace BFS
#endif /* DIRECTORY_H */
@@ -8,4 +8,5 @@ SubDirHdrs $(OBOS_TOP) src add-ons kernel file_systems bfs ;
KernelStaticLibrary boot_bfs :
bfs.cpp
Directory.cpp
;
@@ -0,0 +1,63 @@
/*
** Copyright 2003, Axel Dörfler, [email protected]. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
#ifndef VOLUME_H
#define VOLUME_H
#include <SupportDefs.h>
class Node;
namespace BFS {
#include "bfs.h"
class Directory;
class Volume {
public:
Volume(Node *device);
~Volume();
status_t InitCheck();
bool IsValidSuperBlock();
block_run Root() const { return fSuperBlock.root_dir; }
Directory *RootNode() const { return fRootNode; }
block_run Indices() const { return fSuperBlock.indices; }
const char *Name() const { return fSuperBlock.name; }
int Device() const { return fDevice; }
off_t NumBlocks() const { return fSuperBlock.NumBlocks(); }
off_t UsedBlocks() const { return fSuperBlock.UsedBlocks(); }
off_t FreeBlocks() const { return NumBlocks() - UsedBlocks(); }
uint32 BlockSize() const { return fSuperBlock.BlockSize(); }
uint32 BlockShift() const { return fSuperBlock.BlockShift(); }
uint32 InodeSize() const { return fSuperBlock.InodeSize(); }
uint32 AllocationGroups() const { return fSuperBlock.AllocationGroups(); }
uint32 AllocationGroupShift() const { return fSuperBlock.AllocationGroupShift(); }
disk_super_block &SuperBlock() { return fSuperBlock; }
off_t ToOffset(block_run run) const { return ToBlock(run) << fSuperBlock.block_shift; }
off_t ToBlock(block_run run) const { return ((((off_t)run.AllocationGroup()) << AllocationGroupShift()) | (off_t)run.Start()); }
block_run ToBlockRun(off_t block) const;
status_t ValidateBlockRun(block_run run);
off_t ToVnode(block_run run) const { return ToBlock(run); }
off_t ToVnode(off_t block) const { return block; }
protected:
int fDevice;
disk_super_block fSuperBlock;
BFS::Directory *fRootNode;
};
} // namespace BFS
#endif /* VOLUME_H */
+118 -5
View File
@@ -4,25 +4,138 @@
*/
#include "Volume.h"
#include "Directory.h"
#include <boot/partitions.h>
#include <boot/platform.h>
#include <boot/vfs.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
using namespace BFS;
Volume::Volume(Node *device)
:
fRootNode(NULL)
{
fDevice = open_node(device, O_RDONLY);
if (fDevice < B_OK)
return;
if (read_pos(fDevice, 512, &fSuperBlock, sizeof(disk_super_block)) < B_OK)
return;
if (!IsValidSuperBlock()) {
#ifndef BFS_LITTLE_ENDIAN_ONLY
// try block 0 again (can only happen on the big endian BFS)
if (read_pos(fDevice, 0, &fSuperBlock, sizeof(disk_super_block)) < B_OK)
return;
if (!IsValidSuperBlock())
return;
#else
return;
#endif
}
printf("we do have a valid BFS super block (name = %s)!\n", fSuperBlock.name);
fRootNode = new BFS::Directory(*this, Root());
if (fRootNode == NULL)
return;
if (fRootNode->InitCheck() < B_OK) {
delete fRootNode;
fRootNode = NULL;
return;
}
}
Volume::~Volume()
{
close(fDevice);
}
status_t
Volume::InitCheck()
{
if (fDevice < B_OK)
return B_ERROR;
return fRootNode != NULL ? B_OK : B_ERROR;
}
bool
Volume::IsValidSuperBlock()
{
if (fSuperBlock.Magic1() != (int32)SUPER_BLOCK_MAGIC1
|| fSuperBlock.Magic2() != (int32)SUPER_BLOCK_MAGIC2
|| fSuperBlock.Magic3() != (int32)SUPER_BLOCK_MAGIC3
|| (int32)fSuperBlock.block_size != fSuperBlock.inode_size
|| fSuperBlock.ByteOrder() != SUPER_BLOCK_FS_LENDIAN
|| (1UL << fSuperBlock.BlockShift()) != fSuperBlock.BlockSize()
|| fSuperBlock.AllocationGroups() < 1
|| fSuperBlock.AllocationGroupShift() < 1
|| fSuperBlock.BlocksPerAllocationGroup() < 1
|| fSuperBlock.NumBlocks() < 10
|| fSuperBlock.AllocationGroups() != divide_roundup(fSuperBlock.NumBlocks(), 1L << fSuperBlock.AllocationGroupShift()))
return false;
return true;
}
status_t
Volume::ValidateBlockRun(block_run run)
{
if (run.AllocationGroup() < 0 || run.AllocationGroup() > (int32)AllocationGroups()
|| run.Start() > (1UL << AllocationGroupShift())
|| run.length == 0
|| uint32(run.Length() + run.Start()) > (1UL << AllocationGroupShift())) {
panic("bfs: invalid run(%ld,%d,%d)\n", run.AllocationGroup(), run.Start(), run.Length());
return B_BAD_DATA;
}
return B_OK;
}
block_run
Volume::ToBlockRun(off_t block) const
{
block_run run;
run.allocation_group = HOST_ENDIAN_TO_BFS_INT32(block >> fSuperBlock.AllocationGroupShift());
run.start = HOST_ENDIAN_TO_BFS_INT16(block & ~((1LL << fSuperBlock.AllocationGroupShift()) - 1));
run.length = HOST_ENDIAN_TO_BFS_INT16(1);
return run;
}
// #pragma mark -
static status_t
bfs_get_file_system(Node *device, Directory **_root)
bfs_get_file_system(Node *device, ::Directory **_root)
{
int fd = open_node(device, O_RDONLY);
if (fd >= 0)
close(fd);
Volume *volume = new Volume(device);
if (volume == NULL)
return B_NO_MEMORY;
return B_ERROR;
if (volume->InitCheck() < B_OK) {
delete volume;
return B_ERROR;
}
*_root = volume->RootNode();
return B_OK;
}