From c966bfdab710c45b34c2d839e9bb47ddaf96f7e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Fri, 12 Sep 2003 01:22:40 +0000 Subject: [PATCH] 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 --- .../loader/file_systems/bfs/Directory.cpp | 100 ++++++++++++++ .../boot/loader/file_systems/bfs/Directory.h | 38 ++++++ .../boot/loader/file_systems/bfs/Jamfile | 1 + .../boot/loader/file_systems/bfs/Volume.h | 63 +++++++++ .../boot/loader/file_systems/bfs/bfs.cpp | 123 +++++++++++++++++- 5 files changed, 320 insertions(+), 5 deletions(-) create mode 100644 src/kernel/boot/loader/file_systems/bfs/Directory.cpp create mode 100644 src/kernel/boot/loader/file_systems/bfs/Directory.h create mode 100644 src/kernel/boot/loader/file_systems/bfs/Volume.h diff --git a/src/kernel/boot/loader/file_systems/bfs/Directory.cpp b/src/kernel/boot/loader/file_systems/bfs/Directory.cpp new file mode 100644 index 0000000000..77ffa8cd90 --- /dev/null +++ b/src/kernel/boot/loader/file_systems/bfs/Directory.cpp @@ -0,0 +1,100 @@ +/* +** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. 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 diff --git a/src/kernel/boot/loader/file_systems/bfs/Directory.h b/src/kernel/boot/loader/file_systems/bfs/Directory.h new file mode 100644 index 0000000000..30f220c0d7 --- /dev/null +++ b/src/kernel/boot/loader/file_systems/bfs/Directory.h @@ -0,0 +1,38 @@ +/* +** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ +#ifndef DIRECTORY_H +#define DIRECTORY_H + + +#include + +#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 */ diff --git a/src/kernel/boot/loader/file_systems/bfs/Jamfile b/src/kernel/boot/loader/file_systems/bfs/Jamfile index d5196cf227..be92e9a08b 100644 --- a/src/kernel/boot/loader/file_systems/bfs/Jamfile +++ b/src/kernel/boot/loader/file_systems/bfs/Jamfile @@ -8,4 +8,5 @@ SubDirHdrs $(OBOS_TOP) src add-ons kernel file_systems bfs ; KernelStaticLibrary boot_bfs : bfs.cpp + Directory.cpp ; diff --git a/src/kernel/boot/loader/file_systems/bfs/Volume.h b/src/kernel/boot/loader/file_systems/bfs/Volume.h new file mode 100644 index 0000000000..bc2895258e --- /dev/null +++ b/src/kernel/boot/loader/file_systems/bfs/Volume.h @@ -0,0 +1,63 @@ +/* +** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ +#ifndef VOLUME_H +#define VOLUME_H + + +#include + +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 */ diff --git a/src/kernel/boot/loader/file_systems/bfs/bfs.cpp b/src/kernel/boot/loader/file_systems/bfs/bfs.cpp index 2bda3883de..2a94e2be9f 100644 --- a/src/kernel/boot/loader/file_systems/bfs/bfs.cpp +++ b/src/kernel/boot/loader/file_systems/bfs/bfs.cpp @@ -4,25 +4,138 @@ */ +#include "Volume.h" +#include "Directory.h" + #include +#include #include #include #include #include +#include + + +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; }