(shirait) nfs(wiifs)ライブラリ追加

git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-09-30%20-%20paladin.7z/paladin/ctr_firmware@283 b871894f-2f95-9b40-918c-086798483c85
This commit is contained in:
(no author) 2009-02-13 00:26:03 +00:00
parent 56c174c989
commit 080e5d5613
112 changed files with 47988 additions and 3 deletions

View File

@ -0,0 +1,66 @@
#! make -f
#----------------------------------------------------------------------------
# Project: CtrBrom - libraries - nfs
# File: Makefile
#
# Copyright 2008-2009 Nintendo. All rights reserved.
#
# These coded instructions, statements, and computer programs contain
# proprietary information of Nintendo of America Inc. and/or Nintendo
# Company Ltd., and are protected by Federal copyright law. They may
# not be disclosed to third parties or copied or duplicated in any form,
# in whole or in part, without the prior written consent of Nintendo.
#
# $Date:: $
# $Rev$
# $Author$
#----------------------------------------------------------------------------
SUBDIRS =
SUBMAKES =
#----------------------------------------------------------------------------
# build ARM & THUMB libraries
FIRM_CODEGEN_ALL ?= TRUE
#-------------------------------------------
#BROM_INCDIR = $(CTRBROM_ROOT)/include $(CTRBROM_ROOT)/build/libraries/fatfs/common/include ../common/include
#GINCLUDES = $(CTRBROM_ROOT)/include $(CTRFIRM_ROOT)/include $(CTRALL_ROOT)/include $(CTRBROM_ROOT)/build/libraries/fatfs/common/include ../common/include
INCDIR = $(BROM_ROOT)/include $(FIRM_ROOT)/include $(FIRM_ROOT)/build/libraries/nfs/common/include \
../common/include ../common/include/client ../common/include/driver_interface \
$(FIRM_ROOT)/include/firm/fatfs
#INCDIR = $(CTRBROM_ROOT)/include ../common/include
SRCDIR = ../common/src ../common/src/client ../common/src/driver_interface
SRCS = \
wfskrn_Api.cpp wfskrn_Area.cpp wfskrn_BCache.cpp wfskrn_BitField.cpp \
wfskrn_Dir.cpp wfskrn_DirApi.cpp wfskrn_DirCheck.cpp \
wfskrn_DirFind.cpp wfskrn_DirNodeStack.cpp wfskrn_DirRxTree.cpp \
wfskrn_EPTree.cpp wfskrn_Errors.cpp wfskrn_FreeBlkAlloc.cpp \
wfskrn_FTree.cpp wfskrn_Handles.cpp wfskrn_Heap.cpp wfskrn_Mutex.cpp \
wfskrn_PathCache.cpp wfskrn_Permission.cpp wfskrn_Permission_AccessList.cpp \
wfskrn_Permission_File.cpp wfskrn_Permission_Iop.cpp \
wfskrn_PTree.cpp wfskrn_SubBlkAlloc.cpp wfskrn_Trans.cpp wfskrn_Utils.cpp \
wfskrn_Volume.cpp my_wfskrn_Device.cpp \
wfs_Client_Common.cpp randomlib.cpp wfs_Debug.cpp \
wfs_Heap.cpp wfs_Mutex.cpp wfs_Names.cpp wfs_PathNames.cpp \
wfscli_Handles.cpp WinOSReport.cpp wfs_AsyncUtils.cpp \
drnand.c \
#------------------------------------------------
#MACRO_FLAGS += --c90
TARGET_LIB = libnfs$(FIRM_LIBSUFFIX).a
include $(CTRFIRM_ROOT)/build/buildtools/commondefs
INSTALL_TARGETS = $(TARGETS)
INSTALL_DIR = $(FIRM_INSTALL_LIBDIR)
#----------------------------------------------------------------------------
do-build: $(TARGETS)
include $(CTRFIRM_ROOT)/build/buildtools/modulerules
#===== End of Makefile =====

View File

@ -0,0 +1,53 @@
#! make -f
#----------------------------------------------------------------------------
# Project: CtrBrom - libraries_sp - nfs
# File: Makefile
#
# Copyright 2008-2009 Nintendo. All rights reserved.
#
# These coded instructions, statements, and computer programs contain
# proprietary information of Nintendo of America Inc. and/or Nintendo
# Company Ltd., and are protected by Federal copyright law. They may
# not be disclosed to third parties or copied or duplicated in any form,
# in whole or in part, without the prior written consent of Nintendo.
#
# $Date:: $
# $Rev$
# $Author$
#----------------------------------------------------------------------------
SUBDIRS =
#SUBMAKES = Makefile.CALLTRACE \
# Makefile.FUNCTIONCOST
#----------------------------------------------------------------------------
# build ARM & THUMB libraries
CTR_CODEGEN_ALL ?= TRUE
# Codegen for sub processer
CTR_PROC = ARM9
SRCDIR = . ../common
SRCS = \
TARGET_LIB = libnfs_sp$(CTR_LIBSUFFIX).a
#----------------------------------------------------------------------------
include $(CTRFIRM_ROOT)/build/buildtools/commondefs
INSTALL_TARGETS = $(TARGETS)
INSTALL_DIR = $(CTR_INSTALL_LIBDIR)
#----------------------------------------------------------------------------
do-build: $(TARGETS)
include $(CTRFIRM_ROOT)/build/buildtools/modulerules
#===== End of Makefile =====

View File

@ -0,0 +1,34 @@
#! make -f
#----------------------------------------------------------------------------
# Project: CtrBrom - libraries - mi
# File: Makefile
#
# Copyright 2008 Nintendo. All rights reserved.
#
# These coded instructions, statements, and computer programs contain
# proprietary information of Nintendo of America Inc. and/or Nintendo
# Company Ltd., and are protected by Federal copyright law. They may
# not be disclosed to third parties or copied or duplicated in any form,
# in whole or in part, without the prior written consent of Nintendo.
#
# $Date:: $
# $Rev$
# $Author$
#----------------------------------------------------------------------------
include $(CTRFIRM_ROOT)/build/buildtools/commondefs
#----------------------------------------------------------------------------
SUBDIRS = ARM11
#ifdef CTR_WITH_ARM9
#SUBDIRS += ARM9
#endif
#----------------------------------------------------------------------------
include $(CTRFIRM_ROOT)/build/buildtools/modulerules
#===== End of Makefile =====

View File

@ -0,0 +1,37 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: WinOSReport.h
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: WinOSReport.h,v $
Revision 1.6 2008/08/27 04:50:50 nakanose_jin
add function and defines
Revision 1.5 2007/11/02 00:21:11 paul
started logging changes in the file
*---------------------------------------------------------------------------*/
#pragma once
#if _WIN32
extern FILE *fpOSReport;
#endif
typedef void (*OSReportCallback) (const char *log);
void DebugPrintCallback(const char *pStr);
void DebugPrintCallback2(const char *pStr);
OSReportCallback SetOSReportPrintCallback(OSReportCallback cb);
void InitMyOSReport();
void MyOSReport(const char *format, ...);
void MyOSPanic(const char* file, int line , const char* msg, ...);

View File

@ -0,0 +1,73 @@
/*---------------------------------------------------------------------------*
Project: Revolution WFS library
File: wfs_Server.h - Server API
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfs_Server.h,v $
Revision 1.4 2008/01/10 05:33:20 nakanose_jin
validatePathName => validateDirectory
Revision 1.3 2007/11/02 00:21:56 paul
started logging changes in the file
*---------------------------------------------------------------------------*/
#ifndef __WFS_SERVER_H__
#define __WFS_SERVER_H__
#include <wfs.h>
WFSResult WFSSRVInit(void *pWorkSpaceBuffer, u32 nWorkSpaceSize);
WFSResult WFSSRVGetDeviceInfo(const utf8 *sDeviceName, WFSDeviceInfo *pDi);
WFSResult WFSSRVMountDevice(const utf8 *sDeviceName, utf8 *sVolumeIdBuffer);
WFSResult WFSSRVUnmountVolume(const utf8 *sVolumeId);
WFSResult WFSSRVInitializeDevice(const utf8 *sDeviceName);
WFSResult WFSSRVGetVolumeId(const utf8 *sDeviceName, utf8 *sVolumeId);
WFSResult WFSSRVGetFreeSpaceSize(const utf8 *sPathName, u64 *pSize);
WFSResult WFSSRVCreateDirectory(const utf8 *sPathName, u32 nFlags, u64 nQuota);
WFSResult WFSSRVCreateAndOpenFile(const utf8 *sPathName, u32 nFlags, u32 nPreAllocateSize, WFSFileHandle *pFh);
WFSResult WFSSRVGetAttributes(const utf8 *sPathName, WFSFileAttributes *pFa);
WFSResult WFSSRVChangePermissions(const utf8 *sPathName, u32 nFlags);
WFSResult WFSSRVDelete(const utf8 *sPathName);
WFSResult WFSSRVMoveLocal(const utf8 *sSrcPathName, const utf8 *sDstPathName);
WFSResult WFSSRVOpenFile(const utf8 *sPathName, WFSAccess nDesiredAccess, WFSFileHandle *pFh);
WFSResult WFSSRVReadFile(WFSFileHandle fh, void *pFileDataBuffer, u32 nSize);
WFSResult WFSSRVWriteFile(WFSFileHandle fh, const void *pFileData, u32 nSize);
WFSResult WFSSRVCloseFile(WFSFileHandle fh, u8 bTruncateFlag);
WFSResult WFSSRVSearchDirectoryFirst(const utf8 *sPattern, WFSSearchDirectoryHandle *pSdh, WFSFileInfo *pFi);
WFSResult WFSSRVSearchDirectoryNext(WFSSearchDirectoryHandle sdh, WFSFileInfo *pFi);
WFSResult WFSSRVSearchDirectoryClose(WFSSearchDirectoryHandle sdh);
WFSResult WFSSRVDebugSetTitleID(u64 nTID);
u64 WFSSRVDebugGetTitleID();
// Functions in the WFS API that are NOT in the WFS Server API:
// void WFSSetAttachDeviceCallback(utf8 *sDeviceNameBuffer, WFSDeviceCallback cbAttachDevice, void *pUserData);
// void WFSGetAttachDeviceCallback(utf8 **psDeviceName, WFSDeviceCallback *pCbAttachDevice, void **ppUserData);
// void WFSSetDetachDeviceCallback(utf8 *sDeviceNameBuffer, WFSDeviceCallback cbDetachDevice, void *pUserData);
// void WFSGetDetachDeviceCallback(utf8 **psDeviceName, WFSDeviceCallback *pCbDetachDevice, void **ppUserData);
// WFSResult WFSSetCurrentDirectory(const utf8 *sPathName);
// This function is replaced with:
WFSResult WFSSRVValidateDirectory(const utf8 *sPathName);
// WFSResult WFSGetCurrentDirectory(utf8 *sAbsPathNameBuffer, s32 nBufferSize);
// WFSResult WFSSetFilePosition(WFSFileHandle fh, WFSFileSize nFilePosition);
// WFSResult WFSGetFilePosition(WFSFileHandle fh, WFSFileSize *pFilePosition);
// WFSResult WFSGetFileSize(WFSFileHandle fh, WFSFileSize *pFileSize);
#endif //define __WFS_SERVER_H__

View File

@ -0,0 +1,382 @@
/*---------------------------------------------------------------------------*
Project: Revolution WFSSrv library API = shim layer in RVL version and RPC
layer in WFSDEV version.
File: wfsdev_Defs.h - Definitions common to WFS client and server
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfssrv_Defs.h,v $
Revision 1.34 2008/12/03 00:17:36 kondo_masahiro
Added a argument of WFSSrvFlush().
Revision 1.33 2008/10/21 10:45:09 kondo_masahiro
Added new function WFSWriteFileAndDiscard
Revision 1.32 2008/09/29 01:06:26 kondo_masahiro
Added the argument of WFSSrvInit().
Revision 1.31 2008/07/18 02:59:44 ueno
Renamed WFSDeletePermissions() -> WFSDeleteAccessListEntry().
Revision 1.30 2008/07/17 05:08:41 kondo_masahiro
Added WFSSRV_ATTACH_DETACH
Revision 1.29 2008/07/15 08:43:53 nakanose_jin
change arg order
Revision 1.28 2008/07/14 07:15:46 ueno
Implemented WFSGetAccessListAsync(), WFSSetAccessListEntryAsync() and WFSDeletePermissionsAsync().
Revision 1.27 2008/07/10 06:12:33 nakanose_jin
add permissions API
Revision 1.26 2008/05/22 08:05:49 ueno
Added WFSSrvDebugAclTest to run accesslist test.
Revision 1.25 2008/05/09 14:03:09 nakanose_jin
canceling => reduce settitleid argument
Revision 1.23 2008/04/19 05:52:03 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.22 2008/04/15 02:47:27 ueno
Added WFSSrvGetPermissionForUser() and WFSSrvSetPermissionForUser().
Revision 1.21 2008/03/28 14:14:20 nakanose_jin
chance spec of debug proc
Revision 1.20 2008/02/20 08:10:10 nakanose_jin
add WFSExecDebugProcedure
Revision 1.19 2008/02/08 04:42:00 paul
Changed WFSSrvUnmountVolume parameter bForce to WFSBool
Revision 1.18 2008/02/07 13:02:18 nakanose_jin
WFSUnmountVolume : Add force-close option (but only in detach condition)
Revision 1.17 2008/01/10 05:33:20 nakanose_jin
validatePathName => validateDirectory
Revision 1.16 2007/12/25 14:00:36 ueno
Added WFSSrvConnectToServer() to connect to the server again.
Revision 1.15 2007/12/12 07:51:29 paul
Added WFSSrvGetFileSize
Revision 1.14 2007/12/10 02:51:36 paul
Added function codes for WFSSRV_SET_HOME_DIRECTORY, WFSSRV_SET_CURRENT_DIRECTORY. (These do not need to be implemented in the actual server, both call WFSSrvValidatePathName)
Revision 1.13 2007/11/30 09:43:09 nakanose_jin
refine for multi client
Revision 1.12 2007/11/21 04:17:28 wayne.wong
Many changes that included single request/result RPC messages, bug fixes, code factoring, and English C comment adjustments.
1. Combined RPC messages into a single request message and single result
message. Except for file reads and writes.
2. Fixed+factored some Endianess code.
3. Enabled larger TCP/IP data transfer size. Previous setting was artifically small
to test the code to perform large transfers.
4. Changed the volume id parameters utf8*->WFSVolumeId for SrvGetVolumeId
and SrvMountDevice. More consistent with the way we send this type at the
RPC layer.
5. Changed a couple Japanese comments to be compatible with English
comments. In particular, the "//" comment with a backslash at the end of
the line causes the next line of code to be ignored.
6. Removed Windows-specific debugging output defines for RVL build.
Revision 1.11 2007/11/16 21:54:26 paul
Fixed WFSSrvCloseFile to pass nNewSize instead of bTruncateFlag
Revision 1.10 2007/11/16 02:15:57 wayne.wong
Added enumeration and stubs for WFSFlush call.
Revision 1.9 2007/11/02 00:21:02 paul
started logging changes in the file
Added StartPosition to WFSSrvReadFile, WFSSrvWriteFile
*---------------------------------------------------------------------------*/
#ifndef __WFSSRV_DEFS_H__
#define __WFSSRV_DEFS_H__
#include "wfs_Defs.h"
#ifdef __cplusplus
extern "C" {
#endif
// Enumeration of functions.
// Used by the client to specify functions implemented on the server, or
// by the server to specify functions implemented on the client.
typedef enum {
// server -> client
WFSSRV_ATTACH_DEVICE,
WFSSRV_DETACH_DEVICE,
// client -> server
WFSSRV_INIT,
WFSSRV_EXIT,
WFSSRV_GET_DEVICE_INFO,
WFSSRV_MOUNT_DEVICE,
WFSSRV_UNMOUNT_VOLUME,
WFSSRV_INITIALIZE_DEVICE,
WFSSRV_GET_VOLUME_ID,
WFSSRV_GET_FREE_SPACE_SIZE,
WFSSRV_FLUSH,
WFSSRV_CREATE_DIRECTORY,
WFSSRV_SEARCH_DIRECTORY_FIRST,
WFSSRV_SEARCH_DIRECTORY_NEXT,
WFSSRV_SEARCH_DIRECTORY_CLOSE,
WFSSRV_SET_HOME_DIRECTORY,
WFSSRV_SET_CURRENT_DIRECTORY,
WFSSRV_VALIDATE_PATH_NAME,
WFSSRV_DELETE,
WFSSRV_MOVE_LOCAL,
WFSSRV_GET_ATTRIBUTES,
WFSSRV_CHANGE_PERMISSIONS,
WFSSRV_CREATE_AND_OPEN_FILE,
WFSSRV_OPEN_FILE,
WFSSRV_GET_FILE_SIZE,
WFSSRV_CLOSE_FILE,
WFSSRV_READ_FILE,
WFSSRV_WRITE_FILE,
WFSSRV_WRITE_FILE_AND_DISCARD,
WFSSRV_GET_PERMISSIONS,
WFSSRV_SET_PERMISSIONS,
WFSSRV_GET_ACL,
WFSSRV_SET_ACL_ENTRY,
WFSSRV_DELETE_ACL_ENTRY,
WFSSRV_SET_TITLE_ID,
WFSSRV_TEST,
WFSSRV_EXEC_DEBUG,
WFSSRV_ATTACH_DETACH,
WFSSRV_DEBUG_ACLTEST // [check]
} WFSSrvFunc;
typedef u16 WFSSrvFileHandle;
typedef u16 WFSSrvSearchDirectoryHandle;
#ifndef WFSDEV_SERVER
// The WFSDev server must distinguish between multiple clients.
// This can be done by assigning a ClientId based on the client's IP address,
// which the server learns whenever it receives a request from a client via sockets.
// Note: ClientId is orthogonal to TitleId.
// There can be multiple clients with the same TitleId.
// The same client could change TitleId while the server is running.
// The home directory is only stored on the client side.
// The TitleId, however, is determined by a function in IOS.
// (except for the fake debug/wfsdev version)
//
// This allows a system application built on top of wfs to specify the home directory for
// an app prior to launching it.
//
// Path Names
// The client<->server API uses absolute WFS path names, becuase the server does not know about
// "Current Directory" or "Home Directory".
// The absolute path name does not include the full windows path name, it is a WFS path name.
// For example: "/vol/ABCDEFG/titles/1234/JAKK/gamesave/save1.bin"
// On windows, this could map to:
// "C:/my_project/my_wfs_device/titles/1234/JAKK/gamesave/save1.bin"
// There would be a file called:
// "C:/my_project/my_wfs_device/.Wfs" which contains: "Volume Name: ABCDEFG"
WFSResult WFSSrvInit(void *pWorkSpaceBuffer, u32 nWorkSpaceSize);
// Contact the WFSSrv server so that it can initialize state for this client.
WFSResult WFSSrvExit(void);
// Inform the WFSSrv server that this client is terminating.
WFSResult WFSSrvInitializeDevice(const WFSDeviceName *pDevName);
// pDevName (IN) pointer to device name struct.
// Server would create a volume (deleting any existing data within the device assigned to this folder).
// The server could have a GUI to allow device attach to be simulated.
// It depends on the usage model but this may not be necessary for game developers, so low priority.
// (Assuming a system app mounts the drive and assigns home directory in advance, so the
// game can access an already-mounted device from the start).
WFSResult WFSSrvGetDeviceInfo(const WFSDeviceName *pDevName, WFSDeviceInfo *pDi);
// pDevName (IN) A pointer to a device name struct.
// pDi (OUT) A pointer to a WFSDeviceInfo struct to receive the device information.
WFSResult WFSSrvMountDevice(const WFSDeviceName *pDevName, WFSVolumeId *pVolumeIdBuffer);
// pDevName (IN) A pointer to a device name struct.
// pVolumeIdBuffer (OUT) A pointer to a WFSVolumeId buffer
WFSResult WFSSrvUnmountVolume(const WFSVolumeId *pVolumeId, WFSBool bForce);
// pVolumeId (IN) A pointer to a struct containing a mounted Volume Id.
// bForce (IN) If set to true, forces the volume to be unmounted regardless of open files.
// NOTE: This flag is only valid if the device is currently detached. Un-flushed data will be lost.
WFSResult WFSSrvGetVolumeId(const WFSDeviceName *pDevName, WFSVolumeId *sVolumeIdBuffer);
// pDevName (IN) A pointer to a device name struct.
// sVolumeIdBuffer (OUT) A pointer to a WFSVolumeId buffer
WFSResult WFSSrvGetFreeSpaceSize(const WFSPathName *pAbsPathName, u64 *pSize);
// pAbsPathName (IN) A pointer to a struct containing the absolute pathname of a file or directory.
// pSize (OUT) A pointer to a u64 to receive the free space size value.
WFSResult WFSSrvFlush(const WFSVolumeId *pVolumeId);
WFSResult WFSSrvGetAttributes(const WFSPathName *pAbsPathName, WFSFileAttributes *pFa);
// pAbsPathName (IN) A pointer to a struct containing the absolute pathname of a file or directory.
// pFa (OUT) A pointer to a WFSFileAttributes struct which will be overwritten with the attributes of the specified file or directory.
WFSResult WFSSrvChangePermissions(const WFSPathName *pAbsPathName, u32 nFlags, u32 nMask);
// pAbsPathName (IN) A pointer to a struct containing the absolute pathname of a file or directory.
// nFlags (IN) The new permissions flags that are to be set. Should be a combination of the permission flags: WFS_PERM_*
// nMask (IN) A mask to specify which flags to change.
WFSResult WFSSrvCreateDirectory(const WFSPathName *pAbsPathName, u32 nFlags, u64 nQuota);
// pAbsPathName (IN) A pointer to a struct containing the absolute pathname of a file or directory.
// nFlags (IN) Should be a combination of the permission flags: WFS_PERM_*. Note: WFS_FLAG_DIRECTORY will be set
// whether it is included or not.
// nQuota (IN) This parameter that can be used to restrict the total size of the hierarchy beneath the
// new directory. A quota of 0 means there is no size restriction, i.e. the quota is Infinity.
WFSResult WFSSrvSearchDirectoryFirst(const WFSPathName *pPattern, WFSSrvSearchDirectoryHandle *pSsdh, WFSFileInfo *pFi);
// pPattern (IN) A pointer to a struct specifying the search pattern as an absolute path name.
// pSsdh (OUT) A pointer to a WFSSrvSearchDirectoryHandle handle which is overwritten by the server.
// pFi (OUT) A pointer to a WFSFileInfo struct which will be overwritten with the details of the
WFSResult WFSSrvSearchDirectoryNext(WFSSrvSearchDirectoryHandle ssdh, WFSFileInfo *pFi);
// ssdh (IN) A WFSSrvSearchDirectoryHandle which was created by WFSSrvSearchDirectoryFirst.
// pFi (OUT) A pointer to a WFSFileInfo struct which will be overwritten with the details of the
// next file which matches the search pattern.
//
// If they have read permission on the directory, they can list all files/dirs in that directory. Directory read
// access was already checked by WFSSrvSearchDirectoryFirst. While they can list the directory contents, they may
// not be able to access all contained files/dirs.
WFSResult WFSSrvSearchDirectoryClose(WFSSrvSearchDirectoryHandle ssdh);
// ssdh (IN) A WFSSrvSearchDirectoryHandle which was returned by WFSSrvSearchDirectoryFirst.
WFSResult WFSSrvValidateDirectory(const WFSPathName *pAbsPathName);
// pAbsPathName (IN) A pointer to a struct containing the absolute pathname of a file or directory to validate.
// Returns WFS_RESULT_OK if the specified pathname exists, and is accessible to the current title
WFSResult WFSSrvDelete(const WFSPathName *pAbsPathName);
// pAbsPathName (IN) A pointer to a struct containing the absolute pathname of the file or directory to delete.
WFSResult WFSSrvMoveLocal(const WFSPathName *pSrcAbsPathName, const WFSPathName *pDstAbsPathName);
// pSrcAbsPathName (IN) A pointer to a struct containing the absolute pathname of the source file or directory.
// pDstAbsPathName (IN) A pointer to a struct containing the absolute pathname of the destination file or directory.
// Moves or renames the source file/directory to the destination pathname. This function does not work across volumes.
WFSResult WFSSrvCreateAndOpenFile(const WFSPathName *pAbsPathName, u32 nFlags, WFSContentIdx nCidx, WFSFileSize nPreAllocateSize, WFSSrvFileHandle *pSfh);
// pAbsPathName (IN) A pointer to a struct containing the absolute pathname of the file to create and open.
// nFlags (IN) Should be a combination of the permission flags: WFS_PERM_*
// nCidx (IN) The content idx, used to control access to purchased content.
// nPreAllocateSize (IN) The amount of disk-space to pre-allocate for the file. Hint to the file system.
// pSfh (OUT) A pointer to a server file handle which is overwritten by the server.
WFSResult WFSSrvOpenFile(const WFSPathName *pAbsPathName, WFSAccess nDesiredAccess, WFSSrvFileHandle *pSfh, WFSFileAttributes *pFa);
// pAbsPathName (IN) A pointer to a struct containing the absolute pathname of the file to open.
// nDesiredAccess (IN) The kind of access that is required: should be one of the WFS_ACCESS_* options.
// pSfh (OUT) A pointer to a server file handle, which is overwritten by the server.
// pFa (OUT) A pointer to a WFSFileAttributes struct which will be overwritten by the server,
WFSResult WFSSrvCloseFile(WFSSrvFileHandle sfh, WFSFileSize nNewSize);
// sfh (IN) The server file handle which was returned when the file was opened.
// nNewSize (IN) This value may be set to truncate the size of a file.
WFSResult WFSSrvGetFileSize(WFSSrvFileHandle sfh, WFSFileSize *pNewSize);
// sfh (IN) The server file handle which was returned when the file was opened.
// pNewSize (OUT) A pointer to a WFSFileSize variable which is overwritten by the current file size.
s32 WFSSrvReadFile(WFSSrvFileHandle sfh, void *pFileDataBuffer, WFSFileSize nStartPosition, s32 nSize);
// sfh (IN) The server file handle which was returned when the file was opened.
// pFileDataBuffer (OUT) Points to a buffer which will be overwritten with data from the file.
// nSize (IN) The number of bytes to be read.
WFSResult WFSSrvWriteFile(WFSSrvFileHandle sfh, const void *pFileData, WFSFileSize nStartPosition, WFSFileSize nSize, WFSBool bDiscard);
// sfh (IN) The server file handle which was returned when the file was opened.
// pFileData (IN) Points to the data to be written to the file.
// nSize (IN) The number of bytes to be written.
// bDiscard (IN) If it is true, the user buffer is used as work buffer.
WFSResult WFSSrvSetTitleId(WFSTitleId titleId,WFSGroupId groupId);
// titleId (IN) the title id which is the low 32 bits of the OSTitleId which can be obtained be ESP_GetTitleId()
// groupId (IN) the group id from the TMD, which can be obtained by ES_GetTmd()
// This function informs the server of the title id and group id of the application linked to this instance of the client.
WFSResult WFSSrvExecDebugProcedure( u32 cmd , void *arg0 , void *arg1 );
// cmd (IN) special command No.
// arg0,arg1 (IN/OUT) parameters of special command.
// This function let the server do special tasks.
WFSResult WFSSrvConnectToServer(void);
WFSResult WFSSrvGetPermissionForUser(const WFSPathName *pAbsPathName, u32 *pFlags, WFSTitleId titleId);
// pAbsPathName (IN) A pointer to a struct containing the absolute pathname of the file or the directory.
// pFlags (OUT) A pointer to a u32 which will be overwritten with the permissions the specified title id has to
// access or modify the specified file or directory. See wfstypes.h for WFS_PERM* flag definitions.
// titleId (IN) Title id of the application for which permissions are being set.
WFSResult WFSSrvSetPermissionForUser(const WFSPathName *pAbsPathName, u32 nFlags, u32 nMask, WFSTitleId titleId);
// pAbsPathName (IN) A pointer to a struct containing the absolute pathname of the file or the directory.
// nFlags (IN) The new permissions flags that are to be set. Should be a combination of the permission flags: WFS_PERM_* (see wfstypes.h)
// nMask (IN) The mask determines which flags will be changed. NewAttributes = (OldAttributes & ~nMask) | (nFlags & nMask)
// titleId (IN) Title id of the application for which permissions are being set.
WFSResult WFSSrvDeleteAccessListEntry(const WFSPathName *pAbsPathName, WFSTitleId titleId, WFSTitleId entryCreatorId);
WFSResult WFSSrvSetAccessListEntry(const WFSPathName *pAbsPathName, u32 nFlags, u32 nMask, WFSTitleId titleId);
s32 WFSSrvGetAccessList(const WFSPathName *pAbsPathName, WFSAccessListEntry *pAccessList, u32 nMaxElements);
WFSResult WFSSrvSetWorkspace(void *pWorkSpaceBuffer, u32 nWorkSpaceSize);
#ifdef ACL_TEST
WFSResult WFSSrvDebugAclTest(u32 testNo, void *arg0, void *arg1);
#endif // ACL_TEST
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif //define __WFSSRV_DEFS_H__

View File

@ -0,0 +1,26 @@
#ifndef _RANDOMLIB_H
#define _RANDOMLIB_H
#include "revolution.h"
/*
#if _IOP
#include "types.h"
#else
#include "revolution/types.h"
#endif
*/
#include "wfs_Platform.h"
void RandomInitialise(int ij, int kl);
double RandomUniform(void);
double RandomGaussian(double mean, double stddev);
int RandomInt(int lower, int upper);
double RandomDouble(double lower, double upper);
u32 RandomU32();
#define NUM_UNIQUE_RANDOM_SEEDS_U32 0x382C7A42
void RandomSetSeedU32(u32 nSeed);
#endif

View File

@ -0,0 +1,95 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfs_AsyncUtils.h - mutual exclusion for multi-thread case
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfs_AsyncUtils.h,v $
Revision 1.6 2008/04/19 05:52:50 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.5 2007/11/09 01:19:54 paul
*** empty log message ***
Revision 1.4 2007/11/02 00:25:49 paul
started logging changes in the file
*---------------------------------------------------------------------------*/
#ifndef wfs_AsyncUtils_h
#define wfs_AsyncUtils_h
#include "wfs_PathNames.h"
#include "wfs_Mutex.h"
#ifdef _DEBUG
#define _DEBUG_ASYNC_UTILS 0 // change to 1 if debug info required
#else
#define _DEBUG_ASYNC_UTILS 0
#endif
#define WFSCLI_WRITE_ASYNC_PARAM_AND_INC_PTR(ptr,Type,var) *((Type*)ptr)=var; ptr=(void*)((size_t)pPtr + sizeof(Type))
#define WFSCLI_WRITE_ASYNC_PARAM(ptr,Type,var) *((Type*)ptr)=var
#define WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(ptr,Type,var) Type var=*((Type*)ptr); ptr=(void*)((size_t)pPtr + sizeof(Type))
#define WFSCLI_DECLARE_AND_READ_ASYNC_PARAM(ptr,Type,var) Type var=*((Type*)ptr);
#define WFSCLI_READ_ASYNC_PARAM_AND_INC_PTR(ptr,Type,var) var=*((Type*)ptr); ptr=(void*)((size_t)pPtr + sizeof(Type))
#define WFSCLI_READ_ASYNC_PARAM(ptr,Type,var) var=*((Type*)ptr)
typedef struct WFSAsyncParamHdr WFSAsyncParamHdr;
typedef struct WFSAsyncParamHdrAnchor WFSAsyncParamHdrAnchor;
typedef struct WFSAsyncParamHdrLink WFSAsyncParamHdrLink;
typedef struct WFSAsyncParamGlobals WFSAsyncParamGlobals;
struct WFSAsyncParamHdrLink {
WFSAsyncParamHdr *pNext;
WFSAsyncParamHdr *pPrev;
};
struct WFSAsyncParamHdrAnchor {
WFSAsyncParamHdr *pHead;
WFSAsyncParamHdr *pTail;
};
struct WFSAsyncParamHdr {
WFSAsyncParamHdrLink l;
u32 nSize; // Size of parameters including this header
void *cb;
void *pUserData;
u8 nFunction; // Values are defined in wfssrv_Defs.h
};
struct WFSAsyncGlobals {
WFSAsyncParamHdrAnchor anchor;
WFSThread asyncExecThread;
void *pAsyncExecStack;
WFSMutex mxAccessTheParamQueue;
WFSCond condParamQueueEmpty;
WFSCond condParamQueueNotEmpty;
};
void WFSAsyncUtilsInit();
void WFSAsyncUtilsClose();
WFSResult WFSPrepareAsyncCall(void **ppPtr, u8 nFunction, void *pUserData, void *cb, size_t nOtherParamSize);
WFSResult WFSPrepareAsyncCallWithPathName(void **ppPtr, const utf8 *sInPathName,
WFSPathNameType nPathType, u8 nFunction, void *pUserData, void *cb, size_t nOtherParamSize);
WFSResult WFSPrepareMoveLocalAsyncCall(void **ppPtr, const utf8 *sSrcPathName, const utf8 *sDstPathName,
WFSPathNameType nPathType, u8 nFunction, void *pUserData, void *cb, size_t nOtherParamSize);
WFSResult WFSPrepareAsyncCallWithDeviceName(void **ppPtr, const utf8 *sDeviceName,
u8 nFunction, void *pUserData, void *cb, size_t nOtherParamSize);
WFSResult WFSPrepareAsyncCallWithVolumeId(void **ppPtr, const utf8 *sVolumeId,
u8 nFunction, void *pUserData, void *cb, size_t nOtherParamSize);
#endif //define wfs_AsyncUtils_h

View File

@ -0,0 +1,65 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfs_Client.h - Internal definitions for the PPC side of the WFS API
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfs_Client.h,v $
Revision 1.4 2007/11/02 00:20:34 paul
started logging changes in the file
*---------------------------------------------------------------------------*/
// File created 2007.08.29
#ifndef wfs_Client_h
#define wfs_Client_h
#ifdef _DEBUG
#define _DEBUG_WFS_CLIENT 1
#else
#define _DEBUG_WFS_CLIENT 0
#endif
#include "wfs_Heap.h"
#include "wfs_AsyncUtils.h"
#include "wfscli_Handles.h"
#include "wfssrv_Defs.h"
typedef struct {
bool bMutexInitialized;
WFSMutex mxAccessDeviceCallbackGlobals;
utf8 *pAttachDeviceNameBuffer;
WFSDeviceCallback cbAttachDevice;
void *pAttachDeviceUserData;
utf8 *pDetachDeviceNameBuffer;
WFSDeviceCallback cbDetachDevice;
void *pDetachDeviceUserData;
} WFSDeviceCallbackGlobals;
typedef struct {
bool bLibInitialized;
void *pWorkSpaceBuffer;
WFSHeap heap;
WFSCliHandles hnd;
WFSAsyncGlobals ag;
WFSPathGlobals pg;
WFSDeviceCallbackGlobals dcg;
} WFSClientGlobals;
typedef struct {
WFSSrvFunc nFunction;
WFSPath pathAbs;
} WFSFuncParams_OnePathName;
extern WFSClientGlobals wcg;
#endif //wfs_Client_h

View File

@ -0,0 +1,58 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfs_Config.h - project-wide configuration settings governing resource allocations etc.
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfs_Config.h,v $
Revision 1.8 2008/11/04 06:07:16 ueno
Changed the maximum number of file handles and search handles to 32.
Revision 1.7 2008/09/29 01:06:04 kondo_masahiro
Added several macros.
Revision 1.6 2008/07/09 02:52:33 paul
Increased maximum number of File & Directory Search handles
Revision 1.5 2008/05/12 20:30:22 paul
Added handle defs
Revision 1.4 2007/11/05 18:38:42 paul
WFSDEV flag is now defined in makefile / projectfile
Revision 1.3 2007/11/02 00:25:29 paul
started logging changes in the file
*---------------------------------------------------------------------------*/
#ifndef wfs_Config_h
#define wfs_Config_h
// Define WFSDEV in the makefile/project settings to compile the WFS DEV version of the client
#ifdef WFSDEV
#define _WFSDEV 1
#else
#define _WFSDEV 0
#endif
// This determines the maximum number of asynchronous calls that can be outstanding before a busy error occurs
//#define WFS_MAX_OUTSTANDING_ASYNC_CALLS 4
// Now it is determined by the amount of memory the user supplies with WFSInit
#define WFSCLI_WORK_SPACE_SIZE (40*1024)
#define WFS_ASYNC_EXEC_STACK_SIZE (16*1024) // client common code async handler thread
// WFSDEV-specific
#define WFSDEV_CALLBACK_THREAD_STACK_SIZE (16*1024) // client thread for server-initiated callbacks; for WFSDEV implementation
#define WFSDEV_MAX_CLIENTS (5) // maximum number of clients that the server can support simultaneously
#define WFSCLI_FILE_HANDLE_IDX_BITS 5
#define WFSCLI_SEARCH_DIR_HANDLE_IDX_BITS 5
#endif //wfs_Config_h

View File

@ -0,0 +1,81 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfs_Defs.h
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfs_Defs.h,v $
Revision 1.14 2008/11/05 15:11:45 ueno
Fixed WFS_ROUND_DOWN().
Revision 1.13 2008/07/11 05:27:22 kondo_masahiro
Fixed WFS_ROUND_UP / DOWN
Revision 1.11 2008/04/19 05:52:44 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.10 2007/12/28 07:33:23 nakanose_jin
fix bug
Revision 1.9 2007/12/26 10:17:44 paul
WFS_RANGE_CHK, WFS_INDEX_COUNT ÇÁ
Revision 1.8 2007/11/06 22:44:18 paul
added wfs_Errors.h to list of included headers
Revision 1.7 2007/11/05 18:39:16 paul
removed unused macro
Revision 1.6 2007/11/02 00:24:51 paul
started logging changes in the file
*---------------------------------------------------------------------------*/
#ifndef wfs_Defs_h
#define wfs_Defs_h
#define _WIN32_WINNT 0x500
#include "revolution/wfs.h"
#include "wfs_Platform.h"
#include "wfs_Config.h"
#include "wfs_Errors.h"
#include "wfs_Types.h"
#if !_IOP
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
#define WFS_ROUND_UP(v,x) (((v)+(x)-1)&-((signed)x))
#define WFS_ROUND_DOWN(v,x) ((v)&-((signed)x))
#define WFS_RANGE_CHK(val,min,max) (((val)>=(min))&&((val)<(max)))
#define WFS_INDEX_COUNT(array) (size_t)(sizeof(array)/sizeof(array[0]))
#define BYTES2BITS(b) ((b)<<3)
#ifndef swap_typ
#define swap_typ(Typ,a,b) { Typ t=a; a=b; b=t; }
#endif
#ifdef _DEBUG
#ifndef _ASSERT
#define _ASSERT(x) ASSERT(x)
#endif
#else
#ifndef _ASSERT
#define _ASSERT(x)
#endif
#endif
#endif // wfs_defs_h

View File

@ -0,0 +1,151 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfs_Error_h
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfs_Errors.h,v $
Revision 1.8 2008/07/11 19:14:01 paul
Updated to match latest wfsError.h
Revision 1.7 2007/12/04 05:59:11 paul
bug fix
Revision 1.6 2007/11/21 22:18:13 paul
Added WFS_INTERNAL_RESULT_ALREADY_MOUNTED
Revision 1.5 2007/11/06 22:44:53 paul
Added macro to do validation checks for NULL pointers passed in
Revision 1.4 2007/11/02 00:24:24 paul
started logging changes in the file
*---------------------------------------------------------------------------*/
#ifndef wfs_Error_h
#define wfs_Error_h
#define WFSReturnOnError(x) { WFSResult nResult = x; if (nResult < WFS_RESULT_OK) return nResult; }
#define WFSReturnOnInternalError(x) { WFSInternalResult nResult = x; if (nResult < WFS_INTERNAL_RESULT_OK) return nResult; }
#define WFSReturnOnNullParameter(p) { if (p == NULL) return WFS_RESULT_INVALID; }
typedef enum {
WFS_INTERNAL_RESULT_OK = 0, // Success
// Errors that are usually detected in the client, and would result in the server not being called:
WFS_INTERNAL_RESULT_BUSY = -1, // The request queue is full.
WFS_INTERNAL_RESULT_OUT_OF_MEMORY = -2, // The client does not have enough memory to complete the requested operation. (May be due to too many outstanding aysnc calls).
WFS_INTERNAL_RESULT_INVALID = -3, // The function parameters were invalid, e.g. File name is too long, Path is too long or too deep.
WFS_INTERNAL_RESULT_ACCESS = -4, // Trying to write to a file which was opened for read-only access, or vice versa.
WFS_INTERNAL_RESULT_LIB_NOT_INITIALIZED = -5, // The WFS client has not been initialized. Please call WFSInit(..) (This error message is omitted from the list of return values).
WFS_INTERNAL_RESULT_LIB_INITIALIZED = -6, // The WFS client has already been initialized.
WFS_INTERNAL_RESULT_FILE_TOO_BIG = -7, // The current write/append request would push the file over the size limit.
WFS_INTERNAL_RESULT_NO_CHANGE_SIZE = -8, // The requested operation would cause the file size to change, but this file has WFS_PERM_NO_CHANGE_SIZE flag set.
// Errors that cannot usually be detected early, and would be passed via nResult to the Async callbacks:
WFS_INTERNAL_RESULT_MEDIA_ERROR = -9, // The device or media is not attached, or was removed before the requested operation could be completed.
WFS_INTERNAL_RESULT_DEV_UNUSABLE = -10, // Attached device is not accessible, e.g. because it is an unsupported device, or has an unknown format.
WFS_INTERNAL_RESULT_DEV_NOT_INITIALIZED = -11, // Device not formatted, or does not yet contain a Wii volume
WFS_INTERNAL_RESULT_DEV_IN_USE = -12, // Trying to initialize a device which is in use (mounted) by one or more clients.
WFS_INTERNAL_RESULT_VOL_ID_ERROR = -13, // Attempted to mount a device with the same unique ID as an already mounted device (This could happen if the User backs up an entire Wii partition using a PC)
WFS_INTERNAL_RESULT_WRITE_PROTECTED = -14, // Device is physically write protected (e.g. USB Flash memory, SD Card).
WFS_INTERNAL_RESULT_ALREADY_MOUNTED = -15, // The device is already mounted.
WFS_INTERNAL_RESULT_PERMISSION = -16, // Permission flags do not permit the requested access from this application.
WFS_INTERNAL_RESULT_PERMISSION_CL = -17, // Permission error caused by control level problems.
WFS_INTERNAL_RESULT_ACL_FULL = -18, // The access list is full.
WFS_INTERNAL_RESULT_ACL_ENTRY_NOT_FOUND = -19, // The specified entry does not exist in the access list.
WFS_INTERNAL_RESULT_AUTHENTICATION = -20, // Trying to access content on a different Wii, which does not have the required access rights.
WFS_INTERNAL_RESULT_CORRUPTION = -21, // A corrupted block was encountered which prevented the operation from being completed.
WFS_INTERNAL_RESULT_DIRECTORY_QUOTA = -22, // One of the ancestor directories would exceed its quota.
WFS_INTERNAL_RESULT_MAX_HANDLES = -23, // The maximum number of concurrent file handles / search handles are already in use.
WFS_INTERNAL_RESULT_ALREADY_EXISTS = -24, // The file or directory being created already exists.
WFS_INTERNAL_RESULT_NOT_FOUND = -25, // The specified file or directory or device does not exist.
WFS_INTERNAL_RESULT_NOT_EMPTY = -26, // The specified directory cannot be deleted because it is not empty.
WFS_INTERNAL_RESULT_NOT_FILE = -27, // The specified path is directory instead of a file.
WFS_INTERNAL_RESULT_NOT_DIRECTORY = -28, // The specified path is a file instead of a directory
WFS_INTERNAL_RESULT_FILE_OPEN = -39, // The file is open. Cannot delete, move, rename, change permissions of an open file. Cannot open a file more than once unless all opens are WFS_ACCESS_READ.
WFS_INTERNAL_RESULT_LOCKED = -30, // Cannot perform the requested operation since the file or directory is locked by an existing operation.
WFS_INTERNAL_RESULT_RESOURCE_LIMIT_EXCEEDED = -31, // A resource limit prevents this function call. Try smaller values.
WFS_INTERNAL_RESULT_DIR_ENTRY_FOUND = -40, // The search string was matched and pointed to an entry
WFS_INTERNAL_RESULT_DIR_NODE_STRING_PREFIX = -41, // The search string ended early during comparison with a node sub string. (So this name is a prefix of existing names)
WFS_INTERNAL_RESULT_DIR_CHOICE_PREFIX = -42, // The search string ended at the end of a node sub string, but the node did not have a termination choice. (This name is a prefix of existing names)
WFS_INTERNAL_RESULT_DIR_NODE_STRING_MISMATCH = -43, // A mismatch was encountered while comparing the search string to a sub node prefix string.
WFS_INTERNAL_RESULT_DIR_NODE_CHOICE_NOT_FOUND = -44, // A mismatch was encountered while comparing a character of the search string with a set of choices for that character.
WFS_INTERNAL_RESULT_DIR_BLK_FULL = -45, // Unable to insert the specified string to the radix tree, due to lack of space in the block.
// These result codes are not errors, but normal return values for the path cache functions
WFS_INTERNAL_RESULT_SRV_END_OF_PATH = -60, // Last part of path name parsed
WFS_INTERNAL_RESULT_SRV_PATH_DEPTH_1 = -61, // Path was of depth 1, such as "/something"
WFS_INTERNAL_RESULT_SRV_PATH_DEV = -62, // Path was "/dev"
WFS_INTERNAL_RESULT_SRV_PATH_VOL = -63, // Path was "/vol"
WFS_INTERNAL_RESULT_SRV_PATH_VOL_ROOT = -64, // Path was a volume root path, such as "/vol/xxxxxxx/"
WFS_INTERNAL_RESULT_PTREE_ENTRY_FOUND = -70,
WFS_INTERNAL_RESULT_PTREE_ENTRY_NOT_FOUND = -71,
WFS_INTERNAL_RESULT_PTREE_FULL = -72,
WFS_INTERNAL_RESULT_DEVICE_ERROR = -200,
WFS_INTERNAL_RESULT_DEVICE_INVALID_PARAMETER = -201,
WFS_INTERNAL_RESULT_DEVICE_NOT_FOUND = -202,
WFS_INTERNAL_RESULT_BCACHE_ERROR = -300, // unspecified error
WFS_INTERNAL_RESULT_BCACHE_RESOURCE_LIMIT = -301, // exhausted resources
WFS_INTERNAL_RESULT_BCACHE_INVALID_PARAMETER = -302, // at least one argument is invalid
WFS_INTERNAL_RESULT_BCACHE_NO_MEMORY = -303, // could not malloc
WFS_INTERNAL_RESULT_BCACHE_NOT_FOUND = -304, // sector is not cached
WFS_INTERNAL_RESULT_BCACHE_MAX_DEVICES = -305, // max devices alreay allocated
WFS_INTERNAL_RESULT_BCACHE_INVALID_DEVICE = -306, // device not found/open
WFS_INTERNAL_RESULT_BCACHE_INVALID_HANDLE = -307, // invalid device handle
WFS_INTERNAL_RESULT_BCACHE_INVALID_VOLUME = -308, // invalid volume ID (not mapped)
WFS_INTERNAL_RESULT_BCACHE_ALREADY_MAPPED = -309, // vol or devH already mapped
WFS_INTERNAL_RESULT_BCACHE_ALLOC = -310, // cannot alloc (no mem, or pmem error)
WFS_INTERNAL_RESULT_BCACHE_PMEM = -311, // cannot read or write to pmem device
WFS_INTERNAL_RESULT_VOLUME_ERROR = -400, // unspecified volume error
WFS_INTERNAL_RESULT_VOLUME_INVALID_PARAMETER = -401, // at least one argument is invalid
WFS_INTERNAL_RESULT_VOLUME_BCACHE_ALLOC = -402, // cannot allocate a page/block in memory
WFS_INTERNAL_RESULT_VOLUME_BCACHE_CONFIG = -403, // block cache not configured correctly
WFS_INTERNAL_RESULT_VOLUME_ID = -404, // bad volume ID or not initialized
WFS_INTERNAL_RESULT_VOLUME_CORRUPT_MR = -405, // the MR (or its free lists) are corrupted
WFS_INTERNAL_RESULT_VOLUME_AREA_ALLOC = -406, // area allocation cannot be satisfied
WFS_INTERNAL_RESULT_VOLUME_DEVICE_PARAMETER = -407, // parameters incompatible with device
WFS_INTERNAL_RESULT_VOLUME_NOT_MAPPED = -408, // volume is not mapped; invalid volume ID
WFS_INTERNAL_RESULT_TRANSACTION_ERROR = -500, // unspecified transaction error
WFS_INTERNAL_RESULT_TRANSACTION_INVALID_PARAMETER= -501,
WFS_INTERNAL_RESULT_ACL_ERROR = -600, // unspecified error
WFS_INTERNAL_RESULT_ACL_INVALID_PARAMETER = -601, // at least one argument is invalid
WFS_INTERNAL_RESULT_ACL_MAX_ENTRIES = -602, // max entries already in the access list.
WFS_INTERNAL_RESULT_ACL_BUFFER_TOO_SMALL = -603, // buffer is too small to store an access list.
WFS_INTERNAL_RESULT_ACL_CACHE = -610, // cannot allocate a cache.
WFS_INTERNAL_RESULT_ACL_FILE = -620, // cannot create, modify or delete the access list file.
WFS_INTERNAL_RESULT_ACL_ACLDIR_INCONSISTENT = -621, // access list files and indexlist are inconsistent.
WFS_INTERNAL_RESULT_ACL_FILENAME = -630, // cannot convert acl filename <=> acl content.
WFS_INTERNAL_RESULT_ACL_NAMEDIR_INCONSISTENT = -631, // access name files and indexlist are inconsistent.
WFS_INTERNAL_RESULT_ACL_HANDLE = -640, // cannot allocate an access list handle.
WFS_INTERNAL_RESULT_AREA_ERROR = -700, // unspecified area error
WFS_INTERNAL_RESULT_AREA_INVALID_PARAMETER = -701,
WFS_INTERNAL_RESULT_AREA_BCACHE_ALLOC = -702, // cannot allocate a page/block in memory
WFS_INTERNAL_RESULT_AREA_CORRUPT_HDR = -703, // the area header is corrupted
WFS_INTERNAL_RESULT_AREA_VOLUME_NOT_MAPPED = -704, // volume is not mapped; invalid volume ID
WFS_INTERNAL_RESULT_AREA_ALLOC = -705, // area allocation cannot be satisfied
WFS_INTERNAL_RESULT_NOT_IMPLEMENTED = -1026, // The requested function has not yet been implemented //ToDo: This error should be removed from the final API
WFS_INTERNAL_RESULT_UNKNOWN = -1027, // Unexpected error - could be caused by a bug in the file system.
WFS_INTERNAL_RESULT_FATAL_ERROR = -1028 // May be caused by critical metadata corruption.
} WFSInternalResult;
#define WFSSetLastError(nErr) (wkg.nLastErr = (nErr))
#endif

View File

@ -0,0 +1,73 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfs_Heap.h - memory allocation functions
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfs_Heap.h,v $
Revision 1.8 2008/04/19 05:52:37 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.7 2007/12/26 04:26:41 paul
changed pAllocator to &allocator
Revision 1.6 2007/12/26 04:13:56 paul
Changed RVL version of WFSHeap
Revision 1.5 2007/12/26 00:19:25 paul
Added WFSHeapDestroy()
Revision 1.4 2007/11/02 00:23:58 paul
started logging changes in the file
*---------------------------------------------------------------------------*/
#ifndef wfs_Heap_h
#define wfs_Heap_h
#include "wfs_Defs.h"
#ifdef _DEBUG
#define _DEBUG_HEAP 0 // change to 1 if debug info required
#else
#define _DEBUG_HEAP 0
#endif
#if _WIN32
typedef HANDLE WFSHeap;
#elif _TWL
#define WFS_HEAP_DEFAULT_ALIGNMENT 32
typedef OSHeapHandle WFSHeap;
#elif _RVL
#include <revolution/mem.h>
#define WFS_HEAP_DEFAULT_ALIGNMENT 32
typedef struct {
MEMAllocator allocator;
MEMHeapHandle handle;
} WFSHeap;
#elif _IOP
#define WFSHeap IOSHeapId
#endif
void WFSCreateHeap(WFSHeap *pHeap, void *pBase, size_t nSize);
void *WFSHeapAlloc(WFSHeap *pHeap, size_t nSize);
void WFSHeapFree(WFSHeap *pHeap, void *pAddr);
void WFSHeapDestroy(WFSHeap *pHeap);
#endif //define wfs_Heap_h

View File

@ -0,0 +1,179 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfs_Mutex.h - mutual exclusion for multi-thread case
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfs_Mutex.h,v $
Revision 1.11 2008/04/19 05:52:30 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.10 2007/12/27 01:43:38 ueno
Added WFSIsThreadTerminated() and WFSJoinThread().
Revision 1.9 2007/12/25 13:59:47 ueno
Added WFSSuspendThread().
Revision 1.8 2007/11/21 04:17:28 wayne.wong
Many changes that included single request/result RPC messages, bug fixes, code factoring, and English C comment adjustments.
1. Combined RPC messages into a single request message and single result
message. Except for file reads and writes.
2. Fixed+factored some Endianess code.
3. Enabled larger TCP/IP data transfer size. Previous setting was artifically small
to test the code to perform large transfers.
4. Changed the volume id parameters utf8*->WFSVolumeId for SrvGetVolumeId
and SrvMountDevice. More consistent with the way we send this type at the
RPC layer.
5. Changed a couple Japanese comments to be compatible with English
comments. In particular, the "//" comment with a backslash at the end of
the line causes the next line of code to be ignored.
6. Removed Windows-specific debugging output defines for RVL build.
Revision 1.7 2007/11/02 00:23:33 paul
started logging changes in the file
*---------------------------------------------------------------------------*/
#ifndef wfs_Mutex_h
#define wfs_Mutex_h
#include "wfs_Defs.h"
#ifdef _DEBUG
#define _DEBUG_MUTEX 0 // change to 1 if debug info required
#else
#define _DEBUG_MUTEX 0
#endif
#if _WIN32
typedef struct {
HANDLE hHandle;
} WFSMutex;
typedef struct {
HANDLE hAutoResetEvent;
//HANDLE hManualResetEvent;
} WFSCond;
typedef struct {
HANDLE hThread;
} WFSThread;
void WFSInitMutex(WFSMutex *mutex);
void WFSLockMutex(WFSMutex *mutex);
bool WFSTryLockMutex(WFSMutex *mutex);
void WFSUnlockMutex(WFSMutex *mutex);
void WFSInitCond(WFSCond *pCond);
void WFSSignalCond(WFSCond *pCond);
void WFSWaitCond(WFSCond *pCond, WFSMutex* pMx);
void WFSResetCond(WFSCond *pCond);
typedef LPTHREAD_START_ROUTINE WFSThreadFunc;
bool WFSCreateThread(WFSThread *thread,
WFSThreadFunc threadFunc,
void* param,
void* stackBase,
u32 stackSize,
OSPriority priority);
s32 WFSResumeThread(WFSThread *pThread);
void WFSCancelThread(WFSThread *pThread);
void WFSExitThread(void *pVal);
s32 WFSSuspendThread(WFSThread *pThread);
bool WFSIsThreadTerminated(WFSThread *thread);
bool WFSJoinThread(WFSThread *thread, void** val);
#elif _TWL
#define WFSMutex OSMutex
#define WFSCond OSEvent
#define WFSThread OSThread
#define WFSInitMutex osInitMutex
#define WFSLockMutex osLockMutex
#define WFSTryLockMutex osTryLockMutex
#define WFSUnlockMutex osUnlockMutex
//#define WFSInitCond osInitCond
//#define WFSSignalCond osSignalCond
//#define WFSWaitCond osWaitCond
//#define WFSResetCond(x) // This function does nothing on RVL, only needed for Windows
typedef void *(*WFSThreadFunc)(void *);
bool WFSCreateThread(WFSThread *thread,
WFSThreadFunc threadFunc,
void* param,
void* stackBase,
u32 stackSize,
OSPriority priority);
s32 WFSResumeThread(WFSThread *pThread);
void WFSCancelThread(WFSThread *pThread);
void WFSExitThread(void *pVal);
s32 WFSSuspendThread(WFSThread *pThread);
bool WFSIsThreadTerminated(WFSThread *thread);
bool WFSJoinThread(WFSThread *thread, void** val);
void WFSInitCond(WFSCond *pCond);
void WFSSignalCond(WFSCond *pCond);
void WFSWaitCond(WFSCond *pCond, WFSMutex* pMx);
void WFSResetCond(WFSCond *pCond);
/*
#define WFSResumeThread OSResumeThread
#define WFSCancelThread OSCancelThread
#define WFSExitThread OSExitThread
#define WFSSuspendThread OSSuspendThread
#define WFSIsThreadTerminated OSIsThreadTerminated
#define WFSJoinThread OSJoinThread
*/
#elif _RVL
#define WFSMutex OSMutex
#define WFSCond OSCond
#define WFSThread OSThread
#define WFSInitMutex OSInitMutex
#define WFSLockMutex OSLockMutex
#define WFSTryLockMutex OSTryLockMutex
#define WFSUnlockMutex OSUnlockMutex
#define WFSInitCond OSInitCond
#define WFSSignalCond OSSignalCond
#define WFSWaitCond OSWaitCond
#define WFSResetCond(x) // This function does nothing on RVL, only needed for Windows
typedef void *(*WFSThreadFunc)(void *);
bool WFSCreateThread(WFSThread *thread,
WFSThreadFunc threadFunc,
void* param,
void* stackBase,
u32 stackSize,
OSPriority priority);
#define WFSResumeThread OSResumeThread
#define WFSCancelThread OSCancelThread
#define WFSExitThread OSExitThread
#define WFSSuspendThread OSSuspendThread
#define WFSIsThreadTerminated OSIsThreadTerminated
#define WFSJoinThread OSJoinThread
#elif _IOP
// dummy
typedef void *WFSMutex;
typedef void *WFSThread;
typedef void *WFSCond;
#endif
#endif //define wfs_Mutex_h

View File

@ -0,0 +1,95 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfs_Names.h - global name types used by the WFS project
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfs_Names.h,v $
Revision 1.5 2008/02/25 05:32:50 paul
Reverted to previous version - changed defs instead.
Revision 1.3 2007/11/06 22:43:48 paul
changed include
Revision 1.2 2007/11/02 00:22:34 paul
started logging changes in the file
*---------------------------------------------------------------------------*/
#ifndef wfs_Names_h
#define wfs_Names_h
#include "wfs_Defs.h"
#if (WFS_MAX_PATH_NAME_SIZE<256)
typedef u8 WFSPathNameLengthType;
#elif (WFS_MAX_PATH_NAME_SIZE<65536)
typedef u16 WFSPathNameLengthType;
#else
typedef u32 WFSPathNameLengthType;
#endif
typedef struct {
WFSPathNameLengthType nLen; // This is the length of the string not including the NULL terminator
utf8 sStr[WFS_MAX_PATH_NAME_SIZE+1];
} WFSPathName;
WFSResult WFSSetPathName(WFSPathName *pPathName, const utf8 *sPathName);
#if (WFS_MAX_FILE_NAME_SIZE<256)
typedef u8 WFSFileNameLengthType;
#elif (WFS_MAX_FILE_NAME_SIZE<65536)
typedef u16 WFSFileNameLengthType;
#else
typedef u32 WFSFileNameLengthType;
#endif
typedef struct {
WFSFileNameLengthType nLen; // This is the length of the string not including the NULL terminator
utf8 sStr[WFS_MAX_FILE_NAME_SIZE+1];
} WFSFileName;
WFSResult WFSSetFileName(WFSFileName *pFileName, const utf8 *sFileName);
#if (WFS_MAX_DEVICE_NAME_SIZE<256)
typedef u8 WFSDeviceNameLengthType;
#elif (WFS_MAX_DEVICE_NAME_SIZE<65536)
typedef u16 WFSDeviceNameLengthType;
#else
typedef u32 WFSDeviceNameLengthType;
#endif
typedef struct {
WFSDeviceNameLengthType nLen; // This is the length of the string not including the NULL terminator
utf8 sStr[WFS_MAX_DEVICE_NAME_SIZE+1];
} WFSDeviceName;
WFSResult WFSSetDeviceName(WFSDeviceName *pDeviceName, const utf8 *sDeviceName);
#if (WFS_MAX_VOLUME_ID_SIZE<256)
typedef u8 WFSVolumeIdLengthType;
#elif (WFS_MAX_VOLUME_ID_SIZE<65536)
typedef u16 WFSVolumeIdLengthType;
#else
typedef u32 WFSVolumeIdLengthType;
#endif
typedef struct {
WFSVolumeIdLengthType nLen; // This is the length of the string not including the NULL terminator
utf8 sStr[WFS_MAX_VOLUME_ID_SIZE+1];
} WFSVolumeId;
WFSResult WFSSetVolumeId(WFSVolumeId *pVolumeId, const utf8 *sVolumeId);
#endif //define wfs_Names_h

View File

@ -0,0 +1,79 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfs_PathNames.h - Functions for concatenating relative and absolute pathnames
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfs_PathNames.h,v $
Revision 1.10 2008/08/19 14:05:40 nakanose_jin
smash pathnames bug
Revision 1.9 2008/04/19 20:44:58 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.8 2007/12/10 02:50:11 paul
Added debug output
Revision 1.7 2007/11/09 01:20:52 paul
Added a new path name type to allow validation of path name depth for paths ending in directories
Revision 1.6 2007/11/02 01:09:26 paul
updated path type
Revision 1.5 2007/11/02 00:20:16 paul
started logging changes in the file
*---------------------------------------------------------------------------*/
// File created by Paul Donnelly on 2007.10.05
#ifndef wfs_PathNames_h
#define wfs_PathNames_h
#ifdef _DEBUG
#define _DEBUG_PATHNAMES 0 // change to 1 locally if debug info required. (should be 0 for checkin)
#else
#define _DEBUG_PATHNAMES 0
#endif
#include "wfs_Mutex.h"
typedef enum {
// Initial states
PATH_TYPE_REL_OR_ABS=0, // Path name can be a relative or absolute file or directory
PATH_TYPE_REL_OR_ABS_DIR, // Path name can be a relative or absolute directory
PATH_TYPE_ABS_DIR_ONLY, // Path name must be an absolute directory
PATH_TYPE_PATTERN // Path name (pattern) can be relative or absolute and may include wild cards in file name part.
} WFSPathNameType;
typedef struct {
u16 nNumParts;
WFSPathNameLengthType aPart[WFS_MAX_PATH_DEPTH+1];
} WFSPathPartOffsetArray;
typedef struct {
WFSPathPartOffsetArray ppoa;
WFSPathName pn;
} WFSPath;
typedef struct {
WFSMutex mxAccessPathGlobals;
WFSPath pathHome, pathCurrent;
} WFSPathGlobals;
void WFSPathInit();
WFSResult WFSPathResolve(WFSPathName *pPnOutAbs, WFSPathPartOffsetArray *pPpoaOutAbs, const utf8 *sInPathName, WFSPathNameType nPathType);
WFSResult WFSPathValidate(WFSPath *pPath);
void WFSPathCopy(WFSPathName *pPnDst, WFSPathPartOffsetArray *pPpoaDst, WFSPathName *pPnSrc, WFSPathPartOffsetArray *pPpoaSrc, bool bAppendSeparator, bool bNullTermination);
#endif //define wfs_PathNames_h

View File

@ -0,0 +1,161 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfs_Platform.h - low level definitions and types that are primarily platform dependent
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfs_Platform.h,v $
Revision 1.13 2008/08/28 00:20:35 nakanose_jin
lets standard exception style
Revision 1.11 2008/08/27 04:50:50 nakanose_jin
add function and defines
Revision 1.10 2008/07/17 05:56:25 kondo_masahiro
Added #define SNPRINTF
Revision 1.9 2008/04/24 23:19:15 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.8 2008/04/22 00:59:59 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.6 2007/11/21 04:17:28 wayne.wong
Many changes that included single request/result RPC messages, bug fixes, code factoring, and English C comment adjustments.
1. Combined RPC messages into a single request message and single result
message. Except for file reads and writes.
2. Fixed+factored some Endianess code.
3. Enabled larger TCP/IP data transfer size. Previous setting was artifically small
to test the code to perform large transfers.
4. Changed the volume id parameters utf8*->WFSVolumeId for SrvGetVolumeId
and SrvMountDevice. More consistent with the way we send this type at the
RPC layer.
5. Changed a couple Japanese comments to be compatible with English
comments. In particular, the "//" comment with a backslash at the end of
the line causes the next line of code to be ignored.
6. Removed Windows-specific debugging output defines for RVL build.
Revision 1.5 2007/11/17 03:05:38 paul
removed #include "WinOSReport.h" from NDEV version
Revision 1.4 2007/11/05 18:39:52 paul
removed kernel-specific definitions
Revision 1.3 2007/11/02 00:22:23 paul
started logging changes in the file
*---------------------------------------------------------------------------*/
#ifndef wfs_Platform_h
#define wfs_Platform_h
#include <firm.h>
#define TWL 1
//--twl modified
#if 1
#define _OSX 0
#define _WIN32 0
#define _TWL 1
#define _RVL 0
#define _IOP 0
#else
//--twl modified
#ifdef OSX
#define _OSX 1
#define _WIN32 0
#define _RVL 0
#define _IOP 0
#else
#ifdef WIN32
#define _OSX 0
#define _WIN32 1
#define _RVL 0
#define _IOP 0
#else
#ifdef IOP
#define _OSX 0
#define _WIN32 0
#define _RVL 0
#define _IOP 1
#else // RVL
#define _OSX 0
#define _WIN32 0
#define _RVL 1
#define _IOP 0
#endif
#endif
#endif
#endif //twl modified
#if _WIN32
#pragma warning(disable:4996)
// #define UNALIGNED __unaligned
#define BYTES_PER_INT 4
#define BITS_PER_INT 32
#define BIT_OFFSET_MASK 31
#define BIT_OFFSET_TO_INT_OFFSET_SHIFT 5
#define OSReport printf
#include "WinOSReport.h"
#define OSPanic MyOSPanic
#define SNPRINTF _snprintf
#elif _OSX
#define BYTES_PER_INT 4
#define BITS_PER_INT 32
#define BIT_OFFSET_MASK 31
#define BIT_OFFSET_TO_INT_OFFSET_SHIFT 5
#define OSReport printf
#include "WinOSReport.h"
#define OSPanic MyOSReport
#define SNPRINTF snprintf
//-- twl modified
#elif _TWL
#define BYTES_PER_INT 4
#define BITS_PER_INT 32
#define BIT_OFFSET_MASK 31
#define BIT_OFFSET_TO_INT_OFFSET_SHIFT 5
#define MyOSReport osTPrintf
#define InitMyOSReport()
#define SNPRINTF OS_SNPrintf
#define STRNLEN( str, maxlen ) stdStrLen(str)
//-- twl modified
#elif _RVL
#define BYTES_PER_INT 4
#define BITS_PER_INT 32
#define BIT_OFFSET_MASK 31
#define BIT_OFFSET_TO_INT_OFFSET_SHIFT 5
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define MyOSReport OSReport
#define InitMyOSReport()
#define SNPRINTF snprintf
#elif _IOP
#define BYTES_PER_INT 4
#define BITS_PER_INT 32
#define BIT_OFFSET_MASK 31
#define BIT_OFFSET_TO_INT_OFFSET_SHIFT 5
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define MyOSReport printf
#define InitMyOSReport()
#define SNPRINTF snprintf
#endif // WIN32
#ifndef BIG_ENDIAN
#ifdef WIN32
#define BIG_ENDIAN 0
#elif TWL
#define BIG_ENDIAN 0
#else
#define BIG_ENDIAN 1
#endif // WIN32
#endif // BIG_ENDIAN
#endif //define wfs_Platform_h

View File

@ -0,0 +1,35 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfs_Types.h - global types used by the WFS project
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfs_Types.h,v $
Revision 1.5 2008/04/19 05:52:09 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.4 2007/11/02 23:14:04 paul
*** empty log message ***
Revision 1.3 2007/11/02 22:35:50 paul
*** empty log message ***
Revision 1.2 2007/11/02 00:21:35 paul
started logging changes in the file
*---------------------------------------------------------------------------*/
#ifndef wfs_Types_h
#define wfs_Types_h
//typedef char utf8;
#include "wfs_Names.h"
#endif //define wfs_Types_h

View File

@ -0,0 +1,130 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfs_Handles.h - Module for file handles and search directory handles
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfscli_Handles.h,v $
Revision 1.10 2008/10/07 06:42:05 ueno
Modified WFSCliFileInfoAlloc to set WFSCLI_HANDLE_ALLOCATED in order to indicate the handle is allocated.
Revision 1.9 2008/07/09 02:51:29 paul
Fixed comments
Revision 1.8 2008/05/12 20:30:41 paul
Updated handle defs
Revision 1.7 2007/11/02 00:19:58 paul
started logging changes in the file
*---------------------------------------------------------------------------*/
// File created by Paul Donnelly on 2007.10.06
#ifndef wfs_Handles_h
#define wfs_Handles_h
#ifdef _DEBUG
#define _DEBUG_WFS_HANDLES 1
#else
#define _DEBUG_WFS_HANDLES 0
#endif
#include "wfs_Defs.h"
#include "wfs_Mutex.h"
#define WFSCLI_MAX_FILE_HANDLES (1<<WFSCLI_FILE_HANDLE_IDX_BITS)
#define WFSCLI_MAX_SEARCH_DIR_HANDLES (1<<WFSCLI_SEARCH_DIR_HANDLE_IDX_BITS)
/* Adding WFS_MAX_OUTSTANDING_ASYNC_CALLS so that we guarantee a handle is always available on the client side
#define WFSCLI_MAX_FILE_HANDLES (16 + WFS_MAX_OUTSTANDING_ASYNC_CALLS)
#define WFSCLI_MAX_SEARCH_DIR_HANDLES (4 + WFS_MAX_OUTSTANDING_ASYNC_CALLS)
#define WFSCLI_FILE_HANDLE_IDX_BITS WFS_NUM_BITS_REQUIRED(WFSCLI_MAX_FILE_HANDLES)
#define WFSCLI_SEARCH_DIR_HANDLE_IDX_BITS WFS_NUM_BITS_REQUIRED(WFSCLI_MAX_SEARCH_DIR_HANDLES)*/
#define WFSCLI_FILE_HANDLE_INC (1<<(16+WFSCLI_FILE_HANDLE_IDX_BITS))
#define WFSCLI_SEARCH_DIR_HANDLE_INC (1<<(16+WFSCLI_SEARCH_DIR_HANDLE_IDX_BITS))
#define WFSCLI_HANDLE_MASK 0xFFFF0000
#define WFSCLI_HANDLE_COUNTER_MASK 0x1FFF0000
#define WFSCLI_FILE_HANDLE_TT_FIELD 0x00000000
#define WFSCLI_SEARCH_DIR_HANDLE_TT_FIELD 0x20000000
#define WFSCLI_HANDLE_ALLOCATED 0x0000FFFF // set WFSCliFileInfo.nNext to represent this handle is in use.
// Internal binary format of WFSFileHandle (u32)
//
// 0TTcccccccCCCCCCssssssssssSSSSSS
//
// 0 = always 0 (Number of bits = 1 )
// T = type of handle: 00 for FileHandle (Number of bits = 2 )
// c = incrementally assigned by client (Number of bits = 13 - WFSCLI_FILE_HANDLE_IDX_BITS)
// C = idx of aCliFileInfo array (Number of bits = WFSCLI_FILE_HANDLE_IDX_BITS)
// s = incrementally assigned by server (Number of bits = 16 - WFSCLI_FILE_HANDLE_IDX_BITS)
// S = idx of aSrvFileInfo array (Number of bits = WFSCLI_FILE_HANDLE_IDX_BITS)
typedef struct {
u32 nNext;
WFSMutex mxAccessCliFileInfo;
WFSFileHandle nHandle;
WFSFileAttributes fa;
WFSFileSize nPosition;
WFSFileSize nPreAllocateSize;
u8 nAccess;
} WFSCliFileInfo;
// Internal binary format of WFSSearcDirHandle (u32)
//
// 0TTcccccccCCCCCCssssssssssSSSSSS
//
// 0 = always 0 (Number of bits = 1 )
// T = type of handle: 01 for SearchDirHandle (Number of bits = 2 )
// c = incrementally assigned by client (Number of bits = 13 - WFSCLI_SEARCH_DIR_HANDLE_IDX_BITS)
// C = idx of aCliSearchDirInfo array (Number of bits = WFSCLI_SEARCH_DIR_HANDLE_IDX_BITS)
// s = incrementally assigned by server (Number of bits = 16 - WFSCLI_SEARCH_DIR_HANDLE_IDX_BITS)
// S = idx of aSrvSearchDirInfo array (Number of bits = WFSCLI_SEARCH_DIR_HANDLE_IDX_BITS)
typedef struct {
u32 nNext;
WFSSearchDirectoryHandle nHandle;
} WFSCliSearchDirInfo;
typedef struct {
WFSFileHandle nFileHandleCounter; // Counter for cccc field of file handle.
WFSSearchDirectoryHandle nSearchDirHandleCounter; // Counter for cccc field of search directory handle.
u32 nFirstFreeFileHandle; // Index of the first free element of aClientFileInfo
u32 nFirstFreeSearchDirHandle; // Index of the first free element of aClientSearchDirInfo
u32 nNumUsedFileHandles;
u32 nNumUsedSearchDirHandles;
//u32 nFirstUsedFileHandle; // Index of the first used element of aClientFileInfo
//u32 nFirstUsedSearchDirHandle; // Index of the first used element of aClientSearchDirInfo
WFSMutex mxAccessTheFileInfo;
WFSMutex mxAccessTheSearchDirInfo;
WFSCliFileInfo aCliFileInfo[WFSCLI_MAX_FILE_HANDLES];
WFSCliSearchDirInfo aCliSearchDirInfo[WFSCLI_MAX_SEARCH_DIR_HANDLES];
} WFSCliHandles;
void WFSCliInitHandles();
WFSResult WFSGetCliFileInfo(WFSCliFileInfo **ppFi, WFSFileHandle fh);
WFSResult WFSGetCliSearchDirInfo(WFSCliSearchDirInfo **ppSdi, WFSSearchDirectoryHandle sdh);
WFSResult WFSCliFileInfoAlloc(WFSCliFileInfo **ppFi);
WFSResult WFSCliSearchDirInfoAlloc(WFSCliSearchDirInfo **ppSdi);
void WFSCliFileInfoFree(WFSCliFileInfo *pFi);
void WFSCliSearchDirInfoFree(WFSCliSearchDirInfo *pSdi);
#endif //define wfs_Handles_h

View File

@ -0,0 +1,16 @@
#ifndef __NFS_DRNAND_H__
#define __NFS_DRNAND_H__
#include <brom.h>
#include <firm.h>
#define NFS_DEVCTL_GET_GEOMETRY 0
#define NFS_DEVCTL_FORMAT 1
#define NFS_DEVCTL_REPORT_REMOVE 2
#define NFS_DEVCTL_CHECKSTATUS 3
#define NFS_DEVCTL_WARMSTART 4
#define NFS_DEVCTL_POWER_RESTORE 5
#define NFS_DEVCTL_POWER_LOSS 6
#endif // __NFS_DRNAND_H__

View File

@ -0,0 +1,91 @@
/*---------------------------------------------------------------------------*
Project: TWL - SD driver
File: sdmc.h
Copyright 2006-2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Date:: #$
$Rev$
$Author$
*---------------------------------------------------------------------------*/
#ifndef __SDMC_H__
#define __SDMC_H__
#include <rtfs.h>
#ifdef __cplusplus
extern "C" {
#endif
/*********************************************
SDスペック構造体
*********************************************/
typedef struct {
u32 csd_ver2_flag; //CSDフォーマットバージョン(SDHCのときは1)
u32 memory_capacity; //data areaのサイズ(512Byte単位)
u32 protected_capacity; //protected areaのサイズ(512Byte単位)
u32 card_capacity; //カード全体のサイズ(512Byte単位)
u32 adjusted_memory_capacity; //memory_capacityをシリンダ(heads*secptrack)の倍数に調整したサイズ(cylinders*heads*secptrackになる)
u16 heads;
u16 secptrack;
u16 cylinders;
u16 SC; //sectors per cluster
u16 BU;
u16 RDE; //number of root dir entries(512 fix)
u32 SS; //sector size(512 fix)
u32 RSC; //reserved sector count(1 fix)
// u32 TS; //total sectors
u16 FATBITS; //16 or 32
u16 SF; //sectors per FAT
u32 SSA; //sectors in system area
u32 NOM; //sectors in master boot record
} SdmcSpec;
/*FATパラメータ TODO:SdmcSpecを統合すること*/
typedef struct {
u32 device_capacity; //デバイス全体のサイズ(512Byte単位)
u32 adjusted_device_capacity;
u32 memory_capacity; //data areaのサイズ(512Byte単位)
u32 adjusted_memory_capacity; //memory_capacityをシリンダ(heads*secptrack)の倍数に調整したサイズ(cylinders*heads*secptrackになる)
u16 volume_cylinders;
u16 heads;
u16 secptrack;
u16 cylinders;
u16 SC; //sectors per cluster
u16 BU;
u16 RDE; //number of root dir entries(512 fix)
u16 padding;
u32 SS; //sector size(512 fix)
u32 RSC; //reserved sector count(1 fix)
u16 FATBITS; //16 or 32
u16 SF; //sectors per FAT
u32 SSA; //sectors in system area
u32 NOM; //sectors in master boot record
u32 begin_sect;
} FATSpec;
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*__SDMC_H__*/

View File

@ -0,0 +1,29 @@
/*---------------------------------------------------------------------------*
File: msc_api.h
Copyright 2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
*---------------------------------------------------------------------------*/
typedef u32 MSCError;
#define IOS_ERROR_MSC_OK 0
#define IOS_ERROR_MSC_DEVICE_DETACH -8001
#define IOS_ERROR_MSC_COMMAND_FAILED -8002
#define IOS_ERROR_MSC_PHASE_ERROR -8003
#define IOS_ERROR_MSC_INVALID_CBW_SIGNATURE -8004
#define IOS_ERROR_MSC_INVALID_CBW_TAG -8005
#define IOS_ERROR_MSC_HASH_INCONSISTENT -8101
#if _IOP
IOSError MscCheckCswError(HardDisc *p_hd, IOSError ie);
#endif

View File

@ -0,0 +1,190 @@
/*---------------------------------------------------------------------------*
Project: Revolution WFS library
File: wfs_Debug.h - debugging routines for WFS implementation
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfs_Debug.h,v $
Revision 1.16 2008/10/30 06:10:29 kondo_masahiro
Added WFSDEBUG_CMD_AREA_AND_DIR_CHECK_DISK
Revision 1.15 2008/10/14 03:00:34 nakanose_jin
(none)
Revision 1.14 2008/09/18 10:25:33 nakanose_jin
add new WFSDEBUG_CMD_*
Revision 1.13 2008/08/29 01:14:57 kondo_masahiro
Added a flag WFSDEBUG_CMD_KRN_INIT_AREA_SECTORS.
Revision 1.11 2008/06/26 00:21:30 kondo_masahiro
Added #define WFSDEBUG_CMD_SHIM_WORKSPACE.
Revision 1.10 2008/05/23 02:00:33 nakanose_jin
add new command
Revision 1.9 2008/05/10 04:20:22 kondo_masahiro
Merged and fixed code to accept RM compiler
Revision 1.8 2008/05/08 11:40:58 nakanose_jin
move WFSDebugSetTitleID wfsPerm.h => wfs_Debug.h
Revision 1.7 2008/05/07 13:27:12 nakanose_jin
fix comment
Revision 1.6 2008/04/25 12:06:38 nakanose_jin
add cmd (0x2)
Revision 1.5 2008/04/18 07:53:33 nakanose_jin
merging acl
Revision 1.4 2008/04/03 07:11:05 nakanose_jin
add extern C
Revision 1.3 2008/03/31 04:24:58 nakanose_jin
add comments
Revision 1.2 2008/03/31 00:58:52 nakanose_jin
add args for debugproc
Revision 1.1 2008/03/26 01:11:50 nakanose_jin
WFS Debug functions for tool develpment
Revision 1.6 2008/02/20 08:10:10 nakanose_jin
add WFSExecDebugProcedure
Revision 1.5 2007/12/17 13:29:14 nakanose_jin
add debug utility function
Revision 1.4 2007/11/02 00:25:10 paul
started logging changes in the file
*---------------------------------------------------------------------------*/
#include <revolution/wfs.h>
// #include "wfs_Defs.h"
#ifndef __WFS_DEBUG_H__
#define __WFS_DEBUG_H__
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------------------------------------------------
// WFSDebugSetTitleId
//--------------------------------------------------------------------------------------------------------------
WFSResult WFSDebugSetTitleId(WFSTitleId titleId);
// Arguments:
// ----------
// titleId .. Title Id is assigned per application. Determines the ownership & access permissions of files.
// A value of WFS_ROOT_ID can be specified for SYSTEM level access to all files.
// groupId .. Group Id determines the GROUP access to files. Usually corresponds to a Company Id.
//
// Return Values:
// --------------
// Possible return values for WFSDebugSetTitleId:
// WFS_RESULT_OK .. The search handle has been closed successfully.
// WFS_RESULT_INVALID .. The function parameters were invalid.
//
// Description:
// ------------
// Allows the application to specify it's WFS Title Id, which will be used to determine access permissions to WFS files.
// NOTE: This function is for testing and debugging purposes only, and will be removed from the final API.
// NOTE: This function only affects WFS. It does not change the real Title Id.
// ToDo: This function should be removed before releasing to developers.
/*
* for debug purpose only.
*/
WFSResult WFSDebugSrvTest(const char* deviceName);
WFSResult WFSDebugCloseServerSocket(void);
WFSResult WFSDebugCloseCallbackSocket(void);
const char *WFSDebug_GetResultString(WFSResult result);
WFSResult WFSExecDebugProcedure( u32 cmd , void *arg0 , void *arg1 );
const static u32 WFSDEBUG_CMD_DELETE_DEVICEROOT = 0;
const static u32 WFSDEBUG_CMD_DELETE_PATH = 1;
const static u32 WFSDEBUG_CMD_CLOSE_ALLFILE = 2;
const static u32 WFSDEBUG_CMD_DUMP_PERMISSION = 3;
const static u32 WFSDEBUG_CMD_SET_AUTO_FORMAT_ON_ATTACH = 4;
const static u32 WFSDEBUG_CMD_ATTACH = 5;
const static u32 WFSDEBUG_CMD_ATTACH_WRITE_PROTECTED = 6;
const static u32 WFSDEBUG_CMD_DETACH = 7;
const static u32 WFSDEBUG_CMD_PUSH_PATH = 8;
const static u32 WFSDEBUG_CMD_EXEC_BAT = 9; //
const static u32 WFSDEBUG_CMD_TOUCH = 10;
//#define WFSDEBUG_CMD_KRN_INIT_VIRTUAL_DISK 0x10
#define WFSDEBUG_CMD_KRN_INIT_AREA_SECTORS 0x10
#define WFSDEBUG_CMD_KRN_INIT_CACHE 0x11
#define WFSDEBUG_CMD_DIR_CHECK_DNS_EMPTY 0x12
#define WFSDEBUG_CMD_SHIM_WORKSPACE 0x13
#define WFSDEBUG_CMD_AREA_AND_DIR_CHECK_DISK 0x14
#define WFSDEBUG_CMD_DEVICE_ATTACH_DETACH 0x20
#define WFSDEBUG_CMD_DEVICE_PSEUDO_DETACH 0x21
#define WFSDEBUG_CMD_DEVICE_PSEUDO_HASH_INCONSISTENT 0x22
#define WFSDEBUG_CMD_DEVICE_SET_FLAGS 0x23
/*
WFSDEBUG_CMD_DELETE_DEVICEROOT
brief:
arg0 : ( "msc1" )
arg1 : -
WFSDEBUG_CMD_DELETE_PATH
brief: ()
arg0 : ( "msc1" )
arg1 : *1 ( "/titles" )
WFSDEBUG_CMD_CLOSE_ALLFILE
brief:
arg0 :
arg1 : -
WFSDEBUG_CMD_DUMP_PERMISSION
brief: ()
arg0 : ( "msc1" )
arg1 : *1 ( "/titles" )
WFSDEBUG_CMD_SET_AUTO_FORMAT_ON_ATTACH
brief: / (default:)
arg0 : true/false
arg1 : -
WFSDEBUG_CMD_ATTACH
WFSDEBUG_CMD_ATTACH_WRITE_PROTECTED
brief: WFSDevAttach.exe [-p] arg0 arg1
arg0 : ( ex. "msc1")
arg1 : ( ex. "D:\iifstest\msc01" )
WFSDEBUG_CMD_DETACH
brief: WFSDevAttach.exe -d arg0
arg0 : ( ex. "msc1")
arg1 : -
WFSDEBUG_CMD_EXEC_BAT
brief:
使
arg0 : ( ex. "H:\\iifstest\\bin\\ready_testLongPathName.bat" )
arg1 : ( (NULL)ex. "H:\\iifstest\\bin" )
*1 :
*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif // __WFS_DEBUG_H__

View File

@ -0,0 +1,26 @@
#ifndef _RANDOMLIB_H
#define _RANDOMLIB_H
#include "revolution.h"
/*
#if _IOP
#include "types.h"
#else
#include "revolution/types.h"
#endif
*/
#include "wfs_Platform.h"
void RandomInitialise(int ij, int kl);
double RandomUniform(void);
double RandomGaussian(double mean, double stddev);
int RandomInt(int lower, int upper);
double RandomDouble(double lower, double upper);
u32 RandomU32();
#define NUM_UNIQUE_RANDOM_SEEDS_U32 0x382C7A42
void RandomSetSeedU32(u32 nSeed);
#endif

View File

@ -0,0 +1,17 @@
#ifndef __REVOLUTION_H__
#define __REVOLUTION_H__
#include <brom.h>
#include <firm.h>
#include <revolution/wfsError.h>
//#include <mem/allocator.h>
//#include <mem/heapCommon.h>
typedef u32 OSPriority;
#define ASSERT SDK_ASSERT
//typedef BOOL bool;
//typedef BOOL WFSBool;
#endif // __REVOLUTION_H__

View File

@ -0,0 +1,36 @@
/*---------------------------------------------------------------------------*
Project: MEM library
File: mem.h
Programmers: Takano Makoto
Copyright 2005 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
*---------------------------------------------------------------------------*/
#ifndef __MEM_H__
#define __MEM_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <revolution/mem/heapCommon.h>
#include <revolution/mem/expHeap.h>
#include <revolution/mem/frameHeap.h>
#include <revolution/mem/unitHeap.h>
#include <revolution/mem/allocator.h>
#include <revolution/mem/list.h>
#ifdef __cplusplus
} /* extern "C" */
#endif
/* __MEM_H__ */
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,98 @@
/*---------------------------------------------------------------------------*
Project: Revolution WFS library
File: wfserror.h
Copyright 2007-2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfsError.h,v $
Revision 1.6 2008/09/26 12:04:33 ueno
Changed WFS_RESULT_* to be equal to WFSKRN_RESULT_* to guarantee the casts.
Revision 1.5 2008/07/11 19:02:21 paul
Removed WFS_RESULT_DIRECTORY_FULL. Fixed comments and reordered slightly.
Revision 1.4 2008/07/10 07:03:19 nakanose_jin
add permissions API
Revision 1.3 2008/07/02 06:52:43 nakanose_jin
bye inheritance & dev_full error
Revision 1.2 2008/06/25 00:58:19 nakanose_jin
add control level error
Revision 1.1 2008/04/08 18:25:40 paul
Moved error definitions from wfs.h to this header file.
*---------------------------------------------------------------------------*/
#ifndef __WFS_ERROR_H__
#define __WFS_ERROR_H__
#ifdef __cplusplus
extern "C" {
#endif
// ---------------------------------------------------------------------
// WFS error codes
// ---------------------------------------------------------------------
typedef enum {
WFS_RESULT_OK = 0, // Success
// Errors that can usually be detected early, and if detected, would result in the Async callback not being called:
WFS_RESULT_BUSY = -1, // Too many requests, try waiting then calling again.
WFS_RESULT_OUT_OF_MEMORY = -2, // The library does not have enough memory to complete the requested operation. (May be due to too many outstanding aysnc calls).
WFS_RESULT_INVALID = -3, // The function parameters were invalid, e.g. File name is too long, Path is too long or too deep.
WFS_RESULT_ACCESS = -4, // Trying to write to a file which was opened for read-only access, or vice versa.
WFS_RESULT_LIB_NOT_INITIALIZED = -5, // The WFS library has not been initialized. Please call WFSInit() (This error is checked in functions that require the library to be initialized, but only in the debug versions).
WFS_RESULT_LIB_ALREADY_INITIALIZED = -6, // The WFS library has already been initialized.
WFS_RESULT_FILE_TOO_BIG = -7, // The current write/append request would push the file over the size limit.
WFS_RESULT_NO_CHANGE_SIZE = -8, // The requested operation would cause the file size to change, but this file has WFS_PERM_NO_CHANGE_SIZE flag set.
// Errors that cannot usually be detected early, and would be passed via nResult to the Async callbacks:
WFS_RESULT_MEDIA_ERROR = -9, // The device or media is not attached, or was removed before the requested operation could be completed.
WFS_RESULT_DEV_UNUSABLE = -10, // Attached device is not accessible, e.g. because it is an unsupported device, or has an unknown format.
WFS_RESULT_DEV_NOT_INITIALIZED = -11, // Device not formatted, or does not yet contain a WFS volume
WFS_RESULT_DEV_IN_USE = -12, // Trying to initialize a device which is in use (mounted) by one or more clients.
WFS_RESULT_VOL_ID_ERROR = -13, // Attempted to mount a volume with the same unique Id as an already mounted volume (This could happen if the User backs up an entire WFS volume using a PC)
WFS_RESULT_WRITE_PROTECTED = -14, // Device is physically write protected (e.g. USB Flash memory, SD Card)
WFS_RESULT_ALREADY_MOUNTED = -15, // The device is already mounted
WFS_RESULT_PERMISSION = -16, // Permission flags do not permit the requested access from this application.
WFS_RESULT_PERMISSION_CL = -17, // Permission error caused by control level problems.
WFS_RESULT_ACL_FULL = -18, // The access list is full.
WFS_RESULT_ACL_ENTRY_NOT_FOUND = -19, // The specified entry does not exist in the access list.
WFS_RESULT_AUTHENTICATION = -20, // Trying to access content on a different Wii, which does not have the required access rights.
WFS_RESULT_CORRUPTION = -21, // A corrupted block was encountered which prevented the operation from being completed.
WFS_RESULT_DIRECTORY_QUOTA = -22, // One of the ancestor directories would exceed its quota.
WFS_RESULT_MAX_HANDLES = -23, // The maximum number of concurrent file handles / search handles are already in use.
WFS_RESULT_ALREADY_EXISTS = -24, // The file or directory being created already exists.
WFS_RESULT_NOT_FOUND = -25, // The specified file, directory or device does not exist.
WFS_RESULT_NOT_EMPTY = -26, // The specified directory cannot be deleted because it is not empty.
WFS_RESULT_NOT_FILE = -27, // The specified path is directory instead of a file.
WFS_RESULT_NOT_DIRECTORY = -28, // The specified path is a file instead of a directory.
WFS_RESULT_FILE_OPEN = -29, // The file is open. Cannot delete, move, rename, change permissions of an open file. Cannot open a file more than once unless all opens are WFS_ACCESS_READ.
WFS_RESULT_LOCKED = -30, // Cannot perform the requested operation since the file or directory is locked by an existing operation.
WFS_RESULT_RESOURCE_LIMIT_EXCEEDED = -31, // A resource limit prevents this function call. Try smaller values.
WFS_RESULT_NOT_IMPLEMENTED = -1026, // The requested function has not yet been implemented //ToDo: This error should be removed from the final API
WFS_RESULT_UNKNOWN = -1027, // Unexpected error - could be caused by a bug in the file system.
WFS_RESULT_FATAL_ERROR = -1028 // May be caused by critical metadata corruption.
} WFSResult;
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif //define __WFS_ERROR_H__

View File

@ -0,0 +1,462 @@
/*---------------------------------------------------------------------------*
Project: Revolution WFS library
File: wfsperm.h
Copyright 2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfsPerm.h,v $
Revision 1.20 2008/09/18 10:26:24 nakanose_jin
fix comments
Revision 1.19 2008/08/29 02:24:46 nakanose_jin
add comments
Revision 1.18 2008/08/06 04:12:45 nakanose_jin
add PERMISSION_CL,ACL_ENTRY_NOT_FOUND,ACL_FULL comment
Revision 1.17 2008/07/18 00:33:03 paul
Added descriptions of functions. Rename WFSDeletePermissions() -> WFSDeleteAccessListEntry().
Revision 1.16 2008/07/17 05:07:02 kondo_masahiro
inline -> static inline
Revision 1.15 2008/07/15 08:28:47 nakanose_jin
change define value
Revision 1.14 2008/07/14 07:22:51 ueno
Renamed WFSSetAccessList() by WFSSetAccessListEntry().
Revision 1.13 2008/07/11 09:46:03 ueno
Added async functions.
Revision 1.12 2008/07/11 09:19:36 ueno
Fixed a typo.
Revision 1.11 2008/07/10 07:03:18 nakanose_jin
add permissions API
Revision 1.10 2008/07/02 06:52:43 nakanose_jin
bye inheritance & dev_full error
Revision 1.9 2008/06/23 02:58:31 nakanose_jin
separate relative from absolute
Revision 1.8 2008/06/16 18:23:50 ueno
Removed WFSCreateAccessList().
Revision 1.7 2008/06/05 14:08:06 ueno
Revised permission APIs.
Revision 1.6 2008/05/08 11:41:02 nakanose_jin
move WFSDebugSetTitleID wfsPerm.h => wfs_Debug.h
Revision 1.5 2008/05/07 13:26:55 nakanose_jin
fix ambiguous definision
Revision 1.4 2008/04/29 01:14:52 ueno
Removed WFS_DEBUG_SYSTEM_PROCESS_ID.
Added WFS_ROOT_ID and WFS_EVERYONE_ID.
Revision 1.3 2008/04/23 09:21:24 ueno
Revised directory permission (change -> add).
Revision 1.2 2008/04/18 07:54:12 nakanose_jin
merging acl
Revision 1.1 2008/04/08 18:27:19 paul
Moved permissions related declarations from wfs.h to this header file. Changed permissions API to support access lists.
*---------------------------------------------------------------------------*/
#ifndef __WFS_PERM_H__
#define __WFS_PERM_H__
// Permission Flags Which apply to Files only:
#include <revolution/wfstypes.h>
#ifdef __cplusplus
extern "C" {
#endif
// permissions
#define WFS_PERM_CHANGE_SIZE 0x0001
#define WFS_PERM_WRITE 0x0002
#define WFS_PERM_READ 0x0004
#define WFS_PERM_ADD_OR_DELETE_FILE 0x0008
#define WFS_PERM_ADD_OR_DELETE_SUBDIR 0x0010
#define WFS_PERM_LIST 0x0020
#define WFS_PERM_DELETE_OR_MOVE 0x0040
// reserved
#define WFS_PERM_RESERVED0 0x0080
#define WFS_PERM_RESERVED1 0x0100
#define WFS_PERM_RESERVED2 0x0200
#define WFS_PERM_RESERVED3 0x0400
#define WFS_PERM_RESERVED4 0x0800
// control level
/* ŒÃ‚¢’è‹`
#define WFS_PERM_CL0 0x0000 // 0
#define WFS_PERM_CL_MINUS_1 0x7000 // -1
#define WFS_PERM_CL_MINUS_2 0x6000 // -2
#define WFS_PERM_CL_MINUS_3 0x5000 // -3
#define WFS_PERM_CL_MINUS_4 0x4000 // -4
#define WFS_PERM_CL_MASK 0x7000
*/
#define WFS_PERM_CL_MINUS_0 0xE000 // 0
#define WFS_PERM_CL_MINUS_1 0xC000 // -1
#define WFS_PERM_CL_MINUS_2 0xA000 // -2
#define WFS_PERM_CL_MINUS_3 0x8000 // -3
#define WFS_PERM_CL_0 0x0000 // 0 (absolute)
#define WFS_PERM_CL_1 0x2000 // 1 (absolute)
#define WFS_PERM_CL_2 0x4000 // 2 (absolute)
#define WFS_PERM_CL_3 0x6000 // 3 (absolute)
#define WFS_PERM_CL_MASK 0xE000
#define WFS_PERM_CL_SHIFT 13
#define WFS_PERM_CL_RELATIVE_BIT 0x8000
static inline u32 WFS_PERM_GET_CL_ABSOLUTE(u32 perm)
{
// ASSERT( 0 == (WFS_PERM_CL_RELATIVE_BIT & perm) );
return ((perm & WFS_PERM_CL_MASK) >> WFS_PERM_CL_SHIFT);
}
static inline u32 WFS_PERM_SET_CL_ABSOLUTE(u32 perm , s32 cl)
{
// ASSERT( (cl >= 0) && (cl <= 3) );
perm = (perm & ~WFS_PERM_CL_MASK) | (cl << WFS_PERM_CL_SHIFT);
return perm;
}
static inline u32 WFS_PERM_SET_CL_RELATIVE(u32 perm , s32 cl)
{
// ASSERT( (cl <= 0) && (cl >= -3) );
perm = (perm & ~WFS_PERM_CL_MASK) | ((7 + cl) << WFS_PERM_CL_SHIFT);
return perm;
}
#define WFS_PERM_DIR_FULL (WFS_PERM_CHANGE_SIZE | WFS_PERM_WRITE | WFS_PERM_READ | \
WFS_PERM_ADD_OR_DELETE_FILE | WFS_PERM_ADD_OR_DELETE_SUBDIR | \
WFS_PERM_LIST | WFS_PERM_DELETE_OR_MOVE)
#define WFS_PERM_FILE_FULL (WFS_PERM_CHANGE_SIZE | WFS_PERM_WRITE | WFS_PERM_READ | WFS_PERM_DELETE_OR_MOVE)
#define WFS_PERM_FULL 0xFFFF // this is special keyword. it will be converted to a appropriate value in internal
typedef u32 WFSTitleId;
typedef u32 WFSGroupId;
#define WFS_ROOT_ID 0UL
#define WFS_EVERYONE_ID 0x80000000
typedef struct WFSAccessListEntry {
u32 titleId;
u32 entryCreatorId;
u32 permissions;
} WFSAccessListEntry;
#define WFS_ACL_ENTRY_NET_SIZE (sizeof(u32) + sizeof(u32) + sizeof(u16)) // smaller than sizeof(WFSKrnAccessListEntry).
#define WFS_ACL_MAX_ENTRIES (WFS_MAX_FILE_NAME_SIZE - sizeof(u32)*2)/(WFS_ACL_ENTRY_NET_SIZE*2)
//--------------------------------------------------------------------------------------------------------------
// WFSChangePermissions, WFSChangePermissionsAsync
//--------------------------------------------------------------------------------------------------------------
WFSResult WFSChangePermissions (const utf8 *sPathName, u32 nFlags, u32 nMask);
WFSResult WFSChangePermissionsAsync(const utf8 *sPathName, u32 nFlags, u32 nMask, void *pUserData, WFSResultCallback cb);
// Arguments:
// ----------
// sPathName .. Absolute or relative path name of the file or directory whose permissions are to be changed.
// See "WFS Path Names" for rules about path names.
// nFlags .. The new permissions flags that are to be set. Should be a combination of the permission flags: WFS_PERM_*
// nMask .. The mask determines which flags will be changed. NewAttributes = (OldAttributes & ~nMask) | (nFlags & nMask)
// NOTE: The mask bits for bits which are never allowed to be changed, such as WFS_FLAG_IS_A_DIRECTORY are automatically set to 0.
// pUserData .. Arbitrary user data that is passed to the callback function.
// cb .. Pointer to a callback function to receive the result of WFSChangePermissionsAsync.
//
// Return Values:
// --------------
// Possible return values for WFSChangePermissions:
// WFS_RESULT_OK .. The permissions were updated successfully.
// WFS_RESULT_BUSY .. Too many requests, try waiting then calling again.
// WFS_RESULT_INVALID .. The function parameters were invalid, e.g. File name is too long, Path is too deep.
// WFS_RESULT_MEDIA_ERROR .. The device or media is not attached, or was removed before the requested operation could be completed.
// WFS_RESULT_WRITE_PROTECTED .. Device is physically write protected (e.g. USB Flash memory, SD Card).
// WFS_RESULT_PERMISSION .. The requested change was not allowed due to the existing permissions settings.
// WFS_RESULT_PERMISSION_CL .. You cant set the requested permission because you dont have a appropriate control level.
// WFS_RESULT_ACL_FULL .. You cant set the requested permission because the target access list is full.
// WFS_RESULT_CORRUPTION .. A corrupted block was encountered which prevented the operation from being completed.
// WFS_RESULT_NOT_FOUND .. The specified file or directory does not exist.
// WFS_RESULT_RESOURCE_LIMIT_EXCEEDED .. Too much accesslist variations generated , so quota resource are drained.
// Possible immediate return values for WFSChangePermissionsAsync:
// WFS_RESULT_OK .. Change permissions request was dispatched successfully. The callback will be called in this case only.
// WFS_RESULT_BUSY .. Too many requests, try waiting then calling again.
// WFS_RESULT_OUT_OF_MEMORY .. The library does not have enough memory to dispatch the request. (May be due to too many outstanding aysnc calls).
// WFS_RESULT_INVALID .. The function parameters were invalid, e.g. File name is too long, Path is too deep.
// Possible values of nResult passed to WFSChangePermissionsAsync callback:
// WFS_RESULT_OK .. The permissions were updated successfully.
// WFS_RESULT_MEDIA_ERROR .. The device or media is not attached, or was removed before the requested operation could be completed.
// WFS_RESULT_WRITE_PROTECTED .. Device is physically write protected (e.g. USB Flash memory, SD Card).
// WFS_RESULT_PERMISSION .. Only the owner of a file or directory can change its permission flags.
// WFS_RESULT_PERMISSION_CL .. You cant set the requested permission because you dont have a appropriate control level.
// WFS_RESULT_ACL_FULL .. You cant set the requested permission because the target access list is full.
// WFS_RESULT_CORRUPTION .. A corrupted block was encountered which prevented the operation from being completed.
// WFS_RESULT_NOT_FOUND .. The specified file or directory does not exist.
// WFS_RESULT_RESOURCE_LIMIT_EXCEEDED .. Too much accesslist variations generated , so quota resource are drained.
//
// Description:
// ------------
// These functions can be used to change one's own permissions to access a specified file or directory.
// However the permissions can only be set within the bounds granted by superior users.
// (The purpose is to allow a user to specify a file as read-only, which is common in existing file systems).
//--------------------------------------------------------------------------------------------------------------
// WFSSetPermissionsForUser, WFSSetPermissionsForUserAsync
//--------------------------------------------------------------------------------------------------------------
WFSResult WFSSetPermissionsForUser (const utf8 *sPathName, u32 nFlags, u32 nMask, WFSTitleId titleId);
WFSResult WFSSetPermissionsForUserAsync(const utf8 *sPathName, u32 nFlags, u32 nMask, WFSTitleId titleId, void *pUserData, WFSResultCallback cb);
// Arguments:
// ----------
// sPathName .. Absolute or relative path name of the file or directory whose permissions are to be changed.
// See "WFS Path Names" for rules about path names.
// nFlags .. The new permissions flags that are to be set. Should be a combination of the permission flags: WFS_PERM_*
// nMask .. The mask determines which flags will be changed. NewAttributes = (OldAttributes & ~nMask) | (nFlags & nMask)
// titleId .. The title id of the application for which permissions are being set.
// pUserData .. Arbitrary user data that is passed to the callback function.
// cb .. Pointer to a callback function to receive the result of WFSSetPermissionsForUserAsync.
//
// Return Values:
// --------------
// Possible return values for WFSSetPermissionsForUser:
// WFS_RESULT_OK .. The permissions were updated successfully.
// WFS_RESULT_BUSY .. Too many requests, try waiting then calling again.
// WFS_RESULT_INVALID .. The function parameters were invalid, e.g. File name is too long, Path is too deep.
// WFS_RESULT_MEDIA_ERROR .. The device or media is not attached, or was removed before the requested operation could be completed.
// WFS_RESULT_WRITE_PROTECTED .. Device is physically write protected (e.g. USB Flash memory, SD Card).
// WFS_RESULT_PERMISSION .. The requested change was not allowed due to the existing permissions settings.
// WFS_RESULT_PERMISSION_CL .. You cant set the requested permission because you dont have a appropriate control level.
// WFS_RESULT_ACL_FULL .. You cant set the requested permission because the target access list is full.
// WFS_RESULT_CORRUPTION .. A corrupted block was encountered which prevented the operation from being completed.
// WFS_RESULT_DIRECTORY_QUOTA .. This operation would cause one of the ancestor directories to exceed its quota.
// WFS_RESULT_NOT_FOUND .. The specified file or directory does not exist.
// WFS_RESULT_RESOURCE_LIMIT_EXCEEDED .. Too much accesslist variations generated , so quota resource are drained.
// Possible immediate return values for WFSSetPermissionsForUserAsync:
// WFS_RESULT_OK .. Change permissions request was dispatched successfully. The callback will be called in this case only.
// WFS_RESULT_BUSY .. Too many requests, try waiting then calling again.
// WFS_RESULT_OUT_OF_MEMORY .. The library does not have enough memory to dispatch the request. (May be due to too many outstanding aysnc calls).
// WFS_RESULT_INVALID .. The function parameters were invalid, e.g. File name is too long, Path is too deep.
// Possible values of nResult passed to WFSSetPermissionsForUserAsync callback:
// WFS_RESULT_OK .. The permissions were updated successfully.
// WFS_RESULT_MEDIA_ERROR .. The device or media is not attached, or was removed before the requested operation could be completed.
// WFS_RESULT_WRITE_PROTECTED .. Device is physically write protected (e.g. USB Flash memory, SD Card).
// WFS_RESULT_PERMISSION .. Only the owner of a file or directory can change its permission flags.
// WFS_RESULT_PERMISSION_CL .. You cant set the requested permission because you dont have a appropriate control level.
// WFS_RESULT_ACL_FULL .. You cant set the requested permission because the target access list is full.
// WFS_RESULT_CORRUPTION .. A corrupted block was encountered which prevented the operation from being completed.
// WFS_RESULT_DIRECTORY_QUOTA .. This operation would cause one of the ancestor directories to exceed its quota.
// WFS_RESULT_NOT_FOUND .. The specified file or directory does not exist.
// WFS_RESULT_RESOURCE_LIMIT_EXCEEDED .. Too much accesslist variations generated , so quota resource are drained.
//
// Description:
// ------------
// Use these functions to specify or change the permissions that a particular title id will have to access or modify the specified file or directory.
// NOTE: The permissions are specified as absolute values. However these are represented on access lists as permissions relative to the granter.
// This function operates in such a way as to only create access list entries when necessary, and remove them if possible.
WFSResult WFSGetPermissionsForUser (const utf8 *sPathName, u32 *pFlags, WFSTitleId titleId);
WFSResult WFSGetPermissionsForUserAsync(const utf8 *sPathName, WFSTitleId titleId, void *pUserData, WFSGetPermissionsForUserCallback cb);
// Arguments:
// ----------
// sPathName .. Absolute or relative path name of a file or directory.
// See "WFS Path Names" for rules about path names.
// pFlags .. A pointer to a u32 which will be overwritten with the permissions the specified title id has to
// access or modify the specified file or directory.
// titleId .. The title id of the application for which permissions are being set.
// pUserData .. Arbitrary user data that is passed to the callback function.
// cb .. Pointer to a callback function to receive the result of WFSGetPermissionsForUserAsync.
//
// Return Values:
// --------------
// Possible return values for WFSGetPermissionsForUser:
// WFS_RESULT_OK .. The specified file or directory was found. The permissions were calculated and copied to *pFlags.
// WFS_RESULT_BUSY .. Too many requests, try waiting then calling again.
// WFS_RESULT_INVALID .. The function parameters were invalid, e.g. File name too long, Path is too deep.
// WFS_RESULT_MEDIA_ERROR .. The device or media is not attached, or was removed before the requested operation could be completed.
// WFS_RESULT_WRITE_PROTECTED .. Device is physically write protected (e.g. USB Flash memory, SD Card. Note: Write errors can occur even for read operations).
// WFS_RESULT_PERMISSION .. Permission flags of the target or its parent directory do not permit requested access from this application.
// WFS_RESULT_CORRUPTION .. A corrupted block was encountered which prevented the operation from being completed.
// WFS_RESULT_NOT_FOUND .. The specified file or directory was not found.
// Possible immediate return values for WFSGetPermissionsForUserAsync:
// WFS_RESULT_OK .. The request was dispatched successfully. The callback will be called in this case only.
// WFS_RESULT_BUSY .. Too many requests, try waiting then calling again.
// WFS_RESULT_OUT_OF_MEMORY .. The library does not have enough memory to dispatch the request. (May be due to too many outstanding aysnc calls).
// WFS_RESULT_INVALID .. The function parameters were invalid, e.g. File name too long, Path is too deep.
// Possible values of nResult passed to WFSGetPermissionsForUserAsync callback:
// WFS_RESULT_OK .. The specified file or directory was found and its permissions were calculated and passed as the nFlags parameter.
// WFS_RESULT_MEDIA_ERROR .. The device or media is not attached, or was removed before the requested operation could be completed.
// WFS_RESULT_WRITE_PROTECTED .. Device is physically write protected (e.g. USB Flash memory, SD Card. Note: Write errors can occur even for read operations).
// WFS_RESULT_PERMISSION .. Permission flags of the target or its parent directory do not permit requested access from this application.
// WFS_RESULT_CORRUPTION .. A corrupted block was encountered which prevented the operation from being completed.
// WFS_RESULT_NOT_FOUND .. The specified file or directory was not found.
//
// Description:
// ------------
// Use these functions to read the permissions of a file or directory for a particular user (title id).
// The permissions values returned are absolute values resulting from inheritance and permissions granted by superior users.
s32 WFSGetAccessList (const utf8 *sPathName, WFSAccessListEntry *pAccessList, u32 nMaxEntries);
WFSResult WFSGetAccessListAsync(const utf8 *sPathName, WFSAccessListEntry *pAccessList, u32 nMaxEntries, void *pUserData, WFSGetAccessListCallback cb);
// Arguments:
// ----------
// sPathName .. Absolute or relative path name of a file or directory.
// See "WFS Path Names" for rules about path names.
// pAccessList .. A pointer to an array of WFSAccessListEntry structs which will be overwritten with the access list entries.
// nMaxEntries .. The maximum number of access list entries that the array can hold.
// pUserData .. Arbitrary user data that is passed to the callback function.
// cb .. Pointer to a callback function to receive the result of WFSGetAccessListAsync.
//
// Return Values:
// --------------
// Possible return values for WFSGetAccessList:
// >= 0 .. The number of access list entries that were successfully copied to the specified array.
// WFS_RESULT_BUSY .. Too many requests, try waiting then calling again.
// WFS_RESULT_INVALID .. The function parameters were invalid, e.g. File name too long, Path is too deep.
// WFS_RESULT_MEDIA_ERROR .. The device or media is not attached, or was removed before the requested operation could be completed.
// WFS_RESULT_WRITE_PROTECTED .. Device is physically write protected (e.g. USB Flash memory, SD Card. Note: Write errors can occur even for read operations).
// WFS_RESULT_PERMISSION .. Permission flags of the target or its parent directory do not permit requested access from this application.
// WFS_RESULT_CORRUPTION .. A corrupted block was encountered which prevented the operation from being completed.
// WFS_RESULT_DIRECTORY_QUOTA .. This operation would cause one of the ancestor directories to exceed its quota.
// WFS_RESULT_NOT_FOUND .. The specified file or directory was not found.
// Possible immediate return values for WFSGetAccessListAsync:
// WFS_RESULT_OK .. The request was dispatched successfully. The callback will be called in this case only.
// WFS_RESULT_BUSY .. Too many requests, try waiting then calling again.
// WFS_RESULT_OUT_OF_MEMORY .. The library does not have enough memory to dispatch the request. (May be due to too many outstanding aysnc calls).
// WFS_RESULT_INVALID .. The function parameters were invalid, e.g. File name too long, Path is too deep.
// Possible values of nResult passed to WFSGetAccessListAsync callback:
// >= 0 .. The number of access list entries that were successfully copied to the specified array.
// WFS_RESULT_MEDIA_ERROR .. The device or media is not attached, or was removed before the requested operation could be completed.
// WFS_RESULT_WRITE_PROTECTED .. Device is physically write protected (e.g. USB Flash memory, SD Card. Note: Write errors can occur even for read operations).
// WFS_RESULT_PERMISSION .. Permission flags of the target or its parent directory do not permit requested access from this application.
// WFS_RESULT_CORRUPTION .. A corrupted block was encountered which prevented the operation from being completed.
// WFS_RESULT_DIRECTORY_QUOTA .. This operation would cause one of the ancestor directories to exceed its quota.
// WFS_RESULT_NOT_FOUND .. The specified file or directory was not found.
//
// Description:
// ------------
// Use these functions to read the raw access list for a file or directory.
// The raw access list contains only relative values of permissions and control level. (relative to the permission granter)
// The actual permission to access files and directories depends on the absolute values of permissions and control level,
// which are calculated by following inheritance and the permission-granting links back to root.
WFSResult WFSSetAccessListEntry (const utf8 *sPathName, u32 nFlags, u32 nMask, WFSTitleId titleId);
WFSResult WFSSetAccessListEntryAsync(const utf8 *sPathName, u32 nFlags, u32 nMask, WFSTitleId titleId, void *pUserData, WFSResultCallback cb);
// Arguments:
// ----------
// sPathName .. Absolute or relative path name of a file or directory.
// See "WFS Path Names" for rules about path names.
// titleId .. The title id of the application for which permissions are being set.
// nFlags .. The new permissions flags that are to be set. Should be a combination of the permission flags: WFS_PERM_*
// pUserData .. Arbitrary user data that is passed to the callback function.
// cb .. Pointer to a callback function to receive the result of WFSSetAccessListEntryAsync.
//
// Return Values:
// --------------
// Possible return values for WFSSetAccessListEntry:
// WFS_RESULT_OK .. The specified file or directory was found, and the specified access list entry was created or updated.
// WFS_RESULT_BUSY .. Too many requests, try waiting then calling again.
// WFS_RESULT_INVALID .. The function parameters were invalid, e.g. File name too long, Path is too deep.
// WFS_RESULT_MEDIA_ERROR .. The device or media is not attached, or was removed before the requested operation could be completed.
// WFS_RESULT_WRITE_PROTECTED .. Device is physically write protected (e.g. USB Flash memory, SD Card. Note: Write errors can occur even for read operations).
// WFS_RESULT_PERMISSION_CL .. You cant set the requested permission because you dont have a appropriate control level.
// WFS_RESULT_ACL_FULL .. You cant set the requested permission because the target access list is full.
// WFS_RESULT_CORRUPTION .. A corrupted block was encountered which prevented the operation from being completed.
// WFS_RESULT_DIRECTORY_QUOTA .. This operation would cause one of the ancestor directories to exceed its quota.
// WFS_RESULT_NOT_FOUND .. The specified file or directory was not found.
// WFS_RESULT_RESOURCE_LIMIT_EXCEEDED .. Too much accesslist variations generated , so quota resource are drained.
// Possible immediate return values for WFSSetAccessListEntryAsync:
// WFS_RESULT_OK .. The request was dispatched successfully. The callback will be called in this case only.
// WFS_RESULT_BUSY .. Too many requests, try waiting then calling again.
// WFS_RESULT_OUT_OF_MEMORY .. The library does not have enough memory to dispatch the request. (May be due to too many outstanding aysnc calls).
// WFS_RESULT_INVALID .. The function parameters were invalid, e.g. File name too long, Path is too deep.
// Possible values of nResult passed to WFSSetAccessListEntryAsync callback:
// WFS_RESULT_OK .. The specified file or directory was found, and the specified access list entry was created or updated.
// WFS_RESULT_MEDIA_ERROR .. The device or media is not attached, or was removed before the requested operation could be completed.
// WFS_RESULT_WRITE_PROTECTED .. Device is physically write protected (e.g. USB Flash memory, SD Card. Note: Write errors can occur even for read operations).
// WFS_RESULT_PERMISSION .. Permission flags of the target or its parent directory do not permit requested access from this application.
// WFS_RESULT_CORRUPTION .. A corrupted block was encountered which prevented the operation from being completed.
// WFS_RESULT_DIRECTORY_QUOTA .. This operation would cause one of the ancestor directories to exceed its quota.
// WFS_RESULT_NOT_FOUND .. The specified file or directory was not found.
//
// Description:
// ------------
// Use these functions to create or update a raw access list entry.
// Raw access list entries contain only relative values of permissions and control level. (relative to the permission granter)
// The actual permission to access files and directories depends on the absolute values of permissions and control level,
// which are calculated by following inheritance and the permission-granting links back to root.
// NOTE: SetPermissionsForUser() can be used to specify permissions using absolute values.
WFSResult WFSDeleteAccessListEntry (const utf8 *sPathName, WFSTitleId titleId , WFSTitleId entryCreatorId);
WFSResult WFSDeleteAccessListEntryAsync(const utf8 *sPathName, WFSTitleId titleId , WFSTitleId entryCreatorId, void *pUserData, WFSResultCallback cb);
// Arguments:
// ----------
// sPathName .. Absolute or relative path name of a file or directory.
// See "WFS Path Names" for rules about path names.
// titleId .. The title id of the application for which permissions are being removed.
// entryCreatorId .. The title id of the application which created the access list entry (the permission granter).
// pUserData .. Arbitrary user data that is passed to the callback function.
// cb .. Pointer to a callback function to receive the result of WFSDeletePermissionsAsync.
//
// Return Values:
// --------------
// Possible return values for WFSDeletePermissions:
// WFS_RESULT_OK .. The specified file or directory was found. The permissions were calculated and copied to *pFlags.
// WFS_RESULT_BUSY .. Too many requests, try waiting then calling again.
// WFS_RESULT_INVALID .. The function parameters were invalid, e.g. File name too long, Path is too deep.
// WFS_RESULT_MEDIA_ERROR .. The device or media is not attached, or was removed before the requested operation could be completed.
// WFS_RESULT_WRITE_PROTECTED .. Device is physically write protected (e.g. USB Flash memory, SD Card. Note: Write errors can occur even for read operations).
// WFS_RESULT_PERMISSION .. Permission flags of the target or its parent directory do not permit requested access from this application.
// WFS_RESULT_ACL_ENTRY_NOT_FOUND .. the target access list entry does not exist.
// WFS_RESULT_CORRUPTION .. A corrupted block was encountered which prevented the operation from being completed.
// WFS_RESULT_NOT_FOUND .. The specified file or directory was not found.
// Possible immediate return values for WFSDeletePermissionsAsync:
// WFS_RESULT_OK .. The request was dispatched successfully. The callback will be called in this case only.
// WFS_RESULT_BUSY .. Too many requests, try waiting then calling again.
// WFS_RESULT_OUT_OF_MEMORY .. The library does not have enough memory to dispatch the request. (May be due to too many outstanding aysnc calls).
// WFS_RESULT_INVALID .. The function parameters were invalid, e.g. File name too long, Path is too deep.
// Possible values of nResult passed to WFSDeletePermissionsAsync callback:
// WFS_RESULT_OK .. The specified file or directory was found and its permissions were calculated and passed as the nFlags parameter.
// WFS_RESULT_MEDIA_ERROR .. The device or media is not attached, or was removed before the requested operation could be completed.
// WFS_RESULT_WRITE_PROTECTED .. Device is physically write protected (e.g. USB Flash memory, SD Card. Note: Write errors can occur even for read operations).
// WFS_RESULT_PERMISSION .. Permission flags of the target or its parent directory do not permit requested access from this application.
// WFS_RESULT_CORRUPTION .. A corrupted block was encountered which prevented the operation from being completed.
// WFS_RESULT_NOT_FOUND .. The specified file or directory was not found.
//
// Description:
// ------------
// Use these functions to delete a specified access list entry.
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif //define __WFS_PERM_H__

View File

@ -0,0 +1,209 @@
/*---------------------------------------------------------------------------*
Project: Revolution WFS library
File: wfstypes.h
Copyright 2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfstypes.h,v $
Revision 1.13 2008/12/10 06:55:11 kondo_masahiro
Added the new device types WFS_DEVTYPE_USB_MSC_??.
Revision 1.12 2008/12/03 00:13:29 kondo_masahiro
Added WFS_MAX_WORK_SPACE_SIZE and fixed WFS_MIN_WORK_SPACE_SIZE
Revision 1.11 2008/10/23 11:16:20 nakanose_jin
Open and Search should give a invalid file handle if he fails to execute.
Revision 1.10 2008/09/26 09:32:36 kondo_masahiro
Marged with revision 1.8
Revision 1.9 2008/09/26 09:29:54 kondo_masahiro
Changed WFS_MIN_WORK_SPACE_SIZE.
Revision 1.8 2008/07/30 03:57:46 paul
Fixed WFS_FLAG_CONTIGUOUS_AREA comment
Revision 1.7 2008/07/25 09:46:56 ooizumi
Fixed WFSAccess definition.
Revision 1.6 2008/07/11 09:46:03 ueno
Added async functions.
Revision 1.5 2008/06/20 18:35:39 paul
Added WFS_MIN_DIRECTORY_QUOTA, WFS_FLAG_CONTIGUOUS_AREA
Revision 1.4 2008/04/29 01:14:52 ueno
Removed WFS_DEBUG_SYSTEM_PROCESS_ID.
Added WFS_ROOT_ID and WFS_EVERYONE_ID.
Revision 1.3 2008/04/08 18:24:30 paul
Moved callbacks and other type definitions from wfs.h into this header file. Moved permissions flags to wfsPerm.h
Revision 1.2 2008/02/25 05:35:41 paul
Reduced WFS_MAX_FILE_NAME_SIZE and WFS_MAX_PATH_NAME_SIZE to make structs multiples of 32 bytes, and also allow space for a NULL terminator so we dont have to change existing code.
Revision 1.1 2008/01/17 07:51:43 ooizumi
Moved several definitions from wfs.h.
*---------------------------------------------------------------------------*/
#ifndef __WFSTYPES_H__
#define __WFSTYPES_H__
// ---------------------------------------------------------------------
// wfstypes.h - Wii File System (WFS) API
// ---------------------------------------------------------------------
#include <revolution.h>
#ifdef __cplusplus
extern "C" {
#endif
// ---------------------------------------------------------------------
// WFS attributes
// ---------------------------------------------------------------------
#define WFS_MAX_FILE_SIZE 4294967295 // ((u32)-1)
#define WFS_MAX_PATH_DEPTH 31 // (ToDo: Directories must keep track of their deepest sub-path, so we can validate directory move requests)
// The following represent the maximum size of string fields in Bytes, not including the terminating NULL character.
#define WFS_MAX_FILE_NAME_SIZE 254 // Does not include the path, just the file name.
#define WFS_MAX_PATH_NAME_SIZE 509 // (ToDo: Directories must keep track of their longest sub-path, so we can validate directory move/rename requests)
#define WFS_MAX_DEVICE_NAME_SIZE 15 // maximum size of a device name
#define WFS_MAX_VOLUME_ID_SIZE 7 // maximum size of WFS Volume Id string (This is a randomly assigned string of characters, e.g., 1a2b3c4)
#define WFS_MAX_WORK_SPACE_SIZE ((512+40+40) * 1024) // Used for user data cache, shim layer queueing parameters and async thread stack / queueing async parameters.
#define WFS_MIN_WORK_SPACE_SIZE ((144+40+40) * 1024)
#define WFS_MIN_DIRECTORY_QUOTA (1024 * 1024)
#define WFS_INVALID_HANDLE_VALUE ((u32)-1)
typedef char utf8; // ToDo: Perhaps utf8 should be changed to WFSChar?
typedef u32 WFSFileTime; // Time in seconds since 00:00, 1st January, 2000
typedef u32 WFSFileSize; // Size of file
typedef u32 WFSContentIdx; // Used to identify files which belong to the same unit of purchased content, and control access to them
typedef u8 WFSBool;
// ---------------------------------------------------------------------
// WFS devices
// ---------------------------------------------------------------------
// Possible WFS device states:
// 1. Valid - valid WFS volume exists
// 2. Unusable - bad device
// 3. Unknown format (e.g., FAT12, NTFS, HFS)
// 4. Uninitialized - recognized format (FAT32), but not enough free space for a WFS volume
// Whenever a compatible device is attached, we check to see if a WFS volume already exists. If not,
// we try to create it automatically. If it is not created, then the device must not have enough space.
#define WFS_DEVFLAG_UNUSABLE 1 // Device is unusable (e.g. unknown format, unsupported device)
#define WFS_DEVFLAG_WRITE_PROTECTED 2 // Device is physically write protected
#define WFS_DEVFLAG_NOT_INITIALIZED 4 // Device not formatted or does not yet contain a WFS volume
#define WFS_DEVFLAG_NOT_MOUNTED 8 // Device has not yet been mounted
// ToDo: Can we force this enum to be u8?
typedef enum {
WFS_DEVTYPE_NONE = 0x00,
WFS_DEVTYPE_SD = 0x01,
WFS_DEVTYPE_USB_MSC_10 = 0x02, // MSC device with USB1.0
WFS_DEVTYPE_USB_MSC_11 = 0x03, // MSC device with USB1.1
WFS_DEVTYPE_USB_MSC_20 = 0x04, // MSC device with USB2.0
WFS_DEVTYPE_EXT_SD = 0x05,
WFS_DEVTYPE_NAND = 0x06
} WFSDevType;
typedef struct {
u64 nDevTotalCapacity; // Total capacity of underlying device in bytes
u8 nDevType; // One of WFS_DEVTYPE_*
u8 nDevFlags; // Combination of WFS_DEVFLAG_*
} WFSDeviceInfo;
// ToDo: Should consider the case of users making an exact copy of a WFS volume causing two devices to
// have the same "unique" device Id. This may be an unavoidable problem.
// We can return WFS_RESULT_VOL_ID_ERROR if we attempt to mount a device with the same Id as an existing device.
// ---------------------------------------------------------------------
// WFSFileHandle, WFSSearchDirectoryHandle
// ---------------------------------------------------------------------
typedef u32 WFSFileHandle;
typedef u32 WFSSearchDirectoryHandle;
// ---------------------------------------------------------------------
// WFSFileInfo
// ---------------------------------------------------------------------
typedef struct {
union {
WFSFileSize nFileSize; // Assuming this is a file
u32 nNumEntries; // Assuming this is a directory
};
u32 nFlags; // Includes the permissions for the requesting user: WFS_PERM* and directory status flag: WFS_FLAG_IS_A_DIRECTORY
WFSContentIdx nCidx;
WFSFileTime timeCreated;
WFSFileTime timeUpdated;
} WFSFileAttributes;
typedef struct {
WFSFileAttributes attr;
utf8 sFileName[WFS_MAX_FILE_NAME_SIZE+1];
} WFSFileInfo;
// ---------------------------------------------------------------------
// WFS File Attributes
// ---------------------------------------------------------------------
// The following flags are not stored per-title id, but they are included along with the permissions for the current title id in the nFlags field of WFSFileAttributes
#define WFS_FLAG_IS_A_DIRECTORY 0x80000000 // This flag can not be changed after creation.
#define WFS_FLAG_CONTIGUOUS_AREA 0x40000000 // Specifies that a directory has a contiguous set of blocks allocated to it, and is a self-contained area
// ---------------------------------------------------------------------
// WFSAccess
// ---------------------------------------------------------------------
typedef enum {
WFS_ACCESS_READ = 0x01,
WFS_ACCESS_WRITE = 0x02,
WFS_ACCESS_RW = 0x03 // WFS_ACCESS_READ | WFS_ACCESS_WRITE
} WFSAccess;
// ---------------------------------------------------------------------
// WFS callback types
// ---------------------------------------------------------------------
typedef void (*WFSResultCallback )(WFSResult nResult, void *pUserData);
typedef void (*WFSDeviceCallback )(const utf8 *sDeviceName, void *pUserData); // For attach/detach callbacks
typedef void (*WFSDeviceInfoCallback )(WFSResult nResult, const utf8 *sDeviceName, WFSDeviceInfo *pDi, void *pUserData);
typedef void (*WFSDeviceVolumeCallback )(WFSResult nResult, const utf8 *sDeviceName, utf8 *sVolumeId, void *pUserData);
typedef void (*WFSUnmountVolumeCallback )(WFSResult nResult, const utf8 *sVolumeId, void *pUserData);
typedef void (*WFSInitializeDeviceCallback)(WFSResult nResult, const utf8 *sDeviceName, void *pUserData);
typedef void (*WFSFileOpCallback )(WFSResult nResult, WFSFileHandle fh, void *pUserData);
typedef void (*WFSGetFileSizeCallback )(WFSResult nResult, u32 nFileSize, WFSFileHandle fh, void *pUserData);
typedef void (*WFSReadFileCallback )(s32 nResultOrNumBytesRead, WFSFileHandle fh, void *pUserData);
typedef void (*WFSGetFreeSpaceCallback )(WFSResult nResult, u64 nSize, void *pUserData);
typedef void (*WFSGetAttributesCallback )(WFSResult nResult, const WFSFileAttributes *pFa, void *pUserData);
typedef void (*WFSSearchDirectoryCallback )(WFSResult nResult, WFSSearchDirectoryHandle sdh, const WFSFileInfo *pFi, void *pUserData);
typedef void (*WFSSearchDirectoryCloseCallback)(WFSResult nResult, WFSSearchDirectoryHandle sdh, void *pUserData);
typedef void (*WFSGetPermissionsForUserCallback)(WFSResult nResult, u32 nFlags, void *pUserData);
typedef void (*WFSGetAccessListCallback )(s32 nResultOrNumAclEntries, void *pUserData);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif //define __WFSTYPES_H__

View File

@ -0,0 +1,166 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_Api.h - global types used by the WFS kernel
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Api.h,v $
Revision 1.13 2008/12/04 00:42:37 ooizumi
Changed definition name to enable permission.
Revision 1.12 2008/09/28 23:30:00 kondo_masahiro
Fixed codes to use medium size user block.
Revision 1.11 2008/08/29 00:13:19 kondo_masahiro
Removed gPtr and gSize.
Revision 1.10 2008/07/25 02:54:16 paul
Added TransInfo lists to wkg
Revision 1.9 2008/07/17 22:43:08 paul
removed SubBlkTracker
Revision 1.8 2008/07/17 22:14:25 paul
Added rootDirAttr
Revision 1.7 2008/07/17 04:37:45 kondo_masahiro
Fixed codes for porting IOP.
Revision 1.6 2008/07/09 01:06:24 paul
Added some definitions to support lists of mounted volumes. Moved block cache memory buffer into wkg.
Revision 1.5 2008/06/09 18:16:25 paul
added devAttr
Revision 1.4 2008/05/12 19:19:05 paul
Added SubBlkTracker
Revision 1.3 2008/05/10 04:00:48 kondo_masahiro
Merged and fixed code to accept RM compiler
Revision 1.2 2008/04/25 17:28:32 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.1 2008/04/22 04:39:07 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.6 2008/04/23 00:55:23 paul
Updated WFSKrnGlobals
Revision 1.5 2008/04/19 05:50:11 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.4 2008/02/29 02:38:02 kondo_masahiro
Fixed code to accept IOP compiler
Revision 1.3 2008/02/28 02:38:02 kondo_masahiro
Fixed code to accept PPC compiler
Revision 1.2 2008/02/27 07:27:11 paul
made areaHdrRoot a global so it could be accessed from debug code in wfskrn_Dir.cpp
Revision 1.1 2007/12/27 11:40:03 paul
*** empty log message ***
*---------------------------------------------------------------------------*/
#ifndef wfskrn_Api_h
#define wfskrn_Api_h
#include "revolution/wfs.h"
#include "wfskrn_Config.h"
#include "wfskrn_Defs.h"
#include "wfskrn_Heap.h"
#include "wfskrn_Handles.h"
#include "wfskrn_Area.h"
#include "wfskrn_Bcache.h"
#include "wfskrn_Volume.h"
#include "wfskrn_PathCache.h"
#include "wfskrn_PTree.h"
#include "wfskrn_Device.h"
#include "wfskrn_Volume.h"
typedef struct VolumeLink_ {
struct VolumeInfo_ *pNext;
struct VolumeInfo_ *pPrev;
} VolumeLink;
typedef struct VolumeInfo_ {
VolumeLink vl;
struct DeviceInfo_ *pDevInfo;
VolumeHdr vh;
#if _DEBUG
WFSVolumeId volId;
#endif
AreaInfo rootAreaInfo;
DirEntryAttrHdr rootAttr;
u32 nClientsMountedBy; // A bit vector. Up to 32 clients represented by a bit each.
bool bDetached;
} VolumeInfo;
#define WFSKRN_MAX_VOLUMES (WFSKRN_MAX_DEVICES + WFSKRN_MAX_MOUNTED_VOLUMES)
#define WFS_STATIC_MEM_TOTAL_SIZE (WFS_BLK_CACHE_SIZE + WFS_BCACHE_META_DATA_SIZE + WFS_STATIC_HEAP_SIZE + WFS_STATIC_MEM_ALIGNMENT)
typedef struct {
u8 *pBlkCache;
u8 *pHeapData;
bool bKrnInitialized;
bool bMountedDeviceWasDetached;
WFSKrnHeap heap;
//WFSKrnStrHashTbl strHTbl;
PathCache pathCache;
PTreeHdr ptreeHdr;
PTreeAllocator ptreeAllocator;
WFSBlkAdr nRootDirBlkAdr;
u32 nNumDevices;
DeviceInfo aDevInfo[WFSKRN_MAX_DEVICES];
VolumeInfo aVolInfo[WFSKRN_MAX_VOLUMES];
VolumeLink mountedVolListAnchor;
VolumeInfo *pMountedVolListAnchor; // double link list
VolumeInfo *pFreeVolList; // single link list (stack)
DirEntryAttrHdr rootDirAttr;
DirEntryAttrHdr volDirAttr;
DirEntryAttrHdr devDirAttr;
DirEntryAttrHdr devAttr;
#if _WIN32 || PERM_TEST
WFSTitleId nDebugTitleId;
#endif
TransInfo aTransInfo[WFSKRN_MAX_ACTIVE_TRANSACTIONS];
TransInfoLink activeTransListAnchor;
TransInfo *pActiveTransListAnchor;
TransInfo *pTransInfoFreeList;
WFSKrnHandles hnd;
WFSFileTime time;
u8 aStaticMem[WFS_STATIC_MEM_TOTAL_SIZE]; // it includes block cache for meta block and heap data.
} WFSKrnGlobals;
extern WFSKrnGlobals wkg;
extern DirItr gDi;
extern AreaInfo *pAhInit;
extern WFSBlkAdr *pBaInit;
//extern u8 *gpPtr; // Pointer of vdsk memory
//extern u32 gSize; // Size of vdsk memory
extern u8 *gpHeapPtr; // Pointer of heap memory
extern u32 gHeapSize; // Size of heap memory
#endif //define wfskrn_Api_h

View File

@ -0,0 +1,328 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_Area.h - Module for managing contiguous disk areas
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Area.h,v $
Revision 1.24 2008/12/18 09:03:37 kondo_masahiro
Fixed function name and process from BCacheSetBlkAdr() to BCacheRemap()
Revision 1.23 2008/12/17 01:37:42 kondo_masahiro
Added function BCacheSetBlkAdr()
Revision 1.22 2008/11/26 01:46:19 kondo_masahiro
Fixed arguments of several functions in order to improve access speed.
Revision 1.21 2008/10/17 08:51:27 kondo_masahiro
Added the new MEDIUM size category (40KB-320KB)
Revision 1.20 2008/10/14 10:27:44 kondo_masahiro
Added codes to access very large size file data
Revision 1.19 2008/10/10 02:11:49 kondo_masahiro
Fixed a bug to access large files
Revision 1.18 2008/10/09 04:15:46 kondo_masahiro
Fixed member of AreaHdr and AreaInfo
Revision 1.17 2008/10/08 23:20:09 kondo_masahiro
Added codes to access large size file data
Revision 1.16 2008/09/28 23:30:08 kondo_masahiro
Fixed codes to use medium size user block.
Revision 1.15 2008/09/24 07:32:07 ueno
Added AclHdr{} to AreaHdr{} to save configuration of accesslists in a disk.
Revision 1.14 2008/08/27 09:53:34 paul
Changed information in area header slightly. Added nStride to alloc, free functions
Revision 1.13 2008/08/14 08:04:16 kondo_masahiro
Removed struct AreaHashHdr.
Revision 1.12 2008/08/07 10:42:39 ueno
Modified for BTREE_BASED_ALLOCATOR.
Revision 1.11 2008/08/05 04:17:15 kondo_masahiro
Added error handling for hash error and detach device.
Revision 1.10 2008/07/23 04:21:43 ueno
Modified AreaInfo{} for B-tree based allocator.
Revision 1.9 2008/07/17 04:54:33 kondo_masahiro
Fixed codes for porting IOP.
Revision 1.8 2008/07/09 01:12:34 paul
Many changes to area structs - to allow directory module to write via block cache, support volume initialization and mounting exisiting volumes.
Revision 1.14 2008/04/28 20:20:57 wayne.wong
Changed the interface to block alloc slightly to return WFSKrnResult.
Revision 1.13 2008/04/26 05:51:56 wayne.wong
Fixed prototype name and arg type.
Revision 1.7 2008/05/10 04:00:48 kondo_masahiro
Merged and fixed code to accept RM compiler
Revision 1.6 2008/04/25 19:15:19 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.4 2008/04/25 06:22:55 ueno
Cleanup.
Revision 1.3 2008/04/25 04:40:47 ueno
Added support for WFSDEV.
Revision 1.12 2008/04/26 01:23:55 wayne.wong
Moved area functionality from Volume to Area module. Changed implementation
to support small area sizes for a large mapped number of sectors. Added
block wrapper calls for Area and BCache calls.
Revision 1.11 2008/04/23 00:38:36 paul
Removed old defs
Revision 1.10 2008/04/19 05:50:05 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.9 2008/04/18 09:04:48 nakanose_jin
merging acl
Revision 1.8 2008/04/18 01:58:18 wayne.wong
Created separate Area types for persistent (hdr) and non-persistent (info) types.
Changed function names to be consistent with kernel naming convention.
Defines are included to support the previous naming, but will be deleted in
the future.
Revision 1.7 2008/03/11 03:18:39 wayne.wong
Added sector information to the area header.
Revision 1.6 2008/02/28 13:11:58 ueno
Revised to keep accesslist cache and indexlist handle in WFSAreaHdr{}.
Revision 1.5 2008/02/28 06:37:24 kondo_masahiro
Fixed code to accept PPC compiler
Revision 1.4 2008/02/27 11:17:16 ueno
Added fields for accesslist development to WFSAreaHdr{}.
Revision 1.3 2008/02/20 07:10:44 paul
Added WfsAreaFreeBlks function, WFSTransBlkAdr struct
Revision 1.2 2007/12/27 11:39:22 paul
preliminary API to help me proceed with the Dir module
Revision 1.1 2007/11/16 05:44:48 paul
first checkin
*---------------------------------------------------------------------------*/
#ifndef wfs_Area_h
#define wfs_Area_h
#ifdef _DEBUG
#define _CHECK_BLK_USAGE 0 // change to check for invalid area block and block cache usage
#define _CHECK_BLK_ALLOCATION 0
#else
#define _CHECK_BLK_USAGE 0
#define _CHECK_BLK_ALLOCATION 0
#endif
#include "wfskrn_Defs.h"
#include "wfskrn_BCache.h"
#include "wfskrn_Permission_AccessList_Type.h"
///// The flag enables block cache. /////
#define AREA_ENABLE_BLK_CACHE 1
#if AREA_ENABLE_BLK_CACHE
#define BTREE_BASED_ALLOCATOR 1
#define LIST_BASED_ALLOCATOR 0
#define SIMPLE_ALLOCATOR 0
#else
#define BTREE_BASED_ALLOCATOR 0
#define LIST_BASED_ALLOCATOR 0
#define SIMPLE_ALLOCATOR 1
#endif
#if BTREE_BASED_ALLOCATOR
#include "wfskrn_FreeBlkAlloc_Type.h"
#endif // BTREE_BASED_ALLOCATOR
//#define AREA_SECTOR_SIZE 512
//#define AREA_SECTOR_SIZE_BITS 9
#define AREA_PAGE_SIZE (1<<WFS_LOG2_SMALL_BLK_SIZE)
#define AREA_NULL (-1) // end marker for sxx types
// wfsVolumeAreaEntry attribute bits
#define AREA_EMPTY 0x0000 // empty, not initialized
#define AREA_ALLOCATED 0x0001 // set if allocated
#define AREA_START 0x0002 // set if start of an area
// #define AREA_FIRST 0x0004 // first area has overhead
#define AREA_OVERHEAD 0x0004 // area overhead; header(s) + entry list
#define AREA_FLAG_META_DATA 0
#define AREA_FLAG_USER_DATA BCACHE_FLAG_FILE_BLK
#ifndef _struct_WFSAccessListControlBlock_
#define _struct_WFSAccessListControlBlock_
typedef struct _WFSAccessListControlBlock WFSAccessListControlBlock;
#endif
#if LIST_BASED_ALLOCATOR
typedef WFSBlkAdr AreaEntryIdx;
// Area table entry. Describe the on a min-area sized granularity.
typedef struct _AreaEntry {
s16 nSizeIdx; // size enumeration
u16 nAttributes; // free
AreaEntryIdx nNextIdx; // abs area index/number of next in this list
AreaEntryIdx nPrevIdx; // abs area index/number of prev in this list
} AreaEntry;
typedef struct _AreaList {
u32 nAreaSize; // in sectors
AreaEntryIdx nHeadIdx; // index to heads of freelist
u32 nLen; // length; number of same-sized areas in list
} AreaList;
#endif //LIST_BASED_ALLOCATOR
#if !_IOP
namespace wfsdev_api{
struct tagSAreaInfo;
}
#endif
typedef struct AreaHdr_ {
// This is the part of the AreaInfo struct which is stored on disk
// ** Note: All block addresses and values must be independent of the absolute location of the area **
// ToDo: Move the on-disk generic meta-data header out of the headers
WFSMetaDataFlags nFlags; // 4 Bytes
WFSHashCode hash; // 20 bytes
WFSBlkAdr nRootBlkAdr; // Root directory block of the area relative to the start of the area
WFSBlkAdr nNumBlks; // Total size of the area in blocks (small blocks or meta data blocks)
#if LIST_BASED_ALLOCATOR
WFSBlkAdr nDataStartBlkAdr; // Block address of end of free list management area (relative to start of area)
u16 nMaxNumAreas; // maximum number of minimum-sized areas on device
#endif
#if BTREE_BASED_ALLOCATOR
FBATreeHdr freeBlkAllocHdr;
#endif // BTREE_BASED_ALLOCATOR
AclHdr aclHdr; // Block addresses of the root directories of accesslists and the namefiles.
u8 nLog2BlkSize; // Log to the base 2 of the block size (small blocks or meta data blocks)
u8 nLog2MediumBlkSize; // Log to the base 2 of the medium block size (for Wii, this value is 16)
u8 nLog2LargeBlkSize; // Log to the base 2 of the multiple between the large block size. (large blocks are used for large files only)
} AreaHdr;
typedef struct {
#if LIST_BASED_ALLOCATOR
AreaList aFreeList[WFSKRN_MAX_NUM_AREA_SIZES]; // freelists
#elif SIMPLE_ALLOCATOR
WFSBlkAdr nFirstFreeBlkAdr; // Block address of the first free block (relative to start of area)
WFSBlkAdr nNumFreeBlks;
u8 *pPtr; // pointer to a title area in memory
#endif
} AreaFreeListHdr;
typedef struct AreaInfo_ {
struct AreaInfo_ *pParent; // Points to the parent area info. NULL if this is the root area.
struct VolumeInfo_ *pVolInfo; // Points to the volume info
AreaHdr ah; // Area header information. This is a copy of the header stored on disk
AreaFreeListHdr *pAflh; // Pointer to the free list header
WFSBlkAdr nAbsStartBlkAdr; // Absolute block address of the first block of the area
WFSBlkAdr nRelStartBlkAdr; // block address of the first block of the area relative to the start of the parent area
u32 nBlkSize; // Block size in bytes (for meta data, and small file blocks). On Wii, block size is 8KB
u32 nMediumBlkSize; // Medium block size in bytes (for large file blocks). On Wii, medium block size is 64KB
u32 nLargeBlkSize; // Large block size in bytes (for large file blocks). On Wii, medium block size is 512KB
u32 nLog2BlksPerMediumBlk; // nLog2 number of small blocks in medium block
u32 nLog2BlksPerLargeBlk; // nLog2 number of small blocks in large block
u32 nLog2MediumBlkPerLargeBlk; // nLog2 number of medium blocks in large block
u32 nLargeBlkPtrSize; // Used in indirect block layout calculations
//u32 nMaxLargeBlkPtrsPerAttrSubBlk; // Determines when to switch file layout from large size category to very large size category
u32 nNumLargeBlkPtrsPerBlk; // Used to calculate number of indirect blocks needed to index into large files
u32 nNumMediumBlkPtrsPerBlk; // Used to calculate number of indirect blocks needed to index into medium files
#if LIST_BASED_ALLOCATOR
u32 nNumEntriesInFirstBlk; // Number of free-list entries in first block
u32 nNumEntriesPerBlk; // Number of free-list entries per block
#endif
#if _CHECK_BLK_ALLOCATION
u32 *aBlkAllocState;
#endif
#if !_IOP
struct wfsdev_api::tagSAreaInfo *aclWrapper;
#endif
WFSAccessListControlBlock* accessListCb;
} AreaInfo;
// *** Old Area module API functions (only recording memory) ****
WFSKrnResult AreaAllocBlks(AreaInfo *pAreaInfo, WFSBlkAdr nRefBlkAdr, u32 nLog2BlkSize, u32 nNumBlks, WFSBlkAdr *aBlkAdr, s32 nStride);
WFSKrnResult AreaFreeBlks(AreaInfo *pAreaInfo, u32 nLog2BlkSize, u32 nNumBlks, WFSBlkAdr *pBlkAdr, s32 nStride);
WFSKrnResult AreaInvalidateBlks(AreaInfo *pAreaInfo, u32 nNumBlks, WFSBlkAdr *pBlkAdr, s32 nStride);
WFSBool AreaGetRegionBlkSize(AreaInfo *pAreaInfo, WFSBlkAdr nBlkAdr);
void AreaSetRegionBlkSize(AreaInfo *pAreaInfo, WFSBlkAdr nBlkAdr, WFSBool bLargeBlk);
void AreaFindSubArea(utf8 *pPathName, AreaInfo *pAreaInfo);
void * AreaGetPhysicalBlk(AreaInfo *pAreaInfo, WFSBlkAdr nBlkAdr);
WFSKrnResult AreaInit(AreaInfo *pAreaInfo); // Initializes the area, writes it's header and initial metadata to disk
WFSKrnResult AreaOpen(AreaInfo *pAreaInfo); // Opens and reads an existing area from disk
void AreaClose(AreaInfo *pAreaInfo); // Closes an area
// Display the free list information for an area. (for debug)
WFSKrnResult AreaFreelistPrint(AreaInfo *pAreaInfo);
// Allocate a sub-area.
WFSKrnResult AreaAllocSubArea(AreaInfo *pAreaInfo, // area to allocate from
WFSBlkAdr nNumBlks, // size of sub area expressed as the number of parent area small blocks
AreaInfo *pSubAreaInfo, // returned sub-area
u32 nFlags); //
// Free a sub-area
WFSKrnResult AreaFreeSubArea(AreaInfo *pAreaInfo, // area to free to
AreaInfo *pSubAreaInfo); // sub-area to free
// Block interface to block cache (BCache module)
WFSKrnResult AreaBlkAlloc (AreaInfo *pAreaInfo, WFSBlkAdr nRefBlkAdr, u32 nNumBlks, WFSBlkAdr aBlkAdr[]);
WFSKrnResult AreaBlkStore (AreaInfo *pAreaInfo, WFSBlkAdr blkAdr);
WFSKrnResult AreaBlkFlush (AreaInfo *pAreaInfo, WFSBlkAdr blkAdr);
WFSKrnResult AreaBlkInvalidate (AreaInfo *pAreaInfo, WFSBlkAdr blkAdr);
WFSKrnResult AreaBlkDirty (AreaInfo *pAreaInfo, WFSBlkAdr blkAdr);
WFSKrnResult AreaBlkPin (AreaInfo *pAreaInfo, WFSBlkAdr blkAdr);
WFSKrnResult AreaBlkUnpin (AreaInfo *pAreaInfo, WFSBlkAdr blkAdr);
u32 AreaBlkGetPinCount(AreaInfo *pAreaInfo, WFSBlkAdr blkAdr);
WFSKrnResult AreaBlkGetPtr(AreaInfo *pAreaInfo, WFSBlkAdr blkAdr, void** ppPtr);
WFSKrnResult AreaBlkSetValidSize(AreaInfo *pAreaInfo, WFSBlkAdr blkAdr, u32 nValidSize);
WFSKrnResult AreaBlkRemapCache(AreaInfo *pAreaInfo, WFSBlkAdr nSrcBlkAdr, WFSBlkAdr nDstBlkAdr, WFSBlkAdr nHashBlkAdr, u32 nHashOfs);
//#define _DEBUG_WFSKRN_AREA_
#ifdef _DEBUG_WFSKRN_AREA_
#define dbga(_s) (_s)
#else
#define dbga(_s)
#endif // _DEBUG_WFSKRN_BCACHE_
#endif //define wfs_Area_h

View File

@ -0,0 +1,264 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_BCache.h - disk block buffer cache library
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_BCache.h,v $
Revision 1.16 2008/12/18 09:03:37 kondo_masahiro
Fixed function name and process from BCacheSetBlkAdr() to BCacheRemap()
Revision 1.15 2008/12/17 01:37:42 kondo_masahiro
Added function BCacheSetBlkAdr()
Revision 1.14 2008/12/10 08:20:01 ueno
Added BCacheDumpPinCount() for debug.
Revision 1.13 2008/12/03 00:04:53 kondo_masahiro
Added WFSBCacheStoreVolume and removed WFSBCacheFlushAll.
Revision 1.12 2008/11/26 01:46:19 kondo_masahiro
Fixed arguments of several functions in order to improve access speed.
Revision 1.11 2008/11/05 05:56:30 kondo_masahiro
Added BCacheSet/GetChainId()
Revision 1.10 2008/10/03 08:37:18 kondo_masahiro
Fixed codes for porting IOP
Revision 1.9 2008/09/29 10:19:25 ueno
Revised to support multi-B-tree-based allocator.
Revision 1.8 2008/09/28 23:30:13 kondo_masahiro
Fixed codes to use medium size user block.
Revision 1.7 2008/08/27 23:17:41 paul
Added BCACHE_FLAG_FILE_BLK
Revision 1.6 2008/08/08 13:33:29 ueno
Added BCacheCheck2() to check freeblock allocator.
Revision 1.5 2008/08/05 04:17:20 kondo_masahiro
Added error handling for hash error and detach device.
Revision 1.4 2008/07/17 04:54:48 kondo_masahiro
Fixed codes for porting IOP.
Revision 1.3 2008/07/09 01:15:33 paul
Changed block cache to use block address instead of sector address. Combined block cache globals into a single struct. Added a function to re-tag a cached block.
Revision 1.2 2008/05/12 19:19:20 paul
Merged in Wayne's previous changes
Revision 1.1 2008/04/22 04:39:07 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.9 2008/04/26 01:07:36 wayne.wong
Removed dynamic memory allocation. User is now required to pass memory to
use for descriptor table. A function is added to calculate the size for the user.
Changed type name to be uniform with other modules.
Revision 1.8 2008/03/19 07:36:32 wayne.wong
Fixed a bug with sector tag matching at page granularity.
Revision 1.7 2008/03/11 03:12:27 wayne.wong
Tweaked interface a little. Most noteable is one can now specify whether a page
will be dirty upon allocation. This eliminates a possible second BCache call
to mark as dirty later.
Revision 1.6 2008/02/22 00:40:20 wayne.wong
Change BCache module's prefix for functions and types. Added some new functions.
Revision 1.5 2008/02/20 07:44:37 paul
Changed names to start with PMem
Revision 1.4 2008/02/05 03:13:56 wayne.wong
Added WfsBCacheGetConfig() call.
Revision 1.3 2008/01/30 03:52:33 wayne.wong
Added WfsBCacheValidVolume() call.
Revision 1.2 2008/01/18 06:12:45 wayne.wong
Refined api. Block(page) cache now matches on the tuple (volumeId, sector).
Revision 1.1 2007/12/31 21:19:57 wayne.wong
Initial version.
*---------------------------------------------------------------------------*/
#ifndef _wfskrn_BCache_h_
#define _wfskrn_BCache_h_
#include "wfskrn_Volume.h"
#include "wfskrn_Device.h"
#include "wfskrn_Area.h"
#define BCACHE_FLAG_INVALID 0x00
#define BCACHE_FLAG_READ 0x01
#define BCACHE_FLAG_DIRTY 0x02
#define BCACHE_FLAG_PINNED 0x04
#define BCACHE_FLAG_VALID 0x08
#define BCACHE_FLAG_FILE_BLK 0x10
#define BCACHE_GROUP_ID_METABLK 0x00
#define BCACHE_GROUP_ID_USERBLK_8K 0x01
#define BCACHE_GROUP_ID_USERBLK_64K 0x02
#define BCACHE_NUM_OF_GROUP 3
// The block cache (BCache) caches metadata disk blocks in memory. The metadata disk
// block size blkSize (e.g., 8KB). The buffer cache is fully set-associative. Let us
// call a disk block in memory a page. If no invalid pages are available, pages are
// replaced with a global LRU policy. Pages can be allocated, loaded, stored, flushed,
// invalidated, and pinned. Pinned pages are not candidates for replacement. If all
// pages are pinned and a new page is needed, the wfsBCache call will fail until a page
// is unpinned or invalidated (thus, generating a possible victim page for replacement).
//
// Initially, other than the alloc/read call, the interface was with a u8*. Instead,
// let's try with the tuple (volumeId, a physical sector/LBA address). The sector
// will be aligned to a page granularity. Upon allocation, a pointer to the
// start of the page is returned, even if the sector address specified is in the
// middle of the page.
//
// Wayne - Why not use device handle instead of volumeId? What about the multi-client case
// where each client may have the a different device handle to the same volume?
// Or will this never happen?
//
typedef struct BCacheListNode_ {
void *pData;
struct BCacheListNode_ *pNext;
struct BCacheListNode_ *pPrev;
} BCacheListNode;
typedef struct BCacheList_ {
BCacheListNode *pHead;
BCacheListNode *pTail;
u16 nLen;
} BCacheList;
typedef struct BCacheGroup_ BCacheGroup;
typedef struct {
// ToDo: Later, it may be better to make the block cache use a pointer to the AreaInfo struct (which would
// have to be statically allocated and only reused after all of its blocks have been flushed from cache),
// plus the area-relative block address as the tag.
WFSBlkAdr nAbsBlkAdr; // tag1 - HDD physical absolute block address that is being cached
struct VolumeInfo_ *pVolInfo; // tag2 - pointer to volume struct2
DeviceInfo *pDevInfo;
u32 nState; // stored flags including BCACHE_FLAG_FILE_BLK and BCACHE_FLAG_SIZE_64K
u32 nPinCount;
u8 *pBlkPtr;
WFSBlkAdr nHashBlkAdr;
WFSHashCode *pHash;
BCacheGroup *pGroup;
u32 nValidSize;
u32 nChainId;
#if _CHECK_BLK_USAGE
u32 nCheckSum;
#endif
#if _DEBUG
u32 nDbgCommandCount;
#endif
} BCacheEntry;
struct BCacheGroup_{
u8 *pBCache; // start of actual page/block cache
BCacheEntry *pBCacheTable; // cache info entries
u8 *pMemCache; // starting address of cached pages
u32 nMemCacheSize; // size of cache, in bytes
u32 nLog2BlkSize; // base 2 logarithm of the block size for group
u32 nBlkSize; // block size for group (in bytes)
u32 nNumBlks; // size of cache in blocks
u32 nNumMapped; // number of mapped pages
u32 nNumInvalid; // number of invalid pages
u32 nNumPinned; // number of pinned pages
BCacheList bclInvalid; // head of invalid list
BCacheList bclLru; // LRU/MRU list; head=LRU; contains valid pages
BCacheList bclPinned; // pinned pages; contains valid pages
BCacheList bclFree;
BCacheListNode *pBclNodes;
};
typedef struct BCacheState_ {
// previously global variables:
u8 *pHeap;
u32 nHeapSize;
u32 nLog2UnitBlkSize; // base 2 logarithm of the block size for unit block
u32 nUnitBlkSize; // block size for unit block (in bytes)
u32 nNumGroups;
BCacheGroup aGroup[BCACHE_NUM_OF_GROUP];
#if _DEBUG
bool bSkipCheckPin;
#endif
BCacheList aHashTbl[WFSKRN_BCACHE_HASH_TABLE_SIZE]; // chained hash table
} BCacheGlobals;
extern BCacheGlobals bcg;
u32 BCacheMetadataMemSize(u32 memCacheSize, u32 nBlkSize); // calc pMem arg to BCacheInitLib
//WFSKrnResult BCacheInitLib (u8 *pMemCache, u32 memCacheSize, u32 nLog2BlkSize, u8 *pMem, u32 memSize);
WFSKrnResult BCacheInit (u32 nLog2UnitBlkSize, u8 *pMem, u32 nMemSize);
WFSKrnResult BCacheGroupInit (u32 nBCacheGroupId, u8 *pMemCache, u32 memCacheSize, u32 nLog2BlkSize);
WFSKrnResult BCacheGetState (BCacheGroup *pGroup);
WFSKrnResult BCacheMapVolume (struct VolumeInfo_ *pVolInfo, DeviceInfo *pDevInfo);
bool BCacheValidVolume (struct VolumeInfo_ *pVolInfo);
WFSKrnResult BCacheAlloc (struct VolumeInfo_ *pVolInfo, WFSBlkAdr nAbsBlkAdr, u32 nFlags, u32 nReadSize, u32 nBCacheGroupId,
WFSBlkAdr nHashBlkAdr, u32 nHashOfs, BCacheEntry** ppBce);
WFSKrnResult BCacheSetHash (struct VolumeInfo_ *pVolInfo, WFSBlkAdr nAbsBlkAdr, WFSBlkAdr nHashBlkAdr, u32 nHashOfs);
WFSKrnResult BCacheSetValidSize (struct VolumeInfo_ *pVolInfo, WFSBlkAdr nAbsBlkAdr, u32 nValidSize);
WFSKrnResult BCacheSetChainId (struct VolumeInfo_ *pVolInfo, WFSBlkAdr nAbsBlkAdr, u32 nChainId);
WFSKrnResult BCacheGetChainId (struct VolumeInfo_ *pVolInfo, WFSBlkAdr nAbsBlkAdr, u32 *pChainId);
WFSKrnResult BCacheRemap (struct VolumeInfo_ *pVolInfo, WFSBlkAdr nSrcAbsBlkAdr, WFSBlkAdr nDstAbsBlkAdr, WFSBlkAdr nHashAbsBlkAdr, u32 nHashOfs);
void BCacheReTag (struct VolumeInfo_ *pOldVolInfo, WFSBlkAdr nOldAbsBlkAdr,
struct VolumeInfo_ *pNewVolInfo, WFSBlkAdr nNewAbsBlkAdr);
void* BCacheFind (struct VolumeInfo_ *pVolInfo, WFSBlkAdr nAbsBlkAdr); // find a page
WFSKrnResult BCacheStore (struct VolumeInfo_ *pVolInfo, WFSBlkAdr nAbsBlkAdr); // store page & mark clean
WFSKrnResult BCacheFlush (struct VolumeInfo_ *pVolInfo, WFSBlkAdr nAbsBlkAdr); // store & invalidate page
//WFSKrnResult BCacheFlushAll (); // flush all pages
WFSKrnResult BCacheStoreVolume (struct VolumeInfo_ *pVolInfo); // store a volume's pages
WFSKrnResult BCacheFlushVolume (struct VolumeInfo_ *pVolInfo); // flush a volume's pages
WFSKrnResult BCacheInvalidate (struct VolumeInfo_ *pVolInfo, WFSBlkAdr nAbsBlkAdr); // invalidate a page
WFSKrnResult BCacheInvalidateBlks (struct VolumeInfo_ *pVolInfo, WFSBlkAdr nAbsBlkAdr, u32 nNumBlks); // invalidate a page
WFSKrnResult BCacheTouch (struct VolumeInfo_ *pVolInfo, WFSBlkAdr nAbsBlkAdr); // make a page MRU
WFSKrnResult BCacheDirty (struct VolumeInfo_ *pVolInfo, WFSBlkAdr nAbsBlkAdr); // mark a page as modified
WFSKrnResult BCachePin (struct VolumeInfo_ *pVolInfo, WFSBlkAdr nAbsBlkAdr); // page cannot be evicted
WFSKrnResult BCacheUnpin (struct VolumeInfo_ *pVolInfo, WFSBlkAdr nAbsBlkAdr); // page now can be evicted
u32 BCacheGetPinCount (struct VolumeInfo_ *pVolInfo, WFSBlkAdr nAbsBlkAdr);
void* BCachePointer (struct VolumeInfo_ *pVolInfo, WFSBlkAdr nAbsBlkAdr);
WFSKrnResult BCacheCheck ();
WFSKrnResult BCacheCheck2 ();
static inline
WFSKrnResult BCacheAllocMetaBlk(struct VolumeInfo_ *pVolInfo, WFSBlkAdr nAbsBlkAdr, u32 nFlags, BCacheEntry** ppBce)
{
return BCacheAlloc(pVolInfo, nAbsBlkAdr, nFlags, 1<<bcg.aGroup[BCACHE_GROUP_ID_METABLK].nLog2BlkSize, BCACHE_GROUP_ID_METABLK, nAbsBlkAdr, sizeof(WFSMetaDataFlags), ppBce);
}
u32 BCacheDumpPinCount ( void );
u32 BCacheSkipCheckPin ();
WFSKrnResult BCacheStopSkipCheckPin( u32 initialPinCount );
#if _DEBUG_WFSKRN_BCACHE_
#define dbgb(_s) (_s)
#else
#define dbgb(_s)
#endif // _DEBUG_WFSKRN_BCACHE_
#endif // _wfskrn_BCache_h_

View File

@ -0,0 +1,193 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_BitField.h - functions for manipulating bitfields within bit arrays
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_BitField.h,v $
Revision 1.1 2008/04/22 04:39:07 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.2 2008/04/05 03:09:45 paul
Added WfsSetBitField, WfsTestAndSetBitField
Revision 1.1 2007/12/27 11:39:44 paul
*** empty log message ***
*---------------------------------------------------------------------------*/
#ifndef wfskrn_BitField_h
#define wfskrn_BitField_h
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#define BITFIELD_USE_TEMPLATES 0
#include "wfskrn_Defs.h"
//-----------------------------------------------------------------------------------------------------------------
u32 WfsCalculateFieldSizeInBytes(u32 nVal);
u8 WfsCalculateFieldSizeInBits(u32 nVal);
#if BITFIELD_USE_TEMPLATES
template<int nNumBits> unsigned WfsReadBitField (unsigned *aBitArray, int nStartBit);
#endif
unsigned WfsReadBitField(unsigned *aBitArray, int nStartBit, int nNumBits);
// Arguments:
// ----------
// aBitArray is an array of machine sized unsigned int which are interpreted as a bit array.
// (The first bit of the array is the most significant bit of aBitArray[0])
// nStartBit is the bit offset in the bit array to start reading from.
// Pre Conditions: 1 <= nNumBits <= BITS_PER_INT
//
// Return Values:
// --------------
// Returns a machine sized unsigned int whose least significant nNumBits are the extracted bit field.
//
// Description:
// ------------
// This function reads a bitfield of width nNumBits from a bit array.
// NOTE: It is up to the caller to mask off the least significant nNumBits bits of the return value
// if necessary, using a mask such as ((1<<nNumBits)-1).
//-----------------------------------------------------------------------------------------------------------------
#if BITFIELD_USE_TEMPLATES
template<unsigned nNumBits> void WfsOverwriteBitField(unsigned *aBitArray, int nStartBit, unsigned nValue);
#endif
void WfsOverwriteBitField(unsigned *aBitArray, int nStartBit, unsigned nValue, int nNumBits, unsigned nMask);
// Arguments:
// ----------
// aBitArray is an array of machine sized words which are interpreted as a bit array.
// (The first bit of the array is the most significant bit of aBitArray[0])
// nValue is the value to write.
// nNumBits is the bit width of nValue.
// nStartBit is the bit offset in the bit array to start writing to.
// Pre Conditions: 1 <= nNumBits <= BITS_PER_INT; 0 < nValue < (1<<nNumBits)
//
// Description:
// ------------
// This function overwrites a bitfield of width nNumBits in a bit array.
//-----------------------------------------------------------------------------------------------------------------
void WfsSetBitField(unsigned *aBitArray, int nStartBit, int nNumBits);
// Arguments:
// ----------
// aBitArray is an array of machine sized words which are interpreted as a bit array.
// nStartBit is the first bit offset within the bit array to set.
// nNumBits is the number of bits to set.
//
// Description:
// ------------
// This function sets (makes equal to 1) a atring of bits from nStartBit to (nStartBit + nNumBits - 1) inclusive.
//-----------------------------------------------------------------------------------------------------------------
unsigned WfsTestAndSetBitField(unsigned *aBitArray, int nStartBit, int nNumBits);
// Arguments:
// ----------
// aBitArray is an array of machine sized words which are interpreted as a bit array.
// nStartBit is the first bit offset within the bit array to set.
// nNumBits is the number of bits to set.
//
// Description:
// ------------
// This function sets (makes equal to 1) a atring of bits from nStartBit to (nStartBit + nNumBits - 1) inclusive.
// It returns a non-zero value if any of the bits covered by the string were already set, and 0 otherwise.
//-----------------------------------------------------------------------------------------------------------------
void WfsBitArrayInsertGap(unsigned *aBitArray, int nBitArrayLength, int nGapStartBit, int nNumGapBits);
// Arguments:
// ----------
// aBitArray is an array of machine sized words which are interpreted as a bit array.
// nBitArrayLength is the length of the array in bits.
// nGapStartBit is the bit offset within the bit array to insert the gap.
// nNumGapBits is the number of gap bits to insert.
//
// Description:
// ------------
// This function inserts a gap into a bit array.
// The string of bits from nGapStartBit to nEndBit are shifted nNumGapBits bits to the right,
// leaving a gap which is filled with 0s.
// NOTE: nNumGapBits can be larger than BITS_PER_INT.
//-----------------------------------------------------------------------------------------------------------------
void WfsBitArrayDeleteBitField(unsigned *aBitArray, int nBitArrayLength, int nBitPos, int nNumBits);
// Arguments:
// ----------
// aBitArray is an array of machine sized words which are interpreted as a bit array.
// (The first bit of the array is the most significant bit of aBitArray[0])
// nBitArrayLength is the length of the array in bits.
// nBitPos is the bit offset within the bit array to start deleting from.
// nValue is the value to insert.
// nNumBits is the number of bits to delete.
//
// Description:
// ------------
// This function deletes a bitfield of width nNumBits from a bit array.
// The string of bits from nBitPos to nBitArrayLength are shifted nNumBits bits to the left,
//-----------------------------------------------------------------------------------------------------------------
void WfsBitArrayInsertBitField(unsigned *aBitArray, int nBitArrayLength, int nInsertBit, int nNumBits, unsigned nValue);
// Arguments:
// ----------
// aBitArray is an array of machine sized words which are interpreted as a bit array.
// (The first bit of the array is the most significant bit of aBitArray[0])
// nBitArrayLength is the length of the array in bits.
// nInsertBit is the bit offset within the bit array to insert to.
// nValue is the value to insert.
// nNumBits is the bit width of nValue.
// Pre Conditions: 1 <= nNumBits <= BITS_PER_INT; 0 < nValue < (1<<nNumBits)
//
// Description:
// ------------
// This function inserts a bitfield of width nNumBits into a bit array.
// The string of bits from nInsertBit to nBitArrayLength are shifted nNumBits bits to the right,
// and nValue is inserted in the resulting gap.
//-----------------------------------------------------------------------------------------------------------------
void WfsBitFieldCopy(unsigned *aDstBitArray, int nDstOffset, unsigned *aSrcBitArray, int nSrcOffset, int nCopyLength);
// Arguments:
// ----------
// aDstBitArray is the destination bit array.
// nDstOffset is the bit offset within the destination bit array
// aSrcBitArray is the source bit array.
// nSrcOffset is the bit offset within the source bit array
// nCopyLength is the number of bits to copy
//
// Description:
// ------------
// This function copies nCopyLength bits from a specified offset within a source bit array to a specified offset
// within a destination bit array.
//-----------------------------------------------------------------------------------------------------------------
void WfsTestBitFieldModule();
#endif //wfskrn_BitField_h

View File

@ -0,0 +1,167 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_Config.h - kernel configuration settings governing resource allocations etc.
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Config.h,v $
Revision 1.18 2008/12/03 00:03:46 kondo_masahiro
Added WFS_MAX_USER_BLK_CACHE_SIZE and WFS_MIN_USER_BLK_CACHE_SIZE
Revision 1.17 2008/11/05 15:05:11 ueno
Reduced WFSKRN_BCACHE_HASH_TABLE_SIZE from 2957 to 47.
Revision 1.16 2008/11/04 06:11:07 ueno
Reduced WFS heap size to 8KB.
Changed the maximum number of file handles and search handles to 32.
Revision 1.15 2008/10/21 09:50:09 kondo_masahiro
Added new function WFSWriteFileAndDiscard
Revision 1.14 2008/10/17 08:51:27 kondo_masahiro
Added the new MEDIUM size category (40KB-320KB)
Revision 1.13 2008/10/08 23:20:09 kondo_masahiro
Added codes to access large size file data
Revision 1.12 2008/10/03 08:37:18 kondo_masahiro
Fixed codes for porting IOP
Revision 1.11 2008/09/28 23:30:18 kondo_masahiro
Fixed codes to use medium size user block.
Revision 1.10 2008/08/27 23:45:02 paul
Changed name from WFS_LOG2_HASH_BLK_SIZE to WFS_LOG2_MAX_HASHABLE_BLK_SIZE
Revision 1.9 2008/08/14 08:08:40 kondo_masahiro
Removed several definitions related on wfskrn_Device.
Revision 1.8 2008/08/05 04:17:25 kondo_masahiro
Added error handling for hash error and detach device.
Revision 1.7 2008/07/25 02:53:10 paul
added WFSKRN_MAX_ACTIVE_TRANSACTIONS
Revision 1.6 2008/07/17 22:19:50 paul
changed comment
Revision 1.5 2008/07/09 01:25:15 paul
Changes related to block cache memory.
Revision 1.4 2008/06/09 18:08:48 paul
Increased maximum number of open directory searches to reflect the maximum path depth x 2 devices. Made corresponding change to size of path cache.
Revision 1.3 2008/05/10 04:00:48 kondo_masahiro
Merged and fixed code to accept RM compiler
Revision 1.2 2008/04/25 17:28:26 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.1 2008/04/22 04:39:07 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.9 2008/04/26 01:08:45 wayne.wong
Moved BCache parameters to here.
Revision 1.8 2008/04/23 00:36:39 paul
added defines for file/directory search handles
Revision 1.7 2008/04/19 05:50:00 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.6 2008/04/05 03:07:07 paul
*** empty log message ***
Revision 1.4 2008/02/20 07:16:15 paul
*** empty log message ***
Revision 1.3 2007/12/27 11:38:32 paul
added various config settings
Revision 1.2 2007/11/16 05:45:54 paul
Added definitions for areas and regions
Revision 1.1 2007/11/05 19:03:13 paul
first checkin
*---------------------------------------------------------------------------*/
#ifndef wfskrn_Config_h
#define wfskrn_Config_h
#include "wfscli_Handles.h"
#include "wfssrv_Defs.h"
#define WFS_VERSION_MAJOR 1 // version of WFS (1..255)
#define WFS_VERSION_MINOR 0 // (0..255)
// Block size is not static - can be set within the following range per device / area
#define WFS_LOG2_SMALL_BLK_SIZE 13 // Log to the base 2 of the small block size. (13 would correspond to 8KB)
#define WFS_LOG2_MEDIUM_BLK_SIZE 16 // Log to the base 2 of the medium block size. (16 corresponds to 64KB)
#define WFS_LOG2_LARGE_BLK_SIZE 19 // Log to the base 2 of the large block size. (19 corresponds to 512KB)
#define WFS_LOG2_SMALL_BLKS_PER_REGION 12 // A region is a fixed size subdivision of an area, which is split into either all small blocks or all large blocks
#define WFS_MIN_REGIONS_PER_AREA 2 // one for small and one for large blks
#define WFS_LOG2_MIN_REGION_SIZE (WFS_LOG2_SMALL_BLK_SIZE+WFS_LOG2_SMALL_BLKS_PER_REGION) // log2(bytes)
#define WFS_MIN_REGION_SIZE (1<<(WFS_LOG2_SMALL_BLK_SIZE+WFS_LOG2_SMALL_BLKS_PER_REGION))
#define WFS_LOG2_MIN_AREA_SIZE (WFS_MIN_REGION_SIZE*WFS_MIN_REGIONS_PER_AREA) // in bytes
#define WFS_MIN_AREA_SIZE (1<<(WFS_LOG2_MIN_AREA_SIZE)) // in bytes
#define WFS_LOG2_MAX_CACHE_STORED_FILE_BLK_SIZE 13
#define WFS_LOG2_MAX_HASHABLE_BLK_SIZE WFS_LOG2_MEDIUM_BLK_SIZE
#define WFS_DIR_NODE_STACK_ENTRY_POOL_ALLOC_UNIT 16 // Number of DirNodeStack structs to add to the pool when it runs out. Also used as initial allocation quantity. (42*12B == 504B). DirNodeStack entries are linked together in stacks and used for traversing directories.
#define WFS_LOG2_MAX_FILE_SIZE 32 // 4GB
#define WFS_STATIC_HEAP_SIZE (8 * 1024)
//#define WFS_BLK_CACHE_SIZE (512 * 1024)
#define WFS_BLK_CACHE_SIZE (512 * 256)
#define WFS_BCACHE_META_DATA_SIZE ( 8 * 1024) // Cache 512[KB], Block 8[KB] -> Metadata 3840[B]
#define WFS_STATIC_MEM_ALIGNMENT 512
#define WFS_MAX_USER_BLK_CACHE_SIZE (512 * 1024)
#define WFS_MIN_USER_BLK_CACHE_SIZE (144 * 1024)
// Special in-memory area at the top of WFS to hold "/dev", "/vol" directories
#define WFS_LOG2_PATH_CACHE_SIZE 15
#if _WIN32
#define WFS_LOG2_MAX_AREA_SIZE 29
#else
#define WFS_LOG2_MAX_AREA_SIZE 34 // Max area size of 16GB
#endif
#define WFSKRN_MAX_ACTIVE_TRANSACTIONS 4
#define WFSKRN_MAX_DEVICES 1
#define WFSKRN_MAX_MOUNTED_VOLUMES 1
#define WFSKRN_MAX_NUM_AREA_SIZES 10 // at least 5 (64MB, 256MB, 1GB, 4GB, and 16GB)
#define WFSKRN_MIN_AREA_SIZE (2*WFS_MIN_REGION_SIZE) // 64MB = 32MB + 32MB
#define WFSKRN_FILE_HANDLE_IDX_BITS 5
#define WFSKRN_SEARCH_DIR_HANDLE_IDX_BITS 5
#define WFSKRN_FILE_BUFFER_MEM_ALIGNMENT_SIZE 32
// block cache parameters
#define WFSKRN_BCACHE_HASH_TABLE_SIZE 47 // use for 512KB w/ 8KB pages?
#define WFSKRN_BCACHE_HASH_FN(_key) (_key % WFSKRN_BCACHE_HASH_TABLE_SIZE)
#define WFSKRN_BCACHE_HASH_LIST(_key) (gHash[WFSKRN_BCACHE_HASH_FN(_key)])
// parameter for CATEGORY VERY LARGE
#define WFSKRN_VERY_LARGE_MAP_NUM_INDIRECT_BLKS 8
#define PERMISSION_ENABLED
#define PERM_TEST 1
#endif //wfskrn_Config_h

View File

@ -0,0 +1,107 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_Defs.h - kernel definitions
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Defs.h,v $
Revision 1.5 2008/11/05 15:05:44 ueno
Fixed a bug of WFS_ROUND_DOWN().
Revision 1.4 2008/10/17 08:51:27 kondo_masahiro
Added the new MEDIUM size category (40KB-320KB)
Revision 1.3 2008/10/14 10:27:30 kondo_masahiro
Added #define _DEBUG_BREAK_POINT
Revision 1.2 2008/07/09 01:29:34 paul
Added some macros to convert C definition __DATE__ (object file compilation date) to an integer.
Revision 1.1 2008/04/22 04:39:07 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.3 2008/04/19 05:49:31 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.2 2007/12/27 11:36:55 paul
*** empty log message ***
Revision 1.1 2007/11/05 19:03:13 paul
first checkin
*---------------------------------------------------------------------------*/
#ifndef wfskrn_Defs_h
#define wfskrn_Defs_h
#define _WIN32_WINNT 0x500
#include "revolution/wfs.h"
#include "wfskrn_Platform.h"
#include "wfskrn_Config.h"
#include "wfskrn_Errors.h"
#include "wfskrn_Types.h"
#if !_IOP
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
#define WFS_ROUND_UP(v,x) (((v)+(x)-1)&-((signed)x))
#define WFS_ROUND_DOWN(v,x) ((v)&-((signed)x))
#define WFS_NUM_BITS_REQUIRED(x) \
(((x)<3)?1:((x)<5)?2:((x)<9)?3:\
((x)<0x11)?4:((x)<0x21)?5:((x)<0x41)?6:((x)<0x81)?7:\
((x)<0x101)?8:((x)<0x201)?9:((x)<0x401)?10:((x)<0x801)?11:\
((x)<0x1001)?12:((x)<0x2001)?13:((x)<0x4001)?14:((x)<0x8001)?15:\
((x)<0x10001)?16:((x)<0x20001)?17:((x)<0x40001)?18:((x)<0x80001)?19:\
((x)<0x100001)?20:((x)<0x200001)?21:((x)<0x400001)?22:((x)<0x800001)?23:\
((x)<0x1000001)?24:((x)<0x2000001)?25:((x)<0x4000001)?26:((x)<0x8000001)?27:\
((x)<0x10000001)?28:((x)<0x20000001)?29:((x)<0x40000001)?30:((x)<0x80000001)?31:32)
#define BYTES2BITS(b) ((b)<<3)
#define BUILD_YEAR ((((__DATE__[7]-'0')*10+(__DATE__[8]-'0'))*10+(__DATE__[9]-'0'))*10+(__DATE__[10]-'0'))
#define BUILD_MONTH (__DATE__[2]=='n'?0:__DATE__[2]=='b'?1:__DATE__[2]=='r'?(__DATE__[0]=='M'?2:3):__DATE__[2]=='y'?4:__DATE__[2]=='n'?5:__DATE__[2]=='l'?6:__DATE__[2]=='g'?7:__DATE__[2]=='p'?8:__DATE__[2]=='t'?9:__DATE__[2]=='v'?10:11)
#define BUILD_DAY ((__DATE__[4]==' '?0:__DATE__[4]-'0')*10+(__DATE__[5]-'0'))
#define BUILD_DATE (((BUILD_YEAR-2000)*12+BUILD_MONTH)*31+BUILD_DAY)
#ifndef swap_typ
#define swap_typ(Typ,a,b) { Typ t=a; a=b; b=t; }
#endif
#ifdef _DEBUG
#ifndef _ASSERT
#define _ASSERT(x) ASSERT(x)
#endif
#else
#ifndef _ASSERT
#define _ASSERT(x)
#endif
#endif
#ifdef _DEBUG
#define _DEBUG_BREAK_POINT 1
#else
#define _DEBUG_BREAK_POINT 0
#endif
#endif // wfskrn_Defs_h

View File

@ -0,0 +1,232 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_Device.h - Storage device abstraction.
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Device.h,v $
Revision 1.14 2008/12/10 06:54:02 kondo_masahiro
Added a argument WFSDevType nDevType in DeviceAttachDetachCallback.
Revision 1.13 2008/11/26 02:43:58 kondo_masahiro
Added comments of DeviceRead/Write.
Revision 1.12 2008/11/26 01:46:01 kondo_masahiro
Fixed arguments of several functions in order to improve access speed.
Fixed source code for Win32 version to enable easier debug.
Revision 1.11 2008/10/09 01:40:14 kondo_masahiro
Fixed name of the function DeviceRead/WriteSingleBlk
Revision 1.10 2008/10/08 23:20:09 kondo_masahiro
Added codes to access large size file data
Revision 1.9 2008/10/03 08:37:18 kondo_masahiro
Fixed codes for porting IOP
Revision 1.8 2008/09/30 02:02:27 ueno
Removed an obsolete define, WFSKRN_SIMULATED_DISK_SIZE.
Revision 1.7 2008/09/28 23:30:24 kondo_masahiro
Fixed codes to use medium size user block.
Revision 1.6 2008/08/29 00:12:36 kondo_masahiro
Added DeviceGetVolumeId.
Revision 1.5 2008/08/14 08:20:14 kondo_masahiro
Changed WFSKRN_SIMULATED_DISK_PATH
Revision 1.4 2008/08/14 08:07:27 kondo_masahiro
Changed several APIs in order to access the large size file.
Revision 1.3 2008/08/05 04:17:29 kondo_masahiro
Added error handling for hash error and detach device.
Revision 1.2 2008/07/17 05:07:43 kondo_masahiro
Added codes for IOP
Revision 1.1 2008/07/09 01:39:12 paul
Merged device definitions from wfskrn_PMem.h and wfskrn_Api.h.
*---------------------------------------------------------------------------*/
#ifndef _WFSKRN_DEVICE_H_
#define _WFSKRN_DEVICE_H_
#if _WIN32
#include <stdlib.h>
#include <stdio.h>
#endif
#include "revolution/wfs.h"
#include "wfs_Names.h"
#include "wfskrn_Defs.h"
#include "wfskrn_Config.h"
#if _WIN32
#include "msc_error.h"
#elif _TWL
#include "msc_error.h"
#elif _IOP
#include "msc_includes.h"
#endif
#define DEVICE_EMBEDDED_HASH_DATA 1 // If it is on, the hash data is embedded to the written data.
#define DEVICE_VERIFY_HASH_DATA 1 // If it is on, DeviceRead can outputs error when two hash data discord.
#define DEVICE_DEBUG_PSEUDO_DEVICE_ERROR 1
#define DEVICE_IOP_MAX_ASYNC_NUM 2
#if _WIN32
#define IOSError s32
#define WFSKRN_SIMULATED_DISK_PATH "Y:\\TEMP\\shirait\\WFS_VOL_S\\"
typedef HANDLE DeviceHandle; // Windows handle
#elif _TWL
#define IOSError s32
typedef u32 DeviceHandle;
#elif _RVL
typedef u32 DeviceHandle;
#elif _IOP
#define DEVICE_IOP_MSC_CHECK(mscfunc) if(mscfunc < IOS_ERROR_OK){ return WFSKRN_RESULT_DEVICE_ERROR; }
typedef HardDisc* DeviceHandle;
#else
#endif //_WIN32
//#define _DEBUG_WFSKRN_DEVICE_
#ifdef _DEBUG_WFSKRN_DEVICE_
#define dbgd(_s) (_s)
#else
#define dbgd(_s)
#endif // _DEBUG_WFSKRN_DEVICE_
typedef struct DeviceHdr_ {
u32 nLog2SectorSize; // 1st field: Base 2 logarithm of the sector size (default = 9 corresponding to 512 byte sectors)
u32 nNumSectors; // 2nd field; capacity of device
} DeviceHdr;
typedef struct DeviceInfo_ {
DeviceHdr dh;
#if _WIN32
HANDLE hSimulatedDeviceFile;
#endif
//
bool bInUse;
u32 nSectorSize;
u64 nTotalCapacity;
DeviceHandle nDeviceDevHandle;
struct VolumeInfo_ *pVolInfo;
WFSDeviceName devName;
WFSDevType nDevType;
u8 nFlags;
} DeviceInfo;
// Initialize Device library
void DeviceInitLib();
#if _IOP
// Regist callback function for attach/detach device
typedef void (*DeviceAttachDetachCallback)(u32 bAttach, u32 nDevIdx, u32 nLog2SectorSize, u32 nTotalSize, WFSDevType nDevType, void *pUserData);
void DeviceAttachDetachRegistCallback(DeviceAttachDetachCallback cbAttach, void *pUserData);
#endif
WFSKrnResult DeviceRead(DeviceInfo *pDevInfo, u32 nSectorAdr, u8 *pBuffer, u32 nSectors, WFSHashCode *pHash, u32 nLog2HashSectors, u32 nOffsetHashBlks, s32 nHashStride, s32 nHashStridePerMaxLBlks);
// Arguments:
// ----------
// pDevInfo [IN] .. A pointer of DeviceInfo.
// nSecrorAdr [IN] .. A head sector address of HDD to read.
// pBuffer [OUT] .. A pointer of read buffer.
// nSectors [IN] .. A read sector size of HDD.
// pHash [IN] .. A pointer to compare the hash value.
// nLog2HashSectors [IN] .. A sector size unit for hash value. The hash value is calculated for each the unit.
// nOffsetHashBlks [IN] .. A offset block size for nHashStridePerMaxLBlks.
// nHashStride [IN] .. A stride of hash address for each hash size unit.
// nHashStridePerMaxLBlks [IN] .. A stride of hash address for each 512KB unit.
//
// Description:
// ------------
// Read nSector from device pDevInfo starting at LBA nSectorAdr into buffer pBuffer.
// nLog2HashSector is the hash size unit. The argument nLog2HashSector must be indicate up to 64KB (~16).
// The hash value is calculated and compared with pHash for each buffer size nLog2HashSector.
// The hash address pHash is added by nHashStride for each buffer size nLog2HashSector.
// After total hash calculation size is reached to the multiples of 512KB,
// The hash address pHash is added by nHashStride and nHashStridePerMaxLBlks for "SIZE_CATEGORY_LARGE".
// For example, When nLog2HashSectors is 16(64KB) and nOffsetHashBlks is 3,
// The hash address up to 5th block are added by nHashStride. (512 / 64 - 3 = 5)
// The hash address of 6th block is added by nHashStride and nHashStridePerMaxLBlks.
static inline WFSKrnResult DeviceReadSingleBlk(DeviceInfo *pDevInfo, u32 nSectorAdr, u8 *pBuffer, u32 nSectors, WFSHashCode *pHash, u32 nLog2HashSectors){
dbgd(printf("DeviceRead()\n"));
ASSERT(nSectors <= 1<<(WFS_LOG2_MAX_HASHABLE_BLK_SIZE-pDevInfo->dh.nLog2SectorSize) ); // ~64KB
return DeviceRead(pDevInfo, nSectorAdr, pBuffer, nSectors, pHash, nLog2HashSectors, 0, 0, 0);
}
WFSKrnResult DeviceWrite(DeviceInfo *pDevInfo, u32 nSectorAdr, u8 *pBuffer, u32 nSectors, WFSHashCode *pHash, u32 nLog2HashSectors, u32 nOffsetHashBlks, s32 nHashStride, s32 nHashStridePerMaxLBlks, bool bDecryption);
// Arguments:
// ----------
// pDevInfo [IN] .. A pointer of DeviceInfo.
// nSecrorAdr [IN] .. A head sector address of HDD to read.
// pBuffer [IN] .. A pointer of read buffer.
// nSectors [IN] .. A read sector size of HDD.
// pHash [OUT] .. A pointer to store the hash value.
// nLog2HashSectors [IN] .. A sector size unit for hash value. The hash value is calculated for each the unit.
// nOffsetHashBlks [IN] .. A offset block size for nHashStridePerMaxLBlks.
// nHashStride [IN] .. A stride of hash address for each hash size unit.
// nHashStridePerMaxLBlks [IN] .. A stride of hash address for each 512KB unit.
// bDecryption [IN] .. A flag to indicate whether buffer is decrypted after write access or not.
//
// Description:
// ------------
// Write nSector from device pDevInfo starting at LBA nSectorAdr into buffer pBuffer.
// nLog2HashSector is the hash size unit. The argument nLog2HashSector must be indicate up to 64KB (~16).
// The hash value is calculated and stored to pHash for each buffer size nLog2HashSector.
// The hash address pHash is added by nHashStride for each buffer size nLog2HashSector.
// After total hash calculation size is reached to the multiples of 512KB,
// The hash address pHash is added by nHashStride and nHashStridePerMaxLBlks for "SIZE_CATEGORY_LARGE".
// For example, When nLog2HashSectors is 16(64KB) and nOffsetHashBlks is 3,
// The hash address up to 5th block are added by nHashStride. (512 / 64 - 3 = 5)
// The hash address of 6th block is added by nHashStride and nHashStridePerMaxLBlks.
static inline WFSKrnResult DeviceWriteSingleBlk(DeviceInfo *pDevInfo, u32 nSectorAdr, u8 *pBuffer, u32 nSectors, WFSHashCode *pHash, u32 nLog2HashSectors, bool bDecryption){
dbgd(printf("DeviceWrite()\n"));
ASSERT(nSectors <= 1<<(WFS_LOG2_MAX_HASHABLE_BLK_SIZE-pDevInfo->dh.nLog2SectorSize) ); // ~64KB
return DeviceWrite(pDevInfo, nSectorAdr, pBuffer, nSectors, pHash, nLog2HashSectors, 0, 0, 0, bDecryption);
}
// Get the device info from the device name (from the path cache)
DeviceInfo *DeviceGetDeviceInfo(const WFSDeviceName *pDevName);
// Get a volume id from the device name even if the device is not mounted.
WFSKrnResult DeviceGetVolumeId(const WFSDeviceName *pDevName, WFSVolumeId *pVolId);
// Mount a volume
WFSKrnResult DeviceMountVolume(DeviceInfo *pDevInfo);
// Attach a device - called when user physically attaches a drive
WFSKrnResult DeviceAttach(DeviceInfo *pDevInfo, WFSDevType nDevType, u32 nDevIdx, u32 Log2SectorSize, u32 nNumSectors);
// Detach a device - called when user physically detaches a drive
WFSKrnResult DeviceDetach(DeviceInfo *pDevInfo);
//// Debug functions
void DeviceDebugSetPseudoDetachDevice(s32 cnt);
void DeviceDebugSetPseudoHashInconsistent(s32 cnt);
s32 DeviceDebugGetPseudoDetachDevice();
s32 DeviceDebugGetPseudoHashInconsistent();
#if _WIN32 // * Windows version *
#define DeviceOverhead() (2*sizeof(u32)) // overhead for simulating a device
#else
#define DeviceOverhead() 0
#endif // _WIN32
#endif // _WFSKRN_DEVICE_H_

View File

@ -0,0 +1,800 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_Dir.h - Directory Module
Copyright 2007-2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Dir.h,v $
Revision 1.28 2008/12/04 00:42:37 ooizumi
Changed definition name to enable permission.
Revision 1.27 2008/11/19 05:02:53 ooizumi
Fixed typo.
Revision 1.26 2008/11/18 04:57:11 saito_tomoya
Modified SetBit() and added SetBitArray().
Revision 1.25 2008/11/07 08:55:16 kondo_masahiro
Added DirCalculateAttrSubBlkLog2SizeUpdateAllocSize()
Revision 1.24 2008/11/04 00:25:07 kondo_masahiro
Added DirSbaAllocAndRegistSubBlk()
Revision 1.23 2008/10/31 09:51:42 ueno
Modified WFSSrvAPIs to return WFSKRN_RESULT_RESOURCE_LIMIT_EXCEEDED when path cache is short of memory.
Revision 1.22 2008/10/30 05:09:05 kondo_masahiro
Added DirCheckDisk
Revision 1.21 2008/10/24 09:02:25 kondo_masahiro
Added decrease block process of DirResize.
Revision 1.20 2008/10/17 08:51:27 kondo_masahiro
Added the new MEDIUM size category (40KB-320KB)
Revision 1.19 2008/10/16 09:25:53 ooizumi
Fixed definitions for debug build.
Revision 1.18 2008/10/14 10:27:44 kondo_masahiro
Added codes to access very large size file data
Revision 1.17 2008/10/10 02:11:31 kondo_masahiro
Fixed a bug to access large files
Revision 1.16 2008/10/09 04:15:46 kondo_masahiro
Fixed member of AreaHdr and AreaInfo
Revision 1.15 2008/10/08 23:20:09 kondo_masahiro
Added codes to access large size file data
Revision 1.14 2008/10/07 10:30:34 ooizumi
Added nObjCreator to DirEntryAttrHdr.
Revision 1.13 2008/09/28 23:30:31 kondo_masahiro
Fixed codes to use medium size user block.
Revision 1.12 2008/08/27 09:49:46 paul
Started coding for different size categories
Revision 1.11 2008/08/05 04:17:43 kondo_masahiro
Added error handling for hash error and detach device.
Revision 1.10 2008/07/28 22:26:54 paul
Improved updateMap processing. Added DirGetBlk().
Revision 1.9 2008/07/25 02:56:12 paul
Changed nTransIdx to *pTransInfo. Changed WFSTransBlkAdr to TransBlkAdr
Revision 1.8 2008/07/21 22:50:42 paul
Changed name from DirItrPinBlkAndUpdatePtrs() -> DirItrPinBlkAndFixPtrs()
Revision 1.7 2008/07/17 22:23:52 paul
Changes for update counters
Revision 1.6 2008/07/09 01:33:13 paul
Added DirItrCloseNoUnpin alternative to DirItrClose to give the option of unpinning the cache block while closing an interator. Made other minor changes.
Revision 1.5 2008/06/09 18:15:30 paul
No longer storing the non-persistent state: number of open read/write handles per file, within file attributes - moved this info to path cache which is non-persistent.
Revision 1.4 2008/05/12 19:20:28 paul
Added a list of open directory iterators.
Revision 1.3 2008/05/10 04:00:48 kondo_masahiro
Merged and fixed code to accept RM compiler
Revision 1.2 2008/04/25 17:28:21 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.1 2008/04/22 04:39:08 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.14 2008/04/23 01:30:14 paul
Continued updating and documenting Dir API
Revision 1.13 2008/04/19 05:49:25 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.12 2008/04/18 00:09:02 paul
Changed interface to Dir functions
Revision 1.11 2008/04/15 18:35:38 paul
Changed definition of DirFind to take separate nMaxBlkDepth and nFlags parameters.
Revision 1.10 2008/04/05 03:10:40 paul
Many changes for Delete and associated testing.
Revision 1.9 2008/03/07 01:38:35 paul
added DIR_PREFIX_SEARCH
Revision 1.8 2008/02/29 02:29:46 paul
Added Delete functions, fixed DirCreateAndInitNewBlk4 parameters
Revision 1.7 2008/02/28 06:32:42 kondo_masahiro
Fixed code to accept PPC compiler
Revision 1.5 2008/02/21 04:30:54 paul
reorganization
Revision 1.4 2008/02/21 01:36:56 paul
moved DIR_MAX_BLK_DEPTH to header file
updated definition for DirFind
Revision 1.3 2008/02/21 00:11:34 paul
Moved SubBlk allocation out of the dir module making it more generic. Now DirBlkHdr pseudo-inherits from WFSSubBlkAllocHdr, which in turn inherits from WFSMetaDataHdr
Revision 1.2 2008/02/20 07:46:21 paul
Numerous changes
Revision 1.1 2007/12/27 11:36:29 paul
still at an early stage of development
Revision 1.2 2007/11/08 05:29:16 paul
continued with block layout initialization code
Revision 1.1 2007/11/05 19:03:13 paul
first checkin
*---------------------------------------------------------------------------*/
#ifndef wfskrn_Dir_h
#define wfskrn_Dir_h
#include "wfskrn_Config.h"
#include "wfskrn_SubBlkAlloc.h"
#include "wfskrn_Trans.h"
#include "wfskrn_PTree.h"
#ifdef _DEBUG
#define _DEBUG_DIR 1 // change to 1 if debug info required
#else
#define _DEBUG_DIR 0
#endif
#define DIR_MAX_BLK_DEPTH 5
#define DIR_PREFIX_SEARCH ((u32)-2)
#define DIR_PREFIX_SUPPRESSION 0
#define DIR_SUB_BLK_TYPE_RADIX_NODE 0x00
#define DIR_SUB_BLK_TYPE_BLK_PTR 0x01
#define DIR_SPLIT_BLK_ADR 0
// Flags which are store in the same variable as: WFS_FLAG_IS_A_DIRECTORY, WFS_FLAG_CONTIGUOUS_AREA
#define FILE_SIZE_CATEGORY_VERY_SMALL 0 // Files which fit in the directory leaf block. (up to about 960 bytes - also depends on file name length)
#define FILE_SIZE_CATEGORY_SMALL 1 // Files where the attr block points to between 1 and 5 small blocks.
#define FILE_SIZE_CATEGORY_MEDIUM 2 // Files where the attr block points to between 1 and 5 medium blocks.
#define FILE_SIZE_CATEGORY_LARGE 3 // Files where the attr block points to between 1 and 12 large blocks.
#define FILE_SIZE_CATEGORY_VERY_LARGE 4 // Files where the attr block points to indirect blocks which point to large blocks.
#if _DEBUG_DIR
extern bool bCheckDirBlks;
#endif
#if _DEBUG_DIR
extern u32 nDirTest;
extern u32 nDirTestBreakPoint;
extern u32 nDirTotalTests;
#endif
typedef struct {
WFSSubBlkAllocHdr sbah;
u16 nRootOfs;
u16 nNumRecs; // Number of records in the block, not the whole directory
} DirBlkHdr;
#pragma pack(1)
#define SIZE_OF_DIRSUBBLKHDR 3
typedef struct {
u8 nStrLen;
u8 nNumEntries;
utf8 aFirstChar[1];
} _ATTRIBUTE_PACKED DirSubBlkHdr;
#pragma pack()
typedef struct DirNodeStack_ DirNodeStack;
struct DirNodeStack_ {
DirNodeStack *pParent;
WFSBlkAdr nBlkAdr;
u32 nUpdateCtr; // Compared against counter stored in dir blocks to determine whether the block has been changed since this iterator was last used.
u16 nSubBlkOfs;
u8 nEntryIdx;
u8 nStrIdx;
};
typedef struct {
u16 *pOfs; // A pointer to the offset pointer to the node. This would need to be updated if the sub block is relocated.
DirSubBlkHdr *pSubBlkHdr; // A pointer to the sub block containing the node.
u32 nLog2Size; // The base 2 logarithm of the size of the sub block containing the node.
utf8 *pStrPtr; // A string pointer to the current cursor position within the search name. After DirFind(), it points to the first mismatch.
utf8 *pNodeStrPtr; // A string pointer to the current cursor position within the node string. After DirFind(), it points to the first mismatch.
u32 nEntryIdx; // The entry index of the choice within the current node which is closest but <= search name during DirFind().
DirNodeStack *pDns; // A stack of locators within dir node sub blks recording the path taken through the name radix tree
u32 nDnsDepth; // Number of entries in the DirNodeStack
} DirNodeItr;
typedef struct {
u32 nSize;
u16 nContentIdx;
u16 nVersion;
} DirFileAttr;
typedef struct {
WFSBlkAdr nQuota; // Quota in multiples of blocks
WFSBlkAdr nSubDirBlkAdr;
} DirDirAttr;
typedef struct {
u32 nAccessListIdx;
u32 nAllocSize;
WFSFileTime timeCreated;
WFSFileTime timeUpdated;
#ifdef PERMISSION_ENABLED
WFSTitleId nObjCreator;
#endif
union {
DirFileAttr file;
DirDirAttr dir;
};
u8 nAttrLog2Size; // Log to the base 2 of the file attributes sub-block
u8 nSizeCategory; // Size category of the file
u8 nNameLen; // Length of the file name
u8 aCaseBitArray[1]; // (variable size) A bit per character of the file name to indicate whether each character is upper or lower case
} DirEntryAttrHdr;
typedef struct {
struct DirItr_ *pNext;
struct DirItr_ *pPrev;
} DirItrLink;
typedef struct DirItr_ {
DirItrLink link;
u32 nBlkDepth; // The depth of the block currently pointed to by the iterator. Normally, set to 0 before calling DirFind* functions.
TransBlkAdr tba; // The block currently pointed to by the iterator. Normally, set to the root block of the directory before calling DirFind* functions.
DirEntryAttrHdr *pAttrHdr; // Pointer to the file/dir attributes of the current file.
DirBlkHdr *pBlkHdr; // Pointer to start of block tba.nBlkAdr in memory. (Start of the block is the block header).
u32 nUpdateCtr; // Update counter of the block referenced by tba.nBlkAdr
DirNodeItr dni;
DirNodeStack **ppDnsRootParent; // Pointer to the parent link within the root dir node stack entry - to allow for easy freeing of the whole dir node stack.
WFSFileName name; // Name of the current entry pointed to by the iterator.
} DirItr; // Directory Iterator
#define MAX_INDIRECT_FILE_DEPTH 3
typedef struct {
//TransBlkAdr tba;
//u32 nPos;
u8 *pDataPtr;
u32 nRemainingBlkSize;
} DirFilePos;
typedef struct {
//TransBlkAdr tba;
//u32 nPos;
WFSFileBlkPtr *pFileBlkPtr;
u32 nRemainingBlkSize;
} DirFilePosMedium;
WFSKrnResult DirFindFilePos(DirItr *pDi, WFSFileSize nPos, DirFilePos *pFpos, u32 nTransFlags);
WFSKrnResult DirResizeFile(DirItr *pDi, WFSFileSize nNewSize);
// ToDo: Now that a WFSFileName member has been added to DirItr, I should check for performance problems
// introduced by indiscriminate copies of DirItr structs. Some Dir functions which define a local WFSFileName
// could possibly use the storage space within the DirItr instead (eDirLeafBlkSplit, DirNodeBlkSplit).
typedef struct {
utf8 aToLower[256];
utf8 aToUpper[256];
DirItrLink openDirItrListAnchor;
DirItr *pOpenDirItrListAnchor;
PTreeHdr updateMap; // Maps from nBlkAdr to nUpdateCtr for directory blocks which are referenced by currently open directory iterators
PTreeAllocator updateMapAllocator;
} DirGlobals;
extern DirGlobals dirGlobals;
u32 DirLeafGetSubBlkLog2Size_2(u32 nStrLen, u32 nNumEntries);
u32 DirNodeGetSubBlkLog2Size_3(u32 nStrLen, u32 nNumEntries, utf8 cFirstChoice);
u32 DirCalculateAttrSubBlkLog2Size(AreaInfo *pAreaInfo, u32 nAllocSize, u32 nNameLen, u8 *pSizeCategory);
u32 DirCalculateAttrSubBlkLog2SizeDecrease(AreaInfo *pAreaInfo, u32 nAllocSize, u32 nNameLen, u8 *pSizeCategory);
u32 DirCalculateAttrSubBlkLog2SizeUpdateAllocSize(AreaInfo *pAreaInfo, u32 *pAllocSize, u32 nNameLen, u8 *pSizeCategory);
u32 DirCalculateAttrSubBlkLog2SizeDecreaseUpdateAllocSize(AreaInfo *pAreaInfo, u32 *pAllocSize, u32 nNameLen, u8 *pSizeCategory);
void DirModuleInit();
void DirLeafCheckBlk(DirItr *pDi);
void DirNodeCheckBlk(DirItr *pDi);
void DirCheckBlk(DirItr *pDi);
#define DIR_CHECK_DISK_FOR_DIR_TREE 0
#define DIR_CHECK_DISK_FOR_ACL_TREE 1
WFSKrnResult DirCheckDisk(WFSBlkAdr rootBlkAdr, DirItr *pDi, WFSSrvFileHandle fh, u8* pBuffer, u32 bufferSize, u32 nFlag);
WFSKrnResult DirGetBlk(DirItr *pDi, u32 nTransFlags, DirBlkHdr **ppBlkHdr);
WFSKrnResult DirCreateAndInitNewBlk4(AreaInfo *pAreaInfo, WFSBlkAdr nBlkAdr, WFSMetaDataFlags nFlags, TransInfo *pTransInfo, DirBlkHdr **ppBlkHdr);
//WFSKrnResult DirCreateAndInitNewBlk(TransBlkAdr *pTba, WFSMetaDataFlags nFlags, DirBlkHdr **ppBlkHdr);
void DirBlkCreateRootNode(DirBlkHdr *pBlkHdr);
WFSKrnResult DirReGetHashAdr(AreaInfo *pAreaInfo, DirEntryAttrHdr *pAttrHdr, WFSBlkAdr nNewBlkAdr, DirBlkHdr* pNewBlkHdr);
WFSKrnResult DirSbaAllocAndRegistSubBlk(WFSFileName *pName, DirItr *pDi, u32 nLog2Size, DirEntryAttrHdr **ppNewAttrHdr);
WFSKrnResult DirFindNameWithoutCaseConversion(DirItr *pDi);
WFSKrnResult DirFindName(WFSFileName *pName, DirItr *pDi);
// Arguments:
// ----------
// pName [IN/OUT] .. A pointer to a WFSFileName struct containing the utf8 name to search for.
// pDi [OUT] .. A pointer to a DirItr struct which will be updated with the search location.
//
// Return Values:
// --------------
// WFSKRN_RESULT_OK .. The name was found. *pDi is overwritten with the contents of the directory iterator.
// WFSKRN_RESULT_NOT_FOUND .. The specified name was not found.
// Other error codes are possible - passed back from lower level functions
//
// Description:
// ------------
// This function searches for a specific name in the directory, and if a match is found, returns the location of the
// file or sub-directory attributes for the associated entry.
// NOTE: Some parts of the directory iterator structure are allocated dynamically, and must be freed
// by calling DirItrClose() when pDi is no longer needed.
WFSKrnResult DirFindRaw(DirItr *pDi);
// Arguments:
// ----------
// pDi [IN/OUT] .. A pointer to DirItr struct which will be updated with the details of the location.
// pDi->name contains a raw input name to search for (will not be case-converted)
//
// Return Values:
// --------------
// WFSKRN_RESULT_OK .. The name was found. *ppAttr is overwritten with the contents of the associated attributes block.
// WFSKRN_RESULT_NOT_FOUND .. The specified name was not found.
// Other error codes are possible - passed back from lower level functions
//
// Description:
// ------------
// This function searches for a specific raw name in the directory, and if a match is found, returns the location of the
// attributes for the associated entry.
// NOTE: This function is provided to support Access-lists, and should not be used for normal directories.
// Some parts of the directory iterator structure are allocated dynamically, and must be freed
// by calling DirItrClose() when pDi is no longer needed.
WFSKrnResult DirFindFirstNamePrefixMatch(WFSFileName *pName, DirItr *pDi);
// Arguments:
// ----------
// pName [IN/OUT] .. A pointer to a WFSFileName struct containing the prefix of the utf8 name to search for.
// pDi [OUT] .. A pointer to a directory iterator struct which stores information about the file location.
//
// Return Values:
// --------------
// WFSKRN_RESULT_OK .. The first name which starts with the prefix was found. *pDi contains the location of the file/dir attributes block.
// WFSKRN_RESULT_NOT_FOUND .. No name was found which starts with the specified prefix.
// Other error codes are possible - passed back from lower level functions
//
// Description:
// ------------
// This function searches the directory for a name which starts with a specified prefix. If one or more matching names exsit,
// this function returns the location of the first match, and the corresponding entry attributes data in *pDi.
// pDi can be passed to DirFindNext() to find the next entry in the directory.
// NOTE: Some parts of the directory iterator structure are allocated dynamically, and must be freed
// by calling DirItrClose() when pDi is no longer needed.
WFSKrnResult DirNextName(WFSFileName *pName, DirItr *pDi);
// Arguments:
// ----------
// pName [OUT] .. A pointer to a WFSFileName struct containing the file name to search for.
// pDi [IN/OUT] .. A pointer to a directory iterator struct which stores information about the file location.
//
// Return Values:
// --------------
// WFSKRN_RESULT_OK .. A next entry was found. *pName and *pDi were updated.
// WFSKRN_RESULT_NOT_FOUND .. No further entries were found.
// Other error codes are possible - passed back from lower level functions
//
// Description:
// ------------
// This function increments the directory iterator to the next entry (in lexicographical order)
// The name of the next entry is returned in *pName. The directory location including file attributes is returned in *pDi.
// NOTE: Some parts of the directory iterator structure are allocated dynamically, and must be freed
// by calling DirItrClose() when pDi is no longer needed.
WFSKrnResult DirNextRaw(WFSFileName *pName, DirItr *pDi);
// Arguments:
// ----------
// pName [OUT] .. A pointer to a WFSFileName struct containing the file name to search for.
// pDi [IN/OUT] .. A pointer to a directory iterator struct which stores information about the file location.
//
// Return Values:
// --------------
// WFSKRN_RESULT_OK .. A next entry was found. *pName and *pDi were updated.
// WFSKRN_RESULT_NOT_FOUND .. No further entries were found.
// Other error codes are possible - passed back from lower level functions
//
// Description:
// ------------
// This function increments the directory iterator to the next entry (in lexicographical order)
// The name of the next entry is returned in *pName. The directory location including file attributes is returned in *pDi.
// NOTE: Some parts of the directory iterator structure are allocated dynamically, and must be freed
// by calling DirItrClose() when pDi is no longer needed.
WFSKrnResult DirItrClose(DirItr *pDi);
// Arguments:
// ----------
// pDi [IN] .. A pointer to a directory iterator struct.
//
// Return Values:
// --------------
// WFSKRN_RESULT_OK .. The directory iterator was successfully closed.
// Other error codes may be possible - passed back from lower level functions
//
// Description:
// ------------
// This function closes the directory iterator and frees up dynamically allocated resources.
// Includes unpinning the currently referenced block
WFSKrnResult DirItrCloseNoUnpin(DirItr *pDi);
// Arguments:
// ----------
// pDi [IN] .. A pointer to a directory iterator struct.
//
// Return Values:
// --------------
// WFSKRN_RESULT_OK .. The directory iterator was successfully closed.
// Other error codes may be possible - passed back from lower level functions
//
// Description:
// ------------
// This function closes the directory iterator and frees up dynamically allocated resources.
// Does not include unpinning the currently referenced block
WFSKrnResult DirInsertName(WFSFileName *pName, DirItr *pDi, u32 nAllocSize);
// Arguments:
// ----------
// pName [IN] .. A pointer to a WFSFileName struct containing a utf-8 name string to insert.
// pDi [OUT] .. A pointer to a directory iterator struct which represents the location within the directory.
// nAllocSize [IN] .. The initial size of the file. When creating sub-directories, use nAllocSize = 0.
//
// Return Values:
// --------------
// WFSKRN_RESULT_OK .. The name was inserted successfully.
// WFSKRN_RESULT_ALREADY_EXISTS .. A conflicting name already exists in the directory.
// Other error codes may be possible - passed back from lower level functions
//
// Description:
// ------------
// This function inserts a utf-8 name into the directory. The case information for each character is stored, but is ingored
// when comparing with existing names, so the name will conflict with an existing name which differs only in capitalization.
WFSKrnResult DirInsertRaw(WFSFileName *pName, DirItr *pDi, u32 nAllocSize);
// Arguments:
// ----------
// pName [IN] .. A pointer to a WFSFileName struct containing a raw name to insert. (The name can use any 8-bit characters but must be 0 terminated).
// pDi [OUT] .. A pointer to a directory iterator struct.
// nAllocSize [IN] .. The initial size of the file.
//
// Return Values:
// --------------
// WFSKRN_RESULT_OK .. The name was inserted successfully.
// WFSKRN_RESULT_ALREADY_EXISTS .. The same name already exists in the directory.
// Other error codes may be possible - passed back from lower level functions
//
// Description:
// ------------
// This function inserts a raw string into the directory. No case manipulations are performed,
// so the comparison with existing names is case-sensitive.
// NOTE: This function is provided to support Access-lists, and should not be used for normal directories.
WFSKrnResult DirDeleteEntry(DirItr *pDi);
// Arguments:
// ----------
// pDi [OUT] .. A pointer to a directory iterator struct which is pointing to a particular entry.
//
// Return Values:
// --------------
// WFSKRN_RESULT_OK .. The entry name and its associated attribute data was deleted successfully from the directory.
// Other error codes may be possible - passed back from lower level functions
//
// Description:
// ------------
// This function deletes an entry from a directory. This includes deleting the attribute data for the file or sub-directory,
// but does not include deleting separate data blocks or meta-data blocks associated with the file or sub-directory.
// One of the DirFind* functions should be used to
WFSKrnResult DirDeleteFile(DirItr *pDi);
// Arguments:
// ----------
// pDi [IN] .. A pointer to a directory iterator struct which is pointing to a particular entry.
//
// Return Values:
// --------------
// WFSKRN_RESULT_OK .. The file was deleted successfully.
// Other error codes may be possible - passed back from lower level functions
//
// Description:
// ------------
// This function deletes the data blocks and meta-data blocks associated with a file entry, but does not delete
// the entry itself from its parent directory.
WFSKrnResult DirDeleteSubDir(DirItr *pDi);
// Arguments:
// ----------
// pDi [IN] .. A pointer to a directory iterator struct which is pointing to a particular entry.
//
// Return Values:
// --------------
// WFSKRN_RESULT_OK .. The sub directory was deleted successfully.
// WFSKRN_RESULT_NOT_EMPTY .. The sub directory is not empty, and was not deleted.
// Other error codes may be possible - passed back from lower level functions
//
// Description:
// ------------
// This function deletes the root block associated with a sub-directory entry, but does not delete
// the entry itself from its parent directory.
void DirInitDirEntryAttrHdr(DirEntryAttrHdr *pAttrHdr);
void DirInitFileEntryAttrHdr(DirEntryAttrHdr *pAttrHdr);
WFSKrnResult DirItrPinBlkAndFixPtrs(DirItr *pDi, u32 nTransFlags);
WFSKrnResult DirItrMapBlks(DirItr *pDi);
void DirItrUnmapBlks(DirItr *pDi);
WFSKrnResult DirItrCheckMapBlks(DirItr *pDi);
WFSKrnResult DirItrCheckAndUnmapBlks(DirItr *pDi);
void WFSKrnCopyFileName(WFSFileName *pDst, WFSFileName *pSrc);
void WFSKrnCopyStrAndConvertToLowerCase(utf8 *pDstStr, const utf8 *pSrcStr, u32 nLen);
void WFSKrnCopyFileNameAndConvertToLowerCase(WFSFileName *pDst, WFSFileName *pSrc);
void WFSKrnCopyFileNameAndRestoreCase(utf8 *pDst, WFSFileName *pSrc, u8 *pCaseBitArray);
WFSKrnResult WFSKrnValidateCopyStrAndConvertToLowerCase(utf8 *pDstStr, const utf8 *pSrcStr, u32 nLen, u32 nMaxLen);
void WFSKrnStoreCaseInformationStr(u8 *pCaseBitArray, const utf8 *pStr, u32 nLen);
static inline WFSKrnResult DirCreateAndInitNewBlk(TransBlkAdr *pTba, WFSMetaDataFlags nFlags, DirBlkHdr **ppBlkHdr) {
return DirCreateAndInitNewBlk4(pTba->pAreaInfo, pTba->nBlkAdr, nFlags, pTba->pTransInfo, ppBlkHdr);
}
static inline void WFSKrnStoreCaseInformation(u8 *pCaseBitArray, WFSFileName *pName) {
WFSKrnStoreCaseInformationStr(pCaseBitArray, pName->sStr, pName->nLen);
}
// Inline Functions for FILE_SIZE_CATEGORY_SMALL // 1 block = 8KB (small block size)
static inline WFSFileBlkPtr *WFSKrnGetFileBlkPtrForCategorySmall(DirEntryAttrHdr *pAttrHdr, u32 nAttrLog2Size, u32 nBlkIdx){
return (WFSFileBlkPtr *)((size_t)pAttrHdr + (1<<nAttrLog2Size) - ((1 + nBlkIdx) * sizeof(WFSFileBlkPtr)));
}
static inline WFSFileBlkInfo WFSKrnGetFileBlkInfoForCategorySmall(AreaInfo *pAreaInfo, DirEntryAttrHdr *pAttrHdr, u32 nAttrLog2Size, u32 nBlkIdx){
WFSFileBlkPtr *pFileBlkPtr = WFSKrnGetFileBlkPtrForCategorySmall(pAttrHdr, nAttrLog2Size, nBlkIdx);
WFSFileBlkInfo fileBlkInfo;
fileBlkInfo.nBlkAdr = pFileBlkPtr->nBlkAdr;
fileBlkInfo.pHash = &pFileBlkPtr->hash;
return fileBlkInfo;
}
static inline WFSFileBlkInfo WFSKrnGetFileBlkInfoForCategorySmallCast(AreaInfo *pAreaInfo, void *pMetaData, u32 nLog2MetaSize, u32 nBlkIdx){
return WFSKrnGetFileBlkInfoForCategorySmall(pAreaInfo, (DirEntryAttrHdr*)pMetaData, nLog2MetaSize, nBlkIdx);
}
// Inline Functions for FILE_SIZE_CATEGORY_MEDIUM // 1 block = 64KB (small block size)
#define WFSKrnGetFileBlkPtrForCategoryMedium WFSKrnGetFileBlkPtrForCategorySmall
#define WFSKrnGetFileBlkInfoForCategoryMedium WFSKrnGetFileBlkInfoForCategorySmall
#define WFSKrnGetFileBlkInfoForCategoryMediumCast WFSKrnGetFileBlkInfoForCategorySmallCast
// Inline Functions for FILE_SIZE_CATEGORY_LARGE // Meddium Block Size = 64KB (Max hash size)
static inline WFSFileLargeBlkPtr *WFSKrnGetFileLargeBlkPtrForCategoryLarge(DirEntryAttrHdr *pAttrHdr, u32 nAttrLog2Size, u32 nLargeBlkIdx){
return (WFSFileLargeBlkPtr *)( (size_t)pAttrHdr + (1<<nAttrLog2Size) - ((1 + nLargeBlkIdx) * sizeof(WFSFileLargeBlkPtr)) );
}
static inline WFSFileBlkInfo WFSKrnGetFileBlkInfoForCategoryLarge(AreaInfo *pAreaInfo, WFSFileLargeBlkPtr *pFileLargeBlkPtr, u32 nMedBlkIdx){
WFSFileBlkInfo fileBlkInfo;
fileBlkInfo.nBlkAdr = pFileLargeBlkPtr->nBlkAdr+(nMedBlkIdx<<pAreaInfo->nLog2BlksPerMediumBlk);
fileBlkInfo.pHash = &pFileLargeBlkPtr->aHash[nMedBlkIdx];
return fileBlkInfo;
}
static inline WFSFileBlkInfo WFSKrnGetFileBlkInfoForCategoryLarge4(AreaInfo *pAreaInfo, DirEntryAttrHdr *pAttrHdr, u32 nAttrLog2Size, u32 nMedBlkIdx){
return WFSKrnGetFileBlkInfoForCategoryLarge(pAreaInfo,
WFSKrnGetFileLargeBlkPtrForCategoryLarge(pAttrHdr,
nAttrLog2Size,
nMedBlkIdx>>pAreaInfo->nLog2MediumBlkPerLargeBlk),
nMedBlkIdx%(1<<pAreaInfo->nLog2MediumBlkPerLargeBlk));
}
static inline WFSFileBlkInfo WFSKrnGetFileBlkInfoForCategoryLargeCast(AreaInfo *pAreaInfo, void *pMetaData, u32 nLog2MetaSize, u32 nMedBlkIdx){
return WFSKrnGetFileBlkInfoForCategoryLarge4(pAreaInfo, (DirEntryAttrHdr*)pMetaData, nLog2MetaSize, nMedBlkIdx);
}
// Inline Functions for FILE_SIZE_CATEGORY_VERY_LARGE // Meddium Block Size = 64KB (Max hash size)
static inline WFSBlkAdr *WFSKrnGetBlkAdrPtrFromAttrHdrAndIndirectBlkIdxForCategoryVeryLarge(AreaInfo *pAreaInfo, DirEntryAttrHdr *pAttrHdr, u32 nAttrLog2Size, u32 nIndirectBlkIdx){
return (WFSBlkAdr*)( (size_t)pAttrHdr + (1<<nAttrLog2Size) - ((1 + nIndirectBlkIdx) * sizeof(WFSBlkAdr)) );
}
static inline WFSBlkAdr *WFSKrnGetBlkAdrPtrFromAttrHdrAndLargeBlkIdxForCategoryVeryLarge(AreaInfo *pAreaInfo, DirEntryAttrHdr *pAttrHdr, u32 nAttrLog2Size, u32 nLargeBlkIdx){
u32 nIndirectBlkIdx = (nLargeBlkIdx)/pAreaInfo->nNumLargeBlkPtrsPerBlk;
return WFSKrnGetBlkAdrPtrFromAttrHdrAndIndirectBlkIdxForCategoryVeryLarge(pAreaInfo, pAttrHdr, nAttrLog2Size, nIndirectBlkIdx);
}
static inline WFSBlkAdr *WFSKrnGetBlkAdrPtrFromAttrHdrAndMedBlkIdxForCategoryVeryLarge(AreaInfo *pAreaInfo, DirEntryAttrHdr *pAttrHdr, u32 nAttrLog2Size, u32 nMedBlkIdx){
return WFSKrnGetBlkAdrPtrFromAttrHdrAndLargeBlkIdxForCategoryVeryLarge(pAreaInfo, pAttrHdr, nAttrLog2Size, nMedBlkIdx>>pAreaInfo->nLog2MediumBlkPerLargeBlk);
}
static inline WFSFileLargeBlkPtr *WFSKrnGetFileLargeBlkPtrFromIndirectBlkForCategoryVeryLarge(u8 *pBlkPtr, u32 nLargeBlkIdx){
return (WFSFileLargeBlkPtr *)( (size_t)pBlkPtr + sizeof(WFSMetaDataHdr) + (nLargeBlkIdx * sizeof(WFSFileLargeBlkPtr)) );
}
static inline WFSFileBlkInfo WFSKrnGetFileBlkInfoFromIndirectBlkForCategoryVeryLarge(AreaInfo *pAreaInfo, u8 *pBlkPtr, u32 nMedBlkIdx){
return WFSKrnGetFileBlkInfoForCategoryLarge(pAreaInfo,
WFSKrnGetFileLargeBlkPtrFromIndirectBlkForCategoryVeryLarge(pBlkPtr,
nMedBlkIdx>>pAreaInfo->nLog2MediumBlkPerLargeBlk),
nMedBlkIdx%(1<<pAreaInfo->nLog2MediumBlkPerLargeBlk));
}
static inline WFSFileBlkInfo WFSKrnGetFileBlkInfoFromIndirectBlkForCategoryVeryLargeCast(AreaInfo *pAreaInfo, void *pMetaData, u32 nLog2MetaSize, u32 nMedBlkIdx){
return WFSKrnGetFileBlkInfoFromIndirectBlkForCategoryVeryLarge(pAreaInfo, (u8*)pMetaData, nMedBlkIdx);
}
// Inline Functions for Dir Module
static inline u32 DirLeafGetSubBlkLog2Size(DirSubBlkHdr *pSubBlkHdr) {
return DirLeafGetSubBlkLog2Size_2(pSubBlkHdr->nStrLen, pSubBlkHdr->nNumEntries);
}
static inline u32 DirNodeGetSubBlkLog2Size(DirSubBlkHdr *pSubBlkHdr) {
return DirNodeGetSubBlkLog2Size_3(pSubBlkHdr->nStrLen, pSubBlkHdr->nNumEntries, pSubBlkHdr->aFirstChar[pSubBlkHdr->nStrLen]);
}
static inline u16* DirNodeGetOfsTblStartPtr_ote(DirSubBlkHdr *pSubBlkHdr, u16 *pOfsTblEnd) {
if (pSubBlkHdr->aFirstChar[pSubBlkHdr->nStrLen] == 0) {
return &pOfsTblEnd[-(s32)pSubBlkHdr->nNumEntries-1];
} else {
return &pOfsTblEnd[-(s32)pSubBlkHdr->nNumEntries];
}
}
static inline u16* DirNodeGetOfsTblStartPtr_l2s(DirSubBlkHdr *pSubBlkHdr, u32 nLog2Size) {
u16 *pOfsTblEnd = (u16*)((u8*)pSubBlkHdr + (1<<nLog2Size));
return DirNodeGetOfsTblStartPtr_ote(pSubBlkHdr, pOfsTblEnd);
}
static inline u16* DirNodeGetOfsTblStartPtr(DirSubBlkHdr *pSubBlkHdr) {
u32 nLog2Size = DirNodeGetSubBlkLog2Size(pSubBlkHdr);
return DirNodeGetOfsTblStartPtr_l2s(pSubBlkHdr, nLog2Size);
}
static inline u16* DirNodeGetIntraBlkOfsPtr_ote(s32 nIdx, DirSubBlkHdr *pSubBlkHdr, u16 *pOfsTblEnd) {
#if DIR_SPLIT_BLK_ADR
return &pOfsTblEnd[-nIdx];
#else
if (pSubBlkHdr->aFirstChar[pSubBlkHdr->nStrLen] == 0) {
return &pOfsTblEnd[-nIdx-1];
} else {
return &pOfsTblEnd[-nIdx];
}
#endif
}
static inline u16* DirNodeGetIntraBlkOfsPtr_l2s(s32 nIdx, DirSubBlkHdr *pSubBlkHdr, u32 nLog2Size) {
u16 *pOfsTblEnd = (u16*)((u8*)pSubBlkHdr + (1<<nLog2Size));
return DirNodeGetIntraBlkOfsPtr_ote(nIdx, pSubBlkHdr, pOfsTblEnd);
}
static inline u16* DirNodeGetIntraBlkOfsPtr(s32 nIdx, DirSubBlkHdr *pSubBlkHdr) {
u32 nLog2Size = DirNodeGetSubBlkLog2Size(pSubBlkHdr);
return DirNodeGetIntraBlkOfsPtr_l2s(nIdx, pSubBlkHdr, nLog2Size);
}
static inline u16 DirNodeGetIntraBlkOfs_ote(s32 nIdx, DirSubBlkHdr *pSubBlkHdr, u16 *pOfsTblEnd) {
return *DirNodeGetIntraBlkOfsPtr_ote(nIdx, pSubBlkHdr, pOfsTblEnd);
}
static inline u16 DirNodeGetIntraBlkOfs_l2s(s32 nIdx, DirSubBlkHdr *pSubBlkHdr, u32 nLog2Size) {
return *DirNodeGetIntraBlkOfsPtr_l2s(nIdx, pSubBlkHdr, nLog2Size);
}
static inline u16 DirNodeGetIntraBlkOfs(s32 nIdx, DirSubBlkHdr *pSubBlkHdr) {
return *DirNodeGetIntraBlkOfsPtr(nIdx, pSubBlkHdr);
}
static inline void DirNodeSetIntraBlkOfs_ote(s32 nIdx, u16 nOfs, DirSubBlkHdr *pSubBlkHdr, u16 *pOfsTblEnd) {
*DirNodeGetIntraBlkOfsPtr_ote(nIdx, pSubBlkHdr, pOfsTblEnd) = nOfs;
}
static inline void DirNodeSetIntraBlkOfs_l2s(s32 nIdx, u16 nOfs, DirSubBlkHdr *pSubBlkHdr, u32 nLog2Size) {
*DirNodeGetIntraBlkOfsPtr_l2s(nIdx, pSubBlkHdr, nLog2Size) = nOfs;
}
static inline void DirNodeSetIntraBlkOfs(s32 nIdx, u16 nOfs, DirSubBlkHdr *pSubBlkHdr) {
*DirNodeGetIntraBlkOfsPtr(nIdx, pSubBlkHdr) = nOfs;
}
/*inline WFSBlkAdr DirNodeGetBlkAdr_ote(DirSubBlkHdr *pSubBlkHdr, u16 *pOfsTblEnd) {
#if DIR_SPLIT_BLK_ADR
return (WFSBlkAdr)(pOfsTblEnd[-1] + (pOfsTblEnd[-(s32)pSubBlkHdr->nNumEntries-1]<<16));
#else
DirSubBlkHdr *psbh = pSubBlkHdr; // for warning
return ((WFSBlkAdr*)pOfsTblEnd)[-1];
#endif
}*/
#if DIR_SPLIT_BLK_ADR
#define DirNodeGetBlkAdr_ote(pSubBlkHdr, pOfsTblEnd) ((WFSBlkAdr)(pOfsTblEnd[-1] + (pOfsTblEnd[-(s32)pSubBlkHdr->nNumEntries-1]<<16)));
#else
#define DirNodeGetBlkAdr_ote(pSubBlkHdr, pOfsTblEnd) ((WFSBlkAdr*)pOfsTblEnd)[-1];
#endif
static inline WFSBlkAdr DirNodeGetBlkAdr_l2s(DirSubBlkHdr *pSubBlkHdr, u32 nLog2Size) {
u16 *pOfsTblEnd = (u16*)((u8*)pSubBlkHdr + (1<<nLog2Size));
return DirNodeGetBlkAdr_ote(pSubBlkHdr, pOfsTblEnd);
}
static inline WFSBlkAdr DirNodeGetBlkAdr(DirSubBlkHdr *pSubBlkHdr) {
u32 nLog2Size = DirNodeGetSubBlkLog2Size(pSubBlkHdr);
return DirNodeGetBlkAdr_l2s(pSubBlkHdr, nLog2Size);
}
/*static inline void DirNodeSetBlkAdr_ote(WFSBlkAdr nBlkAdr, DirSubBlkHdr *pSubBlkHdr, u16 *pOfsTblEnd) {
#if DIR_SPLIT_BLK_ADR
pOfsTblEnd[-1] = (u16)nBlkAdr;
pOfsTblEnd[-(s32)pSubBlkHdr->nNumEntries-1] = (u16)(nBlkAdr>>16);
#else
DirSubBlkHdr *psbh = pSubBlkHdr; // for warning
((u32*)pOfsTblEnd)[-1] = nBlkAdr;
#endif
}*/
#if DIR_SPLIT_BLK_ADR
#define DirNodeSetBlkAdr_ote(nBlkAdr, pSubBlkHdr, pOfsTblEnd) { pOfsTblEnd[-1] = (u16)nBlkAdr; pOfsTblEnd[-(s32)pSubBlkHdr->nNumEntries-1] = (u16)(nBlkAdr>>16); }
#else
#define DirNodeSetBlkAdr_ote(nBlkAdr, pSubBlkHdr, pOfsTblEnd) ((u32*)pOfsTblEnd)[-1] = nBlkAdr;
#endif
static inline void DirNodeSetBlkAdr_l2s(WFSBlkAdr nBlkAdr, DirSubBlkHdr *pSubBlkHdr, u32 nLog2Size) {
u16 *pOfsTblEnd = (u16*)((u8*)pSubBlkHdr + (1<<nLog2Size));
DirNodeSetBlkAdr_ote(nBlkAdr, pSubBlkHdr, pOfsTblEnd);
}
static inline void DirNodeSetBlkAdr(WFSBlkAdr nBlkAdr, DirSubBlkHdr *pSubBlkHdr) {
u32 nLog2Size = DirNodeGetSubBlkLog2Size(pSubBlkHdr);
DirNodeSetBlkAdr_l2s(nBlkAdr, pSubBlkHdr, nLog2Size);
}
static inline u16 *DirLeafGetIntraBlkOfsPtr_ote(s32 nIdx, u16 *pOfsTblEnd) {
return &pOfsTblEnd[-nIdx];
}
static inline u16* DirLeafGetIntraBlkOfsPtr_l2s(s32 nIdx, DirSubBlkHdr *pSubBlkHdr, u32 nLog2Size) {
u16 *pOfsTblEnd = (u16*)((u8*)pSubBlkHdr + (1<<nLog2Size));
return DirLeafGetIntraBlkOfsPtr_ote(nIdx, pOfsTblEnd);
}
static inline u16* DirLeafGetIntraBlkOfsPtr(s32 nIdx, DirSubBlkHdr *pSubBlkHdr) {
u32 nLog2Size = DirLeafGetSubBlkLog2Size(pSubBlkHdr);
return DirLeafGetIntraBlkOfsPtr_l2s(nIdx, pSubBlkHdr, nLog2Size);
}
static inline u16 DirLeafGetIntraBlkOfs_ote(s32 nIdx, u16 *pOfsTblEnd) {
return *DirLeafGetIntraBlkOfsPtr_ote(nIdx, pOfsTblEnd);
}
static inline u16 DirLeafGetIntraBlkOfs_l2s(s32 nIdx, DirSubBlkHdr *pSubBlkHdr, u32 nLog2Size) {
return *DirLeafGetIntraBlkOfsPtr_l2s(nIdx, pSubBlkHdr, nLog2Size);
}
static inline u16 DirLeafGetIntraBlkOfs(s32 nIdx, DirSubBlkHdr *pSubBlkHdr) {
return *DirLeafGetIntraBlkOfsPtr(nIdx, pSubBlkHdr);
}
static inline void DirLeafSetIntraBlkOfs_ote(s32 nIdx, u16 nOfs, u16 *pOfsTblEnd) {
*DirLeafGetIntraBlkOfsPtr_ote(nIdx, pOfsTblEnd) = nOfs;
}
static inline void DirLeafSetIntraBlkOfs_l2s(s32 nIdx, u16 nOfs, DirSubBlkHdr *pSubBlkHdr, u32 nLog2Size) {
*DirLeafGetIntraBlkOfsPtr_l2s(nIdx, pSubBlkHdr, nLog2Size) = nOfs;
}
static inline void DirLeafSetIntraBlkOfs(s32 nIdx, u16 nOfs, DirSubBlkHdr *pSubBlkHdr) {
*DirLeafGetIntraBlkOfsPtr(nIdx, pSubBlkHdr) = nOfs;
}
#endif //define wfskrn_Dir_h

View File

@ -0,0 +1,39 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_DirFind.h - Find functions for the Directory Module
Copyright 2007-2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_DirFind.h,v $
Revision 1.3 2008/05/16 18:54:09 paul
Added DirFindNext()
Revision 1.2 2008/05/10 04:00:48 kondo_masahiro
Merged and fixed code to accept RM compiler
Revision 1.1 2008/04/24 23:21:18 kondo_masahiro
Initial check-in
Revision 1.1 2008/04/23 00:34:38 paul
Split off from wfskrn_Dir.cpp
*---------------------------------------------------------------------------*/
#ifndef wfskrn_DirFind_h
#define wfskrn_DirFind_h
#define DIR_FIND_MODE_NORMAL 0
#define DIR_FIND_MODE_PREFIX_SEARCH 1
#define DIR_FIND_MODE_NODE_SEARCH 2
WFSKrnResult DirFind(WFSFileName *pName, DirItr *pDi, u32 nMaxBlkDepth, u32 nMode);
WFSKrnResult DirFindNext(WFSFileName *pName, DirItr *pDi);
#endif //define wfskrn_DirFind_h

View File

@ -0,0 +1,77 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_DirNodeStack.h - Directory Module
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_DirNodeStack.h,v $
Revision 1.3 2008/10/16 09:25:53 ooizumi
Fixed definitions for debug build.
Revision 1.2 2008/05/10 04:00:48 kondo_masahiro
Merged and fixed code to accept RM compiler
Revision 1.1 2008/04/22 04:39:08 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.3 2008/04/17 17:34:24 paul
Added some more debug functions
Revision 1.2 2008/04/05 03:20:57 paul
_DEBUG -> _DEBUG_DIR
Revision 1.1 2008/02/27 09:48:02 paul
*** empty log message ***
*---------------------------------------------------------------------------*/
#ifndef wfskrn_DirNodeStack_h
#define wfskrn_DirNodeStack_h
#include "wfskrn_Dir.h"
#if _DEBUG_DIR
#define _DEBUG_DIR_NODE_STACK 1 // change to 1 if debug info required
#else
#define _DEBUG_DIR_NODE_STACK 0
#endif
#if _DEBUG
void DebugCheckNumFreeDnsPoolEntries(char *str);
#endif
#if _DEBUG_DIR_NODE_STACK
extern bool bCheckDirNodeStack;
void DirNodeStackCheckFreeList();
WFSKrnResult _DirNodeStackGetEntry (char *sFile, u32 nLine, DirNodeItr *pDni);
WFSKrnResult _DirPushNodeStackEntry(char *sFile, u32 nLine, DirNodeItr *pDni, WFSBlkAdr nBlkAdr);
void _DirNodeStackFree (char *sFile, u32 nLine, DirNodeItr *pDni, DirNodeStack **ppParent);
void _DirPopNodeStackEntry (char *sFile, u32 nLine, DirNodeItr *pDni);
void _DirNodeStackCheckEmpty();
#define DirNodeStackGetEntry(pDni) _DirNodeStackGetEntry (_KRN_FILE_, __LINE__, pDni)
#define DirPushNodeStackEntry(pDni,nBlkAdr) _DirPushNodeStackEntry(_KRN_FILE_, __LINE__, pDni, nBlkAdr)
#define DirNodeStackFree(pDni,ppParent) _DirNodeStackFree (_KRN_FILE_, __LINE__, pDni, ppParent)
#define DirPopNodeStackEntry(pDni) _DirPopNodeStackEntry (_KRN_FILE_, __LINE__, pDni)
#define DirNodeStackCheckEmpty _DirNodeStackCheckEmpty();
#else
WFSKrnResult DirNodeStackGetEntry (DirNodeItr *pDni);
WFSKrnResult DirPushNodeStackEntry(DirNodeItr *pDni, WFSBlkAdr nBlkAdr);
void DirNodeStackFree(DirNodeItr *pDni, DirNodeStack **ppParent);
void DirPopNodeStackEntry(DirNodeItr *pDni);
#define DirNodeStackCheckEmpty
#endif
WFSKrnResult DirAllocateMoreNodeStackEntries();
void DirConstructEntryNameFromNodeStack(WFSFileName *pKey, DirItr *pDi);
#endif //wfskrn_DirNodeStack_h

View File

@ -0,0 +1,145 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_DirRxTree.h - Find functions for the Directory Module
Copyright 2007-2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_DirRxTree.h,v $
Revision 1.4 2008/07/30 21:21:08 paul
Changed the default value of _CHECK_RXT to 0 to improve the speed of the stress test
Revision 1.3 2008/07/21 22:49:55 paul
Added callback to RxtCheck()
Revision 1.2 2008/06/09 18:06:12 paul
Rewrote DirRxTree to support PathCache. New version includes parent pointers in each node.
Revision 1.1 2008/05/10 04:00:23 kondo_masahiro
Initial check-in
*---------------------------------------------------------------------------*/
#ifndef wfskrn_DirRxTree_h
#define wfskrn_DirRxTree_h
#include "wfskrn_Bitfield.h"
#include "wfskrn_Dir.h"
#define RXT_LOG2_RESERVE_SIZE 9
#define RXT_MIN_LOG2_NODE_SIZE 4
#define RXT_MAX_LOG2_SIZE 16
#if _DEBUG
#define _CHECK_RXT 0 // Set to 1 to enable radix tree and path cache check. However, it makes the test program run a lot slower
#else
#define _CHECK_RXT 0
#endif
#pragma pack(1)
typedef struct {
u8 nLog2Size; // The value n such that 2^n is the size of the node
u8 nEntryIdx; // The index of the entry in the parent block which points to this node
u16 nParentOfs; // The offset to the parent of this node
u16 nStrLen; // The length of the prefix string of this node
u8 nNumEntries; // The number of entries in this node
utf8 aFirstChar[1]; // The first character of the variable-size part of the node: format is prefix string followed by choice characters
// The table of u16 offsets to child nodes are stored in reverse order starting from the end of the node
} RxtNodeHdr;
//} _ATTRIBUTE_PACKED RxtNodeHdr;
#pragma pack()
typedef struct {
u16 *pOfs; // A pointer to the offset pointer to the node. This would need to be updated if the sub block is relocated.
RxtNodeHdr *pNodeHdr; // A pointer to the sub block containing the node.
utf8 *pStrPtr; // A string pointer to the current cursor position within the search name. After RxtFind(), it points to the first mismatch.
utf8 *pNodeStrPtr; // A string pointer to the current cursor position within the node string. After RxtFind(), it points to the first mismatch.
s32 nEntryIdx; // The entry index of the choice within the current node which is closest but <= search name after RxtFind().
u32 nDepth; // Current depth of iterator
} RxtItr;
typedef struct {
WFSSubBlkAllocHdr sbah;
u16 nRootOfs;
u16 nReserveOfs; // Offset to a sub-block which can be used to guarantee Delete will always succeed
u16 nNumRecs; // Number of records in the block, not the whole directory
} RxtHdr;
typedef struct {
u8 nLog2Size;
u8 nEntryIdx;
u16 nParentOfs;
} RxtAttrHdr;
WFSBool DirBinarySplitSearchChoices(utf8 *aSortedArray, u32 nNumEntries, utf8 cSearchChar, u32 *pEntryIdx);
void RxtInit (RxtHdr *pRxtHdr, u32 nLog2Size);
WFSKrnResult RxtFind (RxtHdr *pRxtHdr, RxtItr *pRxi, u32 nStrLen);
WFSKrnResult RxtFindNext(RxtHdr *pRxtHdr, RxtItr *pRxi, utf8 cSeparator);
WFSKrnResult RxtInsert (RxtHdr *pRxtHdr, RxtItr *pRxi, u32 nSuffixLen, RxtAttrHdr *pAttrHdr);
WFSKrnResult RxtDeleteNode(RxtHdr *pRxtHdr, RxtItr *pRxi, u32 nEntryIdx, u32 nNodeOfs, RxtNodeHdr *pNodeHdr);
WFSKrnResult RxtDelete (RxtHdr *pRxtHdr, RxtItr *pRxi);
WFSKrnResult RxtNext (RxtHdr *pRxtHdr, RxtItr *pRxi);
WFSKrnResult RxtNextUntilSeparator(RxtHdr *pRxtHdr, RxtItr *pRxi, utf8 cSeparator);
void RxtGetString(RxtHdr *pRxtHdr, RxtNodeHdr *pNodeHdr, utf8 *sStr, u32 nStrLen);
#if _CHECK_RXT
typedef void (*RxtCheckEntry)(u32 nRecIdx, u32 nDepth, utf8 *sPath, void *pPtr);
void RxtCheck(RxtHdr *pRxtHdr, u32 nTotalSize, RxtCheckEntry cbCheckEntry);
#endif
void RxtTest();
// Inline Function Definitions
static inline u32 RxtGetNodeLog2Size_2(u32 nStrLen, u32 nNumEntries) {
//u32 nNumBytesRequired = (u32)&((RxtNodeHdr*)0)->aFirstChar + nStrLen + (nNumEntries*3);
u32 nNumBytesRequired = sizeof(RxtNodeHdr)-1 + nStrLen + (nNumEntries*3);
u32 nLog2Size = WfsCalculateFieldSizeInBits(nNumBytesRequired-1);
if (nLog2Size < SBA_MIN_LOG2_SUB_BLK_SIZE) {
nLog2Size = SBA_MIN_LOG2_SUB_BLK_SIZE;
}
return nLog2Size;
}
static inline u32 RxtGetNodeLog2Size(RxtNodeHdr *pNodeHdr) {
return RxtGetNodeLog2Size_2(pNodeHdr->nStrLen, pNodeHdr->nNumEntries);
}
static inline u16 *RxtGetChildOfsPtr_ote(s32 nIdx, u16 *pOfsTblEnd) {
return &pOfsTblEnd[-nIdx];
}
static inline u16* RxtGetChildOfsPtr(s32 nIdx, RxtNodeHdr *pNodeHdr) {
u16 *pOfsTblEnd = (u16*)((u8*)pNodeHdr + (1<<pNodeHdr->nLog2Size));
return RxtGetChildOfsPtr_ote(nIdx, pOfsTblEnd);
}
static inline u16 RxtGetChildOfs_ote(s32 nIdx, u16 *pOfsTblEnd) {
return *RxtGetChildOfsPtr_ote(nIdx, pOfsTblEnd);
}
static inline u16 RxtGetChildOfs(s32 nIdx, RxtNodeHdr *pNodeHdr) {
return *RxtGetChildOfsPtr(nIdx, pNodeHdr);
}
static inline void RxtSetChildOfs_ote(s32 nIdx, u16 nOfs, u16 *pOfsTblEnd) {
*RxtGetChildOfsPtr_ote(nIdx, pOfsTblEnd) = nOfs;
}
static inline void RxtSetChildOfs(s32 nIdx, u16 nOfs, RxtNodeHdr *pNodeHdr) {
*RxtGetChildOfsPtr(nIdx, pNodeHdr) = nOfs;
}
#endif //define wfskrn_DirRxTree_h

View File

@ -0,0 +1,71 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_EPTree.h
Copyright 2007-2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_EPTree.h,v $
Revision 1.4 2008/12/17 05:08:17 ueno
Cleanup.
Revision 1.3 2008/12/15 02:40:27 ueno
Added support for multi p-tree.
Revision 1.1 2008/12/02 04:55:39 ueno
Added EPTree to support multi-PTree.
*---------------------------------------------------------------------------*/
#ifndef __WFSKRN_EPTREE_H__
#define __WFSKRN_EPTREE_H__
#include "wfskrn_Area.h"
#include "wfskrn_FTree.h"
#define EPTREEHDR_OFFSET (BLOCK_SIZE - sizeof(EPTreeHdr))
#define GET_EPTREEHDR(pBlock) ((EPTreeHdr*) ((u8*) (pBlock) + EPTREEHDR_OFFSET))
#define GET_BLOCK_FROM_EPTREEHDR(eptreeHdr) ((u8*) (eptreeHdr) - EPTREEHDR_OFFSET)
#define EPTREE_GET_KEY(epti) ((epti)->nKey)
#define EPTREE_GET_DATA(epti) ((epti)->nData)
typedef struct
{
PTreeHdr ptreeHdr; // 8 bytes.
WFSBlkAdr addr;
u8 height; // height = 1, 2 ...
u8 padding[11];
SubBlockAllocatorHeader sbaHdr; // 8 bytes.
} EPTreeHdr; // sizeof(EPTreeHdr) must be 32 bytes. ( == sizeof(FTreeBlock));
typedef PTreeItr EPTreeItr;
#define EPTREE_MAX_HEIGHT 2
typedef struct
{
EPTreeHdr* eptreeHdr[EPTREE_MAX_HEIGHT]; // inherited FBATreeItr
EPTreeItr epti[EPTREE_MAX_HEIGHT]; // inherited FBATreeItr.
} MEPTreeItr;
EPTreeHdr* EPTreeBlockInit(AreaInfo* area, void* block, WFSBlkAdr addr, u32 offset, u8 height);
EPTreeItr* EPTreeGetLastIter(MEPTreeItr* iter);
WFSKrnResult EPTreeFind(AreaInfo* area, MEPTreeItr* iter, u32 nKey);
WFSKrnResult EPTreePrev(AreaInfo* area, MEPTreeItr* iter);
WFSKrnResult EPTreeNext(AreaInfo* area, MEPTreeItr* iter);
WFSKrnResult EPTreeFirst(AreaInfo* area, MEPTreeItr* iter);
WFSKrnResult EPTreeLast(AreaInfo* area, MEPTreeItr* iter);
WFSKrnResult EPTreeInsert(AreaInfo* area, MEPTreeItr* iter, u32 key, u32 data); // [check] can remove area?
WFSKrnResult EPTreeDelete(AreaInfo* area, MEPTreeItr* iter, u32 key, WFSBlkAdr* freeBlks);
WFSKrnResult EPTreeInit(AreaInfo* area, u32 offset);
#endif // __WFSKRN_EPTREE_H__

View File

@ -0,0 +1,309 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_Errors_h
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Errors.h,v $
Revision 1.19 2008/12/15 02:40:27 ueno
Added support for multi p-tree.
Revision 1.18 2008/11/07 08:54:35 kondo_masahiro
Added WFSKrnExit4/5OnError()
Revision 1.17 2008/10/30 05:08:19 kondo_masahiro
Added error for DirCheckDisk
Revision 1.16 2008/09/28 23:30:40 kondo_masahiro
Fixed codes to use medium size user block.
Revision 1.15 2008/08/27 10:03:58 paul
added WFSKRN_RESULT_BLK_CACHE_ALLOC_FAILED
Revision 1.14 2008/08/05 04:17:52 kondo_masahiro
Added error handling for hash error and detach device.
Revision 1.13 2008/07/17 22:25:49 paul
Added WFSKRN_RESULT_DIR_ITR_INVALID
Fixed value for WFSKRN_RESULT_FILE_OPEN
Revision 1.12 2008/07/17 05:11:44 kondo_masahiro
Added WFSKRN_RESULT_DEVICE_HASH_INCONSISTENT
Revision 1.11 2008/07/17 04:18:24 ueno
Added errors for freeblock allocator.
Revision 1.10 2008/07/11 18:05:17 paul
Updated to match latest wfsError.h
Revision 1.9 2008/07/09 01:35:43 paul
Changed some result code names, and added new result codes for PTree.
Revision 1.8 2008/06/10 20:13:04 kondo_masahiro
Added WFSKrnCommandCountBreak.
Revision 1.7 2008/06/09 18:05:48 paul
Added support for logging calls to WFSSrv functions.
Added new result codes.
Revision 1.6 2008/06/05 08:09:18 ueno
Revised permission APIs.
Revision 1.5 2008/05/28 01:06:13 ueno
Added error codes for AclCheckDisk().
Revision 1.4 2008/05/12 19:21:31 paul
Added an error code.
Revision 1.3 2008/05/10 04:00:48 kondo_masahiro
Merged and fixed code to accept RM compiler
Revision 1.2 2008/04/25 12:07:44 nakanose_jin
add new errors
Revision 1.13 2008/04/26 01:13:53 wayne.wong
Moved area allocation functionality from Volume to Area module.
Changed error codes appropriately.
Revision 1.12 2008/04/25 04:35:29 nakanose_jin
add new errors
Revision 1.11 2008/04/22 23:01:43 paul
Added WFSKRN_RESULT_DEV_IN_USE to match wfsError.h. Added WFSKrnExitOnError
Revision 1.10 2008/04/18 01:42:46 wayne.wong
Added some area-specific error codes.
Revision 1.9 2008/04/15 07:40:11 ueno
Added error codes to WFSKrnResult for accesslist.
Revision 1.8 2008/03/19 07:35:48 wayne.wong
Added and fixed error codes.
Revision 1.7 2008/03/11 03:09:34 wayne.wong
Added some more BCache and Volume errors.
Revision 1.6 2008/02/28 06:32:36 kondo_masahiro
Fixed code to accept PPC compiler
Revision 1.5 2008/02/27 00:46:26 paul
Differentiated names of error functions
Revision 1.4 2008/02/21 22:25:26 wayne.wong
Added errors for the modules BCache, PMem, Volume, and Transaction.
Revision 1.3 2008/02/21 01:37:43 paul
split into wfskrn_Errors.h and wfskrn_Errors.cpp
Revision 1.2 2008/02/20 07:47:52 paul
Updated error codes and added WFSKrnOutputError macro to output error code as a string
Revision 1.1 2007/12/27 11:35:52 paul
internal error definitions
*---------------------------------------------------------------------------*/
#ifndef wfskrn_Errors_h
#define wfskrn_Errors_h
#define WFSKrnReturnOnError(x) { WFSKrnResult nResult = x; if (nResult < WFSKRN_RESULT_OK) return nResult; }
#define WFSKrnExitOnError(x) { nResult = x; if (nResult < WFSKRN_RESULT_OK) goto Exit; }
#define WFSKrnExit1OnError(x) { nResult = x; if (nResult < WFSKRN_RESULT_OK) goto Exit1; }
#define WFSKrnExit2OnError(x) { nResult = x; if (nResult < WFSKRN_RESULT_OK) goto Exit2; }
#define WFSKrnExit3OnError(x) { nResult = x; if (nResult < WFSKRN_RESULT_OK) goto Exit3; }
#define WFSKrnExit4OnError(x) { nResult = x; if (nResult < WFSKRN_RESULT_OK) goto Exit4; }
#define WFSKrnExit5OnError(x) { nResult = x; if (nResult < WFSKRN_RESULT_OK) goto Exit5; }
#define WFSKrnReturnOnNullParameter(p) { if (p == NULL) return WFSKRN_RESULT_INVALID; }
typedef enum {
WFSKRN_RESULT_OK = 0, // Success
// Errors that can usually be detected early, and if detected, would result in the Async callback not being called:
WFSKRN_RESULT_BUSY = -1, // Too many requests, try waiting then calling again.
WFSKRN_RESULT_OUT_OF_MEMORY = -2, // The library does not have enough memory to complete the requested operation. (May be due to too many outstanding aysnc calls).
WFSKRN_RESULT_INVALID = -3, // The function parameters were invalid, e.g. File name is too long, Path is too long or too deep.
WFSKRN_RESULT_ACCESS = -4, // Trying to write to a file which was opened for read-only access, or vice versa.
WFSKRN_RESULT_LIB_NOT_INITIALIZED = -5, // The WFS library has not been initialized. Please call WFSInit() (This error is checked in functions that require the library to be initialized, but only in the debug versions).
WFSKRN_RESULT_LIB_ALREADY_INITIALIZED = -6, // The WFS library has already been initialized.
WFSKRN_RESULT_FILE_TOO_BIG = -7, // The current write/append request would push the file over the size limit.
WFSKRN_RESULT_NO_CHANGE_SIZE = -8, // The requested operation would cause the file size to change, but this file has WFS_PERM_NO_CHANGE_SIZE flag set.
// Errors that cannot usually be detected early, and would be passed via nResult to the Async callbacks:
WFSKRN_RESULT_MEDIA_ERROR = -9, // The device or media is not attached, or was removed before the requested operation could be completed.
WFSKRN_RESULT_DEV_UNUSABLE = -10, // Attached device is not accessible, e.g. because it is an unsupported device, or has an unknown format.
WFSKRN_RESULT_DEV_NOT_INITIALIZED = -11, // Device not formatted, or does not yet contain a WFS volume
WFSKRN_RESULT_DEV_IN_USE = -12, // Trying to initialize a device which is in use (mounted) by one or more clients.
WFSKRN_RESULT_VOL_ID_ERROR = -13, // Attempted to mount a volume with the same unique Id as an already mounted volume (This could happen if the User backs up an entire WFS volume using a PC)
WFSKRN_RESULT_WRITE_PROTECTED = -14, // Device is physically write protected (e.g. USB Flash memory, SD Card)
WFSKRN_RESULT_ALREADY_MOUNTED = -15, // The device is already mounted
WFSKRN_RESULT_PERMISSION = -16, // Permission flags do not permit the requested access from this application.
WFSKRN_RESULT_PERMISSION_CL = -17, // Permission error caused by control level problems.
WFSKRN_RESULT_ACL_FULL = -18, // The access list is full.
WFSKRN_RESULT_ACL_ENTRY_NOT_FOUND = -19, // The specified entry does not exist in the access list.
WFSKRN_RESULT_AUTHENTICATION = -20, // Trying to access content on a different Wii, which does not have the required access rights.
WFSKRN_RESULT_CORRUPTION = -21, // A corrupted block was encountered which prevented the operation from being completed.
WFSKRN_RESULT_DIRECTORY_QUOTA = -22, // One of the ancestor directories would exceed its quota.
WFSKRN_RESULT_MAX_HANDLES = -23, // The maximum number of concurrent file handles / search handles are already in use.
WFSKRN_RESULT_ALREADY_EXISTS = -24, // The file or directory being created already exists.
WFSKRN_RESULT_NOT_FOUND = -25, // The specified file or directory or device does not exist.
WFSKRN_RESULT_NOT_EMPTY = -26, // The specified directory cannot be deleted because it is not empty.
WFSKRN_RESULT_NOT_FILE = -27, // The specified path is directory instead of a file.
WFSKRN_RESULT_NOT_DIRECTORY = -28, // The specified path is a file instead of a directory
WFSKRN_RESULT_FILE_OPEN = -29, // The file is open. Cannot delete, move, rename, change permissions of an open file. Cannot open a file more than once unless all opens are WFS_ACCESS_READ.
WFSKRN_RESULT_LOCKED = -30, // Cannot perform the requested operation since the file or directory is locked by an existing operation.
WFSKRN_RESULT_RESOURCE_LIMIT_EXCEEDED = -31, // A resource limit prevents this function call. Try smaller values.
// Directory find results - these can be errors or expected depending on whether we are trying to access an existing file or trying to create a new one:
WFSKRN_RESULT_DIR_ENTRY_FOUND = -40, // The search string was matched and pointed to an entry
WFSKRN_RESULT_DIR_NODE_STRING_PREFIX = -41, // The search string ended early during comparison with a node sub string. (So this name is a prefix of existing names)
WFSKRN_RESULT_DIR_CHOICE_PREFIX = -42, // The search string ended at the end of a node sub string, but the node did not have a termination choice. (This name is a prefix of existing names)
WFSKRN_RESULT_DIR_NODE_STRING_MISMATCH = -43, // A mismatch was encountered while comparing the search string to a sub node prefix string.
WFSKRN_RESULT_DIR_NODE_CHOICE_NOT_FOUND = -44, // A mismatch was encountered while comparing a character of the search string with a set of choices for that character.
WFSKRN_RESULT_DIR_BLK_FULL = -45, // Unable to insert the specified string to the radix tree, due to lack of space in the block.
WFSKRN_RESULT_DIR_ITR_INVALID = -46, // One or more blocks referenced by the directory iterator and its node stack have been updated since the iterator was last used. DirFind must be called again.
// These result codes are not errors, but normal return values for the path cache functions
WFSKRN_RESULT_SRV_END_OF_PATH = -60, // Last part of path name parsed
WFSKRN_RESULT_SRV_PATH_DEPTH_1 = -61, // Path was of depth 1, such as "/something"
WFSKRN_RESULT_SRV_PATH_DEV = -62, // Path was "/dev"
WFSKRN_RESULT_SRV_PATH_VOL = -63, // Path was "/vol"
WFSKRN_RESULT_SRV_PATH_VOL_ROOT = -64, // Path was a volume root path, such as "/vol/xxxxxxx/"
WFSKRN_RESULT_PTREE_ENTRY_FOUND = -70,
WFSKRN_RESULT_PTREE_ENTRY_NOT_FOUND = -71,
WFSKRN_RESULT_PTREE_FULL = -72,
WFSKRN_RESULT_PTREE_EMPTY = -73,
WFSKRN_RESULT_DEVICE_ERROR = -80,
WFSKRN_RESULT_DEVICE_INVALID_PARAMETER = -81,
WFSKRN_RESULT_DEVICE_NOT_FOUND = -82,
WFSKRN_RESULT_DEVICE_HASH_INCONSISTENT = -83,
WFSKRN_RESULT_BLK_CACHE_ALLOC_FAILED = -90,
WFSKRN_RESULT_BCACHE_ERROR = -300, // unspecified error
WFSKRN_RESULT_BCACHE_RESOURCE_LIMIT = -301, // exhausted resources
WFSKRN_RESULT_BCACHE_INVALID_PARAMETER = -302, // at least one argument is invalid
WFSKRN_RESULT_BCACHE_NO_MEMORY = -303, // could not malloc
WFSKRN_RESULT_BCACHE_NOT_FOUND = -304, // sector is not cached
WFSKRN_RESULT_BCACHE_MAX_DEVICES = -305, // max devices alreay allocated
WFSKRN_RESULT_BCACHE_INVALID_DEVICE = -306, // device not found/open
WFSKRN_RESULT_BCACHE_INVALID_HANDLE = -307, // invalid device handle
WFSKRN_RESULT_BCACHE_INVALID_VOLUME = -308, // invalid volume ID (not mapped)
WFSKRN_RESULT_BCACHE_ALREADY_MAPPED = -309, // vol or devH already mapped
WFSKRN_RESULT_BCACHE_ALLOC = -310, // cannot alloc (no mem, or pmem error)
WFSKRN_RESULT_BCACHE_HASH_BLK_NOT_MAPPED = -311, // hash block isn't mapped on cache
WFSKRN_RESULT_VOLUME_ERROR = -400, // unspecified volume error
WFSKRN_RESULT_VOLUME_INVALID_PARAMETER = -401, // at least one argument is invalid
WFSKRN_RESULT_VOLUME_BCACHE_ALLOC = -402, // cannot allocate a page/block in memory
WFSKRN_RESULT_VOLUME_BCACHE_CONFIG = -403, // block cache not configured correctly
WFSKRN_RESULT_VOLUME_ID = -404, // bad volume ID or not initialized
WFSKRN_RESULT_VOLUME_CORRUPT_MR = -405, // the MR (or its free lists) are corrupted
WFSKRN_RESULT_VOLUME_AREA_ALLOC = -406, // area allocation cannot be satisfied
WFSKRN_RESULT_VOLUME_DEVICE_PARAMETER = -407, // parameters incompatible with device
WFSKRN_RESULT_VOLUME_NOT_MAPPED = -408, // volume is not mapped; invalid volume ID
WFSKRN_RESULT_TRANSACTION_ERROR = -500, // unspecified transaction error
WFSKRN_RESULT_TRANSACTION_INVALID_PARAMETER= -501,
WFSKRN_RESULT_ACL_ERROR = -600, // unspecified error
WFSKRN_RESULT_ACL_INVALID_PARAMETER = -601, // at least one argument is invalid
WFSKRN_RESULT_ACL_MAX_ENTRIES = -602, // max entries alreay in the accesslist.
WFSKRN_RESULT_ACL_BUFFER_TOO_SMALL = -603, // buffer is too small to store an accesslist.
WFSKRN_RESULT_ACL_CACHE = -610, // cannot allocate a cache.
WFSKRN_RESULT_ACL_FILE = -620, // cannot create, modify or delete the accesslist file.
WFSKRN_RESULT_ACL_ACLDIR_INCONSISTENT = -621, // accesslist files and indexlist are inconsistent.
WFSKRN_RESULT_ACL_FILENAME = -630, // cannot convert acl filename <=> acl content.
WFSKRN_RESULT_ACL_NAMEDIR_INCONSISTENT = -631, // access name files and indexlist are inconsistent.
WFSKRN_RESULT_ACL_HANDLE = -640, // cannot allocate an accesslist handle.
WFSKRN_RESULT_AREA_ERROR = -700, // unspecified area error
WFSKRN_RESULT_AREA_INVALID_PARAMETER = -701,
WFSKRN_RESULT_AREA_BCACHE_ALLOC = -702, // cannot allocate a page/block in memory
WFSKRN_RESULT_AREA_CORRUPT_HDR = -703, // the area header is corrupted
WFSKRN_RESULT_AREA_VOLUME_NOT_MAPPED = -704, // volume is not mapped; invalid volume ID
WFSKRN_RESULT_AREA_ALLOC = -705, // area allocation cannot be satisfied
WFSKRN_RESULT_FTREE_RETRY = -801, // retry insert.
WFSKRN_RESULT_FTREE_SPLIT = -802, // cannot split tree.
WFSKRN_RESULT_FTREE_EMPTY = -803, // no entry in the F-tree.
WFSKRN_RESULT_CHECKDISK_INCONSISTENT = -901, // bit arrays does not consistent between free block allocator and dir module.
WFSKRN_RESULT_CHECKDISK_INTERNAL_ERROR = -902, // bit arrays can not construct.
WFSKRN_RESULT_NOT_IMPLEMENTED = -1026, // The requested function has not yet been implemented //ToDo: This error should be removed from the final API
WFSKRN_RESULT_UNKNOWN = -1027, // Unexpected error - could be caused by a bug in the file system.
WFSKRN_RESULT_FATAL_ERROR = -1028 // May be caused by critical metadata corruption.
} WFSKrnResult;
#define WFSSetLastError(nErr) (wkg.nLastErr = (nErr))
const char *WFSKrnGetErrorString( WFSKrnResult nResult );
WFSKrnResult WFSKrnOutputErrorCode(WFSKrnResult nResult);
WFSKrnResult WFSKrnOutputErrorStr(const char *pStr);
void WFSKrnCommandCountBreak();
#if _DEBUG
#define DBG_OUTPUT_TO_LOG_FILE 0
#define DBG_OUTPUT_TO_SCREEN 0
#define DBG_OUTPUT_PREFIX "%5d. "
extern u32 nDbgCommandCount;
extern u32 nDbgCommandOutputStart;
extern u32 nDbgCommandOutputEnd;
extern u32 nDbgCommandCountBreak;
#define WFSKrnDbgOutputTest(x) if ((nDbgCommandCount>=nDbgCommandOutputStart)&&(nDbgCommandCount<nDbgCommandOutputEnd)) { x; WFSKrnCommandCountBreak(); }
#else
#define WFSKrnDbgOutputTest(x)
#endif //_DEBUG
#if (DBG_OUTPUT_TO_LOG_FILE && _WIN32)
extern FILE *fpLog;
#define WFSKrnDbgOutputInit(fileName) fpLog = fopen(fileName, "w");
#define WFSKrnDbgOutputClose() fclose(fpLog);
#if DBG_OUTPUT_TO_SCREEN
#define WFSKrnDbgOutputCmdNum { fprintf(fpLog, DBG_OUTPUT_PREFIX"WFSSrv", nDbgCommandCount); MyOSReport(DBG_OUTPUT_PREFIX, nDbgCommandCount); }
#define WFSKrnDbgOutput1(fmt) { fprintf(fpLog, fmt); MyOSReport(fmt); }
#define WFSKrnDbgOutput2(fmt,a) { fprintf(fpLog, fmt, a); MyOSReport(fmt, a); }
#define WFSKrnDbgOutput3(fmt,a,b) { fprintf(fpLog, fmt, a,b); MyOSReport(fmt, a,b); }
#define WFSKrnDbgOutput4(fmt,a,b,c) { fprintf(fpLog, fmt, a,b,c); MyOSReport(fmt, a,b,c); }
#define WFSKrnDbgOutput5(fmt,a,b,c,d) { fprintf(fpLog, fmt, a,b,c,d); MyOSReport(fmt, a,b,c,d); }
#else //DBG_OUTPUT_TO_SCREEN
#define WFSKrnDbgOutputCmdNum fprintf(fpLog, DBG_OUTPUT_PREFIX"WFSSrv", nDbgCommandCount)
#define WFSKrnDbgOutput1(fmt) fprintf(fpLog, fmt);
#define WFSKrnDbgOutput2(fmt,a) fprintf(fpLog, fmt, a);
#define WFSKrnDbgOutput3(fmt,a,b) fprintf(fpLog, fmt, a,b);
#define WFSKrnDbgOutput4(fmt,a,b,c) fprintf(fpLog, fmt, a,b,c);
#define WFSKrnDbgOutput5(fmt,a,b,c,d) fprintf(fpLog, fmt, a,b,c,d);
#endif //DBG_OUTPUT_TO_SCREEN
#else //(DBG_OUTPUT_TO_LOG_FILE && _WIN32)
#define WFSKrnDbgOutputInit(fileName)
#define WFSKrnDbgOutputClose()
#if DBG_OUTPUT_TO_SCREEN
#define WFSKrnDbgOutputCmdNum MyOSReport(DBG_OUTPUT_PREFIX, nDbgCommandCount)
#define WFSKrnDbgOutput1(fmt) MyOSReport(fmt);
#define WFSKrnDbgOutput2(fmt,a) MyOSReport(fmt, a);
#define WFSKrnDbgOutput3(fmt,a,b) MyOSReport(fmt, a,b);
#define WFSKrnDbgOutput4(fmt,a,b,c) MyOSReport(fmt, a,b,c);
#define WFSKrnDbgOutput5(fmt,a,b,c,d) MyOSReport(fmt, a,b,c,d);
#else //DBG_OUTPUT_TO_SCREEN
#define WFSKrnDbgOutputCmdNum
#define WFSKrnDbgOutput1(fmt)
#define WFSKrnDbgOutput2(fmt,a)
#define WFSKrnDbgOutput3(fmt,a,b)
#define WFSKrnDbgOutput4(fmt,a,b,c)
#define WFSKrnDbgOutput5(fmt,a,b,c,d)
#endif //DBG_OUTPUT_TO_SCREEN
#endif //(DBG_OUTPUT_TO_LOG_FILE && _WIN32)
#endif //wfskrn_Errors_h

View File

@ -0,0 +1,285 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_FTree.h
Copyright 2007-2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_FTree.h,v $
Revision 1.15 2008/12/18 05:09:43 ueno
Added "extern" for VC++.
Revision 1.14 2008/12/18 00:31:45 ueno
Moved FTreeBlkLog2Ofs{} for IOP.
Revision 1.13 2008/12/17 05:08:17 ueno
Cleanup.
Revision 1.12 2008/12/02 00:32:23 ueno
Started implementing EPTree.
Revision 1.11 2008/10/30 04:33:12 ueno
Modified for release build.
Revision 1.10 2008/10/17 08:51:27 kondo_masahiro
Added the new MEDIUM size category (40KB-320KB)
Revision 1.9 2008/10/14 11:25:13 ueno
Disabled runtime check.
Revision 1.8 2008/09/29 10:19:25 ueno
Revised to support multi-B-tree-based allocator.
Revision 1.7 2008/09/02 07:01:05 kondo_masahiro
Fixed VerifyMemoryBlock -> VerifyMemoryBlockFTree
Revision 1.6 2008/08/09 03:34:29 ueno
Disabled runtime check.
Revision 1.5 2008/08/09 02:02:02 ueno
Cleanup.
Revision 1.4 2008/08/08 13:27:22 ueno
Fixed BLOCK_SIZE.
Revision 1.3 2008/08/07 10:46:50 ueno
Modified for BTREE_BASED_ALLOCATOR (now debugging).
Revision 1.2 2008/08/02 11:52:10 ueno
Revised the positions of FTreeHdr{} and FBAPTreeHdr{} in 8KB-blocks to protect hash code.
Revision 1.1 2008/08/01 06:57:39 ueno
Initial Check-in.
*---------------------------------------------------------------------------*/
#ifndef __WFSKRN_FTREE_H__
#define __WFSKRN_FTREE_H__
#include "wfskrn_Area.h"
#if BTREE_BASED_ALLOCATOR
#define MAX_SUB_TREE 7
#include "wfskrn_Defs.h"
#include "wfskrn_Api.h"
#include "wfskrn_Area.h"
#include "wfskrn_Errors.h"
#include "wfskrn_PTree.h"
#define FTREE_LEAF_FAN_OUT 7
#define FTREE_LEAF_APPROPRIATE_NUM 5 // 70% of FTREE_LEAF_FAN_OUT
#define FTREE_NODE_APPROPRIATE_NUM 4 // 70% of PTREE_NODE_FAN_OUT
enum // treeType
{
FTREE_TYPE_A = 0,
FTREE_TYPE_B,
FTREE_TYPE_C,
FTREE_TYPE_D,
FTREE_TYPE_E,
FTREE_TYPE_F,
FTREE_TYPE_G,
FTREE_TYPE_END // this is not used.
};
#define GET_SUBTREE(header, treeType) (&(header)->tree[(treeType)])
#define GET_SUBTREE_TYPE(header, fti) ((fti)->subTree - &(header)->tree[0])
typedef PTreeNode FTreeNode;
/*
[check] should save the number of data.
4 bits * 7 (remainder 4 bits)
<----------------------------------->
+---+---+---+---+---+---+---+---+---+
| x | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+---+---+---+---+---+---+---+---+---+
*/
typedef struct
{
u32 aKey[FTREE_LEAF_FAN_OUT];
u32 data; // 4 bits * 7 (remainder 4 bits)
} FTreeLeaf;
#define LEAF_GET_LEN(leaf, index) ((((leaf)->data) >> (4 * (index))) & 0x0f)
#define FTREE_SBA_OFFSET 24
/*
an 8kb-block.
+-------------------------+ A
| | |
| hash code, areaInfo, | | offset
| volumeInfo, etc... | |
| | |
+-------------------------+ V
| | A
| | |
| | |
| | |
| | |
| | |
| | |
| Sub-blocks | |
| | | size
| | |
| | |
| | |
| | |
| | |
| | V
+-------------------------+ A
| | |
+-------------------------+ | FTreeHdr (footer?)
| SubBlockAllocatorHeader | |
+-------------------------+ V
*/
typedef struct _SubBlockAllocatorHeader
{
u16 freeBlock; // start address of free blocks.
u16 numBlock; // the number of blocks in this 8kB block.
u16 offset;
u16 size;
} SubBlockAllocatorHeader;
typedef struct
{
PTreeHdr tree[MAX_SUB_TREE]; // 8 bytes * 7
SubBlockAllocatorHeader sbaHdr; // 8 bytes
} FTreeHdr; // sizeof(FTreeHdr) == sizeof(FTreeBlock) * NUM_HEADER_BLOCK.
typedef struct
{
u32 prev;
u32 next;
u16 num;
} FTreeFreeBlock;
typedef struct
{
u32 prev;
u32 next;
u16 num;
u8 padding[22]; // sizeof(FTreeBlock) must be 32.
} FTreeBlock;
typedef struct
{
PTreeItr ptree; // inherit PTreeItr.
FTreeLeaf* pLeaf;
PTreeHdr* subTree;
WFSBlkAdr splitKey; // [ToDo] should separete FTreeItr.
WFSBlkAdr newChild; // [ToDo] should separete FTreeItr.
WFSBlkAdr newChildSubTreeType; // [ToDo] should separete FTreeItr.
} FTreeItr;
#define FTREE_GET_KEY(pFti) ((pFti)->ptree.nKey)
#define FTREE_GET_DATA(pFti) ((pFti)->ptree.nData)
#define PTREE_GET_KEY(pPti) ((pPti)->nKey)
#define PTREE_GET_DATA(pPti) ((pPti)->nData)
#define FTREE_MASK_LENGTH 0x07FF
#define FTREE_FLAG_BTREE 0x8000
#define FTREE_BLOCK_SIZE (32)
#define BLOCK_SIZE (1<<WFS_LOG2_SMALL_BLK_SIZE) // [check] should use area->nBlkSize as a block size.
#define FTREE_LOG2_OFS_A 0
#define FTREE_LOG2_OFS_B 3
#define FTREE_LOG2_OFS_C 6
#define FTREE_LOG2_OFS_D 10
#define FTREE_LOG2_OFS_E 14
#define FTREE_LOG2_OFS_F 18
#define FTREE_LOG2_OFS_G 22
#define FTREE_LOG2_OFS_END 26
extern const u32 FTreeBlkLog2Ofs[MAX_SUB_TREE+1];
#define SBAHDR_OFFSET (BLOCK_SIZE - sizeof(SubBlockAllocatorHeader))
#define GET_SBAHDR(pBlock) ((SubBlockAllocatorHeader*) ((u8*) pBlock + SBAHDR_OFFSET))
#define SET_FREEBLOCK(sbaHdr, pBlock) (sbaHdr->freeBlock = ((FTreeBlock*) (pBlock) - CACHE(sbaHdr)))
#define FREEBLOCK_NUMBER(sbaHdr) (sbaHdr->freeBlock)
#define CACHE(sbaHdr) ((FTreeBlock*) ((u8*) (sbaHdr) - (SBAHDR_OFFSET - (sbaHdr)->offset)))
#define END_OF_CACHE(sbaHdr) ((FTreeBlock*) ((u8*) CACHE(sbaHdr) + (sbaHdr)->size))
#define GET_FREEBLOCK(sbaHdr) (CACHE(sbaHdr) + (sbaHdr)->freeBlock)
#define MAX_FREEBLOCK(sbaHdr) ((sbaHdr)->size / sizeof(FTreeBlock))
#define GET_BLOCK_HEAD(treeHdr /* EPTreeHdr or FTreeHdr */) ((FTreeBlock*) ((u8*) &((treeHdr)->sbaHdr) - SBAHDR_OFFSET))
#define FTREEHDR_OFFSET (BLOCK_SIZE - sizeof(FTreeHdr))
#define GET_FTREEHDR(pBlock) ((FTreeHdr*) ((u8*) (pBlock) + FTREEHDR_OFFSET))
#define GET_SUBBLOCK(ftreeHdr, offset) ((FTreeBlock*) ((u8*) GET_BLOCK_HEAD(ftreeHdr) + (offset)))
#ifdef _DEBUG
// #define FTREE_RUNTIME_CHECK // for debug.
#endif // _DEBUG
#ifdef FTREE_RUNTIME_CHECK
#define WFSKRN_FTREE_RUNTIME_CHECK(x) { \
if (FBADebugVerbose) \
{ \
WFSKRN_FTREE_ASSERT(x); \
} \
}
#else
#define WFSKRN_FTREE_RUNTIME_CHECK(x)
#endif
#ifdef _DEBUG
#ifdef WIN32
#define WFSKRN_FTREE_ASSERT(x) assert(x)
#else // Win32
#define WFSKRN_FTREE_ASSERT(x) ASSERT(x)
#endif // WIN32
#else
#define WFSKRN_FTREE_ASSERT(x)
#endif
typedef struct _FTreeExtent
{
u32 start;
u32 len; // the unit is 8kB.
} FTreeExtent;
FTreeHdr* FTreeBlockInit(AreaInfo* area, void* block /* 8kB block */);
WFSKrnResult FTreeFind(FTreeHdr* header, FTreeItr* iter, u32 nKey, WFSBool strictSearch);
WFSKrnResult FTreeInsert(AreaInfo* area, FTreeHdr* header, FTreeItr* iter, u32 nKey, u32 nData);
WFSKrnResult FTreeDelete(FTreeHdr* header, FTreeItr* iter, u32 nKey);
WFSKrnResult FTreeModify(FTreeHdr* header, FTreeItr* iter, u32 originalKey, u32 modKey, u32 modData);
WFSKrnResult FTreeFirst(FTreeHdr* header, FTreeItr* iter);
WFSKrnResult FTreeNext(FTreeHdr* header, FTreeItr* iter);
WFSKrnResult FTreeLast(FTreeHdr* header, FTreeItr* iter);
WFSKrnResult FTreePrev(FTreeHdr* header, FTreeItr* iter);
WFSKrnResult PTreeLast(PTreeHdr *pPTreeHdr, PTreeItr *pPti, PTreeAllocator *pAllocator);
WFSKrnResult PTreePrev(PTreeHdr *pPTreeHdr, PTreeItr *pPti, PTreeAllocator *pAllocator);
PTreeHdr* FTreeSelectSubTree(FTreeHdr* header, WFSBlkAdr unitLen);
u16 FTreeAllocEntry(void *pBase);
WFSKrnResult FTreeAllocEntries(void *pBase, u16 *pNodeOfs, u32 nNumNodes);
void FTreeFreeEntry(void *pBase, u16 nOfs);
FTreeBlock* MemoryBlockAlloc(SubBlockAllocatorHeader* header, int numBlocks);
int MemoryBlockFree(SubBlockAllocatorHeader* header, FTreeBlock* block, u32 numBlocks);
void FTreeSbaInit(AreaInfo* area, void* block, u32 footerSize, u32 offset);
WFSBool VerifyMemoryBlockFTree(SubBlockAllocatorHeader* header); // [check] debug API.
WFSBool FTreeVerifyTree(FTreeHdr* header);
#endif // BTREE_BASED_ALLOCATOR
#endif // __WFSKRN_FTREE_H__

View File

@ -0,0 +1,184 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_FreeBlkAlloc.h
Copyright 2007-2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_FreeBlkAlloc.h,v $
Revision 1.16 2008/12/18 00:32:11 ueno
Removed FBADirtyFtreeBlock().
Revision 1.15 2008/12/17 05:08:17 ueno
Cleanup.
Revision 1.14 2008/12/15 02:40:27 ueno
Added support for multi p-tree.
Revision 1.13 2008/12/02 04:55:39 ueno
Added EPTree to support multi-PTree.
Revision 1.11 2008/11/18 04:57:11 saito_tomoya
Modified SetBit() and added SetBitArray().
Revision 1.10 2008/11/07 03:01:42 ueno
Fixed FTreeExtentInfo{} for IOP.
Revision 1.9 2008/10/14 11:25:13 ueno
Disabled runtime check.
Revision 1.8 2008/09/29 10:19:25 ueno
Revised to support multi-B-tree-based allocator.
Revision 1.7 2008/08/13 04:14:00 ueno
Modified FreeBlkAlloc() to allocate blocks near nRefBlkAdr.
Revision 1.6 2008/08/13 00:14:09 paul
Changed type of nStride from u32 to s32
Revision 1.5 2008/08/09 03:34:29 ueno
Disabled runtime check.
Revision 1.4 2008/08/08 13:27:42 ueno
Added UnpinFTreeBlk().
Revision 1.3 2008/08/07 10:46:50 ueno
Modified for BTREE_BASED_ALLOCATOR (now debugging).
Revision 1.2 2008/08/02 11:52:10 ueno
Revised the positions of FTreeHdr{} and FBAPTreeHdr{} in 8KB-blocks to protect hash code.
Revision 1.1 2008/08/01 06:57:39 ueno
Initial Check-in.
*---------------------------------------------------------------------------*/
#ifndef __WFSKRN_FREEBLKALLOC_H__
#define __WFSKRN_FREEBLKALLOC_H__
#include "wfskrn_Area.h"
#if BTREE_BASED_ALLOCATOR
#include "wfskrn_FreeBlkAlloc_Type.h"
#include "wfskrn_FTree.h"
#include "wfskrn_EPTree.h"
#define FBA_ROOT_BLK 0 // default block for p-tree.
#define FBA_INITIAL_FTREE_BLK 1 // default block for f-tree.
#define GET_FBATREE_HDR(area) (&((area)->ah.freeBlkAllocHdr)) // [check]
#define FBA_SBA_OFFSET (sizeof(AreaHdr) + sizeof(VolumeHdr))
#define FBA_GET_FTREE_BLK(pIter) ((pIter)->epti[(pIter)->height - 1].nData)
typedef struct
{
EPTreeHdr* eptreeHdr[EPTREE_MAX_HEIGHT]; // inherit MEPTreeItr.
EPTreeItr epti[EPTREE_MAX_HEIGHT]; // inherit MEPTreeItr.
FTreeItr fti;
FTreeHdr* ftreeHdr;
WFSBlkAdr ftreeAddr;
WFSBool isInserted;
u8 height;
} FBATreeItr;
typedef struct _ExtentStorageHeader
{
u32 prio; // priority
u32 numPrev;
u32 numNext;
} ExtentStorageHeader;
typedef struct _ExtentStorageEntry
{
WFSBlkAdr start;
WFSBlkAdr len; // block len.
u16 treeType;
u16 nNumBlk;
} ExtentStorageEntry;
typedef struct _FBASingleEntry
{
ExtentStorageHeader header;
ExtentStorageEntry entry;
} FBASingleEntry;
typedef struct _RemainderExtents
{
FTreeExtent head;
FTreeExtent fractionHead;
FTreeExtent tail;
FTreeExtent fractionTail;
} RemainderExtents;
typedef struct _FTreeExtentInfo
{
WFSBlkAdr start;
WFSBlkAdr len; // the unit is 8kB.
FBATreeItr iter;
WFSBool alignment;
} FTreeExtentInfo;
#define FBA_RESULT_KEY(pIter) ((pIter)->fti.ptree.nKey)
#define FBA_RESULT_DATA(pIter) ((pIter)->fti.ptree.nData)
EPTreeHdr* EpTreeBlockInit(AreaInfo* area, void* block, u32 offset);
WFSKrnResult FreeBlkInsert(AreaInfo* area, FBATreeItr* iter, WFSBlkAdr nBlkAdr, WFSBlkAdr nNumBlks);
WFSKrnResult FreeBlkDelete(AreaInfo* area, FBATreeItr* iter, WFSBlkAdr nBlkAdr, WFSBlkAdr nNumBlks, u32 nBlkLog2Size);
WFSKrnResult FreeBlkInit(AreaInfo *pAreaInfo, u32 offset);
WFSKrnResult FreeBlkAlloc(AreaInfo *pAreaInfo, WFSBlkAdr nRefBlkAdr, WFSBlkAdr nNumBlks, WFSBlkAdr *aBlkAdr, s32 nStride, u32 nBlkLog2Size);
WFSKrnResult FreeBlkFree(AreaInfo *pAreaInfo, WFSBlkAdr nNumBlks, WFSBlkAdr *aBlkAdr, s32 nStride, u32 nBlkLog2Size);
WFSKrnResult FreeBlkFirst(AreaInfo* area, FBATreeItr* iter, u32 nSubTreeBlkLog2Size);
WFSKrnResult FreeBlkLast(AreaInfo* area, FBATreeItr* iter, u32 nSubTreeBlkLog2Size);
WFSKrnResult FreeBlkNext(AreaInfo* area, FBATreeItr* iter);
WFSKrnResult FreeBlkPrev(AreaInfo* area, FBATreeItr* iter);
WFSKrnResult FreeBlkFind(AreaInfo* area, FBATreeItr* iter, u32 key, u32 nBlkLog2Size);
WFSKrnResult FreeBlkFindStrict(AreaInfo* area, FBATreeItr* iter, u32 nBlkAdr, u32 nBlkLog2Size);
WFSBlkAdr FreeBlkGetFreeSize(AreaInfo *pAreaInfo);
WFSBool FreeBlkVerify(AreaInfo* area);
WFSKrnResult FreeBlkCheckDisk(AreaInfo* area, WFSSrvFileHandle fh, u8* pBuffer, u32 bufferSize, u32 size);
u32 FreeBlkGetFreeBlkLen(AreaInfo* area, u32 nBlkLog2SizeOfs);
WFSKrnResult FreeBlkDumpFreeblock(AreaInfo* area);
void FBAItrOpen(AreaInfo* area, FBATreeItr* iter);
void FBAItrClose(AreaInfo* area, FBATreeItr* iter);
PTreeHdr* FTreeSelectSubTree(FTreeHdr* header, WFSBlkAdr unitLen);
void FBAUnpinCache(AreaInfo* area, u32 diskAddr);
void FBAUnpinFTreeBlk(AreaInfo* area, FBATreeItr* iter);
void FBAFreeCache(AreaInfo* area, u32 diskAddr);
WFSKrnResult FBAGetCache(AreaInfo* area, u32 diskAddr, u32 flags, void** cache);
#ifdef _DEBUG
// #define FBA_DEBUG_VERBOSE
// #define WFSKRN_FBA_RUNTIME_CHECK
#endif // _DEBUG
#ifdef WFSKRN_FBA_RUNTIME_CHECK
#define FBA_STRICT_ASSERT(x) { \
if (FBADebugVerbose) \
{ \
WFSKRN_FTREE_ASSERT(x); \
} \
}
#else
#define FBA_STRICT_ASSERT(x)
#endif
#endif // BTREE_BASED_ALLOCATOR
#endif // __WFSKRN_FREEBLKALLOC_H__

View File

@ -0,0 +1,71 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_FreeBlkAlloc.h
Copyright 2007-2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_FreeBlkAlloc_Type.h,v $
Revision 1.4 2008/12/02 04:55:39 ueno
Added EPTree to support multi-PTree.
Revision 1.2 2008/08/09 03:34:29 ueno
Disabled runtime check.
Revision 1.1 2008/08/07 10:47:29 ueno
Added for BTREE_BASED_ALLOCATOR (now debugging).
Revision 1.2 2008/08/02 11:52:10 ueno
Revised the positions of FTreeHdr{} and FBAPTreeHdr{} in 8KB-blocks to protect hash code.
Revision 1.1 2008/08/01 06:57:39 ueno
Initial Check-in.
*---------------------------------------------------------------------------*/
#ifndef __WFSKRN_FREEBLKALLOC_TYPE_H__
#define __WFSKRN_FREEBLKALLOC_TYPE_H__
#include "wfskrn_Area.h"
#if BTREE_BASED_ALLOCATOR
#define GET_FBATREE_HDR(area) (&((area)->ah.freeBlkAllocHdr))
#define GET_EPTREEHDR_FROM_AREAINFO(area) ((EPTreeHdr*) ((u8*) ((area)->pAflh) + GET_FBATREE_HDR(area)->ofsEPtreeHdr))
// ~
/*
root disk block in the area.
+-----------------+ <-- pVolInfo - - - - - - - - -A
| | |
+-----------------+ <-- pAreaHdr (pAreaInfo->ah) |
| | |
A +-----------------+ <-- pAreaInfo->pAflh |
| | | A |
| | | | |
| | | | | pAreaInfo->nBlkSize (4kB or 8kB?)
ofsEPtreeHdr | | | | |
| | | | nSizeRemaining |
| | | | |
V +-----------------+ | |
| EPTreeHdr | | |
+-----------------+ V - - - - - - - - - - - - - - V
*/
// FBATreeHdr is stored in a disk.
typedef struct _FBATreeHdr
{
unsigned totalBlks; // freeblocks and metadata blocks in the Freeblock allocator.
unsigned ofsEPtreeHdr; // offset of FBAPTreeHdr from pAreaInfo->pAflh.
unsigned ptreeHeight; // height of ptree blocks. the min is FBA_PTREE_MIN_HEIGHT.
} FBATreeHdr;
#endif // BTREE_BASED_ALLOCATOR
#endif // __WFSKRN_FREEBLKALLOC_TYPE_H__

View File

@ -0,0 +1,136 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_Handles.h - Module for file handles and search directory handles
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Handles.h,v $
Revision 1.6 2008/10/07 06:01:16 ueno
Modified WFSKrnFileInfoAlloc() to set WFSKRN_HANDLE_ALLOCATED in order to indicate the handle is allocated.
Revision 1.5 2008/07/17 22:27:36 paul
Removed nRootBlkAdr from WFSKrnSearchDirInfo. (Now in PathCacheItr)
Revision 1.4 2008/06/09 18:12:18 paul
Made changes to support PathCache. Handles now contain a path cache iterator.
Revision 1.3 2008/05/16 18:53:34 paul
Added nRootBlkAdr to WFSKrnSearchDirInfo
Revision 1.2 2008/05/10 04:00:48 kondo_masahiro
Merged and fixed code to accept RM compiler
Revision 1.1 2008/04/24 23:21:13 kondo_masahiro
Initial check-in
Revision 1.1 2008/04/23 00:27:45 paul
Copied and modified from wfscli_Handles.h
*---------------------------------------------------------------------------*/
#ifndef wfskrn_Handles_h
#define wfskrn_Handles_h
#ifdef _DEBUG
#define _DEBUG_WFSKRN_HANDLES 1
#else
#define _DEBUG_WFSKRN_HANDLES 0
#endif
#include "wfskrn_Defs.h"
#include "wfskrn_Mutex.h"
#include "wfskrn_PathCache.h"
#define WFSKRN_MAX_FILE_HANDLES (1<<WFSKRN_FILE_HANDLE_IDX_BITS)
#define WFSKRN_MAX_SEARCH_DIR_HANDLES (1<<WFSKRN_SEARCH_DIR_HANDLE_IDX_BITS)
#define WFSKRN_LOG2_MAX_NUM_HANDLES WFS_NUM_BITS_REQUIRED(WFSKRN_MAX_FILE_HANDLES + WFSKRN_MAX_SEARCH_DIR_HANDLES)
#define WFSKRN_FILE_HANDLE_INC (1<<WFSKRN_FILE_HANDLE_IDX_BITS)
#define WFSKRN_SEARCH_DIR_HANDLE_INC (1<<WFSKRN_SEARCH_DIR_HANDLE_IDX_BITS)
#define WFSKRN_HANDLE_MASK 0xFFFF
#define WFSKRN_HANDLE_COUNTER_MASK 0xFFFF
#define WFSKRN_HANDLE_ALLOCATED 0xFFFF
// Internal binary format of WFSFileHandle (u32)
//
// 0TTcccccccccCCCCssssssssssSSSSSS
//
// 0 = always 0 (Number of bits = 1 )
// T = type of handle: 00 for FileHandle (Number of bits = 2 )
// c = incrementally assigned by client (Number of bits = 13 - WFSCLI_FILE_HANDLE_IDX_BITS)
// C = idx of aCliFileInfo array (Number of bits = WFSCLI_FILE_HANDLE_IDX_BITS)
// s = incrementally assigned by server (Number of bits = 16 - WFSKRN_FILE_HANDLE_IDX_BITS)
// S = idx of aSrvFileInfo array (Number of bits = WFSKRN_FILE_HANDLE_IDX_BITS)
typedef struct {
u32 nNext;
WFSKrnMutex mxAccessCliFileInfo;
WFSSrvFileHandle nHandle;
DirEntryAttrHdr attr;
u8 nAccess;
PathCacheItr pci;
DirFilePos fpos;
#if _DEBUG
WFSPathName pathDebug;
#endif
} WFSKrnFileInfo;
// Internal binary format of WFSSearcDirHandle (u32)
//
// 0TTcccccccccccCCssssssssssssSSSS
//
// 0 = always 0 (Number of bits = 1 )
// T = type of handle: 01 for SearchDirHandle (Number of bits = 2 )
// c = incrementally assigned by client (Number of bits = 13 - WFSCLI_SEARCH_DIR_HANDLE_IDX_BITS)
// C = idx of aCliSearchDirInfo array (Number of bits = WFSCLI_SEARCH_DIR_HANDLE_IDX_BITS)
// s = incrementally assigned by server (Number of bits = 16 - WFSKRN_SEARCH_DIR_HANDLE_IDX_BITS)
// S = idx of aSrvSearchDirInfo array (Number of bits = WFSKRN_SEARCH_DIR_HANDLE_IDX_BITS)
typedef struct {
u32 nNext;
WFSSrvSearchDirectoryHandle nHandle;
WFSFileName pattern;
PathCacheItr pci;
#if _DEBUG
WFSPathName pathDebug;
#endif
} WFSKrnSearchDirInfo;
typedef struct {
WFSSrvFileHandle nFileHandleCounter; // Counter for ssss field of file handle.
WFSSrvSearchDirectoryHandle nSearchDirHandleCounter; // Counter for ssss field of search directory handle.
u32 nFirstFreeFileHandle; // Index of the first free element of aClientFileInfo
u32 nFirstFreeSearchDirHandle; // Index of the first free element of aClientSearchDirInfo
u32 nNumUsedFileHandles;
u32 nNumUsedSearchDirHandles;
WFSKrnMutex mxAccessTheFileInfo;
WFSKrnMutex mxAccessTheSearchDirInfo;
WFSKrnFileInfo aFileInfo[WFSKRN_MAX_FILE_HANDLES];
WFSKrnSearchDirInfo aSearchDirInfo[WFSKRN_MAX_SEARCH_DIR_HANDLES];
} WFSKrnHandles;
void WFSKrnInitHandles();
WFSKrnResult WFSKrnGetFileInfo(WFSKrnFileInfo **ppFi, WFSSrvFileHandle fh);
WFSKrnResult WFSKrnGetSearchDirInfo(WFSKrnSearchDirInfo **ppSdi, WFSSrvSearchDirectoryHandle ssdh);
WFSKrnResult WFSKrnFileInfoAlloc(WFSKrnFileInfo **ppFi);
WFSKrnResult WFSKrnSearchDirInfoAlloc(WFSKrnSearchDirInfo **ppSdi);
void WFSKrnFileInfoFree(WFSKrnFileInfo *pFi);
void WFSKrnSearchDirInfoFree(WFSKrnSearchDirInfo *pSdi);
#endif //define wfskrn_Handles_h

View File

@ -0,0 +1,66 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_Heap.h - memory allocation functions
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Heap.h,v $
Revision 1.1 2008/04/22 04:39:08 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.1 2007/12/27 11:35:11 paul
similar to wfs_Heap, but will eventually support IOP
*---------------------------------------------------------------------------*/
#ifndef wfskrn_Heap_h
#define wfskrn_Heap_h
#include "wfskrn_Defs.h"
#ifdef _DEBUG
#define _DEBUG_WFSKRN_ALLOC 0 // change to 1 if debug info required
#else
#define _DEBUG_WFSKRN_ALLOC 0
#endif
#if _WIN32
typedef HANDLE WFSKrnHeap;
//-- twl modified
#elif _TWL
typedef OSHeapHandle WFSKrnHeap;
//-- twl modified
#elif _RVL
#include <revolution/mem.h>
#define WFS_HEAP_DEFAULT_ALIGNMENT 32
typedef struct {
MEMAllocator allocator;
MEMHeapHandle handle;
} WFSKrnHeap;
#elif _IOP
#define WFSKrnHeap IOSHeapId
#endif
void WFSKrnCreateHeap(WFSKrnHeap *pHeap, void *pBase, size_t nSize);
void *WFSKrnHeapAlloc(WFSKrnHeap *pHeap, size_t nSize);
void WFSKrnHeapFree(WFSKrnHeap *pHeap, void *pAddr);
void WFSKrnHeapDestroy(WFSKrnHeap *pHeap);
#endif //define wfskrn_Heap_h

View File

@ -0,0 +1,190 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_Mutex.h - mutual exclusion for multi-thread case
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Mutex.h,v $
Revision 1.2 2008/08/05 04:17:58 kondo_masahiro
Added error handling for hash error and detach device.
Revision 1.1 2008/04/22 04:39:08 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.3 2008/04/19 05:48:44 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.2 2008/02/28 06:32:23 kondo_masahiro
Fixed code to accept PPC compiler
Revision 1.1 2007/12/27 11:34:29 paul
similar to wfs_Mutex.h, but will eventually have to support IOP
*---------------------------------------------------------------------------*/
#ifndef wfskrn_Mutex_h
#define wfskrn_Mutex_h
#include "wfskrn_Defs.h"
#define _TWL 1 //twl modified
#ifdef _DEBUG
#define _DEBUG_WFSKRN_MUTEX 0 // change to 1 if debug info required
#else
#define _DEBUG_WFSKRN_MUTEX 0
#endif
#if _WIN32
typedef struct {
HANDLE hHandle;
} WFSKrnMutex;
typedef struct {
HANDLE hAutoResetEvent;
//HANDLE hManualResetEvent;
} WFSKrnCond;
#define WFSKrnSemaphore HANDLE
typedef struct {
HANDLE hThread;
} WFSKrnThread;
void WFSKrnInitMutex(WFSKrnMutex *mutex);
void WFSKrnLockMutex(WFSKrnMutex *mutex);
bool WFSKrnTryLockMutex(WFSKrnMutex *mutex);
void WFSKrnUnlockMutex(WFSKrnMutex *mutex);
void WFSKrnInitCond(WFSKrnCond *pCond);
void WFSKrnSignalCond(WFSKrnCond *pCond);
void WFSKrnWaitCond(WFSKrnCond *pCond, WFSKrnMutex* pMx);
void WFSKrnResetCond(WFSKrnCond *pCond);
#define WFSKrnInitSemaphore(pSem, initNum) *pSem = CreateSemaphore(NULL,initNum,1,NULL);
#define WFSKrnSignalSemaphore(pSem) ReleaseSemaphore(*pSem, 1, NULL);
#define WFSKrnWaitSemaphore(pSem) WaitForSingleObject(*pSem, INFINITE);
s32 WFSKrnResumeThread(WFSKrnThread *pThread);
void WFSKrnCancelThread(WFSKrnThread *pThread);
void WFSKrnExitThread(void *pVal);
s32 WFSKrnSuspendThread(WFSKrnThread *pThread);
bool WFSKrnIsThreadTerminated(WFSKrnThread *thread);
bool WFSKrnJoinThread(WFSKrnThread *thread, void** val);
//-- twl modified
#elif _TWL
typedef u32 OSPriority;
#define WFSKrnMutex OSMutex
#define WFSKrnCond OSEvent
#define WFSKrnSemaphore OSSemaphore
#define WFSKrnThread OSThread
#define WFSKrnInitMutex osInitMutex
#define WFSKrnLockMutex osLockMutex
#define WFSKrnTryLockMutex osTryLockMutex
#define WFSKrnUnlockMutex osUnlockMutex
//#define WFSKrnInitCond osInitCond
//#define WFSKrnSignalCond osSignalCond
//#define WFSKrnWaitCond osWaitCond
//#define WFSKrnResetCond(x) // This function does nothing on RVL, only needed for Windows
void WFSKrnInitCond(WFSCond *pCond);
void WFSKrnSignalCond(WFSCond *pCond);
void WFSKrnWaitCond(WFSCond *pCond, WFSMutex* pMx);
void WFSKrnResetCond(WFSCond *pCond);
#define WFSKrnInitSemaphore osInitSemaphore
#define WFSKrnSignalSemaphore osSignalSemaphore
#define WFSKrnWaitSemaphore osWaitSemaphore
#define WFSKrnResumeThread OSResumeThread
#define WFSKrnCancelThread OSCancelThread
#define WFSKrnExitThread OSExitThread
#define WFSKrnSuspendThread OSSuspendThread
#define WFSKrnIsThreadTerminated OSIsThreadTerminated
#define WFSKrnJoinThread OSJoinThread
//-- twl modified
#elif _RVL
#define WFSKrnMutex OSMutex
#define WFSKrnCond OSCond
#define WFSKrnSemaphore OSSemaphore
#define WFSKrnThread OSThread
#define WFSKrnInitMutex OSInitMutex
#define WFSKrnLockMutex OSLockMutex
#define WFSKrnTryLockMutex OSTryLockMutex
#define WFSKrnUnlockMutex OSUnlockMutex
#define WFSKrnInitCond OSInitCond
#define WFSKrnSignalCond OSSignalCond
#define WFSKrnWaitCond OSWaitCond
#define WFSKrnResetCond(x) // This function does nothing on RVL, only needed for Windows
#define WFSKrnInitSemaphore OSInitSemaphore
#define WFSKrnSignalSemaphore OSSignalSemaphore
#define WFSKrnWaitSemaphore OSWaitSemaphore
#define WFSKrnResumeThread OSResumeThread
#define WFSKrnCancelThread OSCancelThread
#define WFSKrnExitThread OSExitThread
#define WFSKrnSuspendThread OSSuspendThread
#define WFSKrnIsThreadTerminated OSIsThreadTerminated
#define WFSKrnJoinThread OSJoinThread
#elif _IOP
#define WFSKRN_MUTEX_Q_SIZE 1
typedef s32 OSPriority;
typedef struct{
IOSMessageQueueId mqid; // Message queue
IOSMessage mq[WFSKRN_MUTEX_Q_SIZE];
s32 count; // lock count
IOSThreadId owner;
} WFSKrnMutex;
//#define WFSKrnCond
typedef struct {
IOSThreadId tid;
s32 count;
} WFSKrnThread;
void WFSKrnInitMutex(WFSKrnMutex *mutex);
void WFSKrnLockMutex(WFSKrnMutex *mutex);
bool WFSKrnTryLockMutex(WFSKrnMutex *mutex);
void WFSKrnUnlockMutex(WFSKrnMutex *mutex);
//#define WFSKrnInitCond
//#define WFSKrnSignalCond
//#define WFSKrnWaitCond
//#define WFSKrnResetCond
s32 WFSKrnResumeThread(WFSKrnThread *pThread);
void WFSKrnCancelThread(WFSKrnThread *pThread);
void WFSKrnExitThread(void *pVal);
s32 WFSKrnSuspendThread(WFSKrnThread *pThread);
bool WFSKrnIsThreadTerminated(WFSKrnThread *pThread);
bool WFSKrnJoinThread(WFSKrnThread *pThread, void** val);
#endif
typedef void *(*WFSKrnThreadFunc)(void *);
bool WFSKrnCreateThread(WFSKrnThread *thread,
WFSKrnThreadFunc threadFunc,
void* param,
void* stackBase,
u32 stackSize,
OSPriority priority);
#endif //define wfskrn_Mutex_h

View File

@ -0,0 +1,106 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_PTree.h
Copyright 2007-2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_PTree.h,v $
Revision 1.2 2008/07/17 22:33:39 paul
Added adapter functions to the Sba allocators for updateMap
Revision 1.1 2008/07/09 01:42:35 paul
u32->u32 mapping optimized B-Tree. (for use by new block allocator, and transaction block re-mapper)
*---------------------------------------------------------------------------*/
#ifndef wfskrn_PTree_h
#define wfskrn_PTree_h
#ifdef _DEBUG
#define _DEBUG_PTREE 0 // change to 1 if debug info required
#else
#define _DEBUG_PTREE 0
#endif
#include "wfskrn_Defs.h"
#define PTREE_LOG2_NODE_SIZE 5
#define PTREE_NODE_FAN_OUT 6 // (6 * 2 Byte Offset) + (5 * 4 Byte Key) = 32 Bytes
#define PTREE_LEAF_FAN_OUT 4 // 4 * (4 Byte Key + 4 Byte Value) = 32 Bytes
#define PTREE_MAX_HEIGHT 5
// Node Sizes:
typedef struct {
u32 aKey[PTREE_NODE_FAN_OUT-1];
u16 aOfs[PTREE_NODE_FAN_OUT];
} PTreeNode;
typedef struct {
u32 aKey[PTREE_LEAF_FAN_OUT];
u32 aData[PTREE_LEAF_FAN_OUT];
} PTreeLeaf;
typedef struct {
u16 *pOfs; // A pointer to the offset pointer to the node. This would need to be updated if the sub block is relocated.
PTreeLeaf *pLeaf;
PTreeNode *apNode[PTREE_MAX_HEIGHT-1];
u32 aEntryIdx[PTREE_MAX_HEIGHT];
//u32 *apKey[PTREE_MAX_HEIGHT];
u32 nKey;
u32 nData;
} PTreeItr;
typedef u16 (*PTreeAllocNodeFunc) (void *pBase);
typedef WFSKrnResult (*PTreeAllocNodesFunc)(void *pBase, u16 *pNodeOfs, u32 nNumNodes);
typedef void (*PTreeFreeNodeFunc) (void *pBase, u16 nOfs);
typedef struct {
void *pBase;
PTreeAllocNodeFunc fpAllocNode;
PTreeAllocNodesFunc fpAllocNodes;
PTreeFreeNodeFunc fpFreeNode;
} PTreeAllocator;
// Allocator functions which use SubBlkAlloc module
u16 PTreeAllocNodeFromSba(void *pBase);
WFSKrnResult PTreeAllocNodesFromSba(void *pBase, u16 aNodeOfs[], u32 nNumNodes);
void PTreeFreeNodeToSba(void *pBase, u16 nOfs);
typedef struct {
u32 nRootHeight; // height of root node (opposite of depth).
u16 nRootOfs; // Offset to the root node of the tree.
u16 nNumRecs; // Number of records in the tree.
} PTreeHdr;
typedef struct {
u16 nParentOfs; // The offset the to parent of this node
u8 nEntryIdx; // The index of the entry in the parent block which points to this node
u8 nNumEntries; // The number of entries in this node
u32 nLength;
} PTreeAttrHdr;
void PTreeInit (PTreeHdr *pPTreeHdr, PTreeAllocator *pAllocator);
WFSKrnResult PTreeFind (PTreeHdr *pPTreeHdr, PTreeItr *pPti, u32 nKey, PTreeAllocator *pAllocator);
WFSKrnResult PTreeInsert(PTreeHdr *pPTreeHdr, PTreeItr *pPti, u32 nKey, u32 nData, PTreeAllocator *pAllocator);
WFSKrnResult PTreeDelete(PTreeHdr *pPTreeHdr, PTreeItr *pPti, PTreeAllocator *pAllocator);
WFSKrnResult PTreeFirst (PTreeHdr *pPTreeHdr, PTreeItr *pPti, PTreeAllocator *pAllocator);
WFSKrnResult PTreeNext (PTreeHdr *pPTreeHdr, PTreeItr *pPti, PTreeAllocator *pAllocator);
WFSKrnResult PTreeInsertOrUpdateRec(PTreeHdr *pPTreeHdr, u32 nKey, u32 nData, PTreeAllocator *pAllocator);
void PTreeCheck(PTreeHdr *pPTreeHdr, u32 nLog2Size, PTreeAllocator *pAllocator);
void PTreeTest();
#endif //define wfskrn_PTree_h

View File

@ -0,0 +1,202 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_PathCache.h - Caches recently used path names plus root path names "/dev", "/vol"
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_PathCache.h,v $
Revision 1.13 2008/12/04 00:42:37 ooizumi
Changed definition name to enable permission.
Revision 1.12 2008/10/31 09:51:42 ueno
Modified WFSSrvAPIs to return WFSKRN_RESULT_RESOURCE_LIMIT_EXCEEDED when path cache is short of memory.
Revision 1.11 2008/10/07 10:30:01 ooizumi
Defined PathCachePerm.
Added nObjCreator to PathCacheData.
Revision 1.10 2008/07/30 21:25:01 paul
Removed some unused definitions
Revision 1.9 2008/07/30 06:04:34 ooizumi
Added definitions for permission.
Revision 1.8 2008/07/21 22:48:35 paul
Added PathCacheCheck()
Revision 1.7 2008/07/17 22:31:12 paul
Added nRootBlkAdr to PathCacheItr.
Revision 1.6 2008/07/09 01:46:06 paul
Minor change.
Revision 1.5 2008/06/23 13:44:04 nakanose_jin
add cast for avoid warning
Revision 1.4 2008/06/09 18:06:42 paul
Rewrote PathCache to use a radix tree. Now actually provides PathCache functionality.
Also stores a list of open file / directory search paths so that invalid WFSSrv calls can be detected.
Revision 1.3 2008/05/14 02:14:54 paul
Added some comments
Revision 1.2 2008/05/12 19:22:12 paul
Made naming more consistent
Revision 1.1 2008/05/10 04:00:29 kondo_masahiro
Initial check-in
*---------------------------------------------------------------------------*/
#ifndef wfskrn_PathCache_h
#define wfskrn_PathCache_h
#include "wfskrn_Config.h"
#include "wfskrn_DirRxTree.h"
#ifdef _DEBUG
#define _DEBUG_PATH_CACHE 0 // change to 1 if debug info required
#else
#define _DEBUG_PATH_CACHE 0
#endif
#if _CHECK_RXT
#define _CHECK_PATH_CACHE 1
#else
#define _CHECK_PATH_CACHE 0
#endif
#define WFS_DEVICE_DIRECTORY "/dev"
#define WFS_VOLUME_DIRECTORY "/vol"
#define PATH_CACHE_MAX_ENTRIES ((1<<WFSKRN_FILE_HANDLE_IDX_BITS) + (1<<WFSKRN_SEARCH_DIR_HANDLE_IDX_BITS) + 20 + WFSKRN_MAX_VOLUMES)
#define PATH_CACHE_ENABLED 1
#define PATH_CACHE_FLAG_OPEN_FOR_WRITE 0x8000
typedef struct {
struct PathCacheEntry_ *pNext;
struct PathCacheEntry_ *pPrev;
} PathCacheLink;
#ifdef PERMISSION_ENABLED
#define PATH_CACHE_PERM_MAX 2
typedef struct {
WFSTitleId nTitleId;
WFSTitleId nEntryCreatorId;
u32 nFlags;
u32 nEntryCreatorCl;
} PathCachePerm;
#endif
typedef struct {
union {
void *pData;
AreaInfo *pAreaInfo;
};
u32 nBlkAdr;
u16 nOpenHandleCount; // This is calculated as the sum of nPinCount for all sub-paths currently in the cache
u16 nPinCount;
u16 nFlags;
u16 nStrLen;
#ifdef PERMISSION_ENABLED
u32 nAccessListIdx;
WFSTitleId nObjCreator;
// PathCachePerm aPerm[PATH_CACHE_PERM_MAX];
#endif
} PathCacheData;
typedef struct PathCacheEntry_ {
RxtAttrHdr ah;
PathCacheLink ml;
PathCacheData pcd;
} PathCacheEntry;
#define PATH_CACHE_LOG2_NODE_SIZE WFS_NUM_BITS_REQUIRED(sizeof(PathCacheEntry))
typedef struct {
u8 aRxtBuf[1<<WFS_LOG2_PATH_CACHE_SIZE]; // WFS_LOG2_PATH_CACHE_SIZE <= RXT_MAX_LOG2_SIZE
RxtHdr *pRxtHdr;
PathCacheLink mruAnchor;
PathCacheEntry *pMruAnchor; // List from Most Recently Used to Least Recently Used
PathCacheLink pinAnchor;
PathCacheEntry *pPinAnchor; // List of directories that are pinned - do not get automatically deleted to make room for other
#if _DEBUG_PATH_CACHE
u32 nNumPinned;
#endif
} PathCache;
typedef struct {
RxtItr rxi;
DirItr di;
WFSBlkAdr nRootBlkAdr;
const utf8 *pNameEnd;
const utf8 *pRawNameStart;
PathCacheEntry *pEntry;
} PathCacheItr;
#if _DEBUG
void PathCacheDebugOutput();
#endif
PathCacheEntry *PathCacheInsertAfterCursorEntry3(PathCacheEntry *pCursorEntry, utf8 *sStr, u32 nStrLen);
static inline PathCacheEntry *PathCacheInsertAfterCursorEntry2(PathCacheEntry *pCursorEntry, utf8 *sStr) {
u32 nStrLen = (u32)STRNLEN(sStr, WFS_MAX_PATH_NAME_SIZE);
return PathCacheInsertAfterCursorEntry3(pCursorEntry, sStr, nStrLen);
}
PathCacheEntry *PathCacheFind3(RxtItr *pRxi, u32 nStrLen, void **ppData);
static inline PathCacheEntry *PathCacheFind2(RxtItr *pRxi, void **ppData) {
u32 nStrLen = (u32)STRNLEN(pRxi->pStrPtr, WFS_MAX_PATH_NAME_SIZE);
return PathCacheFind3(pRxi, nStrLen, ppData);
}
static inline PathCacheEntry *PathCacheFind1(RxtItr *pRxi) {
void *pData;
return PathCacheFind2(pRxi, &pData);
}
PathCacheEntry *PathCacheIncrementalFindEntry(RxtItr *pRxi, u32 nStrLen, void **ppData);
void PathCacheDeleteEntry(PathCacheEntry *pEntry);
WFSKrnResult PathCacheDeleteSubTree(PathCacheEntry *pEntry);
WFSKrnResult PathCacheDeleteLru();
PathCacheEntry *PathCacheIncrementalInsertAfterCursorEntry(PathCacheEntry *pCursorEntry, RxtItr *pRxi, u32 nPrefixLen, u32 nSuffixLen);
WFSKrnResult PathCacheIncrementalInsertPinnedEntry(PathCacheItr *pPci, u32 nStrLen);
#if _DEBUG_PATH_CACHE
WFSKrnResult PathCacheIncreaseEntryOpenHandleCount(PathCacheItr *pPci, WFSAccess nDesiredAccess, utf8 *sStr);
WFSKrnResult PathCacheDecreaseEntryOpenHandleCount(PathCacheItr *pPci, utf8 *sStr);
void PathCachePinEntry(PathCacheEntry *pEntry, utf8 *sStr);
#else
WFSKrnResult PathCacheIncreaseEntryOpenHandleCount(PathCacheItr *pPci, WFSAccess nDesiredAccess);
WFSKrnResult PathCacheDecreaseEntryOpenHandleCount(PathCacheItr *pPci);
void PathCachePinEntry(PathCacheEntry *pEntry);
#endif
#if _CHECK_PATH_CACHE
void PathCacheCheck();
#endif
void PathCacheInit();
void PathCacheTest();
WFSKrnResult PathCacheFindParentDir(const WFSPathName *pAbsPathName, utf8 *sLowerCaseStr, PathCacheItr *pPci);
WFSKrnResult PathCacheFindPath (const WFSPathName *pAbsPathName, utf8 *sLowerCaseStr, PathCacheItr *pPci);
#endif //define wfskrn_PathCache_h

View File

@ -0,0 +1,79 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfs_Permission.h
Copyright 2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Permission.h,v $
Revision 1.5 2008/12/18 10:28:33 ooizumi
Fixed macro.
Revision 1.4 2008/12/04 00:49:49 ooizumi
Removed old codes.
Fixed.
Revision 1.3 2008/07/31 23:59:09 ooizumi
Fixed permission of special directories..
Revision 1.2 2008/07/30 06:04:34 ooizumi
Added definitions for permission.
Revision 1.1 2008/04/22 04:39:08 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.6 2008/02/28 04:36:47 ueno
Cleanup.
Revision 1.5 2008/02/27 10:05:26 ueno
Revised to use WFSAreaHdr{} to specifiy WFS area.
Revision 1.4 2008/02/27 04:33:36 ueno
Added root ID and alias permission flags.
Revision 1.3 2008/02/26 14:12:06 ueno
Added WFSAccessListAddEntry() and WFSAccessListRemoveEntry() to edit accesslist.
Revision 1.2 2008/02/25 09:44:08 ueno
Added support for accesslist cache.
Revision 1.1 2008/02/22 05:15:55 ueno
Initial Check-in.
*---------------------------------------------------------------------------*/
#ifndef __WFS_PERMISSION_H__
#define __WFS_PERMISSION_H__
#ifdef _DEBUG
#ifdef WIN32
#define WFSKRN_PERM_ASSERT(x) assert(x)
//#define WFSKRN_PERM_REPORT printf
#define WFSKRN_PERM_REPORT
#else // Win32
#define WFSKRN_PERM_ASSERT(x) SDK_ASSERT(x)
//#define WFSKRN_PERM_REPORT(...) printf(__VA_ARGS__)
#define WFSKRN_PERM_REPORT osTPrintf
#endif // WIN32
#else // _DEBUG
#define WFSKRN_PERM_ASSERT(x) SDK_ASSERT(x)
#define WFSKRN_PERM_REPORT(...) osTPrintf(__VA_ARGS__)
//#define WFSKRN_PERM_ASSERT(x)
//#define WFSKRN_PERM_REPORT(...)
#endif // _DEBUG
WFSKrnResult WFSKrnGetInheritedPermissionForUserDi(PathCacheItr* pPci, u32* pFlags, WFSTitleId titleId);
WFSKrnResult WFSKrnGetInheritedPermissionForUserPci(PathCacheItr* pPci, u32* pFlags, WFSTitleId titleId);
WFSKrnResult WFSKrnGetParentInheritedPermissionForUserPci(PathCacheItr* pPci, u32* pFlags, WFSTitleId titleId);
WFSKrnResult WFSKrnSetInheritedPermissionForUser(PathCacheItr* pPci, u32 nFlags, u32 nMask, WFSTitleId entryCreatorId, WFSTitleId titleId);
#endif // __WFS_PERMISSION_H__

View File

@ -0,0 +1,567 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfs_Permission_AccessList.h
Copyright 2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Permission_AccessList.h,v $
Revision 1.23 2008/09/24 07:32:07 ueno
Added AclHdr{} to AreaHdr{} to save configuration of accesslists in a disk.
Revision 1.22 2008/08/14 08:02:57 kondo_masahiro
Fixed definition of ACL_GET_CL_RELATIVE() from inline to static inline.
Revision 1.21 2008/07/23 04:18:07 ueno
Reduced memory size required for accesslist.
Revision 1.20 2008/07/11 08:10:50 ueno
Fixed control level check.
Revision 1.19 2008/06/16 18:03:56 ueno
Fixed comment.
Revision 1.18 2008/06/05 14:04:11 ueno
Modified to reserve accesslist index 0 as the default (empty) accesslist.
Revision 1.17 2008/06/05 08:44:40 ueno
Cleanup.
Revision 1.16 2008/06/05 08:09:18 ueno
Revised permission APIs.
Revision 1.15 2008/06/02 15:09:54 ueno
Revised WFSKrnAccessList{} to reduce the size.
Revision 1.14 2008/05/29 14:08:13 ueno
Modified _WFSAccessListControlBlock().
Revision 1.13 2008/05/28 02:12:57 ueno
Cleanup.
Revision 1.12 2008/05/23 06:31:52 ueno
Cleanup.
Revision 1.11 2008/05/19 05:31:53 ueno
Defined accesslist meta-data types.
Revision 1.10 2008/05/15 13:33:46 ueno
Implemented initialization using directory module.
Revision 1.9 2008/05/06 02:27:21 ueno
Fixed ifdef.
Revision 1.8 2008/04/29 06:25:14 ueno
Cleanup.
Revision 1.7 2008/04/29 01:12:54 ueno
Defined WFS_ROOT_ID and WFS_EVERYONE_ID.
Revision 1.6 2008/04/25 19:15:14 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.4 2008/04/25 06:22:55 ueno
Cleanup.
Revision 1.3 2008/04/25 04:40:47 ueno
Added support for WFSDEV.
Revision 1.1 2008/04/22 04:39:08 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.23 2008/04/23 08:59:55 ueno
Replaced WFSAreaHdr by AreaInfo.
Revised directory permission (change -> add).
Revision 1.22 2008/04/21 06:07:54 ueno
Fixed struct for C99.
Revision 1.21 2008/04/15 07:35:29 ueno
Fixed error codes.
Revision 1.20 2008/04/15 06:45:47 ueno
Changed return type to WFSKrnResult.
Revision 1.19 2008/04/14 13:50:17 ueno
Cleanup.
Revision 1.18 2008/04/14 03:02:16 ueno
Modified WFSKrnCreateRootAccessList() to create an accesslist only for the root.
Added WFSKrnDebugCreateAccessList() for tests.
Revision 1.17 2008/04/11 13:20:13 ueno
Removed WFSKrnAccessListSetInstallerPermission().
Revision 1.16 2008/04/11 06:16:33 ueno
Defined WFSAclFileHandle.
Cleaned up headers.
Revision 1.15 2008/04/11 02:52:11 ueno
Renamed WFSKrnCreateAccessList() to make clear the purpose.
Revision 1.14 2008/04/09 11:31:25 ueno
Changed the maximum number of accesslist handles.
Revision 1.13 2008/04/07 12:47:17 ueno
Added support for group others.
Revision 1.12 2008/04/07 09:18:54 ueno
Modified WFSAccessListControlBlock() to keep permissions for the installer.
Revision 1.11 2008/04/03 09:59:30 ueno
Added manuals of WFS AccessList APIs.
Revision 1.10 2008/04/03 06:40:35 ueno
Removed WFSKRN_ACCESSLIST_FLAG_CONTENT_DIRECTORY flag.
Cleanup.
Revision 1.9 2008/04/02 14:15:13 ueno
Revised permission inheritance.
Revision 1.8 2008/03/31 14:06:49 ueno
Removed WFSKrnAccessListAddUser() and RemoveUser().
Removed WFSKrnAccessListCan*().
Revision 1.7 2008/03/19 10:18:49 ueno
Revised WFSKrnAddUser() and RemoveUser() to specify operator title ID.
Revision 1.6 2008/03/18 13:42:28 ueno
Added WFSKrnAccessListSetControlLevel(), GetControlLevel() to set/get a control level.
Revision 1.5 2008/03/14 08:02:48 ueno
Revised API prefixes (WFS -> WFSKrn).
Revision 1.4 2008/03/12 06:37:34 ueno
Added WFSAccessListCanRead(), Write()...
Revision 1.3 2008/03/11 12:10:35 ueno
Cleanup.
Revision 1.2 2008/03/11 11:38:58 ueno
Cleanup.
Revision 1.1 2008/03/11 11:09:21 ueno
Renamed.
Revision 1.14 2008/03/11 09:51:51 ueno
Fixed EscapeAccessList() to make a filename from UTF-16 characters (0x3300-0x33ff).
Revision 1.13 2008/03/11 06:53:02 ueno
Added WFSAccessListSetPermission() and GetPermission().
Revision 1.12 2008/03/07 05:43:57 ueno
Cleanup.
Revision 1.10 2008/03/06 12:26:04 ueno
Revised cache freelist (signgle -> double link list).
Revision 1.9 2008/03/06 10:46:19 ueno
Cleanup.
Revision 1.8 2008/02/29 00:47:45 ueno
Changed the attribute of index to inout (WFSAccessListAddEntry() and RemoveEntry()).
Revision 1.7 2008/02/28 13:11:58 ueno
Revised to keep accesslist cache and indexlist handle in WFSAreaHdr{}.
Revision 1.6 2008/02/28 04:36:47 ueno
Cleanup.
Revision 1.5 2008/02/27 10:05:26 ueno
Revised to use WFSAreaHdr{} to specifiy WFS area.
Revision 1.4 2008/02/27 04:33:36 ueno
Added root ID and alias permission flags.
Revision 1.3 2008/02/26 14:12:06 ueno
Added WFSAccessListAddEntry() and WFSAccessListRemoveEntry() to edit accesslist.
Revision 1.2 2008/02/25 09:44:08 ueno
Added support for accesslist cache.
Revision 1.1 2008/02/22 05:15:55 ueno
Initial Check-in.
*---------------------------------------------------------------------------*/
#ifndef __WFSKRN_PERMISSION_ACCESSLIST_H__
#define __WFSKRN_PERMISSION_ACCESSLIST_H__
#include <revolution/wfs.h>
#if !_IOP
#include "wfs_Client.h"
#endif
#include "wfskrn_Area.h"
#include "wfskrn_Mutex.h"
#include "wfskrn_Permission_Type.h"
#define WFSKRN_ACCESSLIST_MAX_CONTROL_LEVEL 3
#if !_IOP
namespace wfsdev_api{
struct tagSAreaInfo;
}
#endif
#ifndef ROUNDUP32BYTE
#define ROUNDUP32BYTE(val) (((size_t)val+31)&~31)
#endif // ROUNDUP32BYTE
//
// Accesslist Cache
//
#define ACL_MAX_MEMORY_BLOCK 254 // [check]
#define ACL_NO_ENTRY 255 // [check]
typedef struct WFSKrnAccessListEntry
{
u32 id; // title ID.
u32 ecId; // entry creator's Id.
u32 pm; // permissions and control levels.
} WFSKrnAccessListEntry;
typedef struct _WFSKrnAccessList WFSKrnAccessList;
struct _WFSKrnAccessList
{
u8 num; // number of blocks in this list.
u8 type; // WFSKRN_ACCESSLIST_FREEBLOCK or 0.
u16 ref; // reference count of this cache.
WFSKrnAclHandle handle; // access list handle and WFSKRN_ACCESSLIST_FLAG_* flags
u8 prevFreeCacheBlock; // previous free cache.
u8 nextFreeCacheBlock; // next free cache.
u8 prevBlock; // previous cache.
u8 nextBlock; // next cache.
};
// cache list, free cache list.
typedef struct WFSKrnAccessListLinkList
{
WFSKrnAccessList* head;
WFSKrnAccessList* tail;
} WFSKrnAccessListLinkList;
#define WFSKRN_ACCESSLIST_FREEBLOCK ((u8) 0x1) // Free memory block.
#define WFSKRN_BLOCKS_IN_LIST(x) (sizeof(WFSKrnAccessList)/sizeof(WFSKrnAccessListBlock) + \
WFSKrnAccessListGetNum(x) * (sizeof(WFSKrnAccessListEntry)/sizeof(WFSKrnAccessListBlock)))
typedef struct WFSKrnAccessListBlock
{
u8 num; // number of blocks in this chunk.
u8 type; // WFSKRN_ACCESSLIST_FREEBLOCK or 0.
u8 reserved;
u8 nextBlock; // the block number of the next chunk.
} WFSKrnAccessListBlock;
#define ACL_DEFAULT_CACHESIZE (128 * sizeof(WFSKrnAccessListBlock))
//
// Accesslist Index
//
#define ACL_RELATIVE_CL_FLAG 0x8000
#define ACL_CL_MASK 0x0003
#define WFS_PERM_RELATIVE_CL_FLAG 0x8000
static inline WFSKrnResult ACL_GET_CL_RELATIVE(u32 perm, int* cl)
{
WFSKrnResult result = WFSKRN_RESULT_INVALID;
if (perm & ACL_RELATIVE_CL_FLAG)
{
u32 val = ((~perm >> WFS_PERM_CL_SHIFT) & ACL_CL_MASK);
*cl = -((int) val);
result = WFSKRN_RESULT_OK;
}
return result;
}
#define ACL_ENTRY_NET_SIZE (sizeof(u32) + sizeof(u32) + sizeof(u16)) // smaller than sizeof(WFSKrnAccessListEntry).
#define ACL_MAX_ENTRIES (WFS_MAX_FILE_NAME_SIZE - sizeof(u32)*2)/(ACL_ENTRY_NET_SIZE*2)
// flags for accesslist handle
#define ACL_FLAG_DIRECTORY (1<<31) // accesslist for directory.
#define ACL_FLAG_RESERVED0 (1<<30)
#define ACL_FLAG_RESERVED1 (1<<29)
#define ACL_FLAG_RESERVED2 (1<<28)
#define ACL_TYPE_MASK (~0xf0000000)
#define ACL_TYPE(x) ((x)->handle & ~ACL_TYPE_MASK)
#define ACL_INDEX(x) ((x)->handle & ACL_TYPE_MASK)
#define WFSKRN_ACCESSLIST_GROUP 0x80000000
// escape sequence to convert a content of an accesslist to a filename.
#define ESCAPE 0x33
#define ESCAPED_NULL 0x58
//
// Index List
// which manages indices of free and used accesslists.
//
#define WFSKRN_ACCESSLIST_INDEXES_IN_PAGE 16
#define WFSKRN_ACCESSLIST_INDEXLIST_MAX_PAGE 6
#define WFSKRN_ACCESSLIST_FREEINDEX 0xffffffff
typedef struct IndexListHeader
{
u32 numEntry;
} IndexListHeader;
typedef struct IndexListEntry
{
u32 location;
} IndexListEntry;
//
// Control Block of Accesslists.
//
#if WFSDEV
namespace wfsdev_api{
struct tagSAreaInfo;
}
#endif
#ifndef _struct_WFSAccessListControlBlock_
#define _struct_WFSAccessListControlBlock_
typedef struct _WFSAccessListControlBlock WFSAccessListControlBlock;
#endif
struct _WFSAccessListControlBlock
{
WFSKrnAccessListBlock* freeBlock;
WFSKrnAccessListBlock* memoryBlock; // heap for accesslist cache.
u32 numBlock;
WFSKrnAccessListLinkList cache;
WFSKrnAccessListLinkList cacheFreeList;
#ifdef WFSKRN_ACL_USE_MUTEX
WFSKrnMutex mxMutex;
#endif // WFSKRN_ACL_USE_MUTEX
#if WFSDEV
struct wfsdev_api::tagSAreaInfo *aclWrapper;
#endif
WFSBool initialized;
};
//
// APIs
//
//--------------------------------------------------------------------------------------------------------------
// WFSKrnAccessListInit
//--------------------------------------------------------------------------------------------------------------
// Arguments:
// ----------
// area .. [in] A WFS area.
//
// Return Values:
// --------------
// WFSKRN_RESULT_OK .. success
// WFSKRN_RESULT_ACL_ERROR .. (see wfskrn_Errors.h)
// WFSKRN_RESULT_INVALID
// WFSKRN_RESULT_OUT_OF_MEMORY
// WFSKRN_RESULT_LIB_ALREADY_INITIALIZED
//
// Description:
// ------------
// This function initializes accesslist cache and accesslist index list.
// WFSAccessListControlBlock{} in area (AreaInfo{}) must be properly initialized before calling this function.
// - Memory blocks for accesslist cache must be set in memoryBlock field of WFSAccessListControlBlock{}.
// - The number of blocks must be set in numBlock field.
// - initialized field must be set to FALSE.
WFSKrnResult WFSKrnAccessListInit(AreaInfo* area);
//--------------------------------------------------------------------------------------------------------------
// WFSKrnAccessListOpen
//--------------------------------------------------------------------------------------------------------------
// Arguments:
// ----------
// area .. [in] A WFS area.
//
// Return Values:
// --------------
// WFSKRN_RESULT_OK .. success
// WFSKRN_RESULT_OUT_OF_MEMORY
// WFSKRN_RESULT_LIB_ALREADY_INITIALIZED
//
// Description:
// ------------
// This function initializes accesslist cache and loads accesslist configuration from the device:
// - the root block for accesslist files.
// - the root block for accesslist namefiles and the index list.
// WFSAccessListControlBlock{} in area (AreaInfo{}) must be properly initialized before calling this function.
// - Memory blocks for accesslist cache must be set in memoryBlock field of WFSAccessListControlBlock{}.
// - The number of blocks must be set in numBlock field.
// - initialized field must be set to FALSE.
WFSKrnResult WFSKrnAccessListOpen(const AreaInfo* area);
//--------------------------------------------------------------------------------------------------------------
// WFSKrnAccessListExit
//--------------------------------------------------------------------------------------------------------------
// Arguments:
// ----------
// area .. [in] A WFS area.
//
// Return Values:
// --------------
// WFS_RESULT_OK .. success
//
// Description:
// ------------
// This function is not implemented.
//
WFSKrnResult WFSKrnAccessListExit(const AreaInfo* area);
//--------------------------------------------------------------------------------------------------------------
// WFSKrnDeletePermissions
//--------------------------------------------------------------------------------------------------------------
// Arguments:
// ----------
// area .. [in] A WFS area.
// handle .. [in] Accesslist handle.
// titleId .. [in] Title Id to be deleted.
// entryCreatorId .. [in] Entry creator's Id.
//
// Return Values:
// --------------
// WFSKRN_RESULT_OK .. success
// WFSKRN_RESULT_INVALID
// WFSKRN_RESULT_ACL_ERROR
// WFSKRN_RESULT_ACL_MAX_ENTRIES
// WFSKRN_RESULT_ACL_FILE
//
// Description:
// ------------
// This function deletes the specified entry in the specified accesslist.
WFSKrnResult WFSKrnDeletePermissions(const AreaInfo* area,
WFSKrnAclHandle* handle, WFSTitleId entryCreatorId, WFSTitleId titleId);
// Arguments:
// ----------
// area .. [in] A WFS area.
// handle .. [in] Accesslist handle.
// pAccessList .. [out] Buffer for an accesslist.
// nMaxElements .. [out] Size of the buffer.
//
// Return Values:
// --------------
// The number of entries. .. success
// WFSKRN_RESULT_ACL_BUFFER_TOO_SMALL
//
// Description:
// ------------
// This function gets all entries in the specified accesslist.
s32 WFSKrnGetAccessList(const AreaInfo* area,
WFSKrnAclHandle handle, WFSAccessListEntry *pAccessList, u32 nMaxElements);
//--------------------------------------------------------------------------------------------------------------
// WFSKrnSetAccessList
//--------------------------------------------------------------------------------------------------------------
// Arguments:
// ----------
// area .. [in] A WFS area.
// handle .. [inout] Accesslist handle.
// caller .. [in]
// nFlags .. [in] Permissions and control levels to be set.
// nMask .. [in] Mask of permissions.
// entryCreatorId .. [in] Id of the title which created the entry.
// titleId .. [in] Title Id of the entry to be modified.
//
// Return Values:
// --------------
// WFSKRN_RESULT_OK .. success
// WFSKRN_RESULT_INVALID
// WFSKRN_RESULT_ACL_ERROR
// WFSKRN_RESULT_ACL_MAX_ENTRIES
// WFSKRN_RESULT_ACL_FILE
//
// Description:
// ------------
// This function chnages permissions of the specified entry, or creates a new entry.
WFSKrnResult WFSKrnSetAccessList(const AreaInfo* area, WFSKrnAclHandle* handle,
u32 nFlags, u32 nMask, WFSTitleId entryCreatorId, WFSTitleId titleId);
//--------------------------------------------------------------------------------------------------------------
// WFSKrnReleaseAccessList
//--------------------------------------------------------------------------------------------------------------
// Arguments:
// ----------
// area .. [in] A WFS area.
// handle .. [in] A handle of accesslist .
//
// Return Values:
// --------------
// WFSKRN_RESULT_OK .. success
// WFSKRN_RESULT_ACL_ERROR
// WFSKRN_RESULT_ACL_CACHE
// WFSKRN_RESULT_ACL_FILE
//
// Description:
// ------------
// This function decrements the reference count of the specified accesslist.
// When the count reduces to zero, the accesslist is removed.
// This is called when deleting a file or directory.
WFSKrnResult WFSKrnReleaseAccessList(const AreaInfo* area, WFSKrnAclHandle handle);
//--------------------------------------------------------------------------------------------------------------
// WFSKrnAccessListCheckDirectoryPermission
//--------------------------------------------------------------------------------------------------------------
// Arguments:
// ----------
// area .. [in] WFS area.
// handle .. [in] A handle of an accesslist for a directory.
// titleId .. [in] Title ID.
// flag .. [in] Permissions to be checked.
//
// Return Values:
// --------------
// TRUE .. The title has the specified permissions.
// FALSE .. The title does not have the permissions.
//
// Description:
// ------------
// This function checks if the title has the specified directory permissions.
//
// WFSBool WFSKrnAccessListCheckDirectoryPermission(const AreaInfo* area, WFSKrnAclHandle handle, WFSTitleId titleId, u32 flag);
//--------------------------------------------------------------------------------------------------------------
// WFSKrnAccessListCheckDirectoryPermission
//--------------------------------------------------------------------------------------------------------------
// Arguments:
// ----------
// area .. [in] WFS area.
// handle .. [in] A handle of an accesslist for a file.
// titleId .. [in] Title ID.
// flag .. [in] Permissions to be checked.
//
// Return Values:
// --------------
// TRUE .. The title has the specified permissions.
// FALSE .. The title does not have the permissions.
//
// Description:
// ------------
// This function checks if the title has the specified file permissions.
// WFSBool WFSKrnAccessListCheckFilePermission(const AreaInfo* area,
// WFSKrnAclHandle handle, WFSTitleId titleId, u32 flag);
//
// Memory block allocator for accesslist cache.
//
WFSKrnAccessListBlock* WFSKrnMemoryBlockAlloc(const AreaInfo* area, int numBlocks);
int WFSKrnMemoryBlockFree(const AreaInfo* area, WFSKrnAccessListBlock* block, u32 numBlocks);
#endif // __WFSKRN_PERMISSION_ACCESSLIST_H__

View File

@ -0,0 +1,29 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfs_Permission_AccessList_Type.h
Copyright 2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Permission_AccessList_Type.h,v $
Revision 1.1 2008/09/24 07:50:34 ueno
Added AclHdr{} to AreaHdr{} to save configuration of accesslists in a disk.
*---------------------------------------------------------------------------*/
#ifndef __WFSKRN_PERMISSION_ACCESSLIST_TYPE_H__
#define __WFSKRN_PERMISSION_ACCESSLIST_TYPE_H__
typedef struct _AclHdr
{
WFSBlkAdr aclBlock;
WFSBlkAdr nameBlock;
} AclHdr;
#endif // __WFSKRN_PERMISSION_ACCESSLIST_TYPE_H__

View File

@ -0,0 +1,107 @@
/*---------------------------------------------------------------------------*
Project: wfskrn
File: wfs_Permission.h
Copyright 2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Permission_File.h,v $
Revision 1.9 2008/07/23 04:18:07 ueno
Reduced memory size required for accesslist.
Revision 1.8 2008/05/23 06:31:52 ueno
Cleanup.
Revision 1.7 2008/05/22 06:36:01 ueno
Ported permission APIs to IOP.
Revision 1.6 2008/05/19 10:12:05 ueno
Revised not to use hardlink.
Revision 1.5 2008/05/15 13:33:46 ueno
Implemented initialization using directory module.
Revision 1.4 2008/04/29 06:25:14 ueno
Cleanup.
Revision 1.3 2008/04/25 06:22:55 ueno
Cleanup.
Revision 1.2 2008/04/25 01:22:46 ueno
Moved from RVL_SDK to RM_SDK.
Revision 1.12 2008/04/23 08:59:55 ueno
Replaced WFSAreaHdr by AreaInfo.
Revised directory permission (change -> add).
Revision 1.11 2008/04/21 06:07:55 ueno
Fixed struct for C99.
Revision 1.10 2008/04/15 06:45:48 ueno
Changed return type to WFSKrnResult.
Revision 1.9 2008/04/11 06:16:33 ueno
Defined WFSAclFileHandle.
Cleaned up headers.
Revision 1.8 2008/03/14 08:02:49 ueno
Revised API prefixes (WFS -> WFSKrn).
Revision 1.7 2008/03/11 12:10:35 ueno
Cleanup.
Revision 1.6 2008/02/29 07:28:45 ueno
Added Windows api wrappers.
Revision 1.5 2008/02/27 13:12:23 ueno
Revised to store a filename of an accesslist in a file (*.name).
Revision 1.4 2008/02/27 10:05:26 ueno
Revised to use WFSAreaHdr{} to specifiy WFS area.
Revision 1.3 2008/02/26 14:12:06 ueno
Added WFSAccessListAddEntry() and WFSAccessListRemoveEntry() to edit accesslist.
Revision 1.2 2008/02/25 09:44:08 ueno
Added support for accesslist cache.
Revision 1.1 2008/02/22 05:15:56 ueno
Initial Check-in.
*---------------------------------------------------------------------------*/
#ifndef __WFSKRN_PERMISSION_FILE_H__
#define __WFSKRN_PERMISSION_FILE_H__
#include <revolution/wfs.h>
#include "wfssrv_Defs.h"
#include "wfskrn_Area.h"
#include "wfskrn_Permission_Type.h"
#ifndef WFSDEV
#define IndexDirInfo(x) (((x)->accessListCb->indexDirInfo))
#endif // WFSDEV
int WFSKrnConvertAccessListToFilename(const WFSKrnAccessList* list, utf8* filename, u32 size);
int WFSKrnConvertFilenameToAccessList(const utf8* filename, u32 size, WFSKrnAccessList* list);
int WFSKrnAccessListIndexListInit(const AreaInfo* area);
int WFSKrnAccessListIndexListExit(const AreaInfo* area);
int WFSKrnAccessListCreateFile(const AreaInfo* area, const utf8* filename, WFSKrnAccessList** list);
WFSKrnResult WFSKrnAccessListDeleteFile(const AreaInfo* area, u32 index);
WFSKrnAccessList* WFSKrnAccessListLookupFile(const AreaInfo* area, u32 index);
WFSKrnResult WFSKrnAccessListSetFileReferenceCount(const AreaInfo* area, u32 index, u32 ref);
WFSKrnResult WFSKrnAccessListGetFileReferenceCount(const AreaInfo* area, u32 index, u32* ref);
int WFSKrnAccessListOpenList(const AreaInfo* area, const utf8* filename, AclFileInfo* aclFile,
WFSBool create, WFSAclFileHandle *pFh);
int GetAccessListIndex(const AreaInfo* area, WFSAclFileHandle indexListHandle, WFSKrnAclHandle handle, IndexListEntry* entry);
int OpenIndexList(const AreaInfo* area, WFSAclFileHandle* indexListHandle, AclFileInfo* indexListInfo);
int CloseIndexList(const AreaInfo* area, WFSAclFileHandle indexListHandle);
#endif // __WFSKRN_PERMISSION_FILE_H__

View File

@ -0,0 +1,123 @@
/*---------------------------------------------------------------------------*
Project: wfsKrn
File: wfs_Permission_Iop.h
Copyright 2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Permission_Iop.h,v $
Revision 1.7 2008/09/24 07:32:07 ueno
Added AclHdr{} to AreaHdr{} to save configuration of accesslists in a disk.
Revision 1.6 2008/07/23 04:18:07 ueno
Reduced memory size required for accesslist.
Revision 1.5 2008/05/22 06:36:01 ueno
Ported permission APIs to IOP.
Revision 1.4 2008/05/19 10:12:05 ueno
Revised not to use hardlink.
Revision 1.3 2008/05/19 05:31:53 ueno
Defined accesslist meta-data types.
Revision 1.2 2008/05/15 13:33:46 ueno
Implemented initialization using directory module.
Revision 1.1 2008/05/06 07:38:27 ueno
Initial Check-in.
Revision 1.6 2008/04/29 06:25:14 ueno
Cleanup.
Revision 1.5 2008/04/29 01:12:54 ueno
Defined WFS_ROOT_ID and WFS_EVERYONE_ID.
Revision 1.4 2008/04/25 06:22:55 ueno
Cleanup.
Revision 1.3 2008/04/25 04:40:47 ueno
Added support for WFSDEV.
Revision 1.10 2008/04/23 08:59:55 ueno
Replaced WFSAreaHdr by AreaInfo.
Revised directory permission (change -> add).
Revision 1.9 2008/04/11 06:16:33 ueno
Defined WFSAclFileHandle.
Cleaned up headers.
Revision 1.8 2008/04/07 09:17:44 ueno
Modified WFSKrnAccessListDirectoryInit() to return an integer.
Revision 1.7 2008/04/03 09:59:41 ueno
Cleanup.
Revision 1.6 2008/03/14 08:02:49 ueno
Revised API prefixes (WFS -> WFSKrn).
Revision 1.5 2008/02/29 07:28:45 ueno
Added Windows api wrappers.
Revision 1.4 2008/02/28 13:11:58 ueno
Revised to keep accesslist cache and indexlist handle in WFSAreaHdr{}.
Revision 1.3 2008/02/27 13:12:24 ueno
Revised to store a filename of an accesslist in a file (*.name).
Revision 1.2 2008/02/27 10:05:26 ueno
Revised to use WFSAreaHdr{} to specifiy WFS area.
Revision 1.1 2008/02/22 05:15:56 ueno
Initial Check-in.
*---------------------------------------------------------------------------*/
#ifndef __WFSKRN_PERMISSION_IOP_H__
#define __WFSKRN_PERMISSION_IOP_H__
#include <revolution/wfs.h>
#include "wfssrv_Defs.h"
#include "wfskrn_Area.h"
#include "wfskrn_Permission_Type.h"
#define INDEXLIST_FILENAME "index"
#define ACL_NAMEFILE_LEN 14 // including '\0'.
#define AclBlock(x) (((x)->ah.aclHdr.aclBlock))
#define NameBlock(x) (((x)->ah.aclHdr.nameBlock))
#define ACL_FILEINFO_NAME(aclFileInfo) ((aclFileInfo)->di.name.sStr)
int CreateNamefile(const AreaInfo* area, WFSKrnAclHandle handle, const AclNameFileHeader* header, const utf8* filename);
int DeleteNamefile(const AreaInfo* area, u32 index);
int ReadNamefile(const AreaInfo* area, WFSKrnAclHandle handle, void* buf, WFSFileSize size, WFSFileSize offset);
int WriteNamefile(const AreaInfo* area, WFSKrnAclHandle handle, const void* buf, WFSFileSize size, WFSFileSize offset);
int WFSKrnAccessListDirectoryInit(AreaInfo* area);
int WFSKrnAccessListGetAclFileInfo(const AreaInfo* area, const utf8* filename, u32 type, AclFileInfo* fileInfo);
int GetAccessListPath(const AreaInfo* area, AclFileInfo* aclFile);
//
// Wrapper
//
WFSResult AclGetFileSize(const AreaInfo* area, WFSAclFileHandle fh, WFSFileSize* fileSize);
WFSResult AclWriteFile(const AreaInfo* area, WFSAclFileHandle fh, const void *pFileData, WFSFileSize nSize, WFSFileSize offset);
s32 AclReadFile(const AreaInfo* area, WFSAclFileHandle fh, void *pFileDataBuffer, s32 nSize, WFSFileSize offset);
WFSResult AclCreateFile(const AreaInfo* area, const AclFileInfo* fileInfo, WFSBool create, WFSAclFileHandle *pFh);
WFSResult AclCloseFile(WFSAclFileHandle fh);
WFSResult AclDeleteAccessListFile(const AreaInfo* area, const AclFileInfo* aclFile);
WFSResult AclCreateAccessListFile(const AreaInfo* area, const AclFileInfo* aclFile, WFSBool create, WFSAclFileHandle *pFh);
WFSBool AclAccessListAlreadyExist(const AreaInfo* area, const AclFileInfo* aclFile);
#endif // __WFSKRN_PERMISSION_IOP_H__

View File

@ -0,0 +1,133 @@
/*---------------------------------------------------------------------------*
Project: wfskrn
File: wfs_Permission_Private.h
Copyright 2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Permission_Private.h,v $
Revision 1.8 2008/06/05 14:04:11 ueno
Modified to reserve accesslist index 0 as the default (empty) accesslist.
Revision 1.7 2008/06/05 08:09:18 ueno
Revised permission APIs.
Revision 1.6 2008/05/28 01:06:52 ueno
Added AclCheckDisk() to check acl meta-data.
Revision 1.5 2008/05/23 06:31:52 ueno
Cleanup.
Revision 1.4 2008/05/22 06:36:01 ueno
Ported permission APIs to IOP.
Revision 1.3 2008/04/29 01:12:54 ueno
Defined WFS_ROOT_ID and WFS_EVERYONE_ID.
Revision 1.2 2008/04/25 01:22:46 ueno
Moved from RVL_SDK to RM_SDK.
Revision 1.11 2008/04/23 08:59:55 ueno
Replaced WFSAreaHdr by AreaInfo.
Revised directory permission (change -> add).
Revision 1.10 2008/04/14 03:02:16 ueno
Modified WFSKrnCreateRootAccessList() to create an accesslist only for the root.
Added WFSKrnDebugCreateAccessList() for tests.
Revision 1.9 2008/04/11 06:16:33 ueno
Defined WFSAclFileHandle.
Cleaned up headers.
Revision 1.8 2008/04/11 04:54:06 ueno
Added WFSKRN_ACL_USE_MUTEX to switch mutex.
Revision 1.7 2008/04/09 03:01:27 ueno
Cleanup.
Revision 1.6 2008/04/08 06:39:41 ueno
Cleanup.
Revision 1.5 2008/04/01 08:25:10 ueno
Fixed cache reference count.
Revision 1.4 2008/03/18 13:42:39 ueno
Added a debug function.
Revision 1.3 2008/03/14 08:02:49 ueno
Revised API prefixes (WFS -> WFSKrn).
Revision 1.2 2008/03/07 05:31:07 ueno
Modified WFSCreateAccessList() to be able to create an accesslist for directories.
Revision 1.1 2008/03/06 10:47:12 ueno
New.
*---------------------------------------------------------------------------*/
#ifndef __WFSKRN_PERMISSION_PRIVATE_H__
#define __WFSKRN_PERMISSION_PRIVATE_H__
#include <revolution/wfs.h>
#include "wfssrv_Defs.h"
#include "wfskrn_Area.h"
// private APIs
#ifdef WFSDEV
int AclUtf8ToWchar(const utf8* utf8, LPWSTR wchar, u32 bytes);
int AclWcharToUtf8(const LPWSTR wchar, utf8* utf8, u32 bytes);
#endif // WFSDEV
void WFSKrnAccessListSetNum(WFSKrnAccessList* list, u32 num);
u32 WFSKrnAccessListGetNum(const WFSKrnAccessList* list);
WFSKrnResult WFSKrnAccessListAlloc(const AreaInfo* area, u32 numEntries, WFSKrnAccessList** list);
int WFSKrnAccessListFree(const AreaInfo* area, WFSKrnAccessList* list);
int WFSKrnAllocAccessListIndex(const AreaInfo* area, u32 indexFlags, u32* newIndex, u32 num);
int WFSKrnFreeAccessListIndex(const AreaInfo* area, u32 index);
void WFSKrnAccessListCacheAdd(const AreaInfo* area, WFSKrnAccessList* list);
void WFSKrnAccessListCacheRemove(const AreaInfo* area, WFSKrnAccessList* list);
void WFSKrnAccessListCacheFreeListRemove(const AreaInfo* area, WFSKrnAccessList* list);
WFSKrnAccessList* WFSKrnAccessListLookup(const AreaInfo* area, u32 index);
WFSKrnAccessList* WFSKrnAccessListLookupByIndex(const AreaInfo* area, u32 index);
// debug functions.
WFSBool VerifyMemoryBlock(const AreaInfo* area);
void PrintMemoryBlock(const AreaInfo* area);
void WFSKrnDebugPrintAccessList(const AreaInfo* area, u32 index);
s32 AclDirList(const AreaInfo* area, WFSBlkAdr block);
WFSKrnResult AclCheckDisk(const AreaInfo* area);
//--------------------------------------------------------------------------------------------------------------
// WFSKrnDebugCreateAccessList
//--------------------------------------------------------------------------------------------------------------
// Arguments:
// ----------
// area .. [in] A WFS area.
// aclType .. [in] ACL_FLAG_DIRECTORY (directory) or 0 (file).
// titleId .. [in] The first title in the accesslist to be created.
// nFlags .. [in] permissions and control levels (WFS_PERM_*)
// newHandle .. [out] Pointer to the new accesslist handle.
//
// Return Values:
// --------------
// WFSKRN_RESULT_OK .. success
// WFSKRN_RESULT_INVALID
// WFSKRN_RESULT_ACL_ERROR
// WFSKRN_RESULT_ACL_MAX_ENTRIES
// WFSKRN_RESULT_ACL_FILE
//
// Description:
// ------------
// This function creates an accesslist.
WFSKrnResult WFSKrnDebugCreateAccessList(const AreaInfo* area, u32 aclType,
WFSTitleId entryCreatorId, WFSTitleId titleId, u32 nFlags, WFSKrnAclHandle* newHandle);
#endif // __WFSKRN_PERMISSION_PRIVATE_H__

View File

@ -0,0 +1,137 @@
/*---------------------------------------------------------------------------*
Project: wfskrn
File: wfs_Permission_Type.h
Copyright 2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Permission_Type.h,v $
Revision 1.12 2008/07/23 04:18:07 ueno
Reduced memory size required for accesslist.
Revision 1.11 2008/07/23 02:01:51 ueno
Modified to use mutex on Windows.
Revision 1.10 2008/05/30 08:50:35 ueno
Disabled mutex for IOP.
Revision 1.9 2008/05/23 06:31:52 ueno
Cleanup.
Revision 1.8 2008/05/22 06:36:01 ueno
Ported permission APIs to IOP.
Revision 1.7 2008/05/19 10:12:05 ueno
Revised not to use hardlink.
Revision 1.6 2008/05/19 05:31:53 ueno
Defined accesslist meta-data types.
Revision 1.5 2008/05/16 11:16:58 ueno
Implemented permission APIs with directory module.
Revision 1.4 2008/05/15 13:33:46 ueno
Implemented initialization using directory module.
Revision 1.3 2008/05/06 02:27:21 ueno
Fixed ifdef.
Revision 1.2 2008/04/29 06:25:14 ueno
Cleanup.
Revision 1.1 2008/04/22 04:39:08 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.1 2008/04/11 06:16:33 ueno
Defined WFSAclFileHandle.
Cleaned up headers.
*---------------------------------------------------------------------------*/
#ifndef __WFSKRN_PERMISSION_TYPE_H__
#define __WFSKRN_PERMISSION_TYPE_H__
#include <revolution/wfs.h>
#include "wfskrn_Dir.h"
#include "wfskrn_Handles.h"
#include "wfskrn_DirFind.h"
#include "wfskrn_DirNodeStack.h"
// access list handle
typedef u32 WFSKrnAclHandle;
#if _WIN32
// The maximum path length of an emulation directory is WFSKRN_MAX_PATH_NAME_SIZE.
#define WFSKRN_ACCESSLIST_MAX_PATH_LEN ((WFS_MAX_PATH_NAME_SIZE+1)*2)
#else
#define WFSKRN_ACCESSLIST_MAX_PATH_LEN (WFS_MAX_PATH_NAME_SIZE+1)
#endif // _WIN32
// type of metadata.
#define ACL_TYPE_INDEXLIST 1
#define ACL_TYPE_NAMEFILE 2
#define ACL_TYPE_ACLFILE 3
typedef struct AclFileInfo
{
u32 type; // ACL_TYPE_*
#ifdef WFSDEV
utf8 path[WFSKRN_ACCESSLIST_MAX_PATH_LEN];
#else
DirItr di;
#endif // WIN32
} AclFileInfo;
typedef struct AclNameFileHeader
{
u32 num; // The number of titles in this list.
u32 ref; // The number of files and directories associated with this accesslist.
} AclNameFileHeader;
// file handle
#ifdef WFSDEV
typedef HANDLE WFSAclFileHandle;
#else // WFSDEV
typedef AclFileInfo* WFSAclFileHandle;
#endif // WFSDEV
// mutex
// #define WFSKRN_ACL_USE_MUTEX // [check] how to use mutex on IOP?
#ifdef WFSKRN_ACL_USE_MUTEX
#include "wfskrn_Mutex.h"
#define WFSAclInitMutex(x) WFSKrnInitMutex(x)
#define WFSAclLockMutex(x) WFSKrnLockMutex(x)
#define WFSAclUnlockMutex(x) WFSKrnUnlockMutex(x)
#else
#define WFSAclInitMutex(x)
#define WFSAclLockMutex(x)
#define WFSAclUnlockMutex(x)
#endif
// print message
#define WFSKRN_ACL_DEBUG
#ifdef WFSKRN_ACL_DEBUG
#ifdef WIN32
#define WFSKRN_ACL_ASSERT(x) assert(x)
#else // Win32
#define WFSKRN_ACL_ASSERT(x) ASSERT(x)
#endif // WIN32
#define WFSKRN_ACL_REPORT printf
#else // WFSKRN_ACL_DEBUG
#define WFSKRN_ACL_ASSERT(x)
#define WFSKRN_ACL_REPORT
#endif // WFSKRN_ACL_DEBUG
#endif // __WFSKRN_PERMISSION_TYPE_H__

View File

@ -0,0 +1,127 @@
/*---------------------------------------------------------------------------*
Project: wfsKrn
File: wfs_Permission_Win32.h
Copyright 2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Permission_Win32.h,v $
Revision 1.13 2008/09/24 07:32:07 ueno
Added AclHdr{} to AreaHdr{} to save configuration of accesslists in a disk.
Revision 1.12 2008/05/19 10:12:05 ueno
Revised not to use hardlink.
Revision 1.11 2008/05/19 05:31:53 ueno
Defined accesslist meta-data types.
Revision 1.10 2008/05/15 13:33:46 ueno
Implemented initialization using directory module.
Revision 1.9 2008/05/08 08:08:02 ueno
Revised AclReadFile() and AclWriteFile() to set offset.
Revision 1.8 2008/05/06 03:16:07 ueno
Added AclGetFileSize() to wrap Windows API..
Revision 1.7 2008/05/06 02:27:21 ueno
Fixed ifdef.
Revision 1.6 2008/04/29 06:25:14 ueno
Cleanup.
Revision 1.5 2008/04/29 01:12:54 ueno
Defined WFS_ROOT_ID and WFS_EVERYONE_ID.
Revision 1.4 2008/04/25 06:22:55 ueno
Cleanup.
Revision 1.3 2008/04/25 04:40:47 ueno
Added support for WFSDEV.
Revision 1.10 2008/04/23 08:59:55 ueno
Replaced WFSAreaHdr by AreaInfo.
Revised directory permission (change -> add).
Revision 1.9 2008/04/11 06:16:33 ueno
Defined WFSAclFileHandle.
Cleaned up headers.
Revision 1.8 2008/04/07 09:17:44 ueno
Modified WFSKrnAccessListDirectoryInit() to return an integer.
Revision 1.7 2008/04/03 09:59:41 ueno
Cleanup.
Revision 1.6 2008/03/14 08:02:49 ueno
Revised API prefixes (WFS -> WFSKrn).
Revision 1.5 2008/02/29 07:28:45 ueno
Added Windows api wrappers.
Revision 1.4 2008/02/28 13:11:58 ueno
Revised to keep accesslist cache and indexlist handle in WFSAreaHdr{}.
Revision 1.3 2008/02/27 13:12:24 ueno
Revised to store a filename of an accesslist in a file (*.name).
Revision 1.2 2008/02/27 10:05:26 ueno
Revised to use WFSAreaHdr{} to specifiy WFS area.
Revision 1.1 2008/02/22 05:15:56 ueno
Initial Check-in.
*---------------------------------------------------------------------------*/
#ifndef __WFSKRN_PERMISSION_WIN32_H__
#define __WFSKRN_PERMISSION_WIN32_H__
#include <revolution/wfs.h>
#include "wfs_Client.h"
#include "wfskrn_Area.h"
#include "wfskrn_Permission_Type.h"
#define LONGPATH_PREFIX L"\\\\?\\"
#define ACCESSLIST_DIR ".WFSAccessLists"
#define ACCESSLIST_DIR_WCHAR L".WFSAccessLists"
#define INDEXLIST_FILENAME ".wfsaccesslist_indexlist"
#define NAMEFILE_DIR "name"
#define NAMEFILE_DIR_WCHAR L"name"
WFSBool AlreadyExist(const LPWSTR path);
int Utf8ToWcharAccessList(const AreaInfo* area, const utf8* path, LPWSTR wPath, u32 wPathLen);
int EscapeAccessListToWideChar(const char* encoded, LPWSTR wPath, u32 size);
int UnescapeAccessListFromWideChar(const LPWSTR wPath, utf8* encoded, u32 size);
int CreateNamefile(const AreaInfo* area, WFSKrnAclHandle handle, const AclNameFileHeader* header, const utf8* filename);
int DeleteNamefile(const AreaInfo* area, u32 index);
int ReadNamefile(const AreaInfo* area, WFSKrnAclHandle handle, void* buf, WFSFileSize size, WFSFileSize offset);
int WriteNamefile(const AreaInfo* area, WFSKrnAclHandle handle, const void* buf, WFSFileSize size, WFSFileSize offset);
int WFSKrnAccessListDirectoryInit(AreaInfo* area);
int WFSKrnAccessListGetAclFileInfo(const AreaInfo* area, const utf8* filename, u32 type, AclFileInfo* fileInfo);
int GetAccessListPath(const AreaInfo* area, AclFileInfo* aclFile);
//
// Wrapper
//
WFSResult AclGetFileSize(const AreaInfo* area, WFSAclFileHandle fh, WFSFileSize* fileSize);
WFSResult AclWriteFile(const AreaInfo* area, WFSAclFileHandle fh, const void *pFileData, WFSFileSize nSize, WFSFileSize offset);
s32 AclReadFile(const AreaInfo* area, WFSAclFileHandle fh, void *pFileDataBuffer, s32 nSize, WFSFileSize offset);
WFSResult AclCreateFile(const AreaInfo* area, const AclFileInfo* fileInfo, WFSBool create, WFSAclFileHandle *pFh);
WFSResult AclCloseFile(WFSAclFileHandle fh);
WFSResult AclDeleteAccessListFile(const AreaInfo* area, const AclFileInfo* aclFile);
WFSResult AclCreateAccessListFile(const AreaInfo* area, const AclFileInfo* aclFile, WFSBool create, WFSAclFileHandle *pFh);
WFSBool AclAccessListAlreadyExist(const AreaInfo* area, const AclFileInfo* aclFile);
#endif // __WFSKRN_PERMISSION_WIN32_H__

View File

@ -0,0 +1,176 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_Platform.h - low level definitions and types that are primarily platform dependent
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Platform.h,v $
Revision 1.6 2008/08/27 04:05:21 nakanose_jin
change ospanic definision
Revision 1.5 2008/07/14 01:01:11 kondo_masahiro
Removed _STRICMP
Revision 1.4 2008/06/26 05:37:33 kondo_masahiro
Added function _STRICMP().
Revision 1.3 2008/05/10 04:00:48 kondo_masahiro
Merged and fixed code to accept RM compiler
Revision 1.2 2008/04/25 17:26:30 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.1 2008/04/22 04:39:08 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.4 2008/04/26 05:36:11 paul
Added _ATTRIBUTE_PACKED
Revision 1.3 2008/04/19 05:47:36 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.2 2008/02/28 06:32:17 kondo_masahiro
Fixed code to accept PPC compiler
Revision 1.1 2007/11/05 19:03:13 paul
first checkin
*---------------------------------------------------------------------------*/
#ifndef wfskrn_Platform_h
#define wfskrn_Platform_h
#include <firm.h>
//--twl modified
#define TWL 1
#if 1
#define _OSX 0
#define _WIN32 0
#define _TWL 1
#define _RVL 0
#define _IOP 0
#else
//--twl modified
#ifdef OSX
#define _OSX 1
#define _WIN32 0
#define _RVL 0
#define _IOP 0
#else
#ifdef WIN32
#define _OSX 0
#define _WIN32 1
#define _RVL 0
#define _IOP 0
#else
#ifdef IOP
#define _OSX 0
#define _WIN32 0
#define _RVL 0
#define _IOP 1
#elif RVL
#define _OSX 0
#define _WIN32 0
#define _RVL 1
#define _IOP 0
#endif
#endif
#endif
#endif //twl modified
// Although the cache line size depends on the platform, it is fixed to
// the IOP cache line size, since the goal is not to optimize for different
// platforms, but rather to use other platforms as a development aid.
#define WFS_CPU_CACHE_LINE_SIZE (1<<5)
#if _WIN32
#pragma warning (3: 4101)
#pragma warning (3: 4189)
#pragma warning(disable:4996)
#define _ATTRIBUTE_PACKED
#define BYTES_PER_INT 4
#define BITS_PER_INT 32
#define BIT_OFFSET_MASK 31
#define BIT_OFFSET_TO_INT_OFFSET_SHIFT 5
#define MAX max
#define MIN min
//#define OSReport printf
#include "WinOSReport.h"
#define OSPanic MyOSPanic
#define SNPRINTF _snprintf
#define STRNLEN( str, maxlen ) strlen(str)
#define _ATTRIBUTE_PACKED
#elif _OSX
#define BYTES_PER_INT 4
#define BITS_PER_INT 32
#define BIT_OFFSET_MASK 31
#define BIT_OFFSET_TO_INT_OFFSET_SHIFT 5
//#define OSReport printf
#include "WinOSReport.h"
#define OSPanic MyOSReport
#define SNPRINTF snprintf
#define STRNLEN( str, maxlen ) strlen(str)
#define _ATTRIBUTE_PACKED
//-- twl modified
#elif _TWL
#define BYTES_PER_INT 4
#define BITS_PER_INT 32
#define BIT_OFFSET_MASK 31
#define BIT_OFFSET_TO_INT_OFFSET_SHIFT 5
#define MAX(a,b) (((a)>(b))?(a):(b))
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MyOSReport osTPrintf
#define InitMyOSReport()
#define SNPRINTF OS_SNPrintf
#define STRNLEN( str, maxlen ) stdStrNLen(str, maxlen)
#define _ATTRIBUTE_PACKED
//-- twl modified
#elif _RVL
#pragma warn_unusedarg off
#pragma warn_implicitconv off
#pragma warn_possunwant off
#include <ctype.h>
#define BYTES_PER_INT 4
#define BITS_PER_INT 32
#define BIT_OFFSET_MASK 31
#define BIT_OFFSET_TO_INT_OFFSET_SHIFT 5
#define MAX(a,b) (((a)>(b))?(a):(b))
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MyOSReport OSReport
#define InitMyOSReport()
#define SNPRINTF snprintf
#define STRNLEN( str, maxlen ) strlen(str)
#define _ATTRIBUTE_PACKED
#elif _IOP
#define BYTES_PER_INT 4
#define BITS_PER_INT 32
#define BIT_OFFSET_MASK 31
#define BIT_OFFSET_TO_INT_OFFSET_SHIFT 5
#define MAX(a,b) (((a)>(b))?(a):(b))
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MyOSReport printf
#define InitMyOSReport()
#define SNPRINTF snprintf
#define STRNLEN( str, maxlen ) strnlen( str, maxlen )
#define _ATTRIBUTE_PACKED __attribute__((packed))
#endif // WIN32
#ifndef BIG_ENDIAN
#ifdef WIN32
#define BIG_ENDIAN 0
#elif TWL
#define BIG_ENDIAN 0
#else
#define BIG_ENDIAN 1
#endif // WIN32
#endif // BIG_ENDIAN
#endif //define wfskrn_Platform_h

View File

@ -0,0 +1,96 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_SubBlkAlloc.h - Memory Managed Blocks, and functions for allocating sub blocks from them
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_SubBlkAlloc.h,v $
Revision 1.6 2008/09/28 23:30:46 kondo_masahiro
Fixed codes to use medium size user block.
Revision 1.5 2008/08/27 10:01:32 paul
Removed nTotalFree from block header
Revision 1.4 2008/07/14 23:03:11 paul
Changed<EFBFBD>@nOfs to use u16
Revision 1.3 2008/06/09 18:11:14 paul
Changed SbaBlkInit() to support blocks with different header sizes
Revision 1.2 2008/04/25 17:26:24 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.1 2008/04/22 04:39:08 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.3 2008/04/19 05:47:18 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.2 2008/04/05 03:23:05 paul
Added extra check functions
Revision 1.1 2008/02/21 00:06:19 paul
*** empty log message ***
*---------------------------------------------------------------------------*/
#ifndef wfskrn_SubBlkAlloc_h
#define wfskrn_SubBlkAlloc_h
#include "wfskrn_Defs.h"
#include "wfskrn_Area.h"
#ifdef _DEBUG
#define _DEBUG_SUB_BLK_ALLOC 0 // change to 1 if debug info required
#else
#define _DEBUG_SUB_BLK_ALLOC 0
#endif
#define SBA_MIN_LOG2_SUB_BLK_SIZE 3
#define SBA_MAX_LOG2_SUB_BLK_SIZE 11
#define SBA_MAX_LOG2_SUB_BLK_SIZE_FOR_MIDDLE 10
#define SBA_NUM_SUB_BLK_SIZES (SBA_MAX_LOG2_SUB_BLK_SIZE - SBA_MIN_LOG2_SUB_BLK_SIZE + 1)
//#define SBA_FREE_SUB_BLK_MAGIC 0xFEDCBAF8
#define SBA_FREE_SUB_BLK_MAGIC 0xFEDC // NOTE: This magic number is used to mark free sub blocks. It must not represent valid data for any in-use sub blocks using this allocator.
typedef struct {
WFSIntraBlkOfs nNumFree;
WFSIntraBlkOfs nFirstFree;
} WFSSubBlkList;
typedef struct {
WFSMetaDataHdr mdh;
WFSSubBlkList aSubBlkList[SBA_NUM_SUB_BLK_SIZES];
#if _DEBUG_SUB_BLK_ALLOC
WFSIntraBlkOfs nTotalFree;
u16 pad;
#endif
} WFSSubBlkAllocHdr;
typedef struct {
u16 nMagic;
u16 nNext;
u16 nPrev;
u16 nLog2Size;
} WFSSubBlkFreeHdr;
void SbaCheckOfs(u16 nOfs);
void SbaRemoveSubBlkFromFreeList(WFSSubBlkAllocHdr *pBlkHdr, u16 nOfs, u32 nLog2Size);
u16 SbaAllocSubBlk(WFSSubBlkAllocHdr *pBlkHdr, u32 nLog2Size);
WFSKrnResult SbaAllocSubBlks(WFSSubBlkAllocHdr *pBlkHdr, u32 nLog2Size, u16 aSubBlkOfs[], u32 nNumSubBlks);
void SbaFreeSubBlk(WFSSubBlkAllocHdr *pBlkHdr, u16 nOfs, u32 nLog2Size);
void SbaReduceSubBlkSize(WFSSubBlkAllocHdr *pBlkHdr, u16 nOfs, u32 nOldLog2Size, u32 nNewLog2Size);
WFSSubBlkAllocHdr *SbaBlkInit(void *pBlk, u32 nLog2BlkSize, u32 nLog2HdrSize);
u32 SbaCountFreeSpace(WFSSubBlkAllocHdr *pBlkHdr);
u32 SbaCheckFreeSpace(WFSSubBlkAllocHdr *pBlkHdr, u32 *aUtilization);
#endif //wfskrn_SubBlkAlloc_h

View File

@ -0,0 +1,197 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_Trans.h - Provides access to blocks for transactions including re-mapping functionality
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Trans.h,v $
Revision 1.17 2008/12/18 09:03:37 kondo_masahiro
Fixed function name and process from BCacheSetBlkAdr() to BCacheRemap()
Revision 1.16 2008/12/17 01:37:41 kondo_masahiro
Added function BCacheSetBlkAdr()
Revision 1.15 2008/11/26 01:44:35 kondo_masahiro
Fixed arguments of several functions in order to improve access speed.
Revision 1.14 2008/11/05 15:03:40 ueno
Fixed a typo.
Revision 1.13 2008/11/05 05:55:23 kondo_masahiro
Added TransSetChainId()
Revision 1.12 2008/10/21 09:50:09 kondo_masahiro
Added new function WFSWriteFileAndDiscard
Revision 1.11 2008/10/17 08:51:27 kondo_masahiro
Added the new MEDIUM size category (40KB-320KB)
Revision 1.10 2008/10/14 10:27:44 kondo_masahiro
Added codes to access very large size file data
Revision 1.9 2008/10/10 02:11:31 kondo_masahiro
Fixed a bug to access large files
Revision 1.8 2008/10/08 23:20:09 kondo_masahiro
Added codes to access large size file data
Revision 1.7 2008/10/03 08:37:18 kondo_masahiro
Fixed codes for porting IOP
Revision 1.6 2008/09/28 23:30:51 kondo_masahiro
Fixed codes to use medium size user block.
Revision 1.5 2008/08/27 09:50:04 paul
Started coding to differentiate File/Meta-data blocks
Revision 1.4 2008/08/06 05:28:46 kondo_masahiro
Added debug flags for hash and detach test.
Revision 1.3 2008/07/25 02:57:22 paul
Added TransInfo, TansBegin(), TransEnd()
Revision 1.2 2008/07/17 05:14:51 kondo_masahiro
Fixed codes for porting IOP.
Revision 1.1 2008/07/09 01:48:14 paul
First checkin of transaction API. Currently has no re-mapping.
*---------------------------------------------------------------------------*/
#ifndef wfs_Trans_h
#define wfs_Trans_h
#include "wfskrn_Area.h"
#define TRANS_FLAG_READ_BLK BCACHE_FLAG_READ // Use this flag unless you are ignoring/overwriting any existing data in the blcok
#define TRANS_FLAG_WRITE_BLK BCACHE_FLAG_DIRTY // Use this flag if you intend to write to the block
#define TRANS_FLAG_RW_BLK (BCACHE_FLAG_READ | BCACHE_FLAG_DIRTY) // Use this flag unless you are ignoring/overwriting any existing data in the blcok
typedef struct {
struct TransInfo_ *pNext;
struct TransInfo_ *pPrev;
} TransInfoLink;
typedef struct TransInfo_ {
TransInfoLink link;
WFSTitleId nTitleId;
} TransInfo;
typedef struct {
AreaInfo *pAreaInfo; // Area info
WFSBlkAdr nBlkAdr; // Block address
TransInfo *pTransInfo; // Transaction info
} TransBlkAdr;
void TransModuleInit();
TransInfo *TransBegin();
void TransEnd(TransInfo *pTransInfo);
WFSKrnResult TransGetBlk5(AreaInfo *pAreaInfo, WFSBlkAdr nBlkAdr, TransInfo *pTransInfo, u32 nFlags, void **ppBlkPtr);
static inline WFSKrnResult TransGetBlk(TransBlkAdr *pTba, u32 nFlags, void **ppBlkPtr) {
return TransGetBlk5(pTba->pAreaInfo, pTba->nBlkAdr, pTba->pTransInfo, nFlags, ppBlkPtr);
}
WFSKrnResult TransGetAndPinBlk5(AreaInfo *pAreaInfo, WFSBlkAdr nBlkAdr, TransInfo *pTransInfo, u32 nFlags, void **ppBlkPtr);
static inline WFSKrnResult TransGetAndPinBlk(TransBlkAdr *pTba, u32 nFlags, void **ppBlkPtr) {
return TransGetAndPinBlk5(pTba->pAreaInfo, pTba->nBlkAdr, pTba->pTransInfo, nFlags, ppBlkPtr);
}
WFSKrnResult TransSetChainId4(AreaInfo *pAreaInfo, WFSBlkAdr nBlkAdr, TransInfo *pTransInfo, u32 nChainId);
static inline WFSKrnResult TransSetChainId(TransBlkAdr *pTba, u32 nChainId) {
return TransSetChainId4(pTba->pAreaInfo, pTba->nBlkAdr, pTba->pTransInfo, nChainId);
}
WFSKrnResult TransGetChainId4(AreaInfo *pAreaInfo, WFSBlkAdr nBlkAdr, TransInfo *pTransInfo, u32 *pChainId);
static inline WFSKrnResult TransGetChainId(TransBlkAdr *pTba, u32 *pChainId) {
return TransGetChainId4(pTba->pAreaInfo, pTba->nBlkAdr, pTba->pTransInfo, pChainId);
}
WFSKrnResult TransUnpinBlk3(AreaInfo *pAreaInfo, WFSBlkAdr nBlkAdr, TransInfo *pTransInfo);
static inline WFSKrnResult TransUnpinBlk(TransBlkAdr *pTba) {
return TransUnpinBlk3(pTba->pAreaInfo, pTba->nBlkAdr, pTba->pTransInfo);
}
WFSKrnResult TransDirtyBlk3(AreaInfo *pAreaInfo, WFSBlkAdr nBlkAdr, TransInfo *pTransInfo);
static inline WFSKrnResult TransDirtyBlk(TransBlkAdr *pTba) {
return TransDirtyBlk3(pTba->pAreaInfo, pTba->nBlkAdr, pTba->pTransInfo);
}
WFSKrnResult TransFreeBlks6(AreaInfo *pAreaInfo, u32 nLog2BlkSize, u32 nNumBlks, WFSBlkAdr *pBlkAdr, s32 nStride, TransInfo *pTransInfo);
static inline WFSKrnResult TransFreeBlks5(AreaInfo *pAreaInfo, u32 nLog2BlkSize, u32 nNumBlks, WFSBlkAdr aBlkAdr[], TransInfo *pTransInfo) {
return TransFreeBlks6(pAreaInfo, nLog2BlkSize, nNumBlks, aBlkAdr, sizeof(WFSBlkAdr), pTransInfo);
}
WFSKrnResult TransUnpinAndFreeBlks(AreaInfo *pAreaInfo, u32 nLog2BlkSize, u32 nNumBlks, WFSBlkAdr aBlkAdr[], TransInfo *pTransInfo);
WFSKrnResult TransStoreBlk3(AreaInfo *pAreaInfo, WFSBlkAdr nBlkAdr, TransInfo *pTransInfo);
static inline WFSKrnResult TransStoreBlk(TransBlkAdr *pTba) {
return TransStoreBlk3(pTba->pAreaInfo, pTba->nBlkAdr, pTba->pTransInfo);
}
WFSKrnResult TransFlushBlk3(AreaInfo *pAreaInfo, WFSBlkAdr nBlkAdr, TransInfo *pTransInfo);
static inline WFSKrnResult TransFlushBlk(TransBlkAdr *pTba) {
return TransFlushBlk3(pTba->pAreaInfo, pTba->nBlkAdr, pTba->pTransInfo);
}
WFSKrnResult TransGetFileBlk6(AreaInfo *pAreaInfo, WFSBlkAdr nBlkAdr, TransInfo *pTransInfo, u32 nFlags, void **ppBlkPtr, WFSHashCode *pHash);
static inline WFSKrnResult TransGetFileBlk(TransBlkAdr *pTba, u32 nFlags, void **ppBlkPtr, WFSHashCode *pHash) {
return TransGetFileBlk6(pTba->pAreaInfo, pTba->nBlkAdr, pTba->pTransInfo, nFlags, ppBlkPtr, pHash);
}
WFSKrnResult TransGetAndPinFileBlk8(AreaInfo *pAreaInfo, WFSBlkAdr nParentBlkAdr, u16 nHashOfs,
WFSBlkAdr nFileBlkAdr, TransInfo *pTransInfo, u32 nFlags, u32 nValidSize, u32 nBCacheGroupId, void **ppBlkPtr);
static inline WFSKrnResult TransGetAndPinFileBlk(TransBlkAdr *pTba, WFSBlkAdr nParentBlkAdr, u16 nHashOfs, WFSBlkAdr nFileBlkAdr, u32 nFlags, u32 nValidSize, void **ppBlkPtr) {
return TransGetAndPinFileBlk8(pTba->pAreaInfo, nParentBlkAdr, nHashOfs, nFileBlkAdr, pTba->pTransInfo, nFlags, nValidSize, BCACHE_GROUP_ID_USERBLK_8K, ppBlkPtr);
}
static inline WFSKrnResult TransGetAndPinFileMediumBlk(TransBlkAdr *pTba, WFSBlkAdr nParentBlkAdr, u16 nHashOfs, WFSBlkAdr nFileBlkAdr, u32 nFlags, u32 nValidSize, void **ppBlkPtr) {
return TransGetAndPinFileBlk8(pTba->pAreaInfo, nParentBlkAdr, nHashOfs, nFileBlkAdr, pTba->pTransInfo, nFlags, nValidSize, BCACHE_GROUP_ID_USERBLK_64K, ppBlkPtr);
}
WFSKrnResult TransUnpinFileBlk3(AreaInfo *pAreaInfo, WFSBlkAdr nFileBlkAdr, TransInfo *pTransInfo);
static inline WFSKrnResult TransUnpinFileBlk(TransBlkAdr *pTba, WFSBlkAdr nFileBlkAdr) {
return TransUnpinFileBlk3(pTba->pAreaInfo, nFileBlkAdr, pTba->pTransInfo);
}
WFSKrnResult TransInvalidate3(AreaInfo *pAreaInfo, WFSBlkAdr nBlkAdr, TransInfo *pTransInfo);
WFSKrnResult TransSetValidSize4(AreaInfo *pAreaInfo, WFSBlkAdr nBlkAdr, TransInfo *pTransInfo, u32 nValidSize);
WFSKrnResult TransRemapCache6(AreaInfo *pAreaInfo, WFSBlkAdr nSrcBlkAdr, TransInfo *pTransInfo, WFSBlkAdr nDstBlkAdr, WFSBlkAdr nHashBlkAdr, u32 nHashOfs);
WFSKrnResult TransReadFileBlks7(u8 *pAlignedPtr, AreaInfo *pAreaInfo, u32 nLog2BlkSize, u32 nSize, WFSFileBlkPtr *pFileBlkPtr, s32 nStride, TransInfo *pTransInfo);
static inline WFSKrnResult TransReadFileBlks(u8 *pAlignedPtr, AreaInfo *pAreaInfo, u32 nSize, WFSFileBlkPtr *pFileBlkPtr, s32 nStride, TransInfo *pTransInfo){
return TransReadFileBlks7(pAlignedPtr, pAreaInfo, pAreaInfo->ah.nLog2BlkSize, nSize, pFileBlkPtr, nStride, pTransInfo);
}
static inline WFSKrnResult TransReadFileMediumBlks(u8 *pAlignedPtr, AreaInfo *pAreaInfo, u32 nSize, WFSFileBlkPtr *pFileBlkPtr, s32 nStride, TransInfo *pTransInfo){
return TransReadFileBlks7(pAlignedPtr, pAreaInfo, pAreaInfo->ah.nLog2MediumBlkSize, nSize, pFileBlkPtr, nStride, pTransInfo);
}
WFSKrnResult TransWriteFileBlks7(u8 *pAlignedPtr, AreaInfo *pAreaInfo, u32 nLog2BlkSize, u32 nSize, WFSFileBlkPtr *pFileBlkPtr, s32 nStride, TransInfo *pTransInfo, bool bDecryption);
static inline WFSKrnResult TransWriteFileBlks(u8 *pAlignedPtr, AreaInfo *pAreaInfo, u32 nSize, WFSFileBlkPtr *pFileBlkPtr, s32 nStride, TransInfo *pTransInfo, bool bDecryption){
return TransWriteFileBlks7(pAlignedPtr, pAreaInfo, pAreaInfo->ah.nLog2BlkSize, nSize, pFileBlkPtr, nStride, pTransInfo, bDecryption);
}
static inline WFSKrnResult TransWriteFileMediumBlks(u8 *pAlignedPtr, AreaInfo *pAreaInfo, u32 nSize, WFSFileBlkPtr *pFileBlkPtr, s32 nStride, TransInfo *pTransInfo, bool bDecryption){
return TransWriteFileBlks7(pAlignedPtr, pAreaInfo, pAreaInfo->ah.nLog2MediumBlkSize, nSize, pFileBlkPtr, nStride, pTransInfo, bDecryption);
}
WFSKrnResult TransReadFileLargeBlks (u8 *pAlignedPtr, AreaInfo *pAreaInfo, u32 nSize, u32 nOffsetBlks,
WFSFileLargeBlkPtr *pFileLargeBlkPtr, s32 nStride, TransInfo *pTransInfo);
WFSKrnResult TransWriteFileLargeBlks(u8 *pAlignedPtr, AreaInfo *pAreaInfo, u32 nSize, u32 nOffsetBlks,
WFSFileLargeBlkPtr *pFileLargeBlkPtr, s32 nStride, TransInfo *pTransInfo, bool bDecryption);
WFSKrnResult TransTrancateFileBlk(TransBlkAdr *pTba, WFSBlkAdr nParentBlkAdr, u16 nHashOfs, WFSBlkAdr nFileBlkAdr, u32 nOldSize, u32 nNewSize);
WFSKrnResult TransTrancateFileMediumBlk(TransBlkAdr *pTba, WFSBlkAdr nParentBlkAdr, u16 nHashOfs, WFSBlkAdr nFileBlkAdr, u32 nOldSize, u32 nNewSize);
#endif //wfs_Trans_h

View File

@ -0,0 +1,165 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_Types.h - global types used by the WFS kernel
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Types.h,v $
Revision 1.12 2008/10/24 09:03:09 kondo_masahiro
Added decrease block process of DirResize.
Revision 1.11 2008/10/17 08:51:27 kondo_masahiro
Added the new MEDIUM size category (40KB-320KB)
Revision 1.10 2008/10/10 02:11:31 kondo_masahiro
Fixed a bug to access large files
Revision 1.9 2008/10/08 23:20:09 kondo_masahiro
Added codes to access large size file data
Revision 1.8 2008/09/28 23:30:56 kondo_masahiro
Fixed codes to use medium size user block.
Revision 1.7 2008/08/06 02:24:17 paul
Added WFSFileBlkPtr and DIR_ENTRY_ATTR* defs
Revision 1.6 2008/07/28 22:30:56 paul
Moved defs related to update counter here
Revision 1.5 2008/07/25 08:47:53 ooizumi
Added WFSKrnAccess.
Revision 1.4 2008/07/17 05:15:08 kondo_masahiro
Fixed codes for porting IOP.
Revision 1.3 2008/07/09 01:52:00 paul
Updated definitions for meta-data flags.
Revision 1.2 2008/05/10 04:00:48 kondo_masahiro
Merged and fixed code to accept RM compiler
Revision 1.1 2008/04/22 04:39:08 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.5 2008/04/26 01:25:56 wayne.wong
Added magic number values.
Revision 1.4 2008/04/05 22:43:54 paul
Added WFSMetaDataFlags to make wfskrn_Volume.h compile
Revision 1.3 2008/02/21 00:12:44 paul
Added WFSMetaDataHdr
Revision 1.2 2007/12/27 11:33:28 paul
added various types
Revision 1.1 2007/11/05 19:03:13 paul
first checkin
*---------------------------------------------------------------------------*/
#ifndef wfskrn_Types_h
#define wfskrn_Types_h
#include "wfskrn_Defs.h"
// Magic numbers for WFS block types. Should be the first u32(4B) of a meta-data block (post decryption)
typedef enum { // Flags to identify persistent block types
WFS_MDF_NULL = 0x00000000,
WFS_MDF_DIR_BLK = 0x80000000, // Directory Block
WFS_MDF_DIR_ROOT_BLK = 0x40000000, // Always combined with WFS_MDF_DIR_BLK or WFS_MDF_FREE_LIST
WFS_MDF_DIR_LEAF_BLK = 0x20000000, // Always combined with WFS_MDF_DIR_BLK or WFS_MDF_FREE_LIST
WFS_MDF_INDIRECT_BLK = 0x40000000, // Indirect block. (Block of pointers to user data blocks).
WFS_MDF_FREE_LIST_BLK = 0x20000000, // Free List Management (B-tree) block
WFS_MDF_VOLUME_HDR = 0x10000000, // Master Record. Not combined with anything else
WFS_MDF_AREA_HDR = 0x08000000, // Area Header. Not combined with anything else
WFS_MDF_MAX = 0xffffffff
} WFSMetaDataFlags;
#define WFSKRN_MAX_FILE_HANDLES (1<<WFSKRN_FILE_HANDLE_IDX_BITS)
#define WFSKRN_MAX_SEARCH_DIR_HANDLES (1<<WFSKRN_SEARCH_DIR_HANDLE_IDX_BITS)
#define WFSKRN_LOG2_MAX_NUM_HANDLES WFS_NUM_BITS_REQUIRED(WFSKRN_MAX_FILE_HANDLES + WFSKRN_MAX_SEARCH_DIR_HANDLES)
#define WFSKRN_FILE_HANDLE_INC (1<<WFSKRN_FILE_HANDLE_IDX_BITS)
#define WFSKRN_SEARCH_DIR_HANDLE_INC (1<<WFSKRN_SEARCH_DIR_HANDLE_IDX_BITS)
#define DIR_BLK_REF_COUNT_INC (1<<(32-WFSKRN_LOG2_MAX_NUM_HANDLES))
#define WFS_MDF_DIR_COUNTER_MASK (0x1FFFFFFF & (DIR_BLK_REF_COUNT_INC-1)) // counter for DIR blocks - to detect updates
typedef u32 WFSTransIdx; // Transaction Index
typedef u32 WFSVolIdx; // Volume Index
typedef u32 WFSBlkAdr; // Block Address
typedef u32 WFSLglBlkAdr; // Logical Block Address
typedef u32 WFSPhyBlkAdr; // Physical Block Address
typedef u16 WFSIntraBlkOfs; // Intra Block Offset (for offsets within meta-data blocks)
typedef WFSTitleId WFSUserId;
typedef u32 WFSHashCode[5]; // SHA-1 hash code per block
#pragma pack(1)
typedef struct {
// This is the format for the start of all metadata blocks
WFSMetaDataFlags nFlags; // Contains a few bits for type identification, and the rest update-counter bits
WFSHashCode hash;
} WFSMetaDataHdr;
#pragma pack()
#pragma pack(1)
typedef struct {
// This is the format for pointers from meta-data to user-data blocks. (Note: not needed for pointers to meta-data blocks)
WFSBlkAdr nBlkAdr;
WFSHashCode hash;
} WFSFileBlkPtr;
#pragma pack()
#pragma pack(1)
typedef struct {
// This is the format for pointers from meta-data to user-data blocks. (Note: not needed for pointers to meta-data blocks)
WFSBlkAdr nBlkAdr;
WFSHashCode aHash[1<<(WFS_LOG2_LARGE_BLK_SIZE-WFS_LOG2_MAX_HASHABLE_BLK_SIZE)];
} WFSFileLargeBlkPtr;
#pragma pack()
#pragma pack(1)
typedef struct {
WFSBlkAdr nBlkAdr;
WFSHashCode *pHash;
} WFSFileBlkInfo;
#pragma pack()
#define DIR_ENTRY_ATTR_MAX_SMALL_SIZE 0xA000 // ( 40KB) : Max size = 0x50000 (320KB)
#define DIR_ENTRY_ATTR_MAX_MEDIUM_SIZE 0x50000 // (320KB) : Max size = 0x280000 (2.5MB)
#define DIR_ENTRY_ATTR_MAX_LARGE_SIZE 0x600000 // ( 6MB) : Max size = 0x600000 ( 6MB)
#define DIR_ENTRY_ATTR_MAX_SMALL_SIZE_DECREASE 0x2000 // ( 8KB)
#define DIR_ENTRY_ATTR_MAX_MEDIUM_SIZE_DECREASE 0x10000 // ( 64KB)
#define DIR_ENTRY_ATTR_MAX_LARGE_SIZE_DECREASE 0x80000 // (512KB)
#define DIR_ENTRY_ATTR_MAX_HDR_SIZE ((size_t)(&((DirEntryAttrHdr*)0)->aCaseBitArray) + (WFS_MAX_FILE_NAME_SIZE>>3)) // 28+31 = 59byte
#define DIR_ENTRY_ATTR_MAX_PTR_ARY_SIZE ((1<<SBA_MAX_LOG2_SUB_BLK_SIZE) - DIR_ENTRY_ATTR_MAX_HDR_SIZE)
#define DIR_ENTRY_ATTR_MAX_SMALL_BLK_PTRS (DIR_ENTRY_ATTR_MAX_SMALL_SIZE >> WFS_LOG2_SMALL_BLK_SIZE)
#define DIR_ENTRY_ATTR_MAX_MEDIUM_BLK_PTRS (DIR_ENTRY_ATTR_MAX_MEDIUM_SIZE >> WFS_LOG2_MEDIUM_BLK_SIZE)
#define DIR_ENTRY_ATTR_MAX_LARGE_BLK_PTRS (DIR_ENTRY_ATTR_MAX_LARGE_SIZE >> WFS_LOG2_LARGE_BLK_SIZE)
#define DIR_ENTRY_ATTR_MAX_SMALL_BLK_PTRS_DECREASE (DIR_ENTRY_ATTR_MAX_SMALL_SIZE_DECREASE >> WFS_LOG2_SMALL_BLK_SIZE)
#define DIR_ENTRY_ATTR_MAX_MEDIUM_BLK_PTRS_DECREASE (DIR_ENTRY_ATTR_MAX_MEDIUM_SIZE_DECREASE >> WFS_LOG2_MEDIUM_BLK_SIZE)
#define DIR_ENTRY_ATTR_MAX_LARGE_BLK_PTRS_DECREASE (DIR_ENTRY_ATTR_MAX_LARGE_SIZE_DECREASE >> WFS_LOG2_LARGE_BLK_SIZE)
// Internal WFSAccess value
typedef enum {
WFS_ACCESS_CHANGE_SIZE = 0x04
} WFSKrnAccess;
#endif //define wfskrn_Types_h

View File

@ -0,0 +1,29 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_Utils.h
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Utils.h,v $
Revision 1.1 2008/12/03 00:11:29 kondo_masahiro
Initial check-in.
*---------------------------------------------------------------------------*/
#ifndef wfskrn_Utils_h
#define wfskrn_Utils_h
#include "wfskrn_Defs.h"
void _qsort(void *base, size_t num, size_t size, int (*compare)(const void*, const void*) );
int CompareBlkAdrForward(const void *pA, const void *pB);
int CompareBlkAdrReverse(const void *pA, const void *pB);
#endif // wfskrn_Utils_h

View File

@ -0,0 +1,73 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_Volume.h - handle volume-wide management of area allocation
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Volume.h,v $
Revision 1.4 2008/07/17 05:21:49 kondo_masahiro
Fixed codes for porting IOP.
Revision 1.3 2008/07/09 01:54:58 paul
Many changes to Volume API to support mounting in namespace, and mounting root directory from an existing volume.
Revision 1.2 2008/05/12 19:24:00 paul
Merged in Wayne's previous changes
Revision 1.1 2008/04/22 04:39:08 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.3 2008/04/26 01:26:41 wayne.wong
Moved area allocation functionality from Volume to Area module.
Changed API appropriately.
Revision 1.2 2008/03/19 07:41:22 wayne.wong
Checkpoint. Added initial alloc/free area functions.
Revision 1.1 2008/03/11 03:22:09 wayne.wong
Checkpoint. Preliminary version.
*---------------------------------------------------------------------------*/
#ifndef _WFSKRN_VOLUME_H_
#define _WFSKRN_VOLUME_H_
#include "wfskrn_Device.h"
#define VOLUME_HDR_BLK_ADR 0 // Absolute block address of the volume header
typedef struct VolumeHdr_ {
// This is the part of the VolumeInfo struct which gets stored on disk
WFSMetaDataHdr mdh;
u32 nVolId; // Randomly assigned 32 bit identifier
u16 nWfsVersion; // WFS version; major upper 8b, minor lower 8b
u16 nBuildDate; // Build date (in days since 2008.01.01)
} VolumeHdr;
void VolumeModuleInit();
struct VolumeInfo_ *VolumeAlloc();
void VolumeFree(struct VolumeInfo_ *pVolInfo);
void VolumeRemoveFromMountedList(struct VolumeInfo_ *pVolInfo);
void VolumeAddToMountedList(struct VolumeInfo_ *pVolInfo);
void VolumeConvertU32ToVolId(WFSVolumeId *pVolId, u32 nVolId);
WFSKrnResult VolumeInitRootArea(struct VolumeInfo_ *pVolInfo, u8 nLog2BlkSize);
WFSKrnResult VolumeInit (struct VolumeInfo_ *pVolInfo, u32 nLog2BlkSize, u32 nNumBlks);
WFSKrnResult VolumeUnmount (struct VolumeInfo_ *pVolInfo);
//#define _DEBUG_WFSKRN_VOLUME_
#ifdef _DEBUG_WFSKRN_VOLUME_
#define dbgv(_s) (_s)
#else
#define dbgv(_s)
#endif // _DEBUG_WFSKRN_VOLUME_
#endif // _WFSKRN_VOLUME_H_

View File

@ -0,0 +1,382 @@
/*---------------------------------------------------------------------------*
Project: Revolution WFSSrv library API = shim layer in RVL version and RPC
layer in WFSDEV version.
File: wfsdev_Defs.h - Definitions common to WFS client and server
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfssrv_Defs.h,v $
Revision 1.34 2008/12/03 00:17:36 kondo_masahiro
Added a argument of WFSSrvFlush().
Revision 1.33 2008/10/21 10:45:09 kondo_masahiro
Added new function WFSWriteFileAndDiscard
Revision 1.32 2008/09/29 01:06:26 kondo_masahiro
Added the argument of WFSSrvInit().
Revision 1.31 2008/07/18 02:59:44 ueno
Renamed WFSDeletePermissions() -> WFSDeleteAccessListEntry().
Revision 1.30 2008/07/17 05:08:41 kondo_masahiro
Added WFSSRV_ATTACH_DETACH
Revision 1.29 2008/07/15 08:43:53 nakanose_jin
change arg order
Revision 1.28 2008/07/14 07:15:46 ueno
Implemented WFSGetAccessListAsync(), WFSSetAccessListEntryAsync() and WFSDeletePermissionsAsync().
Revision 1.27 2008/07/10 06:12:33 nakanose_jin
add permissions API
Revision 1.26 2008/05/22 08:05:49 ueno
Added WFSSrvDebugAclTest to run accesslist test.
Revision 1.25 2008/05/09 14:03:09 nakanose_jin
canceling => reduce settitleid argument
Revision 1.23 2008/04/19 05:52:03 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.22 2008/04/15 02:47:27 ueno
Added WFSSrvGetPermissionForUser() and WFSSrvSetPermissionForUser().
Revision 1.21 2008/03/28 14:14:20 nakanose_jin
chance spec of debug proc
Revision 1.20 2008/02/20 08:10:10 nakanose_jin
add WFSExecDebugProcedure
Revision 1.19 2008/02/08 04:42:00 paul
Changed WFSSrvUnmountVolume parameter bForce to WFSBool
Revision 1.18 2008/02/07 13:02:18 nakanose_jin
WFSUnmountVolume : Add force-close option (but only in detach condition)
Revision 1.17 2008/01/10 05:33:20 nakanose_jin
validatePathName => validateDirectory
Revision 1.16 2007/12/25 14:00:36 ueno
Added WFSSrvConnectToServer() to connect to the server again.
Revision 1.15 2007/12/12 07:51:29 paul
Added WFSSrvGetFileSize
Revision 1.14 2007/12/10 02:51:36 paul
Added function codes for WFSSRV_SET_HOME_DIRECTORY, WFSSRV_SET_CURRENT_DIRECTORY. (These do not need to be implemented in the actual server, both call WFSSrvValidatePathName)
Revision 1.13 2007/11/30 09:43:09 nakanose_jin
refine for multi client
Revision 1.12 2007/11/21 04:17:28 wayne.wong
Many changes that included single request/result RPC messages, bug fixes, code factoring, and English C comment adjustments.
1. Combined RPC messages into a single request message and single result
message. Except for file reads and writes.
2. Fixed+factored some Endianess code.
3. Enabled larger TCP/IP data transfer size. Previous setting was artifically small
to test the code to perform large transfers.
4. Changed the volume id parameters utf8*->WFSVolumeId for SrvGetVolumeId
and SrvMountDevice. More consistent with the way we send this type at the
RPC layer.
5. Changed a couple Japanese comments to be compatible with English
comments. In particular, the "//" comment with a backslash at the end of
the line causes the next line of code to be ignored.
6. Removed Windows-specific debugging output defines for RVL build.
Revision 1.11 2007/11/16 21:54:26 paul
Fixed WFSSrvCloseFile to pass nNewSize instead of bTruncateFlag
Revision 1.10 2007/11/16 02:15:57 wayne.wong
Added enumeration and stubs for WFSFlush call.
Revision 1.9 2007/11/02 00:21:02 paul
started logging changes in the file
Added StartPosition to WFSSrvReadFile, WFSSrvWriteFile
*---------------------------------------------------------------------------*/
#ifndef __WFSSRV_DEFS_H__
#define __WFSSRV_DEFS_H__
#include "wfs_Defs.h"
#ifdef __cplusplus
extern "C" {
#endif
// Enumeration of functions.
// Used by the client to specify functions implemented on the server, or
// by the server to specify functions implemented on the client.
typedef enum {
// server -> client
WFSSRV_ATTACH_DEVICE,
WFSSRV_DETACH_DEVICE,
// client -> server
WFSSRV_INIT,
WFSSRV_EXIT,
WFSSRV_GET_DEVICE_INFO,
WFSSRV_MOUNT_DEVICE,
WFSSRV_UNMOUNT_VOLUME,
WFSSRV_INITIALIZE_DEVICE,
WFSSRV_GET_VOLUME_ID,
WFSSRV_GET_FREE_SPACE_SIZE,
WFSSRV_FLUSH,
WFSSRV_CREATE_DIRECTORY,
WFSSRV_SEARCH_DIRECTORY_FIRST,
WFSSRV_SEARCH_DIRECTORY_NEXT,
WFSSRV_SEARCH_DIRECTORY_CLOSE,
WFSSRV_SET_HOME_DIRECTORY,
WFSSRV_SET_CURRENT_DIRECTORY,
WFSSRV_VALIDATE_PATH_NAME,
WFSSRV_DELETE,
WFSSRV_MOVE_LOCAL,
WFSSRV_GET_ATTRIBUTES,
WFSSRV_CHANGE_PERMISSIONS,
WFSSRV_CREATE_AND_OPEN_FILE,
WFSSRV_OPEN_FILE,
WFSSRV_GET_FILE_SIZE,
WFSSRV_CLOSE_FILE,
WFSSRV_READ_FILE,
WFSSRV_WRITE_FILE,
WFSSRV_WRITE_FILE_AND_DISCARD,
WFSSRV_GET_PERMISSIONS,
WFSSRV_SET_PERMISSIONS,
WFSSRV_GET_ACL,
WFSSRV_SET_ACL_ENTRY,
WFSSRV_DELETE_ACL_ENTRY,
WFSSRV_SET_TITLE_ID,
WFSSRV_TEST,
WFSSRV_EXEC_DEBUG,
WFSSRV_ATTACH_DETACH,
WFSSRV_DEBUG_ACLTEST // [check]
} WFSSrvFunc;
typedef u16 WFSSrvFileHandle;
typedef u16 WFSSrvSearchDirectoryHandle;
#ifndef WFSDEV_SERVER
// The WFSDev server must distinguish between multiple clients.
// This can be done by assigning a ClientId based on the client's IP address,
// which the server learns whenever it receives a request from a client via sockets.
// Note: ClientId is orthogonal to TitleId.
// There can be multiple clients with the same TitleId.
// The same client could change TitleId while the server is running.
// The home directory is only stored on the client side.
// The TitleId, however, is determined by a function in IOS.
// (except for the fake debug/wfsdev version)
//
// This allows a system application built on top of wfs to specify the home directory for
// an app prior to launching it.
//
// Path Names
// The client<->server API uses absolute WFS path names, becuase the server does not know about
// "Current Directory" or "Home Directory".
// The absolute path name does not include the full windows path name, it is a WFS path name.
// For example: "/vol/ABCDEFG/titles/1234/JAKK/gamesave/save1.bin"
// On windows, this could map to:
// "C:/my_project/my_wfs_device/titles/1234/JAKK/gamesave/save1.bin"
// There would be a file called:
// "C:/my_project/my_wfs_device/.Wfs" which contains: "Volume Name: ABCDEFG"
WFSResult WFSSrvInit(void *pWorkSpaceBuffer, u32 nWorkSpaceSize);
// Contact the WFSSrv server so that it can initialize state for this client.
WFSResult WFSSrvExit(void);
// Inform the WFSSrv server that this client is terminating.
WFSResult WFSSrvInitializeDevice(const WFSDeviceName *pDevName);
// pDevName (IN) pointer to device name struct.
// Server would create a volume (deleting any existing data within the device assigned to this folder).
// The server could have a GUI to allow device attach to be simulated.
// It depends on the usage model but this may not be necessary for game developers, so low priority.
// (Assuming a system app mounts the drive and assigns home directory in advance, so the
// game can access an already-mounted device from the start).
WFSResult WFSSrvGetDeviceInfo(const WFSDeviceName *pDevName, WFSDeviceInfo *pDi);
// pDevName (IN) A pointer to a device name struct.
// pDi (OUT) A pointer to a WFSDeviceInfo struct to receive the device information.
WFSResult WFSSrvMountDevice(const WFSDeviceName *pDevName, WFSVolumeId *pVolumeIdBuffer);
// pDevName (IN) A pointer to a device name struct.
// pVolumeIdBuffer (OUT) A pointer to a WFSVolumeId buffer
WFSResult WFSSrvUnmountVolume(const WFSVolumeId *pVolumeId, WFSBool bForce);
// pVolumeId (IN) A pointer to a struct containing a mounted Volume Id.
// bForce (IN) If set to true, forces the volume to be unmounted regardless of open files.
// NOTE: This flag is only valid if the device is currently detached. Un-flushed data will be lost.
WFSResult WFSSrvGetVolumeId(const WFSDeviceName *pDevName, WFSVolumeId *sVolumeIdBuffer);
// pDevName (IN) A pointer to a device name struct.
// sVolumeIdBuffer (OUT) A pointer to a WFSVolumeId buffer
WFSResult WFSSrvGetFreeSpaceSize(const WFSPathName *pAbsPathName, u64 *pSize);
// pAbsPathName (IN) A pointer to a struct containing the absolute pathname of a file or directory.
// pSize (OUT) A pointer to a u64 to receive the free space size value.
WFSResult WFSSrvFlush(const WFSVolumeId *pVolumeId);
WFSResult WFSSrvGetAttributes(const WFSPathName *pAbsPathName, WFSFileAttributes *pFa);
// pAbsPathName (IN) A pointer to a struct containing the absolute pathname of a file or directory.
// pFa (OUT) A pointer to a WFSFileAttributes struct which will be overwritten with the attributes of the specified file or directory.
WFSResult WFSSrvChangePermissions(const WFSPathName *pAbsPathName, u32 nFlags, u32 nMask);
// pAbsPathName (IN) A pointer to a struct containing the absolute pathname of a file or directory.
// nFlags (IN) The new permissions flags that are to be set. Should be a combination of the permission flags: WFS_PERM_*
// nMask (IN) A mask to specify which flags to change.
WFSResult WFSSrvCreateDirectory(const WFSPathName *pAbsPathName, u32 nFlags, u64 nQuota);
// pAbsPathName (IN) A pointer to a struct containing the absolute pathname of a file or directory.
// nFlags (IN) Should be a combination of the permission flags: WFS_PERM_*. Note: WFS_FLAG_DIRECTORY will be set
// whether it is included or not.
// nQuota (IN) This parameter that can be used to restrict the total size of the hierarchy beneath the
// new directory. A quota of 0 means there is no size restriction, i.e. the quota is Infinity.
WFSResult WFSSrvSearchDirectoryFirst(const WFSPathName *pPattern, WFSSrvSearchDirectoryHandle *pSsdh, WFSFileInfo *pFi);
// pPattern (IN) A pointer to a struct specifying the search pattern as an absolute path name.
// pSsdh (OUT) A pointer to a WFSSrvSearchDirectoryHandle handle which is overwritten by the server.
// pFi (OUT) A pointer to a WFSFileInfo struct which will be overwritten with the details of the
WFSResult WFSSrvSearchDirectoryNext(WFSSrvSearchDirectoryHandle ssdh, WFSFileInfo *pFi);
// ssdh (IN) A WFSSrvSearchDirectoryHandle which was created by WFSSrvSearchDirectoryFirst.
// pFi (OUT) A pointer to a WFSFileInfo struct which will be overwritten with the details of the
// next file which matches the search pattern.
//
// If they have read permission on the directory, they can list all files/dirs in that directory. Directory read
// access was already checked by WFSSrvSearchDirectoryFirst. While they can list the directory contents, they may
// not be able to access all contained files/dirs.
WFSResult WFSSrvSearchDirectoryClose(WFSSrvSearchDirectoryHandle ssdh);
// ssdh (IN) A WFSSrvSearchDirectoryHandle which was returned by WFSSrvSearchDirectoryFirst.
WFSResult WFSSrvValidateDirectory(const WFSPathName *pAbsPathName);
// pAbsPathName (IN) A pointer to a struct containing the absolute pathname of a file or directory to validate.
// Returns WFS_RESULT_OK if the specified pathname exists, and is accessible to the current title
WFSResult WFSSrvDelete(const WFSPathName *pAbsPathName);
// pAbsPathName (IN) A pointer to a struct containing the absolute pathname of the file or directory to delete.
WFSResult WFSSrvMoveLocal(const WFSPathName *pSrcAbsPathName, const WFSPathName *pDstAbsPathName);
// pSrcAbsPathName (IN) A pointer to a struct containing the absolute pathname of the source file or directory.
// pDstAbsPathName (IN) A pointer to a struct containing the absolute pathname of the destination file or directory.
// Moves or renames the source file/directory to the destination pathname. This function does not work across volumes.
WFSResult WFSSrvCreateAndOpenFile(const WFSPathName *pAbsPathName, u32 nFlags, WFSContentIdx nCidx, WFSFileSize nPreAllocateSize, WFSSrvFileHandle *pSfh);
// pAbsPathName (IN) A pointer to a struct containing the absolute pathname of the file to create and open.
// nFlags (IN) Should be a combination of the permission flags: WFS_PERM_*
// nCidx (IN) The content idx, used to control access to purchased content.
// nPreAllocateSize (IN) The amount of disk-space to pre-allocate for the file. Hint to the file system.
// pSfh (OUT) A pointer to a server file handle which is overwritten by the server.
WFSResult WFSSrvOpenFile(const WFSPathName *pAbsPathName, WFSAccess nDesiredAccess, WFSSrvFileHandle *pSfh, WFSFileAttributes *pFa);
// pAbsPathName (IN) A pointer to a struct containing the absolute pathname of the file to open.
// nDesiredAccess (IN) The kind of access that is required: should be one of the WFS_ACCESS_* options.
// pSfh (OUT) A pointer to a server file handle, which is overwritten by the server.
// pFa (OUT) A pointer to a WFSFileAttributes struct which will be overwritten by the server,
WFSResult WFSSrvCloseFile(WFSSrvFileHandle sfh, WFSFileSize nNewSize);
// sfh (IN) The server file handle which was returned when the file was opened.
// nNewSize (IN) This value may be set to truncate the size of a file.
WFSResult WFSSrvGetFileSize(WFSSrvFileHandle sfh, WFSFileSize *pNewSize);
// sfh (IN) The server file handle which was returned when the file was opened.
// pNewSize (OUT) A pointer to a WFSFileSize variable which is overwritten by the current file size.
s32 WFSSrvReadFile(WFSSrvFileHandle sfh, void *pFileDataBuffer, WFSFileSize nStartPosition, s32 nSize);
// sfh (IN) The server file handle which was returned when the file was opened.
// pFileDataBuffer (OUT) Points to a buffer which will be overwritten with data from the file.
// nSize (IN) The number of bytes to be read.
WFSResult WFSSrvWriteFile(WFSSrvFileHandle sfh, const void *pFileData, WFSFileSize nStartPosition, WFSFileSize nSize, WFSBool bDiscard);
// sfh (IN) The server file handle which was returned when the file was opened.
// pFileData (IN) Points to the data to be written to the file.
// nSize (IN) The number of bytes to be written.
// bDiscard (IN) If it is true, the user buffer is used as work buffer.
WFSResult WFSSrvSetTitleId(WFSTitleId titleId,WFSGroupId groupId);
// titleId (IN) the title id which is the low 32 bits of the OSTitleId which can be obtained be ESP_GetTitleId()
// groupId (IN) the group id from the TMD, which can be obtained by ES_GetTmd()
// This function informs the server of the title id and group id of the application linked to this instance of the client.
WFSResult WFSSrvExecDebugProcedure( u32 cmd , void *arg0 , void *arg1 );
// cmd (IN) special command No.
// arg0,arg1 (IN/OUT) parameters of special command.
// This function let the server do special tasks.
WFSResult WFSSrvConnectToServer(void);
WFSResult WFSSrvGetPermissionForUser(const WFSPathName *pAbsPathName, u32 *pFlags, WFSTitleId titleId);
// pAbsPathName (IN) A pointer to a struct containing the absolute pathname of the file or the directory.
// pFlags (OUT) A pointer to a u32 which will be overwritten with the permissions the specified title id has to
// access or modify the specified file or directory. See wfstypes.h for WFS_PERM* flag definitions.
// titleId (IN) Title id of the application for which permissions are being set.
WFSResult WFSSrvSetPermissionForUser(const WFSPathName *pAbsPathName, u32 nFlags, u32 nMask, WFSTitleId titleId);
// pAbsPathName (IN) A pointer to a struct containing the absolute pathname of the file or the directory.
// nFlags (IN) The new permissions flags that are to be set. Should be a combination of the permission flags: WFS_PERM_* (see wfstypes.h)
// nMask (IN) The mask determines which flags will be changed. NewAttributes = (OldAttributes & ~nMask) | (nFlags & nMask)
// titleId (IN) Title id of the application for which permissions are being set.
WFSResult WFSSrvDeleteAccessListEntry(const WFSPathName *pAbsPathName, WFSTitleId titleId, WFSTitleId entryCreatorId);
WFSResult WFSSrvSetAccessListEntry(const WFSPathName *pAbsPathName, u32 nFlags, u32 nMask, WFSTitleId titleId);
s32 WFSSrvGetAccessList(const WFSPathName *pAbsPathName, WFSAccessListEntry *pAccessList, u32 nMaxElements);
WFSResult WFSSrvSetWorkspace(void *pWorkSpaceBuffer, u32 nWorkSpaceSize);
#ifdef ACL_TEST
WFSResult WFSSrvDebugAclTest(u32 testNo, void *arg0, void *arg1);
#endif // ACL_TEST
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif //define __WFSSRV_DEFS_H__

View File

@ -0,0 +1,145 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: WinOSReport.cpp - implementation of WFSDEV higher-level socket
library.
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: WinOSReport.cpp,v $
Revision 1.9 2008/08/28 00:18:26 nakanose_jin
lets standard exception style
Revision 1.8 2008/08/27 04:50:52 nakanose_jin
add function and defines
Revision 1.7 2008/04/19 05:53:32 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.6 2007/11/26 11:25:13 nakanose_jin
deal error on ndev
Revision 1.5 2007/11/02 01:08:06 paul
now logging changes
*---------------------------------------------------------------------------*/
#if _WIN32
#include <windows.h>
#endif
#if !_IOP
#include <stdio.h>
#include <stdarg.h>
#endif
#include <firm.h>
#include "WinOSReport.h"
static OSReportCallback userCB=0;
#if _WIN32
FILE *fpOSReport;
#endif
void DebugPrintCallback(const char *pStr) {
#if _WIN32
//fpOSReport = fopen("OSReport.txt", "a+, ccs=UTF-8");
//fpOSReport = fopen("OSReport.txt", "a+");
fprintf(fpOSReport, pStr);
//fclose(fpOSReport);
//OutputDebugString(pStr);
#else
osTPrintf(pStr);
#endif
}
void DebugPrintCallback2(const char *pStr) {
#if _WIN32
OutputDebugString(pStr);
#else
osTPrintf(pStr);
#endif
}
OSReportCallback SetOSReportPrintCallback(OSReportCallback cb) {
OSReportCallback oldCb = userCB;
userCB = cb;
return oldCb;
}
#pragma warning(disable:4996)
#if (_MSC_VER) && (_MSC_VER < 1400)
#define VSNPRINTF _vsnprintf
#else
#define VSNPRINTF vsnprintf
#endif
#define SIZEDUMP 1024
static char strdump[SIZEDUMP];
#include "wfs_Mutex.h"
WFSMutex mxOSReport;
#if _WIN32
void InitMyOSReport(void) {
WFSInitMutex(&mxOSReport);
}
#endif
#if _WIN32
void MyOSReport(const char *format, ...) {
if (userCB) {
WFSLockMutex(&mxOSReport);
va_list ap;
va_start(ap, format);
VSNPRINTF(strdump, SIZEDUMP, format, ap);
userCB(strdump);
va_end( ap );
WFSUnlockMutex(&mxOSReport);
} else {
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
fflush(stderr);
}
}
#endif
#if _WIN32
#include <exception>
#endif
void MyOSPanic(const char* file, int line , const char* msg, ...) {
#if _WIN32
MyOSReport(" in \"%s\" on line %d.\n", file, line);
if (userCB) {
WFSLockMutex(&mxOSReport);
va_list ap;
va_start(ap, msg);
VSNPRINTF(strdump, SIZEDUMP, msg, ap);
userCB(strdump);
va_end( ap );
WFSUnlockMutex(&mxOSReport);
} else {
va_list ap;
va_start(ap, msg);
vfprintf(stderr, msg, ap);
va_end(ap);
fflush(stderr);
}
throw std::bad_exception();
abort();
#else
osTPanic( "panic");
#endif
}

View File

@ -0,0 +1,206 @@
#include <math.h>
#include "randomlib.h"
#define FALSE 0
#define TRUE 1
/*
This Random Number Generator is based on the algorithm in a FORTRAN
version published by George Marsaglia and Arif Zaman, Florida State
University; ref.: see original comments below.
At the fhw (Fachhochschule Wiesbaden, W.Germany), Dept. of Computer
Science, we have written sources in further languages (C, Modula-2
Turbo-Pascal(3.0, 5.0), Basic and Ada) to get exactly the same test
results compared with the original FORTRAN version.
April 1989
Karl-L. Noell <NOELL@DWIFH1.BITNET>
and Helmut Weber <WEBER@DWIFH1.BITNET>
This random number generator originally appeared in "Toward a Universal
Random Number Generator" by George Marsaglia and Arif Zaman.
Florida State University Report: FSU-SCRI-87-50 (1987)
It was later modified by F. James and published in "A Review of Pseudo-
random Number Generators"
THIS IS THE BEST KNOWN RANDOM NUMBER GENERATOR AVAILABLE.
(However, a newly discovered technique can yield
a period of 10^600. But that is still in the development stage.)
It passes ALL of the tests for random number generators and has a period
of 2^144, is completely portable (gives bit identical results on all
machines with at least 24-bit mantissas in the floating point
representation).
The algorithm is a combination of a Fibonacci sequence (with lags of 97
and 33, and operation "subtraction plus one, modulo one") and an
"arithmetic sequence" (using subtraction).
Use IJ = 1802 & KL = 9373 to test the random number generator. The
subroutine RANMAR should be used to generate 20000 random numbers.
Then display the next six random numbers generated multiplied by 4096*4096
If the random number generator is working properly, the random numbers
should be:
6533892.0 14220222.0 7275067.0
6172232.0 8354498.0 10633180.0
*/
/* Globals */
double u[97],c,cd,cm;
int i97,j97;
int test = FALSE;
/*
This is the initialization routine for the random number generator.
NOTE: The seed variables can have values between: 0 <= IJ <= 31328
0 <= KL <= 30081
The random number sequences created by these two seeds are of sufficient
length to complete an entire calculation with. For example, if sveral
different groups are working on different parts of the same calculation,
each group could be assigned its own IJ seed. This would leave each group
with 30000 choices for the second seed. That is to say, this random
number generator can create 900 million different subsequences -- with
each subsequence having a length of approximately 10^30.
*/
void RandomInitialise(int ij, int kl)
{
double s,t;
int ii,i,j,k,l,jj,m;
/*
Handle the seed range errors
First random number seed must be between 0 and 31328
Second seed must have a value between 0 and 30081
*/
if (ij < 0 || ij > 31328 || kl < 0 || kl > 30081) {
ij = 1802;
kl = 9373;
}
i = (ij / 177) % 177 + 2;
j = (ij % 177) + 2;
k = (kl / 169) % 178 + 1;
l = (kl % 169);
for (ii=0; ii<97; ii++) {
s = 0.0;
t = 0.5;
for (jj=0; jj<24; jj++) {
m = (((i * j) % 179) * k) % 179;
i = j;
j = k;
k = m;
l = (53 * l + 1) % 169;
if (((l * m % 64)) >= 32)
s += t;
t *= 0.5;
}
u[ii] = s;
}
c = 362436.0 / 16777216.0;
cd = 7654321.0 / 16777216.0;
cm = 16777213.0 / 16777216.0;
i97 = 97;
j97 = 33;
test = TRUE;
}
void RandomSetSeedU32(u32 nSeed) {
// Seeds between 0x0 and 0x382C7A41 inclusive are unique
RandomInitialise((int)(nSeed%31329),(int)((nSeed/31329)%30082));
}
/*
This is the random number generator proposed by George Marsaglia in
Florida State University Report: FSU-SCRI-87-50
*/
double RandomUniform(void)
{
double uni;
// Make sure the initialisation routine has been called
if (!test)
RandomInitialise(1802,9373);
uni = u[i97-1] - u[j97-1];
if (uni <= 0.0)
uni++;
u[i97-1] = uni;
i97--;
if (i97 == 0)
i97 = 97;
j97--;
if (j97 == 0)
j97 = 97;
c -= cd;
if (c < 0.0)
c += cm;
uni -= c;
if (uni < 0.0)
uni++;
return(uni);
}
/*
ALGORITHM 712, COLLECTED ALGORITHMS FROM ACM.
THIS WORK PUBLISHED IN TRANSACTIONS ON MATHEMATICAL SOFTWARE,
VOL. 18, NO. 4, DECEMBER, 1992, PP. 434-435.
The function returns a normally distributed pseudo-random number
with a given mean and standard devaiation. Calls are made to a
function subprogram which must return independent random
numbers uniform in the interval (0,1).
The algorithm uses the ratio of uniforms method of A.J. Kinderman
and J.F. Monahan augmented with quadratic bounding curves.
*/
#if !_IOP
double RandomGaussian(double mean,double stddev)
{
double q,u,v,x,y;
// Generate P = (u,v) uniform in rect. enclosing acceptance region
// Make sure that any random numbers <= 0 are rejected, since
// gaussian() requires uniforms > 0, but RandomUniform() delivers >= 0.
do {
u = RandomUniform();
v = RandomUniform();
if (u <= 0.0 || v <= 0.0) {
u = 1.0;
v = 1.0;
}
v = 1.7156 * (v - 0.5);
// Evaluate the quadratic form
x = u - 0.449871;
y = fabs(v) + 0.386595;
q = x * x + y * (0.19600 * y - 0.25472 * x);
// Accept P if inside inner ellipse
if (q < 0.27597)
break;
// Reject P if outside outer ellipse, or outside acceptance region
} while ((q > 0.27846) || (v * v > -4.0 * log(u) * u * u));
// Return ratio of P's coordinates as the normal deviate
return (mean + stddev * v / u);
}
#endif
// Return random integer within a range, lower -> upper INCLUSIVE
int RandomInt(int lower,int upper)
{
return((int)(RandomUniform() * (upper - lower + 1)) + lower);
}
u32 RandomU32() {
double rX = RandomUniform();
double rY = RandomUniform();
return (u32)((rX * 4294967296.0)+(rY * 65536));
}
// Return random float within a range, lower -> upper
double RandomDouble(double lower,double upper)
{
return((upper - lower) * RandomUniform() + lower);
}

View File

@ -0,0 +1,708 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfs_AsyncUtils.cpp
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfs_AsyncUtils.cpp,v $
Revision 1.42 2008/12/03 00:17:05 kondo_masahiro
Fixed case WFSSRV_FLUSH.
Revision 1.41 2008/10/31 05:37:09 ooizumi
Fixed a bug in WFSExecFunction().
Revision 1.40 2008/10/23 11:15:28 nakanose_jin
Open and Search should give a invalid file handle if he fails to execute.
Revision 1.39 2008/10/21 10:45:20 kondo_masahiro
Added new function WFSWriteFileAndDiscard
Revision 1.38 2008/07/18 02:59:46 ueno
Renamed WFSDeletePermissions() -> WFSDeleteAccessListEntry().
Revision 1.37 2008/07/14 07:15:24 ueno
Implemented WFSGetAccessListAsync(), WFSSetAccessListEntryAsync() and WFSDeletePermissionsAsync().
Revision 1.36 2008/04/24 04:26:29 nakanose_jin
byebye nPermissions param
Revision 1.35 2008/04/18 07:45:03 nakanose_jin
merge acl
Revision 1.34 2008/04/10 13:35:38 ueno
Added WFSSetPermissionsForUser[Async] and WFSGetPermissionsForUser[Async].
Revision 1.33 2008/02/25 08:33:20 paul
BOOL -> WFSBool
Revision 1.32 2008/02/07 13:02:21 nakanose_jin
WFSUnmountVolume : Add force-close option (but only in detach condition)
Revision 1.31 2008/01/23 00:44:30 ueno
Fixed to copy volume ID only when the result is WFS_RESULT_OK.
Revision 1.30 2008/01/23 00:07:02 paul
Fixed WFSGetVolumeIdAsync to only overwrite buffer when result==WFS_RESULT_OK
Revision 1.29 2008/01/10 09:23:26 paul
bugfix for WFSSRV_SET_CURRENT_DIRECTORY, WFSSRV_SET_HOME_DIRECTORY
Revision 1.28 2008/01/10 05:33:23 nakanose_jin
validatePathName => validateDirectory
Revision 1.27 2008/01/08 09:49:46 ueno
Modified WFSExecFunction() to support WFSSRV_MOUNT_DEVICE.
Revision 1.26 2007/12/27 06:02:37 paul
bugfix for WFSSRV_SET_HOME_DIRECTORY, WFSSRV_SET_CURRENT_DIRECTORY
Revision 1.25 2007/12/27 01:43:19 ueno
Added WFSIsThreadTerminated() and WFSJoinThread().
Revision 1.24 2007/12/26 05:43:45 ueno
Fixed WFSAsyncUtilsInit() to create a thread.
Fixed WFSAsyncUtilsClose() to send signal to wake up async thread.
Revision 1.23 2007/12/25 14:03:50 ueno
Modified to initialize mutex, thread and heap only once.
Revision 1.22 2007/12/12 19:57:07 paul
Changed WFSSearchDirectoryFirstAsync to not create a search directory handle, and pass sdh=0 to the callback if WFSSrvSearchDirectoryFirst returns an error code.
Revision 1.21 2007/12/12 07:52:10 paul
Added WFSSRV_GET_FILE_SIZE
Revision 1.20 2007/12/11 00:10:06 paul
Fixed a bug in WFSWriteFileAsync
Revision 1.19 2007/12/10 02:48:49 paul
Fixed WFSSetCurrentDirectoryAsync, WFSSetHomeDirectoryAsync
Revision 1.18 2007/11/21 04:17:45 wayne.wong
Many changes that included single request/result RPC messages, bug fixes, code factoring, and English C comment adjustments.
1. Combined RPC messages into a single request message and single result
message. Except for file reads and writes.
2. Fixed+factored some Endianess code.
3. Enabled larger TCP/IP data transfer size. Previous setting was artifically small
to test the code to perform large transfers.
4. Changed the volume id parameters utf8*->WFSVolumeId for SrvGetVolumeId
and SrvMountDevice. More consistent with the way we send this type at the
RPC layer.
5. Changed a couple Japanese comments to be compatible with English
comments. In particular, the "//" comment with a backslash at the end of
the line causes the next line of code to be ignored.
6. Removed Windows-specific debugging output defines for RVL build.
Revision 1.17 2007/11/16 21:55:08 paul
Changed WFSSrvCloseFile to pass nNewSize instead of bTruncateFlag
Revision 1.16 2007/11/16 02:06:40 paul
Added WFSFlush()
Revision 1.15 2007/11/09 01:17:29 paul
Added sub-directory validation check for WFSMoveLocal
Revision 1.14 2007/11/02 01:57:40 paul
bugfix
Revision 1.13 2007/11/02 00:52:21 paul
now logging changes
added nStartPosition to WFSSrvReadFile, WFSSrvWriteFile
---------------------------------------------------------------------------*/
#include "wfs_Client.h"
#undef dbg
#if _DEBUG_ASYNC_UTILS
#define dbg(s) s
#else
#define dbg(s)
#endif
static BOOL bMutexInitialized;
void WFSExecFunction(WFSAsyncParamHdr *pParamHdr);
void WFSExecFunction(WFSAsyncParamHdr *pParamHdr) {
dbg(MyOSReport("Processing Function: %d\n", pParamHdr->nFunction));
void *pPtr = (void*)((size_t)pParamHdr + sizeof(WFSAsyncParamHdr));
WFSResult nResult = WFS_RESULT_OK;
switch(pParamHdr->nFunction) {
case WFSSRV_EXIT: {
//WFSAsyncUtilsClose();
((WFSResultCallback)pParamHdr->cb)(nResult, pParamHdr->pUserData);
WFSExitThread(NULL);
break;
}
case WFSSRV_GET_DEVICE_INFO: {
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, utf8 *, sDeviceName);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSDeviceInfo *, pDi);
WFSDeviceName *pDevName = (WFSDeviceName *)pPtr;
nResult = WFSSrvGetDeviceInfo(pDevName, pDi);
((WFSDeviceInfoCallback)pParamHdr->cb)(nResult, sDeviceName, pDi, pParamHdr->pUserData);
break;
}
case WFSSRV_MOUNT_DEVICE: {
WFSVolumeId volId;
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, const utf8 *, sDeviceName);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, utf8 *, sVolumeIdBuffer);
WFSDeviceName *pDevName = (WFSDeviceName *)pPtr;
nResult = WFSSrvMountDevice(pDevName, &volId);
if (nResult == WFS_RESULT_OK)
{
strncpy(sVolumeIdBuffer, volId.sStr, WFS_MAX_VOLUME_ID_SIZE+1);
}
((WFSDeviceVolumeCallback)pParamHdr->cb)(nResult, sDeviceName, sVolumeIdBuffer, pParamHdr->pUserData);
break;
}
case WFSSRV_UNMOUNT_VOLUME: {
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, const utf8 *, sVolumeId);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSBool, bForce);
WFSVolumeId *pVolumeId = (WFSVolumeId *)pPtr;
nResult = WFSSrvUnmountVolume(pVolumeId, bForce);
((WFSUnmountVolumeCallback)pParamHdr->cb)(nResult, sVolumeId, pParamHdr->pUserData);
break;
}
case WFSSRV_INITIALIZE_DEVICE: {
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, const utf8 *, sDeviceName);
WFSDeviceName *pDevName = (WFSDeviceName *)pPtr;
nResult = WFSSrvInitializeDevice(pDevName);
((WFSInitializeDeviceCallback)pParamHdr->cb)(nResult, sDeviceName, pParamHdr->pUserData);
break;
}
case WFSSRV_GET_VOLUME_ID: {
WFSVolumeId volId;
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, const utf8 *, sDeviceName);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, utf8 *, sVolumeIdBuffer);
WFSDeviceName *pDevName = (WFSDeviceName *)pPtr;
nResult = WFSSrvGetVolumeId(pDevName, &volId);
if (nResult == WFS_RESULT_OK) {
strncpy(sVolumeIdBuffer, volId.sStr, WFS_MAX_VOLUME_ID_SIZE+1);
}
((WFSDeviceVolumeCallback)pParamHdr->cb)(nResult, sDeviceName, sVolumeIdBuffer, pParamHdr->pUserData);
break;
}
case WFSSRV_GET_FREE_SPACE_SIZE: {
WFSPathName *pAbsPathName = (WFSPathName *)pPtr;
u64 nSize;
nResult = WFSSrvGetFreeSpaceSize(pAbsPathName, &nSize);
((WFSGetFreeSpaceCallback)pParamHdr->cb)(nResult, nSize, pParamHdr->pUserData);
break;
}
case WFSSRV_SET_HOME_DIRECTORY: {
WFSPathName *pAbsPathName = (WFSPathName *)pPtr;
nResult = WFSSrvValidateDirectory(pAbsPathName);
if (nResult == WFS_RESULT_OK) {
WFSLockMutex(&wcg.pg.mxAccessPathGlobals);
if (pAbsPathName->sStr[pAbsPathName->nLen-1]!='/') {
pAbsPathName->sStr[pAbsPathName->nLen++] ='/';
pAbsPathName->sStr[pAbsPathName->nLen] =0;
}
WFSPathResolve(&wcg.pg.pathHome.pn, &wcg.pg.pathHome.ppoa, pAbsPathName->sStr, PATH_TYPE_ABS_DIR_ONLY);
WFSUnlockMutex(&wcg.pg.mxAccessPathGlobals);
}
((WFSResultCallback)pParamHdr->cb)(nResult, pParamHdr->pUserData);
break;
}
case WFSSRV_SET_CURRENT_DIRECTORY: {
WFSPathName *pAbsPathName = (WFSPathName *)pPtr;
nResult = WFSSrvValidateDirectory(pAbsPathName);
if (nResult == WFS_RESULT_OK) {
WFSLockMutex(&wcg.pg.mxAccessPathGlobals);
if (pAbsPathName->sStr[pAbsPathName->nLen-1]!='/') {
pAbsPathName->sStr[pAbsPathName->nLen++] ='/';
pAbsPathName->sStr[pAbsPathName->nLen] =0;
}
WFSPathResolve(&wcg.pg.pathCurrent.pn, &wcg.pg.pathCurrent.ppoa, pAbsPathName->sStr, PATH_TYPE_ABS_DIR_ONLY);
WFSUnlockMutex(&wcg.pg.mxAccessPathGlobals);
}
((WFSResultCallback)pParamHdr->cb)(nResult, pParamHdr->pUserData);
break;
}
case WFSSRV_VALIDATE_PATH_NAME: {
WFSPathName *pAbsPathName = (WFSPathName *)pPtr;
nResult = WFSSrvValidateDirectory(pAbsPathName);
((WFSResultCallback)pParamHdr->cb)(nResult, pParamHdr->pUserData);
break;
}
case WFSSRV_CREATE_DIRECTORY: {
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, u32, nFlags);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, u64, nQuota);
WFSPathName *pAbsPathName = (WFSPathName *)pPtr;
nResult = WFSSrvCreateDirectory(pAbsPathName, nFlags, nQuota);
((WFSResultCallback)pParamHdr->cb)(nResult, pParamHdr->pUserData);
break;
}
case WFSSRV_GET_ATTRIBUTES: {
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSFileAttributes *, pFa);
WFSPathName *pAbsPathName = (WFSPathName *)pPtr;
nResult = WFSSrvGetAttributes(pAbsPathName, pFa);
((WFSGetAttributesCallback)pParamHdr->cb)(nResult, pFa, pParamHdr->pUserData);
break;
}
case WFSSRV_CHANGE_PERMISSIONS: {
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, u32, nFlags);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, u32, nMask);
WFSPathName *pAbsPathName = (WFSPathName *)pPtr;
nResult = WFSSrvChangePermissions(pAbsPathName, nFlags, nMask);
((WFSResultCallback)pParamHdr->cb)(nResult, pParamHdr->pUserData);
break;
}
case WFSSRV_DELETE: {
WFSPathName *pAbsPathName = (WFSPathName *)pPtr;
nResult = WFSSrvDelete(pAbsPathName);
((WFSResultCallback)pParamHdr->cb)(nResult, pParamHdr->pUserData);
break;
}
case WFSSRV_DELETE_ACL_ENTRY: {
WFSPathName *pAbsPathName;
// restore arguments.
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSTitleId, titleId);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSTitleId, entryCreatorId);
pAbsPathName = (WFSPathName *)pPtr;
nResult = WFSSrvDeleteAccessListEntry(pAbsPathName, titleId, entryCreatorId);
((WFSResultCallback)pParamHdr->cb)(nResult, pParamHdr->pUserData);
break;
}
case WFSSRV_SET_ACL_ENTRY: {
WFSPathName *pAbsPathName;
// restore arguments.
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, u32, nFlags);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, u32, nMask);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSTitleId, titleId);
pAbsPathName = (WFSPathName *)pPtr;
nResult = WFSSrvSetAccessListEntry(pAbsPathName, nFlags, nMask, titleId);
((WFSResultCallback)pParamHdr->cb)(nResult, pParamHdr->pUserData);
break;
}
case WFSSRV_GET_ACL: {
WFSPathName *pAbsPathName;
s32 nResultOrNumAclEntries;
// restore arguments.
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSAccessListEntry*, pAccessList);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, u32, nMaxElements);
pAbsPathName = (WFSPathName *)pPtr;
nResultOrNumAclEntries = WFSSrvGetAccessList(pAbsPathName, pAccessList, nMaxElements);
((WFSGetAccessListCallback)pParamHdr->cb)(nResultOrNumAclEntries, pParamHdr->pUserData);
break;
}
case WFSSRV_MOVE_LOCAL: {
WFSPathName *pSrcAbsPathName = (WFSPathName *)pPtr;
WFSPathName *pDstAbsPathName = (WFSPathName *)((size_t)pPtr + pSrcAbsPathName->nLen + sizeof(WFSPathName) - WFS_MAX_PATH_NAME_SIZE - 1);
nResult = WFSSrvMoveLocal(pSrcAbsPathName, pDstAbsPathName);
((WFSResultCallback)pParamHdr->cb)(nResult, pParamHdr->pUserData);
break;
}
case WFSSRV_CREATE_AND_OPEN_FILE: {
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, u32, nFlags);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSContentIdx, nCidx);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, u32, nPreAllocateSize);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSCliFileInfo *, pFi);
WFSSrvFileHandle sfh;
WFSPathName *pAbsPathName = (WFSPathName *)pPtr;
nResult = WFSSrvCreateAndOpenFile(pAbsPathName, nFlags, nCidx, nPreAllocateSize, &sfh);
WFSFileHandle fh;
if (nResult == WFS_RESULT_OK) {
fh = pFi->nHandle |= sfh;
pFi->fa.nFileSize = pFi->nPosition = 0;
pFi->fa.nFlags = nFlags;
pFi->fa.nCidx = nCidx;
pFi->nAccess = WFS_ACCESS_RW;
} else {
WFSCliFileInfoFree(pFi);
fh = NULL;
}
((WFSFileOpCallback)pParamHdr->cb)(nResult, fh, pParamHdr->pUserData);
break;
}
case WFSSRV_OPEN_FILE: {
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSAccess, nDesiredAccess);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSCliFileInfo *, pFi);
WFSSrvFileHandle sfh;
WFSPathName *pAbsPathName = (WFSPathName *)pPtr;
nResult = WFSSrvOpenFile(pAbsPathName, nDesiredAccess, &sfh, &pFi->fa);
WFSFileHandle fh;
if (nResult == WFS_RESULT_OK) {
fh = pFi->nHandle |= sfh;
pFi->nPosition = 0;
pFi->nAccess = nDesiredAccess;
} else {
WFSCliFileInfoFree(pFi); // fh = NULL;
fh = WFS_INVALID_HANDLE_VALUE;
}
((WFSFileOpCallback)pParamHdr->cb)(nResult, fh, pParamHdr->pUserData);
break;
}
case WFSSRV_GET_FILE_SIZE: {
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM(pPtr, WFSFileHandle, fh);
WFSSrvFileHandle sfh = (WFSSrvFileHandle)fh;
WFSFileSize nFileSize;
nResult = WFSSrvGetFileSize(sfh, &nFileSize);
((WFSGetFileSizeCallback)pParamHdr->cb)(nResult, nFileSize, fh, pParamHdr->pUserData);
break;
}
case WFSSRV_READ_FILE: {
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSFileHandle, fh);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, void *, pFileDataBuffer);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSFileSize, nStartPosition);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM(pPtr, s32, nSize);
WFSSrvFileHandle sfh = (WFSSrvFileHandle)fh;
s32 nResultOrNumBytesRead = WFSSrvReadFile(sfh, pFileDataBuffer, nStartPosition, nSize);
#if 0 // This code has been disabled, because we are no longer updating file position after async read/write
if (nResultOrNumBytesRead >= 0) {
WFSCliFileInfo *pFi;
WFSGetCliFileInfo(&pFi, fh);
pFi->nPosition += nResultOrNumBytesRead;
if (pFi->fa.nFileSize < pFi->nPosition) {
pFi->fa.nFileSize = pFi->nPosition;
}
}
#endif
((WFSReadFileCallback)pParamHdr->cb)(nResultOrNumBytesRead, fh, pParamHdr->pUserData);
break;
}
case WFSSRV_WRITE_FILE: {
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSFileHandle, fh);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, const void *, pFileData);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSFileSize, nStartPosition);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM(pPtr, WFSFileSize, nSize);
WFSSrvFileHandle sfh = (WFSSrvFileHandle)fh;
nResult = WFSSrvWriteFile(sfh, pFileData, nStartPosition, nSize, FALSE);
if (nResult == WFS_RESULT_OK) {
WFSCliFileInfo *pFi;
WFSGetCliFileInfo(&pFi, fh);
u32 nEndPosition = nStartPosition + nSize;
if (pFi->fa.nFileSize < nEndPosition) {
pFi->fa.nFileSize = nEndPosition;
}
}
((WFSFileOpCallback)pParamHdr->cb)(nResult, fh, pParamHdr->pUserData);
break;
}
case WFSSRV_WRITE_FILE_AND_DISCARD: {
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSFileHandle, fh);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, const void *, pFileData);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSFileSize, nStartPosition);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM(pPtr, WFSFileSize, nSize);
WFSSrvFileHandle sfh = (WFSSrvFileHandle)fh;
nResult = WFSSrvWriteFile(sfh, pFileData, nStartPosition, nSize, TRUE);
if (nResult == WFS_RESULT_OK) {
WFSCliFileInfo *pFi;
WFSGetCliFileInfo(&pFi, fh);
u32 nEndPosition = nStartPosition + nSize;
if (pFi->fa.nFileSize < nEndPosition) {
pFi->fa.nFileSize = nEndPosition;
}
}
((WFSFileOpCallback)pParamHdr->cb)(nResult, fh, pParamHdr->pUserData);
break;
}
case WFSSRV_CLOSE_FILE: {
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSFileHandle, fh);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM(pPtr, WFSFileSize, nNewSize);
WFSSrvFileHandle sfh = (WFSSrvFileHandle)fh;
nResult = WFSSrvCloseFile(sfh, nNewSize);
if (nResult == WFS_RESULT_OK) {
WFSCliFileInfo *pFi;
WFSGetCliFileInfo(&pFi, fh);
WFSCliFileInfoFree(pFi);
}
((WFSFileOpCallback)pParamHdr->cb)(nResult, fh, pParamHdr->pUserData);
break;
}
case WFSSRV_FLUSH: {
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, const utf8 *, sVolumeId);
WFSVolumeId *pVolumeId = (WFSVolumeId *)pPtr;
nResult = WFSSrvFlush(pVolumeId);
((WFSResultCallback)pParamHdr->cb)(nResult, pParamHdr->pUserData);
break;
}
case WFSSRV_SEARCH_DIRECTORY_FIRST: {
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSCliSearchDirInfo *, pSdi);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSFileInfo *, pFi);
WFSPathName *pAbsPattern = (WFSPathName *)pPtr;
WFSSrvSearchDirectoryHandle ssdh;
nResult = WFSSrvSearchDirectoryFirst(pAbsPattern, &ssdh, pFi);
pSdi->nHandle |= ssdh;
WFSFileHandle fh = pSdi->nHandle;
if (nResult != WFS_RESULT_OK) {
WFSCliSearchDirInfoFree(pSdi);
fh = WFS_INVALID_HANDLE_VALUE; // fh = 0;
}
((WFSSearchDirectoryCallback)pParamHdr->cb)(nResult, fh, pFi, pParamHdr->pUserData);
break;
}
case WFSSRV_SEARCH_DIRECTORY_NEXT: {
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSSearchDirectoryHandle, sdh);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM(pPtr, WFSFileInfo *, pFi);
WFSSrvSearchDirectoryHandle ssdh = (WFSSrvSearchDirectoryHandle)sdh;
nResult = WFSSrvSearchDirectoryNext(ssdh, pFi);
((WFSSearchDirectoryCallback)pParamHdr->cb)(nResult, sdh, pFi, pParamHdr->pUserData);
break;
}
case WFSSRV_SEARCH_DIRECTORY_CLOSE: {
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSSearchDirectoryHandle, sdh);
WFSSrvSearchDirectoryHandle ssdh = (WFSSrvSearchDirectoryHandle)sdh;
nResult = WFSSrvSearchDirectoryClose(ssdh);
if (nResult == WFS_RESULT_OK) {
WFSCliSearchDirInfo *pSdi;
WFSGetCliSearchDirInfo(&pSdi, sdh);
WFSCliSearchDirInfoFree(pSdi);
}
((WFSSearchDirectoryCloseCallback)pParamHdr->cb)(nResult, sdh, pParamHdr->pUserData);
break;
}
case WFSSRV_GET_PERMISSIONS: {
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSTitleId, titleId);
WFSPathName *pAbsPathName = (WFSPathName *)pPtr;
u32 nFlags;
nResult = WFSSrvGetPermissionForUser(pAbsPathName, &nFlags, titleId);
((WFSGetPermissionsForUserCallback)pParamHdr->cb)(nResult, nFlags, pParamHdr->pUserData);
break;
}
case WFSSRV_SET_PERMISSIONS: {
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, u32, nFlags);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, u32, nMask);
WFSCLI_DECLARE_AND_READ_ASYNC_PARAM_THEN_INC_PTR(pPtr, WFSTitleId, titleId);
WFSPathName *pAbsPathName = (WFSPathName *)pPtr;
nResult = WFSSrvSetPermissionForUser(pAbsPathName, nFlags, nMask, titleId);
((WFSResultCallback)pParamHdr->cb)(nResult, pParamHdr->pUserData);
break;
}
}
}
#if _WIN32
DWORD WINAPI WFSAsyncExecThread(LPVOID pParam);
#elif _RVL
void *WFSAsyncExecThread(void *pParam);
#elif _TWL
void *WFSAsyncExecThread(void *pParam);
#endif
#if _WIN32
DWORD WINAPI WFSAsyncExecThread(LPVOID pParam)
#elif _RVL
void *WFSAsyncExecThread(void *pParam)
#elif _TWL
void *WFSAsyncExecThread(void *pParam)
#endif
{
#pragma unused(pParam)
(void)osEnableInterrupts();
dbg(MyOSReport("Starting WFSAsyncExecThread()\n"));
while(1) {
WFSLockMutex(&wcg.ag.mxAccessTheParamQueue);
while (wcg.ag.anchor.pHead == (WFSAsyncParamHdr*)&wcg.ag.anchor) {
if (wcg.bLibInitialized==false) {
WFSSignalCond(&wcg.ag.condParamQueueEmpty);
return NULL;
}
WFSWaitCond(&wcg.ag.condParamQueueNotEmpty, &wcg.ag.mxAccessTheParamQueue);
}
WFSResetCond(&wcg.ag.condParamQueueNotEmpty);
WFSAsyncParamHdr *pParamHdr = wcg.ag.anchor.pHead;
wcg.ag.anchor.pHead = pParamHdr->l.pNext;
pParamHdr->l.pNext->l.pPrev = (WFSAsyncParamHdr*)&wcg.ag.anchor;
WFSUnlockMutex(&wcg.ag.mxAccessTheParamQueue);
WFSExecFunction(pParamHdr);
WFSHeapFree(&wcg.heap, pParamHdr);
}
}
void WFSAsyncUtilsInit() {
wcg.ag.anchor.pHead = wcg.ag.anchor.pTail = (WFSAsyncParamHdr*)&wcg.ag.anchor;
if (!bMutexInitialized)
{
bMutexInitialized = true;
WFSInitMutex(&wcg.ag.mxAccessTheParamQueue);
WFSInitCond(&wcg.ag.condParamQueueNotEmpty);
}
wcg.ag.pAsyncExecStack = WFSHeapAlloc(&wcg.heap, WFS_ASYNC_EXEC_STACK_SIZE);
WFSCreateThread(&wcg.ag.asyncExecThread, WFSAsyncExecThread, 0, wcg.ag.pAsyncExecStack, WFS_ASYNC_EXEC_STACK_SIZE, 15);
WFSResumeThread(&wcg.ag.asyncExecThread);
}
void WFSAsyncUtilsClose() {
WFSLockMutex(&wcg.ag.mxAccessTheParamQueue);
WFSSignalCond(&wcg.ag.condParamQueueNotEmpty); // [check]
if (wcg.ag.anchor.pHead != wcg.ag.anchor.pTail) {
WFSWaitCond(&wcg.ag.condParamQueueEmpty, &wcg.ag.mxAccessTheParamQueue);
}
WFSUnlockMutex(&wcg.ag.mxAccessTheParamQueue);
WFSJoinThread(&wcg.ag.asyncExecThread, NULL);
// Assumes all workspace memory will be deleted, so does not bother to free space
// ToDo: blocking wait for last async to finish
}
static void WfsPrepareAsyncCallCommon(void **ppPtr, u8 nFunction, void *pUserData, void *cb, size_t nOtherParamSize, u32 nSize, WFSAsyncParamHdr *pParamHdr) {
pParamHdr->nSize = nSize;
pParamHdr->nFunction = nFunction;
pParamHdr->cb = cb;
pParamHdr->pUserData = pUserData;
WFSLockMutex(&wcg.ag.mxAccessTheParamQueue);
if (wcg.ag.anchor.pHead == (WFSAsyncParamHdr*)&wcg.ag.anchor) {
// ParamQueue was previously empty, but will now have an entry added.
// It is OK to signal in advance of actually adding the entry, becuase
// the async execution thread won't be able to proceed until we unlock the mutex.
WFSSignalCond(&wcg.ag.condParamQueueNotEmpty);
}
pParamHdr->l.pNext = (WFSAsyncParamHdr*)&wcg.ag.anchor;
pParamHdr->l.pPrev = wcg.ag.anchor.pTail;
wcg.ag.anchor.pTail->l.pNext = pParamHdr;
wcg.ag.anchor.pTail = pParamHdr;
if (nOtherParamSize==0) {
WFSUnlockMutex(&wcg.ag.mxAccessTheParamQueue);
}
if (ppPtr) {
*ppPtr = (void*)((size_t)pParamHdr + sizeof(WFSAsyncParamHdr));
}
}
WFSResult WFSPrepareAsyncCall(void **ppPtr, u8 nFunction, void *pUserData, void *cb, size_t nOtherParamSize) {
// This function allocates memory for storing away parameters of asynchronous function calls which do not include path names.
// If any errors occur, it releases the allocated memory and returns with an error code.
// If no errors occur, the memory remains allocated, and a parameter header entry is added to the async execution ParamQueue.
// If nOtherParamSize is 0, the ParamQueue item is complete, and the access mutex is unlocked.
// otherwise, it is assumed that the calling function will fill out the remaining elements and will unlock the mutex.
size_t nTotalAllocSize = sizeof(WFSAsyncParamHdr) + nOtherParamSize;
WFSAsyncParamHdr *pParamHdr = (WFSAsyncParamHdr *)WFSHeapAlloc(&wcg.heap, nTotalAllocSize);
if (pParamHdr == 0) {
return WFS_RESULT_OUT_OF_MEMORY;
}
WfsPrepareAsyncCallCommon(ppPtr, nFunction, pUserData, cb, nOtherParamSize, nTotalAllocSize, pParamHdr);
return WFS_RESULT_OK;
}
WFSResult WFSPrepareAsyncCallWithPathName(void **ppPtr, const utf8 *sInPathName,
WFSPathNameType nPathType, u8 nFunction, void *pUserData, void *cb, size_t nOtherParamSize)
{
// This function allocates memory for storing away parameters of asynchronous function calls, including a pathname parameter.
// It resolves, stores, and validates the specified pathname.
// If any errors occur, it releases the allocated memory and returns with an error code.
// If no errors occur, the memory remains allocated, and a parameter header entry is added to the async execution ParamQueue.
// If nOtherParamSize is 0, the ParamQueue item is complete, and the access mutex is unlocked.
// otherwise, it is assumed that the calling function will fill out the remaining elements and will unlock the mutex.
size_t nOffset = sizeof(WFSAsyncParamHdr) + nOtherParamSize;
size_t nTotalAllocSize = nOffset + sizeof(WFSPathName);
WFSAsyncParamHdr *pParamHdr = (WFSAsyncParamHdr *)WFSHeapAlloc(&wcg.heap, nTotalAllocSize);
if (pParamHdr == 0) {
return WFS_RESULT_OUT_OF_MEMORY;
}
WFSPathPartOffsetArray ppoa;
WFSPathName *pPnAbs = (WFSPathName *)((u8*)pParamHdr + nOffset);
WFSResult nResult = WFSPathResolve(pPnAbs, &ppoa, sInPathName, nPathType);
if (nResult != WFS_RESULT_OK) {
WFSHeapFree(&wcg.heap, pParamHdr);
return nResult;
}
WfsPrepareAsyncCallCommon(ppPtr, nFunction, pUserData, cb, nOtherParamSize, nTotalAllocSize, pParamHdr);
return WFS_RESULT_OK;
}
WFSResult WFSPrepareMoveLocalAsyncCall(void **ppPtr, const utf8 *sSrcPathName, const utf8 *sDstPathName,
WFSPathNameType nPathType, u8 nFunction, void *pUserData, void *cb, size_t nOtherParamSize)
{
// This function allocates memory for storing away parameters of asynchronous function calls, including a pathname parameter.
// It resolves, stores, and validates the specified pathname.
// If any errors occur, it releases the allocated memory and returns with an error code.
// If no errors occur, the memory remains allocated, and a parameter header entry is added to the async execution ParamQueue.
// If nOtherParamSize is 0, the ParamQueue item is complete, and the access mutex is unlocked.
// otherwise, it is assumed that the calling function will fill out the remaining elements and will unlock the mutex.
size_t nOffset = sizeof(WFSAsyncParamHdr) + nOtherParamSize;
size_t nTotalAllocSize = nOffset + (2 * sizeof(WFSPathName));
WFSAsyncParamHdr *pParamHdr = (WFSAsyncParamHdr *)WFSHeapAlloc(&wcg.heap, nTotalAllocSize);
if (pParamHdr == 0) {
return WFS_RESULT_OUT_OF_MEMORY;
}
WFSPathPartOffsetArray ppoa;
WFSPathName *pPnSrcAbs = (WFSPathName *)((u8*)pParamHdr + nOffset);
WFSResult nResult = WFSPathResolve(pPnSrcAbs, &ppoa, sSrcPathName, nPathType);
if (nResult != WFS_RESULT_OK) {
goto Error;
}
nOffset += pPnSrcAbs->nLen + sizeof(WFSPathName) - WFS_MAX_PATH_NAME_SIZE - 1;
WFSPathName *pPnDstAbs = (WFSPathName *)((u8*)pParamHdr + nOffset);
nResult = WFSPathResolve(pPnDstAbs, &ppoa, sDstPathName, nPathType);
if (nResult != WFS_RESULT_OK) {
goto Error;
}
if (strncmp(pPnSrcAbs->sStr, pPnDstAbs->sStr, pPnSrcAbs->nLen)==0) {
if (pPnDstAbs->sStr[pPnSrcAbs->nLen]=='/') {
// trying to move a directory to it's own sub-directory
nResult = WFS_RESULT_INVALID;
goto Error;
}
}
nOffset += pPnDstAbs->nLen + sizeof(WFSPathName) - WFS_MAX_PATH_NAME_SIZE - 1;
WfsPrepareAsyncCallCommon(ppPtr, nFunction, pUserData, cb, nOtherParamSize, nOffset, pParamHdr);
return WFS_RESULT_OK;
Error:
WFSHeapFree(&wcg.heap, pParamHdr);
return nResult;
}
WFSResult WFSPrepareAsyncCallWithDeviceName(void **ppPtr, const utf8 *sDeviceName,
u8 nFunction, void *pUserData, void *cb, size_t nOtherParamSize)
{
size_t nDeviceNameOffset = sizeof(WFSAsyncParamHdr) + sizeof(const utf8 *) + nOtherParamSize;
size_t nTotalAllocSize = nDeviceNameOffset + sizeof(WFSDeviceName);
WFSAsyncParamHdr *pParamHdr = (WFSAsyncParamHdr *)WFSHeapAlloc(&wcg.heap, nTotalAllocSize);
if (pParamHdr == 0) {
return WFS_RESULT_OUT_OF_MEMORY;
}
void *pPtr = (void*)((size_t)pParamHdr + sizeof(WFSAsyncParamHdr));
WFSCLI_WRITE_ASYNC_PARAM(pPtr, const utf8 *, sDeviceName);
WFSDeviceName *pDeviceName = (WFSDeviceName *)((u8*)pParamHdr + nDeviceNameOffset);
WFSResult nResult = WFSSetDeviceName(pDeviceName, sDeviceName);
if (nResult != WFS_RESULT_OK) {
WFSHeapFree(&wcg.heap, pParamHdr);
return nResult;
}
WfsPrepareAsyncCallCommon(ppPtr, nFunction, pUserData, cb, nOtherParamSize, nTotalAllocSize, pParamHdr);
if (ppPtr) {
*ppPtr = (void*)((size_t)*ppPtr + sizeof(const utf8 *));
}
return WFS_RESULT_OK;
}
WFSResult WFSPrepareAsyncCallWithVolumeId(void **ppPtr, const utf8 *sVolumeId,
u8 nFunction, void *pUserData, void *cb, size_t nOtherParamSize)
{
size_t nVolumeIdOffset = sizeof(WFSAsyncParamHdr) + sizeof(const utf8 *) + nOtherParamSize;
size_t nTotalAllocSize = nVolumeIdOffset + sizeof(WFSVolumeId);
WFSAsyncParamHdr *pParamHdr = (WFSAsyncParamHdr *)WFSHeapAlloc(&wcg.heap, nTotalAllocSize);
if (pParamHdr == 0) {
return WFS_RESULT_OUT_OF_MEMORY;
}
void *pPtr = (void*)((size_t)pParamHdr + sizeof(WFSAsyncParamHdr));
WFSCLI_WRITE_ASYNC_PARAM(pPtr, const utf8 *, sVolumeId);
WFSVolumeId *pVolumeId = (WFSVolumeId *)((u8*)pParamHdr + nVolumeIdOffset);
WFSResult nResult = WFSSetVolumeId(pVolumeId, sVolumeId);
if (nResult != WFS_RESULT_OK) {
WFSHeapFree(&wcg.heap, pParamHdr);
return nResult;
}
WfsPrepareAsyncCallCommon(ppPtr, nFunction, pUserData, cb, nOtherParamSize, nTotalAllocSize, pParamHdr);
if (ppPtr) {
*ppPtr = (void*)((size_t)*ppPtr + sizeof(const utf8 *));
}
return WFS_RESULT_OK;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,170 @@
/*---------------------------------------------------------------------------*
Project: Revolution WFS library
File: wfs_Debug.cpp - implementation of debugging routines for WFS
implementation
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfs_Debug.cpp,v $
Revision 1.14 2008/12/10 06:55:50 kondo_masahiro
Added the new device types WFS_DEVTYPE_USB_MSC_??.
Revision 1.13 2008/10/23 11:15:28 nakanose_jin
Open and Search should give a invalid file handle if he fails to execute.
Revision 1.12 2008/07/15 08:43:57 nakanose_jin
change arg order
Revision 1.11 2008/06/25 01:00:08 nakanose_jin
add control level error
Revision 1.10 2008/04/21 04:39:42 nakanose_jin
merging acl
Revision 1.9 2008/04/18 07:45:03 nakanose_jin
merge acl
Revision 1.8 2008/03/26 01:18:02 nakanose_jin
move wfs_Debug.h from local to private folder.
Revision 1.7 2008/02/08 09:52:05 paul
Added WFS_RESULT_DEV_IN_USE
Revision 1.6 2008/02/07 13:02:21 nakanose_jin
WFSUnmountVolume : Add force-close option (but only in detach condition)
Revision 1.5 2007/12/26 10:25:51 paul
Changed to use WFS_RANGE_CHK, WFS_INDEX_COUNT from wfs_defs.h, instead of linking jut_utility.cpp
Revision 1.4 2007/12/17 13:29:17 nakanose_jin
add debug utility function
Revision 1.3 2007/11/02 00:55:00 paul
now logging changes
*---------------------------------------------------------------------------*/
#include "wfs_Defs.h"
#include "private/wfs_Debug.h"
// Print to stdout for now via printf's
void WFSDevTypePrint(WFSDevType devType) {
switch(devType) {
case WFS_DEVTYPE_NONE:
printf("WFS_DEVTYPE_NONE");
break;
case WFS_DEVTYPE_SD:
printf("WFS_DEVTYPE_SD");
break;
case WFS_DEVTYPE_USB_MSC_10:
printf("WFS_DEVTYPE_USB_MSC_10");
break;
case WFS_DEVTYPE_USB_MSC_11:
printf("WFS_DEVTYPE_USB_MSC_11");
break;
case WFS_DEVTYPE_USB_MSC_20:
printf("WFS_DEVTYPE_USB_MSC_20");
break;
default:
printf("unknown");
}
}
void WFSDevInfoPrint(WFSDeviceInfo *pDevInfo) {
printf("DevTotalCapacity (MB) = %I64u\n", pDevInfo->nDevTotalCapacity/(1024*1024));
printf("DevType = "); WFSDevTypePrint((WFSDevType)pDevInfo->nDevType); printf("\n");
printf("DevFlags = 0x%1x\n", pDevInfo->nDevFlags);
}
void WFSFileAttrPrint(WFSFileAttributes *pFileAttr) {
if (pFileAttr->nFlags & WFS_FLAG_IS_A_DIRECTORY)
printf("NumEntries = %u\n", pFileAttr->nNumEntries);
else
printf("FileSize (MB) = %I64u\n", pFileAttr->nFileSize/(1024*1024));
printf("Permissions = 0x%8x\n", pFileAttr->nFlags);
// printf("ContentIdx = %u\n", pFileAttr->nNumEntries);
printf("timeCreated = %u\n", pFileAttr->timeCreated);
printf("timeUpdated = %u\n", pFileAttr->timeUpdated);
}
void WFSFileInfoPrint(WFSFileInfo *pFileInfo) {
WFSFileAttrPrint(&pFileInfo->attr);
printf("sFilename = %s\n", pFileInfo->sFileName);
}
static char *_result_strings[] = {
"OK ",
"BUSY ",
"OUT_OF_MEMORY ",
"INVALID ",
"ACCESS ",
"LIB_NOT_INITIAL",
"LIB_ALREADY_INI",
"FILE_TOO_BIG ",
"NO_CHANGE_SIZE ",
"MEDIA_ERROR ",
"DEV_UNUSABLE ",
"DEV_NOT_INITIAL",
"DEV_IN_USE ",
"VOL_ID_ERROR ",
"WRITE_PROTECTED",
"ALREADY_MOUNTED",
"PERMISSION ",
"PERMISSION_CL ",
"ACL_FULL ",
"ACL_NOT_FOUND ",
"AUTHENTICATION ",
"CORRUPTION ",
"DIRECTORY_QUOTA",
"MAX_HANDLES ",
"ALREADY_EXISTS ",
"NOT_FOUND ",
"NOT_EMPTY ",
"NOT_FILE ",
"NOT_DIRECTORY ",
"FILE_OPEN ",
"LOCKED ",
"RESOURCE_LIMIT_",
""
};
static char *_result_strings2[] = {
"NOT_IMPLEMENTED",
"UNKNOWN ",
"FATAL_ERROR "
};
/*--------------------------------------------------------------------------*/
//! \fn iiFSDev_PrintResult(WFSResult result)
//! \par <20>à¾:
//!
//! \param result
//! \return
/*--------------------------------------------------------------------------*/
const char *
WFSDebug_GetResultString(WFSResult result)
{
s32 idx = -1 * (s32)result;
if (WFS_RANGE_CHK(idx , 0 , WFS_INDEX_COUNT(_result_strings)))
{
return _result_strings[idx];
}
else if (WFS_RANGE_CHK(idx , -WFS_RESULT_NOT_IMPLEMENTED , -WFS_RESULT_NOT_IMPLEMENTED+WFS_INDEX_COUNT(_result_strings2)) )
{
return _result_strings2[idx+WFS_RESULT_NOT_IMPLEMENTED];
}
else
{
return "???";
}
}

View File

@ -0,0 +1,119 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfs_Heap.cpp
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfs_Heap.cpp,v $
Revision 1.8 2007/12/26 04:26:18 paul
changed pAllocator to &allocator
Revision 1.7 2007/12/26 04:14:14 paul
Changed RVL version of WFSHeap
Revision 1.6 2007/12/26 00:19:07 paul
Added WFSHeapDestroy()
Revision 1.5 2007/12/25 14:03:49 ueno
Modified to initialize mutex, thread and heap only once.
Revision 1.4 2007/11/02 00:55:27 paul
now logging changes
*---------------------------------------------------------------------------*/
#include "wfs_Heap.h"
#undef dbg
#if _DEBUG_HEAP
#define dbg(s) s
#else
#define dbg(s)
#endif
#if _WIN32
dbg(u32 nSizeAvaliable=0;)
void WFSCreateHeap(WFSHeap *pHeap, void *pBase, size_t nSize) {
*pHeap = HeapCreate(0, nSize, nSize);
dbg(nSizeAvaliable = nSize);
}
void *WFSHeapAlloc(WFSHeap *pHeap, size_t nSize) {
void *pAddr = HeapAlloc(*pHeap, 0, nSize);
dbg(nSizeAvaliable -= nSize;
MyOSReport("A:Heap:%d\n", nSizeAvaliable));
return pAddr;
}
void WFSHeapFree(WFSHeap *pHeap, void *pAddr) {
dbg(nSizeAvaliable += HeapSize(pHeap, NULL, pAddr);
MyOSReport("F:Heap:%d\n", nSizeAvaliable));
HeapFree(*pHeap, 0, pAddr);
}
void WFSHeapDestroy(WFSHeap *pHeap) {
dbg(MyOSReport("WFSHeapDestroy()\n"));
HeapDestroy(*pHeap);
}
//-- twl modified
#elif _TWL
void WFSCreateHeap(WFSHeap *pHeap, void *pBase, size_t nSize) {
osTPrintf( "%s needs modify.\n", __FUNCTION__);
//main.cÅ<E2809A>sÁÄ¢é
}
void *WFSHeapAlloc(WFSHeap *pHeap, size_t nSize) {
// void *pAddr = OS_AllocFromHeap( OS_ARENA_MAIN_SUBPRIV, *pHeap, nSize);
void *pAddr = osAlloc( nSize);
if( pAddr == NULL) {
osTPrintf( "%s error!\n", __FUNCTION__);
}
return pAddr;
}
void WFSHeapFree(WFSHeap *pHeap, void *pAddr) {
osFree( pAddr);
// OS_FreeToHeap( OS_ARENA_MAIN_SUBPRIV, *pHeap, pAddr);
}
void WFSHeapDestroy(WFSHeap *pHeap) {
osTPrintf( "%s needs modify.\n", __FUNCTION__);
// OS_DestroyHeap( OS_ARENA_MAIN_SUBPRIV, *pHeap);
}
//-- twl modified
#elif _RVL
void WFSCreateHeap(WFSHeap *pHeap, void *pBase, size_t nSize) {
pHeap->handle = MEMCreateExpHeap(pBase, nSize);
MEMInitAllocatorForExpHeap(&pHeap->allocator, pHeap->handle, WFS_HEAP_DEFAULT_ALIGNMENT);
}
void *WFSHeapAlloc(WFSHeap *pHeap, size_t nSize) {
// printf("==> %s:%d pHeap: 0x%08x size: %d\n", __FILE__, __LINE__, pHeap->pAllocator, nSize);
void *pAddr = MEMAllocFromAllocator(&pHeap->allocator, nSize);
// printf("==> %s:%d pAddr: 0x%08x\n", __FILE__, __LINE__, pAddr);
return pAddr;
}
void WFSHeapFree(WFSHeap *pHeap, void *pAddr) {
MEMFreeToAllocator(&pHeap->allocator, pAddr);
}
void WFSHeapDestroy(WFSHeap *pHeap) {
MEMDestroyExpHeap(pHeap->handle);
}
#endif

View File

@ -0,0 +1,242 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfs_Mutex.cpp
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfs_Mutex.cpp,v $
Revision 1.9 2008/04/19 05:53:50 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.8 2007/12/27 01:43:19 ueno
Added WFSIsThreadTerminated() and WFSJoinThread().
Revision 1.7 2007/12/25 14:01:49 ueno
Added WFSSuspendThread().
Revision 1.6 2007/11/02 01:00:36 paul
now logging changes
*---------------------------------------------------------------------------*/
#include "wfs_Mutex.h"
#undef dbg
#if _DEBUG_MUTEX
#define dbg(s) s
#else
#define dbg(s)
#endif
#if _WIN32
dbg(u32 aSignalCounter[0x2000]);
void WFSInitMutex(WFSMutex *pMx) {
pMx->hHandle = CreateMutex(NULL, false, NULL);
ReleaseMutex(pMx->hHandle);
dbg(aSignalCounter[(u32)pMx->hHandle&0x1fff]=1;
MyOSReport("InitMutex(%x:%d)\n", pMx->hHandle, aSignalCounter[(u32)pMx->hHandle&0x1fff]));
}
void WFSLockMutex(WFSMutex *pMx) {
dbg(MyOSReport("Wait(%x:%d)\n", pMx->hHandle, aSignalCounter[(u32)pMx->hHandle&0x1fff]));
WaitForSingleObject(pMx->hHandle, INFINITE);
dbg(aSignalCounter[(u32)pMx->hHandle&0x1fff]--);
}
bool WFSTryLockMutex(WFSMutex *pMx) {
return (WaitForSingleObject(pMx->hHandle, 0) != WAIT_TIMEOUT);
}
void WFSUnlockMutex(WFSMutex *pMx) {
dbg(aSignalCounter[(u32)pMx->hHandle&0x1fff]++;
MyOSReport("Release(%x:%d)\n", pMx->hHandle, aSignalCounter[(u32)pMx->hHandle&0x1fff]));
ReleaseMutex(pMx->hHandle);
}
void WFSInitCond(WFSCond *pCond) {
pCond->hAutoResetEvent = CreateEvent(NULL, false, false, NULL);
dbg(aSignalCounter[(u32)pCond->hAutoResetEvent&0x1fff]=0;
MyOSReport("InitCond(%x:%d)\n", pCond->hAutoResetEvent, aSignalCounter[(u32)pCond->hAutoResetEvent&0x1fff]));
//ResetEvent(pCond->hAutoResetEvent);
//pCond->hManualResetEvent = CreateEvent(NULL, true, false, NULL);
}
void WFSSignalCond(WFSCond *pCond) {
//PulseEvent(pCond->hAutoResetEvent);
dbg(aSignalCounter[(u32)pCond->hAutoResetEvent&0x1fff]++;
MyOSReport("Signal(%x:%d)\n", pCond->hAutoResetEvent, aSignalCounter[(u32)pCond->hAutoResetEvent&0x1fff]));
SetEvent(pCond->hAutoResetEvent);
}
void WFSWaitCond(WFSCond *pCond, WFSMutex* pMx) {
#if 1
dbg(aSignalCounter[(u32)pMx->hHandle&0x1fff]++;
MyOSReport("Signal(%x:%d) And Wait(%x:%d)\n", pMx->hHandle, aSignalCounter[(u32)pMx->hHandle&0x1fff], pCond->hAutoResetEvent, aSignalCounter[(u32)pCond->hAutoResetEvent&0x1fff]));
DWORD nRet = SignalObjectAndWait(pMx->hHandle, pCond->hAutoResetEvent, INFINITE, false);
dbg(aSignalCounter[(u32)pCond->hAutoResetEvent&0x1fff]--);
#else
ReleaseMutex(pMx->hHandle);
WaitForSingleObject(pCond->hAutoResetEvent, INFINITE);
#endif
dbg(MyOSReport("Wait(%x:%d)\n", pMx->hHandle, aSignalCounter[(u32)pMx->hHandle&0x1fff]));
WaitForSingleObject(pMx->hHandle, INFINITE);
dbg(aSignalCounter[(u32)pMx->hHandle&0x1fff]--);
}
void WFSResetCond(WFSCond *pCond) {
ResetEvent(pCond->hAutoResetEvent);
}
bool WFSCreateThread(WFSThread *pThread,
WFSThreadFunc threadFunc,
void* param,
void* stackBase,
u32 stackSize,
OSPriority priority)
{
pThread->hThread = CreateThread(NULL, stackSize, threadFunc, param, CREATE_SUSPENDED, 0);
SetThreadPriority(pThread->hThread, 16-priority);
return true;
}
s32 WFSResumeThread(WFSThread *pThread) {
return ResumeThread(pThread->hThread);
}
void WFSCancelThread(WFSThread *pThread) {
// Note: On windows, this does not do any cleanup - should avoid using
TerminateThread(pThread->hThread, 0);
}
void WFSExitThread(void *pVal) {
ExitThread((DWORD)pVal);
}
s32 WFSSuspendThread(WFSThread *pThread)
{
return SuspendThread(pThread->hThread);
}
bool WFSIsThreadTerminated(WFSThread *pThread)
{
switch (WaitForSingleObject(pThread->hThread, 0))
{
case WAIT_TIMEOUT:
return false;
case WAIT_OBJECT_0: // the thread has exited.
case WAIT_ABANDONED: // [check]
case WAIT_FAILED: // the thread does not exist. [check] should check error code?
default:
break;
}
return true;
}
bool WFSJoinThread(WFSThread *pThread, void** val)
{
#pragma unused (val) // exit value is not supported.
switch (WaitForSingleObject(pThread->hThread, INFINITE))
{
case WAIT_OBJECT_0:
return true;
case WAIT_TIMEOUT:
case WAIT_ABANDONED:
case WAIT_FAILED:
default:
break;
}
return false;
}
#elif _RVL
bool WFSCreateThread(WFSThread *pThread,
WFSThreadFunc threadFunc,
void* param,
void* stackBase,
u32 stackSize,
OSPriority priority)
{
return OSCreateThread(pThread, threadFunc, param, (void*)((u32)stackBase+stackSize), stackSize, priority, 0); // joinable
}
//-- twl modified
#elif _TWL
typedef void (*MyThreadFunc)(void*);
bool WFSCreateThread(WFSThread *pThread,
WFSThreadFunc threadFunc,
void* param,
void* stackBase,
u32 stackSize,
OSPriority priority)
{
osCreateThread( pThread, (MyThreadFunc)threadFunc, param, (void*)((u32)stackBase+stackSize), stackSize, priority);
return true;
}
s32 WFSResumeThread(WFSThread *pThread) {
osWakeupThreadDirect( pThread);
// osTPrintf( "Need TWL modifies.\n");
return 0;
}
void WFSCancelThread(WFSThread *pThread) {
osDestroyThread( pThread);
}
void WFSExitThread(void *pVal) {
osExitThread();
}
s32 WFSSuspendThread(WFSThread *pThread)
{
osTPrintf( "Need TWL modifies.\n");
return 0;
}
bool WFSIsThreadTerminated(WFSThread *pThread)
{
return( osIsThreadTerminated( pThread));
}
bool WFSJoinThread(WFSThread *pThread, void** val)
{
#pragma unused (val) // exit value is not supported.
osJoinThread( pThread);
return true;
}
void WFSInitCond(WFSCond *pCond) {
osInitEvent( pCond);
}
void WFSSignalCond(WFSCond *pCond) {
osSignalEvent( pCond, 1);
}
void WFSWaitCond(WFSCond *pCond, WFSMutex* pMx) {
osUnlockMutex( pMx);
osWaitEventEx( pCond, 1, OS_EVENT_MODE_OR, 1); //イベント待ち後にクリアを伴う
}
void WFSResetCond(WFSCond *pCond) {
osClearAllEvent( pCond);
return;
}
//-- twl modified
#endif

View File

@ -0,0 +1,71 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfs_Names.cpp - Functions for setting and validating name types
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfs_Names.cpp,v $
Revision 1.5 2007/11/19 13:28:27 nakanose_jin
bug fix for null pointer check
Revision 1.4 2007/11/06 22:42:56 paul
Added validation checks for NULL pointers passed in
Revision 1.3 2007/11/02 01:01:00 paul
now logging changes
*---------------------------------------------------------------------------*/
#include "wfs_Names.h"
#include <string.h>
WFSResult WFSSetPathName(WFSPathName *pPathName, const utf8 *sPathName) {
WFSReturnOnNullParameter(sPathName);
u32 nStrLen = strlen(sPathName);
if (nStrLen > WFS_MAX_PATH_NAME_SIZE) {
return WFS_RESULT_INVALID;
}
pPathName->nLen = (WFSPathNameLengthType)nStrLen;
strcpy(pPathName->sStr, sPathName);
return WFS_RESULT_OK;
}
WFSResult WFSSetFileName(WFSFileName *pFileName, const utf8 *sFileName) {
WFSReturnOnNullParameter(sFileName);
u32 nStrLen = strlen(sFileName);
if (nStrLen > WFS_MAX_FILE_NAME_SIZE) {
return WFS_RESULT_INVALID;
}
pFileName->nLen = (WFSFileNameLengthType)nStrLen;
strcpy(pFileName->sStr, sFileName);
return WFS_RESULT_OK;
}
WFSResult WFSSetDeviceName(WFSDeviceName *pDeviceName, const utf8 *sDeviceName) {
WFSReturnOnNullParameter(sDeviceName);
u32 nStrLen = strlen(sDeviceName);
if (nStrLen > WFS_MAX_DEVICE_NAME_SIZE) {
return WFS_RESULT_INVALID;
}
pDeviceName->nLen = (WFSDeviceNameLengthType)nStrLen;
strcpy(pDeviceName->sStr, sDeviceName);
return WFS_RESULT_OK;
}
WFSResult WFSSetVolumeId(WFSVolumeId *pVolumeId, const utf8 *sVolumeId) {
WFSReturnOnNullParameter(sVolumeId);
u32 nStrLen = strlen(sVolumeId);
if (nStrLen > WFS_MAX_VOLUME_ID_SIZE) {
return WFS_RESULT_INVALID;
}
pVolumeId->nLen = (WFSVolumeIdLengthType)nStrLen;
strcpy(pVolumeId->sStr, sVolumeId);
return WFS_RESULT_OK;
}

View File

@ -0,0 +1,353 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfs_PathNames.cpp - Functions for concatenating relative and absolute path names
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfs_PathNames.cpp,v $
Revision 1.23 2008/08/19 14:12:41 nakanose_jin
bug : relative dir from long path current dir causes buffer-overflow
Revision 1.22 2008/07/15 02:32:17 paul
Fixed so that single "/" is still accepted
Revision 1.21 2008/07/09 02:50:34 paul
Changed to ensure absolute paths do not end with a '/'
Revision 1.20 2008/04/28 18:37:29 paul
Fixed a bug with parsing relative patterns which start with a wildcard character
Revision 1.19 2008/04/19 05:53:44 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.18 2008/02/29 07:21:55 paul
The previous fix was not adequate. Should be fixed now.
Revision 1.17 2008/02/29 02:07:16 paul
Fixed a bug where pathnames which ended with a filename that was 1 byte too long were incorrectly accepted.
Revision 1.16 2008/02/25 05:37:06 paul
Fixed bug in pathname length check
Revision 1.15 2008/02/13 05:47:08 paul
Changed spec to make empty pathnames "" invalid. Previously it was treated as current directory.
Revision 1.14 2008/02/07 06:32:06 paul
fixed a problem with filenames such as ~File
Revision 1.13 2008/02/04 05:44:00 paul
Fixed a bug with checking the length of a directory entry
Revision 1.12 2008/01/25 04:33:39 paul
Fixed a bug with WFSPathResolve for directories relative to the home directory "~/dir"
Revision 1.11 2008/01/17 10:18:11 paul
Fixed a bug where characters >=0x80 were being treated as -ve indexes in the table lookup
Revision 1.10 2007/12/25 14:03:49 ueno
Modified to initialize mutex, thread and heap only once.
Revision 1.9 2007/12/10 02:49:38 paul
Added debug output
Revision 1.8 2007/11/09 01:19:32 paul
Added a new start state to allow validation of path name depth for paths ending in directories
Revision 1.7 2007/11/06 22:43:12 paul
Added validation checks for NULL pointers passed in
Revision 1.6 2007/11/02 01:06:49 paul
now logging changes
*---------------------------------------------------------------------------*/
// File created by Paul Donnelly on 2007.10.05
#include "wfs_Client.h"
#undef dbg
#if _DEBUG_PATHNAMES
#define dbg(s) s
#else
#define dbg(s)
#endif
// A Lookup table is used to categorize characters for the purposes of resolving path names.
// It maps a single utf-8 byte to one of the following categories:
#define CHAR_CATEGORY_NORMAL 0
#define CHAR_CATEGORY_DOT 1
#define CHAR_CATEGORY_SLASH 2
#define CHAR_CATEGORY_TILDA 3
#define CHAR_CATEGORY_NULL 4
#define CHAR_CATEGORY_BAD 5
#define NUM_CHAR_CATEGORIES 6
// Invalid Utf-8 bytes, control characters, and wildcards are not allowed in path names
utf8 aCharCategory[256] = {
CHAR_CATEGORY_NULL, CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD,
CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD,
CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD,
CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD,
CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD,
CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD,
CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD,
CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD,
// ! " # $ % & ' ( ) * + , - . /
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CHAR_CATEGORY_BAD, 0, 0, 0, CHAR_CATEGORY_DOT, CHAR_CATEGORY_SLASH,
// 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CHAR_CATEGORY_BAD,
// @ A B C D E F G H I J K L M N O
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// P Q R S T U V W X Y Z [ \ ] ^ _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// ` a b c d e f g h i j k l m n o
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// p q r s t u v w x y z { | } ~ DEL
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CHAR_CATEGORY_TILDA, CHAR_CATEGORY_BAD,
// 0x80..0x8F (128..143)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0x90..0x9F (144..159)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0xA0..0xAF (160..175)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0xB0..0xBF (176..191)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0xC0..0xCF (192..207)
CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0xD0..0xDF (208..223)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0xE0..0xEF (224..239)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0xF0..0xFF (240..255)
0, 0, 0, 0, 0, CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD,
CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD,
CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD, CHAR_CATEGORY_BAD,
};
// Finite State Machine for resolving and normalizing path names
typedef enum {
// Initial states - see wfs_PathNames.h
STATE_START_REL = PATH_TYPE_REL_OR_ABS,
STATE_START_REL_DIR = PATH_TYPE_REL_OR_ABS_DIR,
STATE_START_ABS_DIR = PATH_TYPE_ABS_DIR_ONLY,
STATE_START_PTN = PATH_TYPE_PATTERN,
// Mid-parsing states
STATE_START_DOT,
STATE_START_SLASH,
STATE_START_TILDA,
STATE_START_NAME,
STATE_START_WILD,
STATE_TWO_DOTS,
STATE_IGNORE,
STATE_MID,
STATE_DOT,
STATE_TILDA,
STATE_HOME,
STATE_SLASH,
STATE_PARENT,
// for parsing search patterns including wild-cards
STATE_CHK_WILD,
STATE_WILD,
// End states (Do not require an entry in the state table, since no further transition is possible)
STATE_END,
STATE_HOME_END,
STATE_NAME_END,
STATE_PARENT_END,
STATE_ERROR
} WFSPathFsmState;
u8 aStateMachine[][NUM_CHAR_CATEGORIES] = {
// A-Z . / ~ NULL * ?
{ STATE_START_NAME, STATE_START_DOT, STATE_START_SLASH, STATE_START_TILDA, STATE_ERROR, STATE_ERROR }, // STATE_START_REL
{ STATE_START_NAME, STATE_START_DOT, STATE_START_SLASH, STATE_START_TILDA, STATE_ERROR, STATE_ERROR }, // STATE_START_REL_DIR
{ STATE_ERROR, STATE_ERROR, STATE_START_SLASH, STATE_ERROR, STATE_ERROR, STATE_ERROR }, // STATE_START_ABS_DIR
{ STATE_START_NAME, STATE_START_DOT, STATE_START_SLASH, STATE_START_TILDA, STATE_ERROR, STATE_START_WILD}, // STATE_START_PTN
{ STATE_MID, STATE_TWO_DOTS, STATE_IGNORE, STATE_MID, STATE_END, STATE_CHK_WILD }, // STATE_START_DOT
{ STATE_MID, STATE_DOT, STATE_IGNORE, STATE_TILDA, STATE_END, STATE_CHK_WILD }, // STATE_START_SLASH
{ STATE_START_NAME, STATE_START_NAME, STATE_HOME, STATE_START_NAME, STATE_HOME_END, STATE_CHK_WILD }, // STATE_START_TILDA
{ STATE_MID, STATE_MID, STATE_SLASH, STATE_MID, STATE_NAME_END, STATE_CHK_WILD }, // STATE_START_NAME
{ STATE_WILD, STATE_WILD, STATE_ERROR, STATE_WILD, STATE_NAME_END, STATE_WILD }, // STATE_START_WILD
{ STATE_MID, STATE_MID, STATE_PARENT, STATE_MID, STATE_PARENT_END, STATE_CHK_WILD }, // STATE_TWO_DOTS
{ STATE_MID, STATE_DOT, STATE_IGNORE, STATE_TILDA, STATE_END, STATE_CHK_WILD }, // STATE_IGNORE
{ STATE_MID, STATE_MID, STATE_SLASH, STATE_MID, STATE_NAME_END, STATE_CHK_WILD }, // STATE_MID
{ STATE_MID, STATE_TWO_DOTS, STATE_IGNORE, STATE_MID, STATE_END, STATE_CHK_WILD }, // STATE_DOT
{ STATE_MID, STATE_MID, STATE_ERROR, STATE_MID, STATE_ERROR, STATE_CHK_WILD }, // STATE_TILDA
{ STATE_MID, STATE_DOT, STATE_IGNORE, STATE_TILDA, STATE_END, STATE_CHK_WILD }, // STATE_HOME
{ STATE_MID, STATE_DOT, STATE_IGNORE, STATE_TILDA, STATE_END, STATE_CHK_WILD }, // STATE_SLASH
{ STATE_MID, STATE_DOT, STATE_IGNORE, STATE_TILDA, STATE_END, STATE_CHK_WILD }, // STATE_PARENT
{ STATE_WILD, STATE_WILD, STATE_ERROR, STATE_WILD, STATE_NAME_END, STATE_WILD }, // STATE_CHK_WILD
{ STATE_WILD, STATE_WILD, STATE_ERROR, STATE_WILD, STATE_NAME_END, STATE_WILD }, // STATE_WILD
};
static bool bMutexInitialized;
static void WfsPathClear(WFSPathName *pPn, WFSPathPartOffsetArray *pPpoa) {
pPn->nLen = 1;
pPpoa->nNumParts = 0;
pPpoa->aPart[pPpoa->nNumParts] = pPn->nLen;
pPn->sStr[0] = '/';
pPn->sStr[1] = 0;
}
void WFSPathInit() {
if (!bMutexInitialized)
{
bMutexInitialized = true;
WFSInitMutex(&wcg.pg.mxAccessPathGlobals);
}
WfsPathClear(&wcg.pg.pathCurrent.pn, &wcg.pg.pathCurrent.ppoa);
WfsPathClear(&wcg.pg.pathHome.pn, &wcg.pg.pathHome.ppoa);
}
static void WfsPathParent(WFSPathName *pPn, WFSPathPartOffsetArray *pPpoa) {
if (pPpoa->nNumParts == 0) {
return;
}
pPpoa->nNumParts--;
pPn->nLen = pPpoa->aPart[pPpoa->nNumParts];
pPn->sStr[pPn->nLen] = 0;
}
void WFSPathCopy(WFSPathName *pPnDst, WFSPathPartOffsetArray *pPpoaDst, WFSPathName *pPnSrc, WFSPathPartOffsetArray *pPpoaSrc, bool bAppendSeparator, bool bNullTermination) {
pPnDst->nLen = pPnSrc->nLen;
pPpoaDst->nNumParts = pPpoaSrc->nNumParts;
memcpy(pPpoaDst->aPart, pPpoaSrc->aPart, sizeof(pPpoaSrc->aPart[0]) * (pPpoaSrc->nNumParts+1));
memcpy(pPnDst->sStr, pPnSrc->sStr, sizeof(pPnSrc->sStr[0]) * pPnSrc->nLen);
if ((bAppendSeparator) && (pPnDst->sStr[pPnDst->nLen-1]!='/')) {
pPnDst->sStr[pPnDst->nLen++] = '/';
pPpoaDst->aPart[pPpoaDst->nNumParts]++;
}
if (bNullTermination)
{
pPnDst->sStr[pPnDst->nLen] = 0;
}
}
WFSResult WFSPathResolve(WFSPathName *pPnOutAbs, WFSPathPartOffsetArray *pPpoaOutAbs, const utf8 *sInPathName, WFSPathNameType nPathType) {
// Arguments:
// ----------
// pOutAbsPath .. The output normalized absolute path name
// sInPathName .. The input path name
// nPathType .. Specifies whether to allow relative or absolute, absolute-only, or patterns
//
// Description:
// ------------
// Uses a state machine to process input path names or search patterns.
// Relative paths are concatenated to the current directory or home directory.
// The output is a normalized absolute path name or pattern.
// normalized means "../" == "go back one directory" are processed and removed.
// Invalid path names are detected, and cause a WFS_RESULT_INVALID error.
WFSPathPartOffsetArray ppoa;
WFSReturnOnNullParameter(sInPathName);
if (pPpoaOutAbs == NULL) {
pPpoaOutAbs = &ppoa;
}
const utf8 *pParse = sInPathName;
const utf8 *pName = pParse;
s32 nState = (WFSPathFsmState)nPathType;
s32 nDepthLimit = WFS_MAX_PATH_DEPTH;
s32 nLenAdjust = 0;
if ((nPathType==STATE_START_REL_DIR)||(nPathType==STATE_START_ABS_DIR)) {
nDepthLimit--;
}
WFSLockMutex(&wcg.pg.mxAccessPathGlobals);
WfsPathClear(pPnOutAbs, pPpoaOutAbs);
while(nState < STATE_END) {
s32 nCharCategory = aCharCategory[*((u8*)pParse++)];
nState = aStateMachine[nState][nCharCategory];
switch(nState) {
case STATE_START_DOT: // ". "
case STATE_START_NAME: // "A "
case STATE_START_WILD: // "* "
WFSPathCopy(pPnOutAbs, pPpoaOutAbs, &wcg.pg.pathCurrent.pn, &wcg.pg.pathCurrent.ppoa, true, false);
break;
case STATE_START_SLASH: // "/ "
WfsPathClear(pPnOutAbs, pPpoaOutAbs);
pName++;
break;
case STATE_HOME:
case STATE_HOME_END:
WFSPathCopy(pPnOutAbs, pPpoaOutAbs, &wcg.pg.pathHome.pn, &wcg.pg.pathHome.ppoa, true, false);
// Falls through
case STATE_IGNORE:
pName = pParse;
break;
case STATE_NAME_END:
nLenAdjust = -1;
// Falls through
case STATE_SLASH: {
s32 nPartLen = pParse - pName;
if (nPartLen>(WFS_MAX_FILE_NAME_SIZE+1)) {
goto Error;
}
s32 nNewLen = pPnOutAbs->nLen + nPartLen + nLenAdjust;
s32 nNewDepth = pPpoaOutAbs->nNumParts+1;
if ((nNewLen>WFS_MAX_PATH_NAME_SIZE)||(nNewDepth>nDepthLimit)) {
goto Error;
}
memcpy(&pPnOutAbs->sStr[pPnOutAbs->nLen], pName, (u32)nPartLen);
pPnOutAbs->nLen = (WFSPathNameLengthType)nNewLen;
pPpoaOutAbs->nNumParts++;
pPpoaOutAbs->aPart[pPpoaOutAbs->nNumParts] = (WFSPathNameLengthType)pPnOutAbs->nLen;
pName = pParse;
break;
}
case STATE_PARENT:
case STATE_PARENT_END:
WfsPathParent(pPnOutAbs, pPpoaOutAbs);
pName = pParse;
break;
case STATE_CHK_WILD:
if (nPathType != PATH_TYPE_PATTERN) {
goto Error;
}
break;
case STATE_ERROR:
goto Error;
case STATE_START_TILDA: case STATE_TILDA: case STATE_DOT:
case STATE_START_REL: case STATE_TWO_DOTS: case STATE_MID: case STATE_END:
case STATE_START_REL_DIR: case STATE_START_ABS_DIR:
break;
}
}
if ((pPnOutAbs->sStr[pPnOutAbs->nLen-1] == '/') && (pPnOutAbs->nLen>1)) {
pPnOutAbs->sStr[--pPnOutAbs->nLen] = 0;
--pPpoaOutAbs->aPart[pPpoaOutAbs->nNumParts];
}
pPnOutAbs->sStr[pPnOutAbs->nLen] = 0;
WFSUnlockMutex(&wcg.pg.mxAccessPathGlobals);
dbg(MyOSReport("path: %s\n", pPnOutAbs->sStr));
return WFS_RESULT_OK;
Error:
WFSUnlockMutex(&wcg.pg.mxAccessPathGlobals);
dbg(MyOSReport("path: WFS_RESULT_INVALID\n"));
return WFS_RESULT_INVALID;
}

View File

@ -0,0 +1,125 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfscli_Handles.cpp - Module for file handles and search directory handles
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfscli_Handles.cpp,v $
Revision 1.11 2008/10/07 06:41:51 ueno
Modified WFSCliFileInfoAlloc to set WFSCLI_HANDLE_ALLOCATED in order to indicate the handle is allocated.
Revision 1.10 2008/04/19 05:53:38 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.9 2007/12/25 14:03:49 ueno
Modified to initialize mutex, thread and heap only once.
Revision 1.8 2007/11/16 02:15:59 wayne.wong
Added enumeration and stubs for WFSFlush call.
Revision 1.7 2007/11/02 01:07:38 paul
now logging changes
*---------------------------------------------------------------------------*/
// File created by Paul Donnelly on 2007.10.06
#include "wfs_Client.h"
static bool bMutexInitialized; // [check]
void WFSCliInitHandles() {
if (!bMutexInitialized)
{
bMutexInitialized = true;
WFSInitMutex(&wcg.hnd.mxAccessTheFileInfo);
WFSInitMutex(&wcg.hnd.mxAccessTheSearchDirInfo);
}
wcg.hnd.nFileHandleCounter = 0;
wcg.hnd.nSearchDirHandleCounter = 0;
wcg.hnd.nFirstFreeFileHandle = 0;
wcg.hnd.nFirstFreeSearchDirHandle = 0;
wcg.hnd.nNumUsedFileHandles = 0;
wcg.hnd.nNumUsedSearchDirHandles = 0;
//wcg.hnd.nFirstUsedFileHandle = WFSCLI_MAX_FILE_HANDLES; // A value of WFSCLI_MAX_FILE_HANDLES is the list terminator
//wcg.hnd.nFirstUsedSearchDirHandle = WFSCLI_MAX_SEARCH_DIR_HANDLES; // A value of WFSCLI_MAX_SEARCH_DIR_HANDLES is the list terminator
for(u32 nI=0; nI<WFSCLI_MAX_FILE_HANDLES; nI++) {
wcg.hnd.aCliFileInfo[nI].nNext = nI+1;
}
for(u32 nI=0; nI<WFSCLI_MAX_SEARCH_DIR_HANDLES; nI++) {
wcg.hnd.aCliSearchDirInfo[nI].nNext = nI+1;
}
}
WFSResult WFSGetCliFileInfo(WFSCliFileInfo **ppFi, WFSFileHandle fh) {
*ppFi = &wcg.hnd.aCliFileInfo[(fh>>16)&(WFSCLI_MAX_FILE_HANDLES-1)];
return ((*ppFi)->nHandle == fh)?WFS_RESULT_OK:WFS_RESULT_INVALID;
}
WFSResult WFSGetCliSearchDirInfo(WFSCliSearchDirInfo **ppSdi, WFSSearchDirectoryHandle sdh) {
*ppSdi = &wcg.hnd.aCliSearchDirInfo[(sdh>>16)&(WFSCLI_MAX_SEARCH_DIR_HANDLES-1)];
return ((*ppSdi)->nHandle == sdh)?WFS_RESULT_OK:WFS_RESULT_INVALID;
}
WFSResult WFSCliFileInfoAlloc(WFSCliFileInfo **ppFi) {
WFSLockMutex(&wcg.hnd.mxAccessTheFileInfo);
if (wcg.hnd.nFirstFreeFileHandle == WFSCLI_MAX_FILE_HANDLES) {
WFSUnlockMutex(&wcg.hnd.mxAccessTheFileInfo);
return WFS_RESULT_MAX_HANDLES;
}
wcg.hnd.nNumUsedFileHandles++;
u32 nIdx = wcg.hnd.nFirstFreeFileHandle;
wcg.hnd.nFirstFreeFileHandle = wcg.hnd.aCliFileInfo[nIdx].nNext;
wcg.hnd.aCliFileInfo[nIdx].nNext = WFSCLI_HANDLE_ALLOCATED; // this means the handle is open.
*ppFi = &wcg.hnd.aCliFileInfo[nIdx];
wcg.hnd.aCliFileInfo[nIdx].nHandle = WFSCLI_FILE_HANDLE_TT_FIELD | wcg.hnd.nFileHandleCounter | (nIdx<<16);
wcg.hnd.nFileHandleCounter += WFSCLI_FILE_HANDLE_INC;
wcg.hnd.nFileHandleCounter &= WFSCLI_HANDLE_COUNTER_MASK;
WFSUnlockMutex(&wcg.hnd.mxAccessTheFileInfo);
return WFS_RESULT_OK;
}
WFSResult WFSCliSearchDirInfoAlloc(WFSCliSearchDirInfo **ppSdi) {
WFSLockMutex(&wcg.hnd.mxAccessTheSearchDirInfo);
if (wcg.hnd.nFirstFreeSearchDirHandle == WFSCLI_MAX_SEARCH_DIR_HANDLES) {
WFSUnlockMutex(&wcg.hnd.mxAccessTheSearchDirInfo);
return WFS_RESULT_MAX_HANDLES;
}
wcg.hnd.nNumUsedSearchDirHandles++;
u32 nIdx = wcg.hnd.nFirstFreeSearchDirHandle;
wcg.hnd.nFirstFreeSearchDirHandle = wcg.hnd.aCliSearchDirInfo[nIdx].nNext;
wcg.hnd.aCliSearchDirInfo[nIdx].nNext = WFSCLI_HANDLE_ALLOCATED; // this means the handle is open.
*ppSdi = &wcg.hnd.aCliSearchDirInfo[nIdx];
wcg.hnd.aCliSearchDirInfo[nIdx].nHandle = WFSCLI_SEARCH_DIR_HANDLE_TT_FIELD | wcg.hnd.nSearchDirHandleCounter | (nIdx<<16);
wcg.hnd.nSearchDirHandleCounter += WFSCLI_SEARCH_DIR_HANDLE_INC;
wcg.hnd.nSearchDirHandleCounter &= WFSCLI_HANDLE_COUNTER_MASK;
WFSUnlockMutex(&wcg.hnd.mxAccessTheSearchDirInfo);
return WFS_RESULT_OK;
}
void WFSCliFileInfoFree(WFSCliFileInfo *pFi) {
WFSLockMutex(&wcg.hnd.mxAccessTheFileInfo);
u32 nIdx = (u32)(pFi - wcg.hnd.aCliFileInfo);
pFi->nHandle ^= 0x55555555; // ensures the deleted handle is invalid
pFi->nNext = wcg.hnd.nFirstFreeFileHandle;
wcg.hnd.nNumUsedFileHandles--;
wcg.hnd.nFirstFreeFileHandle = nIdx;
WFSUnlockMutex(&wcg.hnd.mxAccessTheFileInfo);
}
void WFSCliSearchDirInfoFree(WFSCliSearchDirInfo *pSdi) {
WFSLockMutex(&wcg.hnd.mxAccessTheSearchDirInfo);
u32 nIdx = (u32)(pSdi - wcg.hnd.aCliSearchDirInfo);
pSdi->nHandle ^= 0x55555555; // ensures the deleted handle is invalid
pSdi->nNext = wcg.hnd.nFirstFreeSearchDirHandle;
wcg.hnd.nNumUsedSearchDirHandles--;
wcg.hnd.nFirstFreeSearchDirHandle = nIdx;
WFSUnlockMutex(&wcg.hnd.mxAccessTheSearchDirInfo);
}

View File

@ -0,0 +1,203 @@
/*---------------------------------------------------------------------------*
Project: TWL - rtfs interface for SD Memory Card
File: drnand.h
Copyright 2006-2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Date:: #$
$Rev$
$Author$
*---------------------------------------------------------------------------*/
#include <brom.h>
#include <brom/nand/nand.h>
#include <sdmc.h>
#include <drnand.h>
#define PRINTDEBUG( ...) ((void)0)
/*
#if (SD_DEBUG_PRINT_ON == 1)
#define PRINTDEBUG osTPrintf
#else
#define PRINTDEBUG( ...) ((void)0)
#endif
*/
/*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*/
#define NUM_SD_PAGES
#define SD_PAGE_SIZE
/*---------------------------------------------------------------------------*
extern変数
*---------------------------------------------------------------------------*/
/*SDメモリカードのスペック構造体*/
SdmcSpec sdmc_current_spec;
/*---------------------------------------------------------------------------*
extern関数
*---------------------------------------------------------------------------*/
extern void nandReset( void);
void i_nandCalcSize( void); //TODO:sdmc_current_specを構造体に入れること
BOOL nandCrashBootSectors( u32* buf);
/*---------------------------------------------------------------------------*
static変数
*---------------------------------------------------------------------------*/
static FATSpec NandFatSpec[4]; //FATパラメータ(パーティション03個別)
static int nand_calculated_fat_params = 0;
/*---------------------------------------------------------------------------*
static関数
*---------------------------------------------------------------------------*/
BOOL nandFillPartition( int partition_no, u32* buf, u32 blocks);
void i_nandCalcSize( void);
#if 1 //アプリケーションでパーティション構成を決めたいとき
u32 NAND_FAT_PARTITION_COUNT;
u32 NAND_RAW_SECTORS;
u32 NAND_FAT0_SECTORS = 0;
u32 NAND_FAT1_SECTORS;
u32 NAND_FAT2_SECTORS;
u32 NAND_FAT3_SECTORS;
void nandSetFormatRequest( u16 partition_num, u32* partition_sectors);
void nandSetFormatRequest( u16 partition_num, u32* partition_sectors)
{
NAND_RAW_SECTORS = partition_sectors[0];
NAND_FAT0_SECTORS = partition_sectors[1] + NAND_RAW_SECTORS;
NAND_FAT1_SECTORS = partition_sectors[2];
NAND_FAT2_SECTORS = partition_sectors[3];
NAND_FAT3_SECTORS = partition_sectors[4];
NAND_FAT_PARTITION_COUNT = partition_num;
}
#else //パーティション構成を決め打ちするとき
/* RAW:1MB, FAT0:206MB, FAT1:32.75MB */
#define NAND_FAT_PARTITION_COUNT (3)
#define NAND_RAW_SECTORS (( 1*1024*1024)/512);
#define NAND_FAT0_SECTORS (((206*1024*1024)/512) + NAND_RAW_SECTORS); //計算上RAWを含めておく
#define NAND_FAT1_SECTORS ((33536*1024)/512);
#define NAND_FAT2_SECTORS (( 1*1024*1024)/512);
#define NAND_FAT3_SECTORS (0);
#endif
/*---------------------------------------------------------------------------*
Name: nandNfsIo
Description:
Arguments: driveno :
block :
buffer :
count :
reading : TRUE
Returns: TRUE/FALSE
*---------------------------------------------------------------------------*/
BOOL nandNfsIo( int driveno, u32 block, void* buffer, u16 count, BOOL reading)
{
if( reading) {
PRINTDEBUG( "DEVCTL_IO_READ ... block:%x, count:%x -> buf:%x\n", block, count, buffer);
nandReadSector( buffer, block, count);
}else{
PRINTDEBUG( "DEVCTL_IO_WRITE ... block:%x, count:%x <- buf:%x\n", block, count, buffer);
nandWriteSector( buffer, block, count);
}
return TRUE;
}
/*---------------------------------------------------------------------------*
Name: nandNfsCtrl
Description:
Arguments: driveno :
opcode :
pargs :
Returns:
Memo : DRIVE_FLAGS_REMOVABLEの場合IO関数を呼ぶ前に
CTRL関数のDEVCTL_CHECK_STATUSが呼ばれる
DEVTEST_CHANGEDDEVTEST_NOCHANGEが確認されるとRTFSはセクタ0を
FATパラメータを取得した上で目的のセクタを読みに行く
CTRL関数の前にはDEVCTL_CHECK_STATUSが呼ばれないのでDEVCTL_
GET_GEOMETRYでは自前で再挿入をチェックする必要がある
*---------------------------------------------------------------------------*/
int nandNfsCtrl( int driveno, int opcode, void* pargs)
{
switch( opcode) {
case NFS_DEVCTL_GET_GEOMETRY: //formatまたはpartirionするときにRTFSが使うパラメータ
return( 0);
case NFS_DEVCTL_FORMAT:
PRINTDEBUG( "DEVCTL_FORMAT\n");
return( 0);
case NFS_DEVCTL_REPORT_REMOVE: //抜かれたとき
PRINTDEBUG( "DEVCTL_REPORT_REMOVE\n");
return( 0);
case NFS_DEVCTL_CHECKSTATUS: //REMOVABLEの場合、毎回R/W前に呼ばれる
PRINTDEBUG( "DEVCTL_CHECKSTATUS\n");
return(DEVTEST_NOCHANGE);
// }
case NFS_DEVCTL_WARMSTART: //attachのときしか呼ばれない
PRINTDEBUG( "DEVCTL_WARMSTART\n");
/*-- NANDのみ初期化 --*/
// nandReset();
/*--------------------*/
return( 0);
case NFS_DEVCTL_POWER_RESTORE:
PRINTDEBUG( "DEVCTL_POWER_RESTORE\n");
break;
case NFS_DEVCTL_POWER_LOSS:
PRINTDEBUG( "DEVCTL_POWER_LOSS\n");
break;
default:
PRINTDEBUG( "DEVCTL_unknown\n");
break;
}
return( 0);
}
/*---------------------------------------------------------------------------*
Name: i_nandCalcSize
Description:
Arguments:
Returns: None
*---------------------------------------------------------------------------*/
void i_nandCalcSize( void)
{
sdmc_current_spec.csd_ver2_flag = 0;
sdmc_current_spec.protected_capacity = (20*256); //20Blocks
sdmc_current_spec.card_capacity = NAND_GUARANTEED_SECTORS;
sdmc_current_spec.memory_capacity = sdmc_current_spec.card_capacity -
sdmc_current_spec.protected_capacity;
}
//#endif /*(INCLUDE_SD)*/

View File

@ -0,0 +1,545 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_Device.cpp - storage device abstraction.
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
*---------------------------------------------------------------------------*/
#include "wfskrn_Device.h"
#include "wfskrn_Api.h"
#include <brom/nand/nand.h>
#include <drnand.h>
//TODO:¼Å<E2809A>錾µÄinclude·é
#ifdef __cplusplus
extern "C" {
#endif
BOOL nandNfsIo( int driveno, u32 block, void* buffer, u16 count, BOOL reading);
int nandNfsCtrl( int driveno, int opcode, void* pargs);
#ifdef __cplusplus
}
#endif
typedef struct{
u32 cmd;
s32 status;
WFSHashCode *pHash;
WFSHashCode readHash;
} DeviceMscResourceRequest;
static DeviceMscResourceRequest gPmrr[DEVICE_IOP_MAX_ASYNC_NUM];
#if _WIN32
char sDevicePathWin32[sizeof(WFSKRN_SIMULATED_DISK_PATH)+WFS_MAX_DEVICE_NAME_SIZE+1] = WFSKRN_SIMULATED_DISK_PATH;
char *DeviceGetWin32PathName(const utf8 *sDevName) {
memcpy(&sDevicePathWin32[sizeof(WFSKRN_SIMULATED_DISK_PATH)-1], sDevName, WFS_MAX_DEVICE_NAME_SIZE+1);
return sDevicePathWin32;
}
WFSHashCode aHashDummyData = {0xbeefbeef,0xbeefbeef,0xbeefbeef,0xbeefbeef,0xbeefbeef};
#elif _IOP
static IOSMessageQueueId gMqidPmrr;
static IOSMessage gMqPmrr[DEVICE_IOP_MAX_ASYNC_NUM];
static IOSMessageQueueId gMqidIrrFb;
static IOSMessage gMqIrrFb[1];
static IOSResourceRequest gIrrFuncBlock;
static DeviceAttachDetachCallback gCbAttach = 0;
#endif
static s32 cntDebugPseudoDetachDrive = -1;
static s32 cntDebugPseudoHashInconsistent = -1;
#define WFS_MAX_DEVICE_PATH (sizeof(WFS_DEVICE_DIRECTORY) + WFS_MAX_DEVICE_NAME_SIZE + 2)
// Initialize Device library
// x86 - initialize parameter
void DeviceInitLib() {
dbgd(osTPrintf("DeviceInitLib()\n"));
wkg.nNumDevices = 0;
memset(&wkg.aDevInfo, 0, sizeof(wkg.aDevInfo));
memset(&gPmrr, 0, sizeof(DeviceMscResourceRequest)*DEVICE_IOP_MAX_ASYNC_NUM);
}
void DeviceDebugSetPseudoDetachDevice(s32 cnt)
{
cntDebugPseudoDetachDrive = cnt;
}
void DeviceDebugSetPseudoHashInconsistent(s32 cnt)
{
cntDebugPseudoHashInconsistent = cnt;
}
s32 DeviceDebugGetPseudoDetachDevice()
{
return cntDebugPseudoDetachDrive;
}
s32 DeviceDebugGetPseudoHashInconsistent()
{
return cntDebugPseudoHashInconsistent;
}
#if _WIN32
static IOSError _WIN32DeviceRead(DeviceInfo *pDevInfo, u32 nSectorAdr, u8 *pData, u16 nSectors, u8 *pHash, u16 nHashSectors, s32 nHashStride)
{
u64 filePos = (u64)nSectorAdr * pDevInfo->nSectorSize;
filePos += 2 * sizeof(u32); // initial bytes have sector size + dev capacity
LONG posLow = (LONG) filePos & 0xffffffff;
LONG posHigh = filePos >> 32;
SetFilePointer(pDevInfo->hSimulatedDeviceFile, posLow, &posHigh, FILE_BEGIN);
DWORD numBytes = pDevInfo->nSectorSize * nSectors;
DWORD bytesRead;
if (!ReadFile(pDevInfo->hSimulatedDeviceFile, pData, numBytes, &bytesRead, NULL)) {
dbgd(osTPrintf("DeviceRead: read failed\n"));
return IOS_ERROR_MSC_COMMAND_FAILED;
}
if(pData[0] == 0xaa){
int a; a=0;
}
if (numBytes != bytesRead) {
dbgd(osTPrintf("DeviceRead: bytes read does not match\n"));
return IOS_ERROR_MSC_COMMAND_FAILED;
}
s32 nSize = numBytes;
int nNumBlks = 0;
while(nSize>0){
u8 *pHashPtr = (u8*)pHash+(nNumBlks*nHashStride);
u32 *pHashDummyData32 = (u32*)aHashDummyData;
*pHashDummyData32++ = nSectorAdr+(nNumBlks*nHashSectors);
*pHashDummyData32++ = nSize < (nHashSectors<<pDevInfo->dh.nLog2SectorSize) ? nSize : (nHashSectors<<pDevInfo->dh.nLog2SectorSize);
if(memcmp(pHashPtr, (u8*)aHashDummyData, sizeof(WFSHashCode))){
return IOS_ERROR_MSC_HASH_INCONSISTENT;
}
nSize -= (nHashSectors<<pDevInfo->dh.nLog2SectorSize);
++nNumBlks;
}
return IOS_ERROR_MSC_OK;
}
static IOSError _WIN32DeviceWrite(DeviceInfo *pDevInfo, u32 nSectorAdr, u8 *pData, u16 nSectors, u8 *pHash, u16 nHashSectors, s32 nHashStride, bool bDecryption)
{
u64 filePos = (u64)nSectorAdr * pDevInfo->nSectorSize;
filePos += sizeof(pDevInfo->dh); // initial bytes have sector size + dev capacity
LONG posLow = (LONG) filePos & 0xffffffff;
LONG posHigh = filePos >> 32;
SetFilePointer(pDevInfo->hSimulatedDeviceFile, posLow, &posHigh, FILE_BEGIN);
DWORD numBytes = pDevInfo->nSectorSize * nSectors;
DWORD bytesWritten;
s32 nSize = numBytes;
int nNumBlks = 0;
while(nSize>0){
u8 *pHashPtr = (u8*)pHash+(nNumBlks*nHashStride);
u32 *pHashDummyData32 = (u32*)aHashDummyData;
*pHashDummyData32++ = nSectorAdr+(nNumBlks*nHashSectors);
if(nSectorAdr+(nNumBlks*nHashSectors) == 0x180){
int a; a=0;
}
*pHashDummyData32++ = nSize < (nHashSectors<<pDevInfo->dh.nLog2SectorSize) ? nSize : (nHashSectors<<pDevInfo->dh.nLog2SectorSize);
memcpy(pHashPtr, (u8*)aHashDummyData, sizeof(WFSHashCode));
nSize -= (nHashSectors<<pDevInfo->dh.nLog2SectorSize);
++nNumBlks;
}
if (!WriteFile(pDevInfo->hSimulatedDeviceFile, pData, numBytes, &bytesWritten, NULL)) {
dbgd(osTPrintf("DeviceWrite: write failed\n"));
return IOS_ERROR_MSC_COMMAND_FAILED;
}
if(pData[0] == 0xaa){
int a; a=0;
}
if (numBytes != bytesWritten) {
dbgd(osTPrintf("DeviceWrite: bytes written does not match\n"));
return IOS_ERROR_MSC_COMMAND_FAILED;
}
if(!bDecryption){
memset(pData, 0xaa, numBytes);
}
return IOS_ERROR_MSC_OK;
}
#endif
// Read nNumSectors sectors from device devHandle starting at LBA nSectorAdr into buffer
// pBuffer. nSectorAdr == LBA.
WFSKrnResult DeviceRead(DeviceInfo *pDevInfo, u32 nSectorAdr, u8 *pBuffer, u32 nSectors, WFSHashCode *pHash, u32 nLog2HashSectors, u32 nOffsetHashBlks, s32 nHashStride, s32 nHashStridePerMaxLBlks)
{
dbgd(osTPrintf("DeviceRead()\n"));
ASSERT(nLog2HashSectors <= (WFS_LOG2_MAX_HASHABLE_BLK_SIZE-pDevInfo->dh.nLog2SectorSize)); // ~64KB
#if _DEBUG
//osTPrintf("Read: nSectorAdr = 0x%x, pDevInfo->dh.nNumSectors = 0x%x\n", nSectorAdr, pDevInfo->dh.nNumSectors);
if (nSectorAdr >= pDevInfo->dh.nNumSectors) {
WFSKrnOutputErrorStr("Attempted access beyond end of device");
}
#endif
WFSKrnResult nResult = WFSKRN_RESULT_OK;
DeviceMscResourceRequest *pCurrentReply;
u32 nMaxSectors = 1<<(WFS_LOG2_LARGE_BLK_SIZE-pDevInfo->dh.nLog2SectorSize);
u32 nHashSectors = (1<<nLog2HashSectors);
u8 *pData = pBuffer;
u32 nNumBlks = nSectors ? ((nSectors-1)>>nLog2HashSectors)+1 : 0;
u32 nNumLoop = (((nHashSectors<<pDevInfo->dh.nLog2SectorSize)*(nNumBlks+nOffsetHashBlks)-1)>>WFS_LOG2_LARGE_BLK_SIZE)+1;
u32 nRcvLoop = nNumLoop < DEVICE_IOP_MAX_ASYNC_NUM ? nNumLoop : DEVICE_IOP_MAX_ASYNC_NUM;
int i;
for(i=0;i<nNumLoop+nRcvLoop;i++){
#if _TWL
pCurrentReply = &gPmrr[0];
if(i>=nRcvLoop){
#endif
switch(pCurrentReply->status){
case IOS_ERROR_MSC_DEVICE_DETACH:
case IOS_ERROR_MSC_COMMAND_FAILED:
case IOS_ERROR_MSC_PHASE_ERROR:
case IOS_ERROR_MSC_INVALID_CBW_SIGNATURE:
case IOS_ERROR_MSC_INVALID_CBW_TAG:
nResult = WFSKRN_RESULT_DEVICE_NOT_FOUND;
break;
#if DEVICE_VERIFY_HASH_DATA
case IOS_ERROR_MSC_HASH_INCONSISTENT:
pDevInfo->nFlags |= WFS_DEVFLAG_NOT_INITIALIZED;
nResult = WFSKRN_RESULT_DEVICE_HASH_INCONSISTENT;
break;
#endif
}
#if DEVICE_DEBUG_PSEUDO_DEVICE_ERROR
if(cntDebugPseudoDetachDrive == 0){
cntDebugPseudoDetachDrive = -1;
nResult = WFSKRN_RESULT_DEVICE_NOT_FOUND;
}
else if(cntDebugPseudoDetachDrive){
--cntDebugPseudoDetachDrive;
}
#if DEVICE_VERIFY_HASH_DATA
if(cntDebugPseudoHashInconsistent == 0){
pDevInfo->nFlags |= WFS_DEVFLAG_NOT_INITIALIZED;
nResult = WFSKRN_RESULT_DEVICE_HASH_INCONSISTENT;
cntDebugPseudoHashInconsistent = -1;
}
else if(cntDebugPseudoHashInconsistent){
--cntDebugPseudoHashInconsistent;
}
#endif
#endif
}
if(i<nNumLoop){
u32 nSec = (nSectors+(nOffsetHashBlks<<nLog2HashSectors)) < nMaxSectors ? nSectors : (nMaxSectors-(nOffsetHashBlks<<nLog2HashSectors));
pCurrentReply->pHash = pHash;
IOSError ie;
#if _WIN32
ie = _WIN32DeviceRead(pDevInfo, nSectorAdr, pData, (u16)nSec, (u8*)pCurrentReply->pHash, (u16)(1<<nLog2HashSectors), nHashStride);
#elif _TWL
if( nandNfsIo( 0, nSectorAdr, pData, nSec, TRUE) == FALSE) {
ie = IOS_ERROR_MSC_COMMAND_FAILED;
nResult = WFSKRN_RESULT_MEDIA_ERROR;
}else{
ie = IOS_ERROR_MSC_OK;
}
#endif
if (ie < IOS_ERROR_MSC_OK){
pCurrentReply->status = ie;
}
nSectors -= nSec;
pData += nSec<<pDevInfo->dh.nLog2SectorSize;
nSectorAdr += nSec;
u32 nBlks = ((nSec-1)>>nLog2HashSectors)+1;
pHash = (WFSHashCode*)((u8*)pHash+nBlks*nHashStride+nHashStridePerMaxLBlks);
nOffsetHashBlks = 0;
}
#if _TWL
}
#endif
return nResult;
}
// Write nNumSectors sectors to device devHandle starting at LBA nSectorAdr from buffer
// pBuffer. nSectorAdr == LBA.
WFSKrnResult DeviceWrite(DeviceInfo *pDevInfo, u32 nSectorAdr, u8 *pBuffer, u32 nSectors, WFSHashCode *pHash, u32 nLog2HashSectors, u32 nOffsetHashBlks, s32 nHashStride, s32 nHashStridePerMaxLBlks, bool bDecryption)
{
#if _DEBUG_BREAK_POINT
if (nSectorAdr==0x28800) {
int a;a=0;
}
#endif
dbgd(osTPrintf("DeviceWrite()\n"));
ASSERT(nLog2HashSectors <= (WFS_LOG2_MAX_HASHABLE_BLK_SIZE-pDevInfo->dh.nLog2SectorSize)); // ~64KB
#if _DEBUG
//osTPrintf("Write: nSectorAdr = 0x%x, pDevInfo->dh.nNumSectors = 0x%x\n", nSectorAdr, pDevInfo->dh.nNumSectors);
if (nSectorAdr >= pDevInfo->dh.nNumSectors) {
WFSKrnOutputErrorStr("Attempted access beyond end of device");
}
#endif
WFSKrnResult nResult = WFSKRN_RESULT_OK;
DeviceMscResourceRequest *pCurrentReply;
u32 nMaxSectors = 1<<(WFS_LOG2_LARGE_BLK_SIZE-pDevInfo->dh.nLog2SectorSize);
u32 nHashSectors = (1<<nLog2HashSectors);
u8 *pData = pBuffer;
u32 nNumBlks = nSectors ? ((nSectors-1)>>nLog2HashSectors)+1 : 0;
u32 nNumLoop = (((nHashSectors<<pDevInfo->dh.nLog2SectorSize)*(nNumBlks+nOffsetHashBlks)-1)>>WFS_LOG2_LARGE_BLK_SIZE)+1;
u32 nRcvLoop = nNumLoop < DEVICE_IOP_MAX_ASYNC_NUM ? nNumLoop : DEVICE_IOP_MAX_ASYNC_NUM;
int i;
for(i=0;i<nNumLoop+nRcvLoop;i++){
#if _TWL
pCurrentReply = &gPmrr[0];
if( i>=1 && i<=nNumLoop ){
#endif
switch(pCurrentReply->status){
case IOS_ERROR_MSC_DEVICE_DETACH:
case IOS_ERROR_MSC_COMMAND_FAILED:
case IOS_ERROR_MSC_PHASE_ERROR:
case IOS_ERROR_MSC_INVALID_CBW_SIGNATURE:
case IOS_ERROR_MSC_INVALID_CBW_TAG:
nResult = WFSKRN_RESULT_DEVICE_NOT_FOUND;
}
#if DEVICE_DEBUG_PSEUDO_DEVICE_ERROR
if(cntDebugPseudoDetachDrive == 0){
nResult = WFSKRN_RESULT_DEVICE_NOT_FOUND;
cntDebugPseudoDetachDrive = -1;
}
else if(cntDebugPseudoDetachDrive){
--cntDebugPseudoDetachDrive;
}
#endif
}
if(i<nNumLoop){
u32 nSec = (nSectors+(nOffsetHashBlks<<nLog2HashSectors)) < nMaxSectors ? nSectors : (nMaxSectors-(nOffsetHashBlks<<nLog2HashSectors));
pCurrentReply->pHash = pHash;
IOSError ie;
#if _WIN32
ie = _WIN32DeviceWrite(pDevInfo, nSectorAdr, pData, (u16)nSec, (u8*)pCurrentReply->pHash, (u16)(1<<nLog2HashSectors), nHashStride, bDecryption);
#elif _TWL
if( nandNfsIo( 0, nSectorAdr, pData, nSec, FALSE) == FALSE) {
ie = IOS_ERROR_MSC_COMMAND_FAILED;
nResult = WFSKRN_RESULT_MEDIA_ERROR;
}else{
ie = IOS_ERROR_MSC_OK;
}
#endif
if (ie < IOS_ERROR_MSC_OK){
pCurrentReply->status = ie;
}
nSectors -= nSec;
pData += nSec<<pDevInfo->dh.nLog2SectorSize;
nSectorAdr += nSec;
u32 nBlks = ((nSec-1)>>nLog2HashSectors)+1;
pHash = (WFSHashCode*)((u8*)pHash+nBlks*nHashStride+nHashStridePerMaxLBlks);
nOffsetHashBlks = 0;
}
#if _TWL
}
#endif
return WFSKRN_RESULT_OK;
}
DeviceInfo *DeviceGetDeviceInfo(const WFSDeviceName *pDevName) {
dbgd(osTPrintf("DeviceGetDeviceInfo()\n"));
utf8 sDevPath[WFS_MAX_DEVICE_NAME_SIZE + 6];
void *pDevInfo;
RxtItr rxi;
rxi.pStrPtr = sDevPath;
osSNPrintf(sDevPath, WFS_MAX_DEVICE_NAME_SIZE + 6,"/dev/%s", pDevName->sStr);
if ((!PathCacheFind3(&rxi, pDevName->nLen+5, &pDevInfo)) ||
((DeviceInfo*)pDevInfo < wkg.aDevInfo) ||
((DeviceInfo*)pDevInfo >= &wkg.aDevInfo[WFSKRN_MAX_DEVICES]))
{
return 0;
}
return (DeviceInfo*)pDevInfo;
}
WFSKrnResult DeviceGetVolumeId(const WFSDeviceName *pDevName, WFSVolumeId *pVolId) {
dbgd(osTPrintf("DeviceGetVolumeInfo()\n"));
DeviceInfo *pDevInfo = DeviceGetDeviceInfo(pDevName);
if(!pDevInfo || !pDevInfo->bInUse) {
return WFSKRN_RESULT_NOT_FOUND;
}
else if (pDevInfo->nFlags & WFS_DEVFLAG_UNUSABLE) {
return WFSKRN_RESULT_DEV_UNUSABLE;
}
else if (pDevInfo->nFlags & WFS_DEVFLAG_NOT_INITIALIZED) {
return WFSKRN_RESULT_DEV_NOT_INITIALIZED;
}
else if(pDevInfo->pVolInfo){
VolumeConvertU32ToVolId(pVolId, pDevInfo->pVolInfo->vh.nVolId);
return WFSKRN_RESULT_OK;
}
VolumeInfo tempVolInfo;
tempVolInfo.pDevInfo = pDevInfo;
pDevInfo->pVolInfo = &tempVolInfo;
BCacheEntry* pBce;
WFSKrnResult nResult = BCacheAllocMetaBlk(&tempVolInfo, VOLUME_HDR_BLK_ADR, BCACHE_FLAG_PINNED | BCACHE_FLAG_READ, &pBce);
if(nResult < WFSKRN_RESULT_OK){
return nResult;
}
VolumeHdr *pVh = (VolumeHdr *)pBce->pBlkPtr;
VolumeConvertU32ToVolId(pVolId, pVh->nVolId);
nResult = BCacheUnpin(&tempVolInfo, VOLUME_HDR_BLK_ADR);
pDevInfo->pVolInfo = 0;
return nResult;
}
WFSKrnResult DeviceMountVolume(DeviceInfo *pDevInfo) {
dbgd(osTPrintf("DeviceMountVolume()\n"));
WFSKrnResult nResult = WFSKRN_RESULT_OK;
VolumeInfo tempVolInfo;
tempVolInfo.pDevInfo = pDevInfo;
pDevInfo->pVolInfo = &tempVolInfo;
BCacheEntry* pBce;
nResult = BCacheAllocMetaBlk(&tempVolInfo, VOLUME_HDR_BLK_ADR, BCACHE_FLAG_PINNED | BCACHE_FLAG_READ, &pBce);
if(nResult < WFSKRN_RESULT_OK){
return nResult;
}
VolumeHdr *pVh = (VolumeHdr *)pBce->pBlkPtr;
tempVolInfo.vh = *(VolumeHdr *)pVh;
BCacheUnpin(&tempVolInfo, VOLUME_HDR_BLK_ADR);
VolumeInfo *pVolInfo = wkg.pMountedVolListAnchor->vl.pNext;
while(pVolInfo != wkg.pMountedVolListAnchor) {
if (pVh->nVolId == pVolInfo->vh.nVolId) {
// The volume Id matches a currently mounted volume
if (pVolInfo->bDetached) {
// ToDo: Check Session ID
pVolInfo->bDetached = false;
pDevInfo->pVolInfo = pVolInfo;
//pDevInfo->nFlags &= ~WFS_DEVFLAG_NOT_MOUNTED;
} else {
nResult = WFSKRN_RESULT_VOL_ID_ERROR;
}
goto Exit;
}
}
BCacheReTag(&tempVolInfo, VOLUME_HDR_BLK_ADR, pVolInfo, VOLUME_HDR_BLK_ADR);
// The volume Id did not match any currently mounted volumes
pVolInfo = pDevInfo->pVolInfo = VolumeAlloc();
pVolInfo->pDevInfo = pDevInfo;
pVolInfo->vh = tempVolInfo.vh;
VolumeAddToMountedList(pVolInfo);
pVolInfo->rootAreaInfo.pVolInfo = pVolInfo;
pVolInfo->rootAreaInfo.pParent = 0;
pVolInfo->rootAreaInfo.nRelStartBlkAdr = 0;
//pVolInfo->rootAreaInfo.ah.nLog2BlkSize = nLog2BlkSize;
//pVolInfo->rootAreaInfo.ah.nNumBlks = nNumBlks;
nResult = AreaOpen(&pVolInfo->rootAreaInfo); // for debug wfskrn
BCacheUnpin(pVolInfo, VOLUME_HDR_BLK_ADR); // kondo_masahiro 080729
Exit:
//BCacheUnpin(pVolInfo, VOLUME_HDR_BLK_ADR);
return nResult;
}
WFSKrnResult DeviceAttach(DeviceInfo *pDevInfo, WFSDevType nDevType, u32 nDevIdx, u32 nLog2SectorSize, u32 nNumSectors) {
dbgd(osTPrintf("DeviceAttach()\n"));
// Called when user physically attaches a drive
if(pDevInfo->bInUse){
// return WFSKRN_RESULT_OK;
DeviceDetach(pDevInfo);
}
nandNfsCtrl( 0, NFS_DEVCTL_WARMSTART, NULL);
WFSKrnResult nResult = WFSKRN_RESULT_OK;
++wkg.nNumDevices;
pDevInfo->bInUse = true;
pDevInfo->nDevType = nDevType;
pDevInfo->dh.nLog2SectorSize = nLog2SectorSize;
pDevInfo->nSectorSize = 1<<nLog2SectorSize;
pDevInfo->dh.nNumSectors = nNumSectors;
pDevInfo->nTotalCapacity = (u64)nNumSectors * (u64)(pDevInfo->nSectorSize);
WFSPathName path;
switch(nDevType) {
case WFS_DEVTYPE_USB_MSC_10:
osTPrintf("Attach device with USB1.0\n");
break;
case WFS_DEVTYPE_USB_MSC_11:
osTPrintf("Attach device with USB1.1\n");
break;
case WFS_DEVTYPE_USB_MSC_20:
osTPrintf("Attach device with USB2.0\n");
break;
default:
return WFSKRN_RESULT_DEVICE_ERROR;
}
pDevInfo->devName.nLen = 5;
osSNPrintf(pDevInfo->devName.sStr, pDevInfo->devName.nLen+1, "msc%02d", nDevIdx+1);
path.nLen = sizeof(WFS_MAX_DEVICE_PATH)+1+ pDevInfo->devName.nLen;
osSNPrintf(path.sStr, WFS_MAX_DEVICE_PATH, WFS_DEVICE_DIRECTORY"/%s", pDevInfo->devName.sStr);
PathCacheEntry *pEntry = PathCacheInsertAfterCursorEntry2(wkg.pathCache.pPinAnchor, path.sStr);
pEntry->pcd.pData = pDevInfo;
#if _IOP
if(__p_hd[nDevIdx]->state < HARDDISC_STATUS_IDLE){
return WFSKRN_RESULT_DEVICE_ERROR;
}
pDevInfo->nDeviceDevHandle = __p_hd[nDevIdx];
#endif
if (wkg.bMountedDeviceWasDetached) {
DeviceMountVolume(pDevInfo);
} else {
pDevInfo->pVolInfo = 0;
//pDevInfo->nFlags = WFS_DEVFLAG_NOT_MOUNTED;
}
return nResult;
}
WFSKrnResult DeviceDetach(DeviceInfo *pDevInfo) {
dbgd(osTPrintf("DeviceDetach()\n"));
if(!pDevInfo->bInUse){
return WFSKRN_RESULT_OK;
}
// Called when user physically detaches a drive
utf8 sDevicePathWfs[WFS_MAX_DEVICE_PATH];
osSNPrintf(sDevicePathWfs, WFS_MAX_DEVICE_PATH, WFS_DEVICE_DIRECTORY"/%s", pDevInfo->devName.sStr);
WFSPathName path;
path.nLen = sizeof(WFS_MAX_DEVICE_PATH)+1+ pDevInfo->devName.nLen;
PathCacheItr pci;
WFSKrnResult nResult = WFSKRN_RESULT_OK;
WFSKrnExitOnError(WFSKrnValidateCopyStrAndConvertToLowerCase(path.sStr, sDevicePathWfs, path.nLen, WFS_MAX_FILE_NAME_SIZE));
WFSKrnExitOnError(PathCacheFindPath(&path, path.sStr, &pci));
PathCacheDeleteEntry(pci.pEntry);
#if _DEBUG
WFSDeviceName devName;
//WFSSetDeviceName(&devName, pDevInfo->devName.sStr);
devName.nLen = STRNLEN(pDevInfo->devName.sStr, WFS_MAX_DEVICE_NAME_SIZE);
strncpy(devName.sStr, pDevInfo->devName.sStr, WFS_MAX_DEVICE_NAME_SIZE);
DeviceInfo *pFoundDevInfo = DeviceGetDeviceInfo(&devName);
if (pFoundDevInfo != 0) {
WFSKrnOutputErrorStr("Delete failed");
}
#endif
pDevInfo->bInUse = false;
VolumeInfo *pVolInfo = pDevInfo->pVolInfo;
if (pVolInfo){
if (pVolInfo->nClientsMountedBy) {
wkg.bMountedDeviceWasDetached = true;
pVolInfo->bDetached = true;
} else {
VolumeRemoveFromMountedList(pDevInfo->pVolInfo);
VolumeFree(pDevInfo->pVolInfo);
pDevInfo->pVolInfo = 0;
}
}
--wkg.nNumDevices;
Exit:
return nResult;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,477 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_BitField.cpp - functions for manipulating bitfields within bit arrays
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_BitField.cpp,v $
Revision 1.4 2008/12/22 08:57:15 ueno
Fixed WfsSetBitField() when 32 < nNumBits.
Revision 1.3 2008/07/17 22:45:41 paul
fixed a performance problem
Revision 1.2 2008/05/10 03:59:43 kondo_masahiro
Merged and fixed code to accept RM compiler
Revision 1.4 2008/04/19 05:51:14 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.3 2008/04/04 20:54:35 paul
Added WfsSetBitField, WfsTestAndSetBitField (used by dir check code to map coverage of used and free parts of block)
Revision 1.2 2008/02/28 06:32:02 kondo_masahiro
Fixed code to accept PPC compiler
Revision 1.1 2007/12/27 11:14:47 paul
Most of this is not used at the moment.. but I'll leave it here for now
*---------------------------------------------------------------------------*/
#include "wfskrn_BitField.h"
#include "wfskrn_Platform.h"
#ifdef _DEBUG
#define _BITFIELD_NUM_TESTS 10000
#else
#define _BITFIELD_NUM_TESTS 10000
#endif
#define BITFIELD_MASK ((1<<nNumBits)-1)
u32 WfsCalculateFieldSizeInBytes(u32 nVal) {
if (nVal<256) return 1; else if (nVal<256) return 2; else if (nVal<256) return 3; else return 4;
}
u8 WfsCalculateFieldSizeInBits(u32 nVal) {
u8 nRet=0;
static const u8 aBitTbl[16] = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4 };
for(; nVal>=16; nVal>>=4) {
nRet+=4;
}
return (u8)( nRet + aBitTbl[nVal] );
}
unsigned WfsReadBitField(unsigned *aBitArray, int nStartBit, int nNumBits) {
// Masking should be performed by the caller
unsigned *pBitArray = &aBitArray[nStartBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT];
int nShift=BITS_PER_INT-(nStartBit&BIT_OFFSET_MASK)-nNumBits;
if (nShift>0) {
return (pBitArray[0]>>nShift);
} else {
if (nShift==0) {
return pBitArray[0];
} else {
return pBitArray[1]>>(BITS_PER_INT+nShift) | pBitArray[0]<<(-nShift);
}
}
}
#if BITFIELD_USE_TEMPLATES
template<unsigned nNumBits>
unsigned WfsReadBitField (unsigned *aBitArray, int nStartBit) {
unsigned *pBitArray = &aBitArray[nStartBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT];
int nShift=BITS_PER_INT-(nStartBit&BIT_OFFSET_MASK)-nNumBits;
if (nShift>0) {
return (pBitArray[0]>>nShift) & BITFIELD_MASK;
} else {
if (nShift==0) {
return pBitArray[0] & BITFIELD_MASK;
} else {
return (pBitArray[1]>>(BITS_PER_INT+nShift) | pBitArray[0]<<(-nShift)) & BITFIELD_MASK;
}
}
}
#endif //BITFIELD_USE_TEMPLATES
void WfsOverwriteBitField(unsigned *aBitArray, int nStartBit, unsigned nValue, int nNumBits, unsigned nMask) {
unsigned *pBitArray = &aBitArray[nStartBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT];
int nShift=BITS_PER_INT-(nStartBit&BIT_OFFSET_MASK)-nNumBits;
if (nShift>0)
pBitArray[0] = (pBitArray[0]&~(nMask<<nShift)) | (nValue<<nShift);
else if (nShift<0) {
int nS1 = -nShift;
pBitArray[0] = (pBitArray[0]&~(nMask>>nS1)) | (nValue>>nS1);
int nS2 = BITS_PER_INT+nShift;
pBitArray[1] = (pBitArray[1]&~(nMask<<nS2)) | (nValue<<nS2);
} else {
pBitArray[0] = (pBitArray[0]&~nMask) | nValue;
}
}
#if BITFIELD_USE_TEMPLATES
template<unsigned nNumBits>
void WfsOverwriteBitField(unsigned *aBitArray, int nStartBit, int nValue) {
unsigned *pBitArray = &aBitArray[nStartBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT];
int nShift=BITS_PER_INT-(nStartBit&BIT_OFFSET_MASK)-nNumBits;
if (nShift>0)
pBitArray[0] = (pBitArray[0]&~(BITFIELD_MASK<<nShift)) | (nValue<<nShift);
else {
int nS1 = -nShift;
pBitArray[0] = (pBitArray[0]&~(BITFIELD_MASK>>nS1)) | (nValue>>nS1);
int nS2 = BITS_PER_INT+nShift;
pBitArray[1] = (pBitArray[1]&~(BITFIELD_MASK<<nS2)) | (nValue<<nS2);
}
}
#endif //BITFIELD_USE_TEMPLATES
void WfsBitArrayInsertBitField(unsigned *aBitArray, int nBitArrayLength, int nBitPos, int nNumBits, unsigned nValue) {
unsigned *pCopyFrom = &aBitArray[nBitArrayLength>>BIT_OFFSET_TO_INT_OFFSET_SHIFT];
unsigned *pCopyTo = &aBitArray[(nBitArrayLength+nNumBits)>>BIT_OFFSET_TO_INT_OFFSET_SHIFT];
unsigned *pStart = &aBitArray[nBitPos>>BIT_OFFSET_TO_INT_OFFSET_SHIFT];
unsigned nOldStartWord = *pStart;
unsigned nStartShift = (u32)(nBitPos&BIT_OFFSET_MASK);
unsigned nStartMask = ((unsigned)-1) >> nStartShift;
// Insert right side of value
s32 nValueShift = (s32)(BITS_PER_INT - nStartShift);
*pStart &= nStartMask;
if (nStartShift) {
*pStart |= (nValue<<nValueShift);
}
if (nNumBits!=BITS_PER_INT) {
unsigned nShiftLeft = (u32)(BITS_PER_INT - nNumBits);
unsigned nTrailingBits = (u32)(nBitArrayLength & BIT_OFFSET_MASK);
if (nTrailingBits >= nShiftLeft) {
if (nTrailingBits > nShiftLeft) {
*pCopyTo = *pCopyFrom<<nShiftLeft;
}
pCopyTo--;
}
while(pCopyFrom > pStart) {
*pCopyTo-- = (pCopyFrom[-1]<<nShiftLeft) | (pCopyFrom[0]>>nNumBits);
pCopyFrom--;
}
*pCopyTo-- = pCopyFrom[0]>>nNumBits;
} else {
// Need a special case for no shift right, becuase shift left by 32 does nothing
if ((nBitArrayLength & BIT_OFFSET_MASK)==0) {
pCopyTo--;
pCopyFrom--;
}
while(pCopyFrom >= pStart) {
*pCopyTo-- = *pCopyFrom--;
}
*pCopyTo = 0;
}
// Insert left side of value
*pStart |= nOldStartWord & ~nStartMask;
nValueShift -= nNumBits;
if (nValueShift > 0) {
*pStart |= nValue<<nValueShift;
} else {
*pStart |= nValue>>-nValueShift;
}
}
void WfsBitArrayDeleteBitField(unsigned *aBitArray, int nBitArrayLength, int nBitPos, int nNumBits) {
unsigned *pCopyStart = &aBitArray[ nBitPos >>BIT_OFFSET_TO_INT_OFFSET_SHIFT];
unsigned nOldCopyStart = *pCopyStart & ~(((unsigned)-1)>>(nBitPos&BIT_OFFSET_MASK));
unsigned nFromBit = (u32)(nBitPos+nNumBits);
unsigned *pCopyFrom = &aBitArray[nFromBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT];
unsigned *pCopyTo = pCopyStart;
unsigned *pCopyEnd = &aBitArray[(nBitArrayLength-nNumBits)>>BIT_OFFSET_TO_INT_OFFSET_SHIFT];
unsigned nShiftLeft = (u32)(nNumBits & BIT_OFFSET_MASK);
unsigned nShiftRight = BITS_PER_INT - nShiftLeft;
*pCopyFrom &= (((unsigned)-1) >> (nFromBit&BIT_OFFSET_MASK));
if (pCopyTo == pCopyFrom) {
while(pCopyTo <= pCopyEnd) {
pCopyTo[0] = (pCopyTo[0]<<nShiftLeft) | (pCopyTo[1]>>nShiftRight);
pCopyTo++;
}
} else {
if (nShiftLeft) {
if ((((pCopyFrom-pCopyTo)*BITS_PER_INT) + nShiftLeft) > nNumBits) {
*pCopyTo++ = pCopyFrom[0]>>nShiftRight;
}
while(pCopyTo <= pCopyEnd) {
pCopyTo[0] = (pCopyFrom[0]<<nShiftLeft) | (pCopyFrom[1]>>nShiftRight);
pCopyTo++; pCopyFrom++;
}
} else {
while(pCopyTo <= pCopyEnd) {
*pCopyTo++ = *pCopyFrom++;
}
}
}
*pCopyStart |= nOldCopyStart;
}
void WfsSetBitField(unsigned *aBitArray, int nStartBit, int nNumBits) {
unsigned *pBitArray = &aBitArray[nStartBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT];
unsigned nEndBit = (unsigned)(nStartBit + nNumBits - 1);
unsigned *pEnd = &aBitArray[nEndBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT];
unsigned nLeftShift = nStartBit&BIT_OFFSET_MASK;
unsigned nRightShift= (nEndBit&BIT_OFFSET_MASK)^BIT_OFFSET_MASK;
if (pBitArray == pEnd) {
*pBitArray |= (((unsigned)-1)<<nLeftShift) & (((unsigned)-1)>>nRightShift);
} else {
*pBitArray |= ((u32)-1)<<nLeftShift;
nNumBits -= (BITS_PER_INT - nLeftShift);
while(nNumBits >= BITS_PER_INT) {
*(++pBitArray) = ((u32)-1);
nNumBits -= BITS_PER_INT;
}
*(++pBitArray) |= ((u32)-1)>>nRightShift;
}
}
unsigned WfsTestAndSetBitField(unsigned *aBitArray, int nStartBit, int nNumBits) {
unsigned *pBitArray = &aBitArray[nStartBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT];
unsigned nEndBit = (unsigned)(nStartBit + nNumBits - 1);
unsigned *pEnd = &aBitArray[nEndBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT];
unsigned nLeftShift = nStartBit&BIT_OFFSET_MASK;
unsigned nRightShift= (nEndBit&BIT_OFFSET_MASK)^BIT_OFFSET_MASK;
unsigned nTest;
if (pBitArray == pEnd) {
nTest = *pBitArray & (((unsigned)-1)<<nLeftShift) & (((unsigned)-1)>>nRightShift);
*pBitArray |= (((unsigned)-1)<<nLeftShift) & (((unsigned)-1)>>nRightShift);
} else {
nTest = *pBitArray & (((u32)-1)<<nLeftShift);
*pBitArray |= ((u32)-1)<<nLeftShift;
nNumBits -= nLeftShift;
while(++pBitArray < pEnd) {
nTest |= *pBitArray;
*pBitArray = ((u32)-1);
}
nTest |= *pBitArray & (((u32)-1)>>nRightShift);
*pBitArray |= ((u32)-1)>>nRightShift;
}
return nTest;
}
void WfsBitFieldCopy(unsigned *aDstBitArray, int nDstOffset, unsigned *aSrcBitArray, int nSrcOffset, int nCopyLength) {
unsigned *pDstStart = &aDstBitArray[ nDstOffset>>BIT_OFFSET_TO_INT_OFFSET_SHIFT];
unsigned *pSrcStart = &aSrcBitArray[ nSrcOffset>>BIT_OFFSET_TO_INT_OFFSET_SHIFT];
unsigned nDstEndBit = (u32)(nDstOffset + nCopyLength - 1);
unsigned *pDstEnd = &aDstBitArray[nDstEndBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT];
unsigned nOldDstStart = *pDstStart;
unsigned nOldDstEnd = *pDstEnd;
int nShift = (nDstOffset&BIT_OFFSET_MASK) - (nSrcOffset&BIT_OFFSET_MASK);
unsigned nShiftRight = (u32)(nShift & BIT_OFFSET_MASK);
unsigned nShiftLeft = BITS_PER_INT - nShiftRight;
if (nShift<0) {
if (pDstStart <= pSrcStart) {
unsigned *pDst = pDstStart;
unsigned *pSrc = pSrcStart;
while(pDst <= pDstEnd) {
pDst[0] = (pSrc[0]<<nShiftLeft) | (pSrc[1]>>nShiftRight);
pDst++; pSrc++;
}
} else {
unsigned *pDst = pDstEnd;
unsigned *pSrc = pSrcStart+(pDstEnd-pDstStart);
while(pDst >= pDstStart) {
pDst[0] = (pSrc[0]<<nShiftLeft) | (pSrc[1]>>nShiftRight);
pDst--; pSrc--;
}
}
} else if (nShift>0) {
if (pDstStart < pSrcStart) {
unsigned *pDst = pDstStart;
unsigned *pSrc = pSrcStart;
while(pDst <= pDstEnd) {
pDst[0] = (pSrc[-1]<<nShiftLeft) | (pSrc[0]>>nShiftRight);
pDst++; pSrc++;
}
} else {
unsigned *pDst = pDstEnd;
unsigned *pSrc = pSrcStart+(pDstEnd-pDstStart);
while(pDst >= pDstStart) {
pDst[0] = (pSrc[-1]<<nShiftLeft) | (pSrc[0]>>nShiftRight);
pDst--; pSrc--;
}
}
} else {
if (pDstStart < pSrcStart) {
unsigned *pDst = pDstStart;
unsigned *pSrc = pSrcStart;
while(pDst <= pDstEnd) {
*pDst++ = *pSrc++;
}
} else {
unsigned *pDst = pDstEnd;
unsigned *pSrc = pSrcStart+(pDstEnd-pDstStart);
while(pDst >= pDstStart) {
*pDst-- = *pSrc--;
}
}
}
unsigned nDstStartMask = (((unsigned)-1) >>(nDstOffset&BIT_OFFSET_MASK));
unsigned nDstEndMask = ((((unsigned)-1)>>1)>>(nDstEndBit&BIT_OFFSET_MASK));
*pDstStart = (*pDstStart & nDstStartMask) | (nOldDstStart & ~nDstStartMask);
*pDstEnd = (*pDstEnd & ~nDstEndMask ) | (nOldDstEnd & nDstEndMask);
}
#define BitMask(b) (1<<(BIT_OFFSET_MASK-((b)&BIT_OFFSET_MASK)))
#include "randomlib.h"
void WfsTestBitFieldModule() {
#if _BITFIELD_NUM_TESTS
int nDstOffset, nSrcOffset, nCopyLength;
unsigned aOldBitArray[8];
unsigned aNewBitArray[8];
s32 nRandomSeed;
#ifdef WIN32
LARGE_INTEGER sysClock;
QueryPerformanceCounter(&sysClock);
nRandomSeed = ((u32*)&sysClock)[0] ^ ((u32*)&sysClock)[1];
#else
nRandomSeed = 0x1;
#endif
RandomSetSeedU32((u32)nRandomSeed);
osTPrintf("nRandomSeed=0x%08x\n", nRandomSeed);
osTPrintf("WfsBitArrayInsertBitField() Test\n");
int nTest;
for(nTest=1; nTest<=_BITFIELD_NUM_TESTS; nTest++) {
//for(unsigned nI=0; nI<8; nI++) { aOldBitArray[nI] = 0xFFFFFFFF; } //RandomU32(); }
unsigned nI;
for(nI=0; nI<8; nI++) { aOldBitArray[nI] = RandomU32(); }
int nNumBits = RandomInt(1, 32);
int nBitArrayLength = RandomInt(0, 256-nNumBits);
int nInsertBit = RandomInt(0, nBitArrayLength);
unsigned nValue = RandomU32();
nValue >>= (32-nNumBits);
aOldBitArray[(nBitArrayLength-1)>>BIT_OFFSET_TO_INT_OFFSET_SHIFT] |= BitMask(nBitArrayLength);
int nBit;
for(nBit=nBitArrayLength; nBit<256; nBit++) {
aOldBitArray[nBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT] &= ~BitMask(nBit);
}
for(nI=0; nI<8; nI++) { aNewBitArray[nI] = aOldBitArray[nI]; } //RandomU32(); }
WfsBitArrayInsertBitField(aNewBitArray, nBitArrayLength, nInsertBit, nNumBits, nValue);
for(nBit=0; nBit<nInsertBit; nBit++) {
if ((aOldBitArray[nBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT]&BitMask(nBit)) !=
(aNewBitArray[nBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT]&BitMask(nBit))) {
osTPrintf("ERROR! Test:%d Mismatch before insertion point at bit %02X\n", nTest, nBit);
goto Error;
}
}
for(; nBit<nInsertBit+nNumBits; nBit++) {
if (((aNewBitArray[nBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT]&BitMask(nBit))==0) ^
((nValue&(1<<(nNumBits-1-(nBit-nInsertBit))))==0)) {
osTPrintf("ERROR! Test:%d Mismatch in inserted Value at bit %02X:%02x\n", nTest, nBit, nNumBits-1-(nBit-nInsertBit));
goto Error;
}
}
for(; nBit<256; nBit++) {
if (((aOldBitArray[(nBit-nNumBits)>>BIT_OFFSET_TO_INT_OFFSET_SHIFT]&BitMask(nBit-nNumBits))==0) ^
((aNewBitArray[nBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT]&BitMask(nBit))==0)) {
osTPrintf("ERROR! Test:%d Mismatch after insertion point at bit %02x:%02x\n(aOldBitArray[%d] & %08x = %08x)\n(aNewBitArray[%d] & %08x = %08x)\n",
nTest, nBit, nBit-nNumBits,
(nBit-nNumBits)>>BIT_OFFSET_TO_INT_OFFSET_SHIFT, BitMask(nBit-nNumBits),
(aOldBitArray[(nBit-nNumBits)>>BIT_OFFSET_TO_INT_OFFSET_SHIFT]&BitMask(nBit-nNumBits)),
nBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT, BitMask(nBit),
(aNewBitArray[nBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT]&BitMask(nBit)));
goto Error;
}
}
}
osTPrintf("WfsDeleteBitField() Test\n");
for(nTest=1; nTest<=_BITFIELD_NUM_TESTS; nTest++) {
unsigned nI;
for(nI=0; nI<8; nI++) { aOldBitArray[nI] = RandomU32(); }
int nBitArrayLength = RandomInt(0, 256);
int nDeleteStartBit = RandomInt(0, nBitArrayLength-1);
int nDeleteNumBits = RandomInt(1, 96);
if (nDeleteNumBits >(nBitArrayLength-nDeleteStartBit)) {
nDeleteNumBits = nBitArrayLength-nDeleteStartBit;
}
int nBit;
for(nBit=nBitArrayLength; nBit<256; nBit++) {
aOldBitArray[nBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT] &= ~BitMask(nBit);
}
for(nI=0; nI<8; nI++) { aNewBitArray[nI] = aOldBitArray[nI]; }
WfsBitArrayDeleteBitField(aNewBitArray, nBitArrayLength, nDeleteStartBit, nDeleteNumBits);
for(nBit=0; nBit<nDeleteStartBit; nBit++) {
if ((aOldBitArray[nBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT]&BitMask(nBit)) !=
(aNewBitArray[nBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT]&BitMask(nBit))) {
osTPrintf("ERROR! Test:%d Mismatch at bit %02X\n", nTest, nBit);
goto Error;
}
}
nBit += nDeleteNumBits;
for(; nBit<nBitArrayLength; nBit++) {
if (((aNewBitArray[(nBit-nDeleteNumBits)>>BIT_OFFSET_TO_INT_OFFSET_SHIFT]&BitMask(nBit-nDeleteNumBits))==0) ^
((aOldBitArray[nBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT]&BitMask(nBit))==0)) {
osTPrintf("ERROR! Test:%d Mismatch between bits %02x:%02x\n(aOldBitArray[%d] & %08x = %08x)\n(aNewBitArray[%d] & %08x = %08x)\n",
nTest, nBit, nBit-nDeleteNumBits,
(nBit-nDeleteNumBits)>>BIT_OFFSET_TO_INT_OFFSET_SHIFT, BitMask(nBit-nDeleteNumBits),
(aOldBitArray[(nBit-nDeleteNumBits)>>BIT_OFFSET_TO_INT_OFFSET_SHIFT]&BitMask(nBit-nDeleteNumBits)),
nBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT, BitMask(nBit),
(aNewBitArray[nBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT]&BitMask(nBit)));
goto Error;
}
}
}
osTPrintf("WfsBitFieldCopy() Test\n");
for(nTest=1; nTest<=_BITFIELD_NUM_TESTS; nTest++) {
unsigned nI;
for(nI=0; nI<8; nI++) { aOldBitArray[nI] = RandomU32(); }
nDstOffset = RandomInt(0, 255);
nSrcOffset = RandomInt(0, 255);
int nMaxLength = 256 - max(nSrcOffset, nDstOffset);
nCopyLength = RandomInt(1, nMaxLength);
int nBit;
/*for(nBit=nBitArrayLength; nBit<256; nBit++) {
aOldBitArray[nBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT] &= ~BitMask(nBit);
}*/
for(nI=0; nI<8; nI++) { aNewBitArray[nI] = aOldBitArray[nI]; }
WfsBitFieldCopy(aNewBitArray, nDstOffset, aNewBitArray, nSrcOffset, nCopyLength);
for(nBit=0; nBit<nDstOffset; nBit++) {
if ((aOldBitArray[nBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT]&BitMask(nBit)) !=
(aNewBitArray[nBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT]&BitMask(nBit))) {
osTPrintf("ERROR! Test:%d Mismatch at bit %02X\n", nTest, nBit);
goto WfsBitFieldCopyError;
}
}
for(; nBit<nDstOffset+nCopyLength; nBit++) {
int nSrcBit = nBit-nDstOffset+nSrcOffset;
if (((aOldBitArray[nSrcBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT]&BitMask(nSrcBit))==0) ^
((aNewBitArray[nBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT]&BitMask(nBit))==0)) {
osTPrintf("ERROR! Test:%d Mismatch at bit %02X\n", nTest, nBit);
goto WfsBitFieldCopyError;
}
}
for(; nBit<256; nBit++) {
if ((aOldBitArray[nBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT]&BitMask(nBit)) !=
(aNewBitArray[nBit>>BIT_OFFSET_TO_INT_OFFSET_SHIFT]&BitMask(nBit))) {
osTPrintf("ERROR! Test:%d Mismatch at bit %02X\n", nTest, nBit);
goto WfsBitFieldCopyError;
}
}
}
return;
WfsBitFieldCopyError:;
osTPrintf("WfsBitFieldCopy(New, nDstOffset=%02x, Src, nSrcOffset=%02x, nCopyLength=%02x)\n", nDstOffset, nSrcOffset, nCopyLength);
goto Error;
Error:;
unsigned nI;
osTPrintf("Old: "); for(nI=0; nI<8; nI++) { osTPrintf("%08x", aOldBitArray[nI]); } osTPrintf("\n");
osTPrintf("New: "); for(nI=0; nI<8; nI++) { osTPrintf("%08x", aNewBitArray[nI]); } osTPrintf("\n");
osTPrintf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f \n");
osTPrintf(" 048c048c048c048c048c048c048c048c048c048c048c048c048c048c048c048c\n");
#endif
}
// nStartBit = 9
// nBitArrayLength = 45
// nNumGapBits = 18
// nBitArrayLength - nNumGapBits = 36
// pStart = &aBitArray[0]
// pCopyTo = &aBitArray[1]
// pCopyFrom = &aBitArray[1]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,695 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_DirApi.cpp - Top layer of the Directory module
Copyright 2007-2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_DirApi.cpp,v $
Revision 1.26 2008/11/05 15:08:20 ueno
Modified DirItrMapBlks() to roll back the update map in case of error.
Revision 1.25 2008/10/31 09:51:11 ueno
Modified WFSSrvAPIs to return WFSKRN_RESULT_RESOURCE_LIMIT_EXCEEDED when path cache is short of memory.
Revision 1.24 2008/10/30 04:51:28 kondo_masahiro
Fixed DirDeleteFile
Revision 1.23 2008/10/20 00:30:54 nakanose_jin
(none)
Revision 1.22 2008/10/17 08:50:48 kondo_masahiro
Added the new MEDIUM size category (40KB-320KB)
Revision 1.21 2008/10/16 09:30:39 ooizumi
Fixed definitions for debug build.
Revision 1.20 2008/10/15 00:14:57 kondo_masahiro
Fixed a bug about 4GB-1
Revision 1.19 2008/10/14 12:11:49 kondo_masahiro
Fixed a bug in DirDeleteFile
Revision 1.18 2008/10/14 10:26:24 kondo_masahiro
Added codes to access very large size file data
Revision 1.17 2008/10/10 02:11:20 kondo_masahiro
Fixed a bug to access large files
Revision 1.16 2008/10/09 04:16:53 kondo_masahiro
Fixed member of AreaHdr and AreaInfo
Revision 1.15 2008/10/08 23:19:54 kondo_masahiro
Added codes to access large size file data
Revision 1.14 2008/09/28 23:31:51 kondo_masahiro
Fixed codes to use medium size user block.
Revision 1.13 2008/09/02 23:34:39 ooizumi
Added several casting.
Revision 1.12 2008/09/02 23:02:47 ooizumi
Fixed a bug failed to treat utf8 as unsigned value.
Revision 1.11 2008/08/05 03:58:49 kondo_masahiro
Added error handling for hash error and detach device.
Revision 1.10 2008/07/28 22:05:32 paul
Improved updateMap processing. Fixed a bug in DirDeleteSubDir().
Revision 1.9 2008/07/25 02:51:28 paul
Changed from nTransIdx to *pTransInfo
Revision 1.8 2008/07/21 22:39:16 paul
Fixed a bug in DirItrCheckAndUnmapBlks()
Changed name from DirItrPinBlkAndUpdatePtrs() -> DirItrPinBlkAndFixPtrs()
Revision 1.7 2008/07/17 22:47:11 paul
Added functions to support updateMap
Revision 1.6 2008/07/09 00:30:20 paul
Changes to make directory code work with block cache.
Revision 1.5 2008/06/09 17:21:58 paul
Added WFSKrnValidateCopyStrAndConvertToLowerCase()
Revision 1.4 2008/05/12 22:35:37 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.3 2008/05/12 19:11:22 paul
Moved DirModuleInit here from wfskrn_Dir.cpp.
Updated DirItrClose to remove pDi from list of open iterators.
Revision 1.2 2008/05/10 03:59:44 kondo_masahiro
Merged and fixed code to accept RM compiler
Revision 1.1 2008/04/25 17:29:16 kondo_masahiro
Initial check-in
Revision 1.2 2008/04/23 00:25:23 paul
Modified some functions to take utf8 strings instead of WFSFileName structs
Revision 1.1 2008/04/21 18:58:30 paul
*** empty log message ***
*---------------------------------------------------------------------------*/
#undef _KRN_FILE_
#define _KRN_FILE_ "DirApi"
#include "wfskrn_Api.h"
#include "wfskrn_Dir.h"
#include "wfskrn_DirFind.h"
#include "wfskrn_DirNodeStack.h"
#include "wfskrn_Area.h"
#include "wfskrn_PTree.h"
#include "wfskrn_Handles.h"
DirGlobals dirGlobals;
void DirModuleInit() {
u32 nI=0;
for(nI=0; nI<256; nI++) {
dirGlobals.aToLower[nI] = dirGlobals.aToUpper[nI] = (utf8)nI;
}
for(nI='A'; nI<='Z'; nI++) {
dirGlobals.aToLower[nI] = (utf8)(nI + ('a'-'A'));
}
for(nI='a'; nI<='z'; nI++) {
dirGlobals.aToUpper[nI] = (utf8)(nI - ('a'-'A'));
}
DirAllocateMoreNodeStackEntries();
dirGlobals.pOpenDirItrListAnchor = (DirItr *)((u8*)&dirGlobals.openDirItrListAnchor - (size_t)&((DirItr *)0)->link);
dirGlobals.openDirItrListAnchor.pNext = dirGlobals.openDirItrListAnchor.pPrev = dirGlobals.pOpenDirItrListAnchor;
PathCacheInit(); //dirGlobals.nUpdateCtr = 0;
dirGlobals.updateMapAllocator.pBase = (void*)&wkg.pathCache.pRxtHdr->sbah;
dirGlobals.updateMapAllocator.fpAllocNode = (PTreeAllocNodeFunc) PTreeAllocNodeFromSba;
dirGlobals.updateMapAllocator.fpAllocNodes = (PTreeAllocNodesFunc)PTreeAllocNodesFromSba;
dirGlobals.updateMapAllocator.fpFreeNode = (PTreeFreeNodeFunc) PTreeFreeNodeToSba;
PTreeInit(&dirGlobals.updateMap, &dirGlobals.updateMapAllocator);
}
void WFSKrnCopyFileName(WFSFileName *pDst, WFSFileName *pSrc) {
if (pSrc->nLen > WFS_MAX_FILE_NAME_SIZE) {
pSrc->nLen = WFS_MAX_FILE_NAME_SIZE;
}
pDst->nLen = pSrc->nLen;
strncpy(pDst->sStr, pSrc->sStr, pDst->nLen);
pDst->sStr[pDst->nLen] = 0;
}
inline void WFSKrnCopyStrAndConvertToLowerCase(utf8 *pDstStr, const utf8 *pSrcStr, u32 nLen) {
const utf8 *pSrcEnd = pSrcStr + nLen;
for(; pSrcStr<pSrcEnd; ++pSrcStr, ++pDstStr) {
*pDstStr = dirGlobals.aToLower[(u32)*(u8*)pSrcStr]; // sometimes VC cannot treat 0x80 over utf8 value.
}
*pDstStr = 0;
}
WFSKrnResult WFSKrnValidateCopyStrAndConvertToLowerCase(utf8 *pDstStr, const utf8 *pSrcStr, u32 nLen, u32 nMaxLen) {
if (nLen > nMaxLen) {
return WFSKRN_RESULT_INVALID;
}
WFSKrnCopyStrAndConvertToLowerCase(pDstStr, pSrcStr, nLen);
return WFSKRN_RESULT_OK;
}
void WFSKrnCopyFileNameAndConvertToLowerCase(WFSFileName *pDst, WFSFileName *pSrc) {
if (pSrc->nLen > WFS_MAX_FILE_NAME_SIZE) {
pSrc->nLen = WFS_MAX_FILE_NAME_SIZE;
}
pDst->nLen = pSrc->nLen;
WFSKrnCopyStrAndConvertToLowerCase(pDst->sStr, pSrc->sStr, pSrc->nLen);
}
void WFSKrnCopyFileNameAndRestoreCase(utf8 *pDst, WFSFileName *pSrc, u8 *pCaseBitArray) {
u32 nCaseBits = (u32)(256 + *pCaseBitArray);
if (pSrc->nLen > WFS_MAX_FILE_NAME_SIZE) {
pSrc->nLen = WFS_MAX_FILE_NAME_SIZE;
}
utf8 *pDstStr = pDst;
utf8 *pSrcStr = pSrc->sStr;
utf8 *pSrcEnd = pSrcStr + pSrc->nLen;
for(; pSrcStr<pSrcEnd; ++pSrcStr, ++pDstStr) {
if (nCaseBits & 1) {
*pDstStr = dirGlobals.aToUpper[(u32)*(u8*)pSrcStr]; // sometimes VC cannot treat 0x80 over utf8 value.
} else {
*pDstStr = *pSrcStr;
}
nCaseBits >>= 1;
if (nCaseBits == 1) {
nCaseBits = (u32)(256 + *(++pCaseBitArray));
}
}
*pDstStr = 0;
}
void WFSKrnStoreCaseInformationStr(u8 *pCaseBitArray, const utf8 *pStr, u32 nLen) {
u32 nCaseBit = 1;
u8 nCaseByte = 0;
const utf8 *pStrEnd = pStr + nLen;
for(; pStr<pStrEnd; ++pStr) {
if (*pStr != dirGlobals.aToLower[(u32)*(u8*)pStr]) { // sometimes VC cannot treat 0x80 over utf8 value.
nCaseByte |= nCaseBit;
}
nCaseBit += nCaseBit;
if (nCaseBit == 256) {
*pCaseBitArray++ = nCaseByte;
nCaseByte = 0;
nCaseBit = 1;
}
}
if (nCaseBit > 1) {
*pCaseBitArray = nCaseByte;
}
}
// Update Counter & Update Map Operations:
//
// BlkAdr:
// * Blocks must be referred to by absolute block address in the update map.
//
// Interaction with the transaction process:
// * In transactions, the block to be updated is first re-mapped to a different physical block.
// * When the update has been commited, it is copied to the logical block address.
// * For the purpose of update map processing, it should be OK to ignore the transaction process.
//
// When a block is initialized as a directory block:
// - First check the update map to see if any iterator is already referring to it. If so, copy the initial update count from there.
// Otherwise, the initial update count is initialized to 0.
//
// When a directory meta-data block gets freed:
// - If the block is in the update-map, increment its counter, then reduce its reference count, removing it if the reference count is zero.
//
// When a block is accessed by a directory iterator during DirFind or DirFindNext
// - The iterator copies the update counter of the block to its DirNodeStack.
//
// When a block is to be updated in the course of a executing a WFS command
// - Update the update counter in the block. //ToDo: it would be better if we only updated the counter when an existing sub-block is moved or deleted.
// - If the counter exists in the update map, increment it. Otherwise (in debug mode at least), reset the counter to 0.
//
// When an iterator is to be left open by a WFS command:
// - Increment the reference count of the blocks in the update map, or add them to the update map if neccessary.
// - Update the counter
//
// When an iterator is to re-used after a gap
// - The blocks it references should be found in the update map, and checked against the values stored in the iterator.
// - If necessary, the file attributes should be re-located using DirFind.
static DirNodeStack* MapBlks(DirItr *pDi) {
#if _DEBUG_BREAK_POINT
static int c=0;++c;if(c>=7019){//8194){
int a;a=0;
}
if (wkg.pathCache.pRxtHdr->sbah.aSubBlkList[0].nNumFree > 16) {
int a;a=0;
}
#endif
// When a new iterator is to be left open, we need to register the address of any blocks referenced in its DirNodeStack,
// and map each of these to the latest value of that block's update counter.
// However there are some complications:
// The same block could be referenced by multiple iterators, so they need to be reference-counted.
// An update operation consists of incrementing the reference count, and overwriting the update counter.
DirNodeStack *pDns = pDi->dni.pDns;
WFSBlkAdr nAbsStartBlkAdr = pDi->tba.pAreaInfo->nAbsStartBlkAdr;
WFSBlkAdr nBlkAdr = pDi->tba.nBlkAdr;
u32 nUpdateCtr = (u32)(pDi->nUpdateCtr & WFS_MDF_DIR_COUNTER_MASK);
while(nBlkAdr) {
WFSBlkAdr nAbsBlkAdr = nAbsStartBlkAdr + nBlkAdr;
PTreeItr pti;
u32 nData = DIR_BLK_REF_COUNT_INC | (nUpdateCtr & WFS_MDF_DIR_COUNTER_MASK);
Retry:;
WFSKrnResult nResult = PTreeInsert(&dirGlobals.updateMap, &pti, nAbsBlkAdr, nData, &dirGlobals.updateMapAllocator);
if (nResult == WFSKRN_RESULT_PTREE_ENTRY_FOUND) {
pti.pLeaf->aData[pti.aEntryIdx[0]] = nData + (pti.pLeaf->aData[pti.aEntryIdx[0]] & (u32)(-DIR_BLK_REF_COUNT_INC));
} else if (nResult == WFSKRN_RESULT_PTREE_FULL) {
nResult = PathCacheDeleteLru();
if (nResult != WFSKRN_RESULT_OK)
{
return pDns;
}
goto Retry;
}
#if _DEBUG
else if (nResult != WFSKRN_RESULT_OK) {
WFSKrnOutputErrorCode(nResult);
}
#endif
if (pDns==0) {
return pDns;
}
while(pDns->nBlkAdr == nBlkAdr) {
pDns = pDns->pParent;
if (pDns==0) {
return pDns;
}
}
nBlkAdr = pDns->nBlkAdr;
nUpdateCtr = pDns->nUpdateCtr;
}
return NULL;
}
static void UnmapBlks(DirItr* pDi, DirNodeStack* pDns)
{
PTreeItr pti;
WFSBlkAdr nAbsBlkAdr;
WFSKrnResult nResult;
u32 nUpdateCtr;
WFSBlkAdr nBlkAdr;
WFSBlkAdr nAbsStartBlkAdr = pDi->tba.pAreaInfo->nAbsStartBlkAdr;
DirNodeStack* pDnsEnd = pDi->dni.pDns;
while (pDns != pDnsEnd)
{
// [check] must check this rollback routine.
pDns = pDns->pParent;
nBlkAdr = pDns->nBlkAdr;
nUpdateCtr = pDns->nUpdateCtr;
nAbsBlkAdr = nAbsStartBlkAdr + nBlkAdr;
nResult = PTreeFind(&dirGlobals.updateMap, &pti, nAbsBlkAdr, &dirGlobals.updateMapAllocator);
#if _DEBUG
if (nResult != WFSKRN_RESULT_PTREE_ENTRY_FOUND)
{
WFSKrnOutputErrorStr("DirItr block not found in updateMap");
}
ASSERT(nResult == WFSKRN_RESULT_PTREE_ENTRY_FOUND);
#endif
// Decrement the reference counter
pti.pLeaf->aData[pti.aEntryIdx[0]] -= DIR_BLK_REF_COUNT_INC;
if ((pti.pLeaf->aData[pti.aEntryIdx[0]] & (u32)(-DIR_BLK_REF_COUNT_INC)) == 0)
{
// The reference counter is zero, so remove the mapping
PTreeDelete(&dirGlobals.updateMap, &pti, &dirGlobals.updateMapAllocator);
}
while (pDns->nBlkAdr == nBlkAdr)
{
pDns = pDns->pParent;
}
}
}
WFSKrnResult DirItrMapBlks(DirItr *pDi)
{
WFSKrnResult nResult = WFSKRN_RESULT_OK;
DirNodeStack* pDns;
pDns = MapBlks(pDi);
if (pDns) // [check] name.
{
// roll back.
nResult = WFSKRN_RESULT_RESOURCE_LIMIT_EXCEEDED;
UnmapBlks(pDi, pDns);
#if _DEBUG
WFSKrnOutputErrorStr("DirItrMapBlks() : WFSKRN_RESULT_RESOURCE_LIMIT_EXCEEDED\n");
#endif
}
return nResult;
}
void DirItrUnmapBlks(DirItr *pDi) {
#if _DEBUG_BREAK_POINT
static int c=0;++c;if(c>=2284){
int a;a=0;
}
#endif
#if _DEBUG
if (dirGlobals.updateMap.nRootOfs == 0) {
WFSKrnOutputErrorStr("updateMap invalid");
}
#endif
// Reduce the reference count of the blocks referenced by an iterator, and unmap them if the reference count reaches 0
DirNodeStack *pDns = pDi->dni.pDns;
WFSBlkAdr nAbsStartBlkAdr = pDi->tba.pAreaInfo->nAbsStartBlkAdr;
WFSBlkAdr nBlkAdr = pDi->tba.nBlkAdr;
u32 nUpdateCtr = (u32)(pDi->nUpdateCtr & WFS_MDF_DIR_COUNTER_MASK);
while(nBlkAdr) {
WFSBlkAdr nAbsBlkAdr = nAbsStartBlkAdr + nBlkAdr;
PTreeItr pti;
WFSKrnResult nResult = PTreeFind(&dirGlobals.updateMap, &pti, nAbsBlkAdr, &dirGlobals.updateMapAllocator);
if (nResult != WFSKRN_RESULT_PTREE_ENTRY_FOUND) {
WFSKrnOutputErrorStr("DirItr block not found in updateMap");
}
#if _DEBUG
else if (nResult != WFSKRN_RESULT_PTREE_ENTRY_FOUND) {
WFSKrnOutputErrorCode(nResult);
}
#endif
// Decrement the reference counter
pti.pLeaf->aData[pti.aEntryIdx[0]] -= DIR_BLK_REF_COUNT_INC;
if ((pti.pLeaf->aData[pti.aEntryIdx[0]] & (u32)(-DIR_BLK_REF_COUNT_INC)) == 0) {
// The reference counter is zero, so remove the mapping
PTreeDelete(&dirGlobals.updateMap, &pti, &dirGlobals.updateMapAllocator);
}
if (pDns==0) {
return;
}
while(pDns->nBlkAdr == nBlkAdr) {
pDns = pDns->pParent;
if (pDns==0) {
return;
}
}
nBlkAdr = pDns->nBlkAdr;
nUpdateCtr = pDns->nUpdateCtr;
}
}
WFSKrnResult DirItrCheckMapBlks(DirItr *pDi) {
// Check the updateCounter of blocks referenced by an iterator.
DirNodeStack *pDns = pDi->dni.pDns;
WFSBlkAdr nAbsStartBlkAdr = pDi->tba.pAreaInfo->nAbsStartBlkAdr;
WFSBlkAdr nBlkAdr = pDi->tba.nBlkAdr;
u32 nUpdateCtr = (u32)(pDi->nUpdateCtr & WFS_MDF_DIR_COUNTER_MASK);
while(nBlkAdr) {
WFSBlkAdr nAbsBlkAdr = nAbsStartBlkAdr + nBlkAdr;
PTreeItr pti;
WFSKrnResult nResult = PTreeFind(&dirGlobals.updateMap, &pti, nAbsBlkAdr, &dirGlobals.updateMapAllocator);
if (nResult != WFSKRN_RESULT_PTREE_ENTRY_FOUND) {
WFSKrnOutputErrorStr("DirItr block not found in updateMap");
}
#if _DEBUG
else if (nResult != WFSKRN_RESULT_PTREE_ENTRY_FOUND) {
WFSKrnOutputErrorCode(nResult);
}
#endif
if ((pti.nData ^ nUpdateCtr) & WFS_MDF_DIR_COUNTER_MASK) {
return WFSKRN_RESULT_DIR_ITR_INVALID;
}
if (pDns==0) {
return WFSKRN_RESULT_OK;
}
while(pDns->nBlkAdr == nBlkAdr) {
pDns = pDns->pParent;
if (pDns==0) {
return WFSKRN_RESULT_OK;
}
}
nBlkAdr = pDns->nBlkAdr;
nUpdateCtr = pDns->nUpdateCtr;
}
return WFSKRN_RESULT_OK;
}
WFSKrnResult DirItrCheckAndUnmapBlks(DirItr *pDi) {
#if _DEBUG_BREAK_POINT
static int c=0;++c;if(c>=4749){//5045
int a;a=0;
}
#endif
// Check the updateCounter of blocks referenced by an iterator, and decrement the reference count for all blocks.
DirNodeStack *pDns = pDi->dni.pDns;
WFSKrnResult nResult = WFSKRN_RESULT_OK;
WFSBlkAdr nAbsStartBlkAdr = pDi->tba.pAreaInfo->nAbsStartBlkAdr;
WFSBlkAdr nBlkAdr = pDi->tba.nBlkAdr;
u32 nUpdateCtr = (u32)(pDi->nUpdateCtr & WFS_MDF_DIR_COUNTER_MASK);
while(nBlkAdr) {
WFSBlkAdr nAbsBlkAdr = nAbsStartBlkAdr + nBlkAdr;
PTreeItr pti;
WFSKrnResult nTempResult = PTreeFind(&dirGlobals.updateMap, &pti, nAbsBlkAdr, &dirGlobals.updateMapAllocator);
// #if _DEBUG
if (nTempResult != WFSKRN_RESULT_PTREE_ENTRY_FOUND) {
WFSKrnOutputErrorStr("DirItr block not found in updateMap");
}
// #endif
if ((pti.nData ^ nUpdateCtr) & WFS_MDF_DIR_COUNTER_MASK) {
nResult = WFSKRN_RESULT_DIR_ITR_INVALID;
}
// Decrement the reference counter
pti.pLeaf->aData[pti.aEntryIdx[0]] -= DIR_BLK_REF_COUNT_INC;
if ((pti.pLeaf->aData[pti.aEntryIdx[0]] & (u32)(-DIR_BLK_REF_COUNT_INC)) == 0) {
// The reference counter is zero, so remove the mapping
PTreeDelete(&dirGlobals.updateMap, &pti, &dirGlobals.updateMapAllocator);
}
if (pDns==0) {
break;
}
while(pDns->nBlkAdr == nBlkAdr) {
pDns = pDns->pParent;
if (pDns==0) {
goto Done;
}
}
nBlkAdr = pDns->nBlkAdr;
nUpdateCtr = pDns->nUpdateCtr;
}
Done:
return nResult;
}
WFSKrnResult DirItrClose(DirItr *pDi) {
WFSKrnResult nResult = WFSKRN_RESULT_OK;
if (pDi->ppDnsRootParent) {
nResult = TransUnpinBlk(&pDi->tba);
//MyOSReport("%d: Close(%p)\n", nDirTest, pDi);
DirNodeStackFree(&pDi->dni, pDi->ppDnsRootParent);
//#if _DEBUG
pDi->ppDnsRootParent = 0;
//#endif
pDi->link.pNext->link.pPrev = pDi->link.pPrev;
pDi->link.pPrev->link.pNext = pDi->link.pNext;
}
return nResult;
}
WFSKrnResult DirItrCloseNoUnpin(DirItr *pDi) {
WFSKrnResult nResult = WFSKRN_RESULT_OK;
if (pDi->ppDnsRootParent) {
//MyOSReport("%d: Close(%p)\n", nDirTest, pDi);
DirNodeStackFree(&pDi->dni, pDi->ppDnsRootParent);
//#if _DEBUG
pDi->ppDnsRootParent = 0;
//#endif
pDi->link.pNext->link.pPrev = pDi->link.pPrev;
pDi->link.pPrev->link.pNext = pDi->link.pNext;
}
return nResult;
}
WFSKrnResult DirItrPinBlkAndFixPtrs(DirItr *pDi, u32 nTransFlags) {
// Ensure that the block referenced to by the directory iterator is in memory,
// If not, load it into memory and adjust the pDi->pAttrHdr and pDi->dni.pOfs pointers to point to the new location
s32 nPtrAdjustment = -(s32)pDi->pBlkHdr;
DirBlkHdr *pBlkHdr;
WFSKrnReturnOnError(DirGetBlk(pDi, nTransFlags | BCACHE_FLAG_PINNED, &pBlkHdr));
nPtrAdjustment += (s32)pBlkHdr;
pDi->dni.pOfs = (u16*)((u8*)pDi->dni.pOfs + nPtrAdjustment);
pDi->pAttrHdr = (DirEntryAttrHdr *)((u8*)pDi->pAttrHdr + nPtrAdjustment);
return WFSKRN_RESULT_OK;
}
WFSKrnResult DirFindName(WFSFileName *pName, DirItr *pDi) {
WFSKrnCopyFileNameAndConvertToLowerCase(&pDi->name, pName);
pDi->nBlkDepth = 0;
WFSKrnResult nResult = DirFind(&pDi->name, pDi, DIR_MAX_BLK_DEPTH, DIR_FIND_MODE_NORMAL);
switch(nResult) {
case WFSKRN_RESULT_DIR_ENTRY_FOUND:
WFSKrnCopyFileNameAndRestoreCase(pName->sStr, &pDi->name, pDi->pAttrHdr->aCaseBitArray);
pName->nLen = pDi->name.nLen;
return WFSKRN_RESULT_OK;
case WFSKRN_RESULT_DIR_NODE_STRING_MISMATCH:
case WFSKRN_RESULT_DIR_NODE_CHOICE_NOT_FOUND:
return WFSKRN_RESULT_NOT_FOUND;
default:
return nResult;
}
}
WFSKrnResult DirFindRaw(DirItr *pDi) {
pDi->nBlkDepth = 0;
WFSKrnResult nResult = DirFind(&pDi->name, pDi, DIR_MAX_BLK_DEPTH, DIR_FIND_MODE_NORMAL);
switch(nResult) {
case WFSKRN_RESULT_DIR_ENTRY_FOUND:
return WFSKRN_RESULT_OK;
case WFSKRN_RESULT_DIR_NODE_STRING_MISMATCH:
case WFSKRN_RESULT_DIR_NODE_CHOICE_NOT_FOUND:
return WFSKRN_RESULT_NOT_FOUND;
default:
return nResult;
}
}
WFSKrnResult DirFindFirstNamePrefixMatch(WFSFileName *pName, DirItr *pDi) {
pDi->nBlkDepth = 0;
WFSKrnCopyFileNameAndConvertToLowerCase(&pDi->name, pName);
WFSKrnResult nResult = DirFind(&pDi->name, pDi, DIR_MAX_BLK_DEPTH, DIR_FIND_MODE_PREFIX_SEARCH);
switch(nResult) {
case WFSKRN_RESULT_DIR_ENTRY_FOUND:
case WFSKRN_RESULT_DIR_NODE_STRING_PREFIX:
case WFSKRN_RESULT_DIR_CHOICE_PREFIX:
WFSKrnCopyFileNameAndRestoreCase(pName->sStr, &pDi->name, pDi->pAttrHdr->aCaseBitArray);
pName->nLen = pDi->name.nLen;
return WFSKRN_RESULT_OK;
case WFSKRN_RESULT_DIR_NODE_STRING_MISMATCH:
case WFSKRN_RESULT_DIR_NODE_CHOICE_NOT_FOUND:
return WFSKRN_RESULT_NOT_FOUND;
default:
return nResult;
}
}
WFSKrnResult DirNextName(WFSFileName *pName, DirItr *pDi) {
pDi->nBlkDepth = 0;
//WFSKrnCopyFileNameAndConvertToLowerCase(&pDi->name, pName);
WFSKrnResult nResult = DirNextRaw(&pDi->name, pDi);
switch(nResult) {
case WFSKRN_RESULT_OK:
case WFSKRN_RESULT_DIR_ENTRY_FOUND:
WFSKrnCopyFileNameAndRestoreCase(pName->sStr, &pDi->name, pDi->pAttrHdr->aCaseBitArray);
pName->nLen = pDi->name.nLen;
return WFSKRN_RESULT_OK;
default:
return nResult;
}
}
WFSKrnResult DirInsertName(WFSFileName *pName, DirItr *pDi, u32 nAllocSize) {
WFSKrnCopyFileNameAndConvertToLowerCase(&pDi->name, pName);
WFSKrnReturnOnError(DirInsertRaw(&pDi->name, pDi, nAllocSize));
WFSKrnStoreCaseInformation(pDi->pAttrHdr->aCaseBitArray, pName);
// ToDo: Add other file attributes to pDi->pAttrHdr
return WFSKRN_RESULT_OK;
}
void DirInitFileEntryAttrHdr(DirEntryAttrHdr *pAttrHdr) {
memset(pAttrHdr, 0, sizeof(DirEntryAttrHdr));
}
void DirInitDirEntryAttrHdr(DirEntryAttrHdr *pAttrHdr) {
memset(pAttrHdr, 0, sizeof(DirEntryAttrHdr));
pAttrHdr->nAccessListIdx = WFS_FLAG_IS_A_DIRECTORY;
}
WFSKrnResult DirDeleteFile(DirItr *pDi) {
DirEntryAttrHdr *pAttrHdr = pDi->pAttrHdr;
TransBlkAdr tba = pDi->tba;
switch(pAttrHdr->nSizeCategory){
case FILE_SIZE_CATEGORY_VERY_SMALL:
return WFSKRN_RESULT_OK;
case FILE_SIZE_CATEGORY_SMALL:{
u32 nNumBlks = pAttrHdr->nAllocSize ? ((pAttrHdr->nAllocSize-1) >> tba.pAreaInfo->ah.nLog2BlkSize) + 1 : 0;
WFSFileBlkPtr *pFileBlkPtr = WFSKrnGetFileBlkPtrForCategorySmall(pAttrHdr, pAttrHdr->nAttrLog2Size, 0);
return TransFreeBlks6(tba.pAreaInfo, tba.pAreaInfo->ah.nLog2BlkSize, nNumBlks, (WFSBlkAdr*)pFileBlkPtr, -(s32)sizeof(WFSFileBlkPtr), tba.pTransInfo);
}
case FILE_SIZE_CATEGORY_MEDIUM:{
u32 nNumMediumBlks = pAttrHdr->nAllocSize ? ((pAttrHdr->nAllocSize-1) >> tba.pAreaInfo->ah.nLog2MediumBlkSize) + 1 : 0;
WFSFileBlkPtr *pFileBlkPtr = WFSKrnGetFileBlkPtrForCategoryMedium(pAttrHdr, pAttrHdr->nAttrLog2Size, 0);
return TransFreeBlks6(tba.pAreaInfo, tba.pAreaInfo->ah.nLog2MediumBlkSize, nNumMediumBlks, (WFSBlkAdr*)pFileBlkPtr, -(s32)sizeof(WFSFileBlkPtr), tba.pTransInfo);
}
case FILE_SIZE_CATEGORY_LARGE: {
u32 nNumLargeBlks = pAttrHdr->nAllocSize ? ((pAttrHdr->nAllocSize-1) >> tba.pAreaInfo->ah.nLog2LargeBlkSize) + 1 : 0;
WFSFileLargeBlkPtr *pFileBlkLargePtr = WFSKrnGetFileLargeBlkPtrForCategoryLarge(pAttrHdr, pAttrHdr->nAttrLog2Size, 0);
return TransFreeBlks6(tba.pAreaInfo, tba.pAreaInfo->ah.nLog2LargeBlkSize, nNumLargeBlks,
(WFSBlkAdr*)pFileBlkLargePtr, -(s32)sizeof(WFSFileLargeBlkPtr), tba.pTransInfo);
}
case FILE_SIZE_CATEGORY_VERY_LARGE: {
u32 nNumLargeBlks = pAttrHdr->nAllocSize ? ((pAttrHdr->nAllocSize-1) >> tba.pAreaInfo->ah.nLog2LargeBlkSize) + 1 : 0;
u32 nNumIndirectBlks = (nNumLargeBlks+tba.pAreaInfo->nNumLargeBlkPtrsPerBlk-1)/tba.pAreaInfo->nNumLargeBlkPtrsPerBlk;
WFSBlkAdr *pIndirectBlkAdr = WFSKrnGetBlkAdrPtrFromAttrHdrAndIndirectBlkIdxForCategoryVeryLarge(tba.pAreaInfo, pAttrHdr, pAttrHdr->nAttrLog2Size, 0);
s32 nI;
for(nI=0;nI<nNumIndirectBlks;nI++){
u8 *pIndirectBlkPtr;
WFSKrnReturnOnError(TransGetAndPinBlk5(tba.pAreaInfo, pIndirectBlkAdr[-nI], tba.pTransInfo, TRANS_FLAG_READ_BLK, (void**)&pIndirectBlkPtr));
if(nI+1==nNumIndirectBlks){
WFSKrnReturnOnError(TransFreeBlks6(tba.pAreaInfo, tba.pAreaInfo->ah.nLog2LargeBlkSize, (nNumLargeBlks-1)%tba.pAreaInfo->nNumLargeBlkPtrsPerBlk+1,
(WFSBlkAdr*)(pIndirectBlkPtr+sizeof(WFSMetaDataHdr)), (s32)sizeof(WFSFileLargeBlkPtr), tba.pTransInfo));
} else {
WFSKrnReturnOnError(TransFreeBlks6(tba.pAreaInfo, tba.pAreaInfo->ah.nLog2LargeBlkSize, tba.pAreaInfo->nNumLargeBlkPtrsPerBlk,
(WFSBlkAdr*)(pIndirectBlkPtr+sizeof(WFSMetaDataHdr)), (s32)sizeof(WFSFileLargeBlkPtr), tba.pTransInfo));
}
WFSKrnReturnOnError(TransUnpinBlk3(tba.pAreaInfo, pIndirectBlkAdr[-nI], tba.pTransInfo));
}
return TransFreeBlks6(tba.pAreaInfo, tba.pAreaInfo->ah.nLog2BlkSize, nNumIndirectBlks, pIndirectBlkAdr, -(s32)sizeof(WFSBlkAdr), tba.pTransInfo);
}
default:
return WFSKRN_RESULT_NOT_IMPLEMENTED;
}
}
WFSKrnResult DirDeleteSubDir(DirItr *pDi) {
DirEntryAttrHdr *pAttrHdr = pDi->pAttrHdr;
TransBlkAdr tba = pDi->tba;
tba.nBlkAdr = pAttrHdr->dir.nSubDirBlkAdr;
DirBlkHdr *pSubDirBlkHdr;
WFSKrnReturnOnError(TransGetAndPinBlk(&tba, TRANS_FLAG_READ_BLK, (void**)&pSubDirBlkHdr));
/*
nResult = TransGetAndPinBlk(&tba, TRANS_FLAG_READ_BLK, (void**)&pSubDirBlkHdr);
if (nResult < WFSKRN_RESULT_OK){
return nResult;
}
*/
if (pSubDirBlkHdr->nNumRecs) {
TransUnpinBlk(&tba);
return WFSKRN_RESULT_NOT_EMPTY;
}
WFSKrnReturnOnError(TransUnpinAndFreeBlks(pDi->tba.pAreaInfo, pDi->tba.pAreaInfo->ah.nLog2BlkSize, 1, &tba.nBlkAdr, pDi->tba.pTransInfo));
return WFSKRN_RESULT_OK;
}

View File

@ -0,0 +1,655 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_DirCheck.cpp
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_DirCheck.cpp,v $
Revision 1.14 2008/11/18 04:57:12 saito_tomoya
Modified SetBit() and added SetBitArray().
Revision 1.13 2008/10/30 04:50:45 kondo_masahiro
Added DirCheckDisk
Revision 1.12 2008/10/17 08:50:48 kondo_masahiro
Added the new MEDIUM size category (40KB-320KB)
Revision 1.11 2008/10/16 09:30:39 ooizumi
Fixed definitions for debug build.
Revision 1.10 2008/09/01 01:57:26 kondo_masahiro
Minor fixed for IOP compiler.
Revision 1.9 2008/08/27 23:02:55 ooizumi
Fixed newline to CR+LF(Windows format).
Revision 1.8 2008/08/27 09:47:43 paul
Removed nTotalFree from block header. Added pAttrHdr->nAttrLog2Size
Revision 1.7 2008/07/09 00:31:36 paul
Minor changes
Revision 1.6 2008/06/09 17:22:38 paul
Changed comment
Revision 1.5 2008/05/27 18:44:19 paul
Made utf8 variable definitions more consistent, and use (unsigned) for comparisons
Revision 1.4 2008/05/14 02:16:52 paul
Fixed the node choice ordering check to prevent utf8 being upgraded to signed int
Revision 1.3 2008/05/10 03:59:44 kondo_masahiro
Merged and fixed code to accept RM compiler
Revision 1.2 2008/04/25 17:29:46 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.1 2008/04/22 04:39:08 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.5 2008/04/22 23:26:55 paul
Changed areaHdrRoot to areaInfoRoot
Revision 1.4 2008/04/19 05:50:57 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.3 2008/04/15 18:51:26 paul
Made some changes to debug code
Revision 1.2 2008/04/08 00:25:34 paul
Added an extra check for radix tree nodes with 0 entries
Revision 1.1 2008/04/05 00:03:30 paul
Integrity checks for directory node blocks and directory leaf blocks
*---------------------------------------------------------------------------*/
#undef _KRN_FILE_
#define _KRN_FILE_ "DirCheck"
#include "wfskrn_Dir.h"
#include "wfskrn_SubBlkAlloc.h"
#include "wfskrn_DirNodeStack.h"
#include "wfskrn_Area.h"
#include "wfskrn_BitField.h"
#include "wfskrn_Heap.h"
#include "wfskrn_Api.h"
#include "wfskrn_Mutex.h"
#if _DEBUG_DIR
bool bCheckDirBlks = true; // extern
#endif
static
void DirSubBlkDebugPrint(DirSubBlkHdr *pSubBlkHdr) {
utf8 *pChoiceChar = &pSubBlkHdr->aFirstChar[pSubBlkHdr->nStrLen];
utf8 cTemp = *pChoiceChar;
*pChoiceChar = 0;
MyOSReport("%d,%d,\"%s\"", pSubBlkHdr->nStrLen, pSubBlkHdr->nNumEntries, pSubBlkHdr->aFirstChar);
*pChoiceChar = cTemp;
u32 nI;
for(nI=0; nI<pSubBlkHdr->nNumEntries; nI++) {
if ((*pChoiceChar<32)||(*pChoiceChar>127)) {
MyOSReport(",%d", *pChoiceChar);
} else {
MyOSReport(",'%c'", *pChoiceChar);
}
++pChoiceChar;
}
MyOSReport("\n");
}
void DirLeafCheckBlk(DirItr *pDi) {
#if _DEBUG_DIR
// Checks that all allocated sub blocks of pDi->pBlkHdr are reachable, and all non-allocated blocks are on the free list
if (!bCheckDirBlks) {
return;
}
#endif
#if _DEBUG_DIR_NODE_STACK
bool bOldCheckDirNodeStack = bCheckDirNodeStack;
bCheckDirNodeStack = false;
#endif
DirItr di = *pDi;
di.dni.nDnsDepth = 0;
WFSKrnResult nResult = DirNodeStackGetEntry(&di.dni);
di.ppDnsRootParent = &di.dni.pDns->pParent;
DirBlkHdr *pBlkHdr = (DirBlkHdr *)di.pBlkHdr;
u32 nSrcNodeOfs = pBlkHdr->nRootOfs;
utf8 *pChoiceChar;
u32 nConnectedSize=(1<<WFS_NUM_BITS_REQUIRED(sizeof(DirBlkHdr)));
u32 aUtilization[1<<(WFS_LOG2_MEDIUM_BLK_SIZE - SBA_MIN_LOG2_SUB_BLK_SIZE - 5)];
memset(aUtilization, 0, sizeof(aUtilization));
WfsSetBitField((unsigned*)aUtilization, 0, 1<<(WFS_NUM_BITS_REQUIRED(sizeof(DirBlkHdr))-SBA_MIN_LOG2_SUB_BLK_SIZE));
u32 nRecIdx = 0;
u32 nSrcLeafStartDepth = di.dni.nDnsDepth;
while(1) {
di.dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + nSrcNodeOfs);
WFSSubBlkFreeHdr *pSbfHdr = (WFSSubBlkFreeHdr *)di.dni.pSubBlkHdr;
if (pSbfHdr->nMagic == SBA_FREE_SUB_BLK_MAGIC) {
WFSKrnOutputErrorStr("Pointer to deleted sub block detected!");
}
di.dni.nLog2Size = DirLeafGetSubBlkLog2Size(di.dni.pSubBlkHdr);
di.dni.pDns->nBlkAdr = di.tba.nBlkAdr;
di.dni.pDns->nSubBlkOfs = nSrcNodeOfs;
#if _DEBUG_DIR
if ((nDirTest>=nDirTestBreakPoint-1)&&(nDirTest<=nDirTestBreakPoint)) {
u32 nI;
for(nI=nSrcLeafStartDepth; nI<di.dni.nDnsDepth; nI++) {
MyOSReport(" ");
}
MyOSReport("%03x: ", nSrcNodeOfs);
DirSubBlkDebugPrint(di.dni.pSubBlkHdr);
}
#endif
if (WfsTestAndSetBitField((unsigned*)aUtilization, nSrcNodeOfs>>SBA_MIN_LOG2_SUB_BLK_SIZE, 1<<(di.dni.nLog2Size-SBA_MIN_LOG2_SUB_BLK_SIZE))) {
WFSKrnOutputErrorStr("Overlap!");
}
nConnectedSize += (u32)(1<<di.dni.nLog2Size);
u16 *pSrcNodeOfsTblEnd = (u16*)((u8*)di.dni.pSubBlkHdr + (1<<di.dni.nLog2Size));
di.dni.pDns->nEntryIdx = 1;
if (di.dni.pSubBlkHdr->nNumEntries == 0) {
if (pBlkHdr->nNumRecs) {
WFSKrnOutputErrorStr("No entries!");
}
}
pChoiceChar = &di.dni.pSubBlkHdr->aFirstChar[di.dni.pSubBlkHdr->nStrLen];
if (*pChoiceChar == 0) {
// String terminator char indicates this is a record, so increment the record count
u32 nAttrOfs = pSrcNodeOfsTblEnd[-1];
SbaCheckOfs(nAttrOfs);
DirEntryAttrHdr *pAttrHdr = (DirEntryAttrHdr *)((u8*)pBlkHdr + nAttrOfs);
WFSSubBlkFreeHdr *pSbfHdr = (WFSSubBlkFreeHdr *)pAttrHdr;
if (pSbfHdr->nMagic == SBA_FREE_SUB_BLK_MAGIC) {
WFSKrnOutputErrorStr("Pointer to deleted attr block detected!");
}
u8 nSizeCategory;
u16 nAttrLog2Size = (u16)DirCalculateAttrSubBlkLog2Size(di.tba.pAreaInfo, pAttrHdr->nAllocSize, pAttrHdr->nNameLen, &nSizeCategory);
if (nSizeCategory != pAttrHdr->nSizeCategory) {
nAttrLog2Size = (u16)DirCalculateAttrSubBlkLog2SizeDecrease(di.tba.pAreaInfo, pAttrHdr->nAllocSize, pAttrHdr->nNameLen, &nSizeCategory);
if (nSizeCategory != pAttrHdr->nSizeCategory) {
WFSKrnOutputErrorStr("Size category incorrect");
}
}
if (WfsTestAndSetBitField((unsigned*)aUtilization, nAttrOfs>>SBA_MIN_LOG2_SUB_BLK_SIZE, 1<<(nAttrLog2Size-SBA_MIN_LOG2_SUB_BLK_SIZE))) {
WFSKrnOutputErrorStr("Overlap!");
}
if (nAttrLog2Size != pAttrHdr->nAttrLog2Size) {
WFSKrnOutputErrorStr("Attr log 2 size incorrect");
}
if (nSizeCategory != pAttrHdr->nSizeCategory) {
WFSKrnOutputErrorStr("Size category incorrect");
}
nConnectedSize += (u32)(1<<nAttrLog2Size);
++nRecIdx;
++di.dni.pDns->nEntryIdx;
} else if (di.dni.pSubBlkHdr->nNumEntries == 1) {
WFSKrnOutputErrorStr("Non-terminating single-choice node!");
}
if (di.dni.pDns->nEntryIdx > di.dni.pSubBlkHdr->nNumEntries) {
do {
if (di.dni.nDnsDepth == nSrcLeafStartDepth) {
// We reached the top of the stack, so this should be the last record
goto CheckFreeSpace;
}
DirPopNodeStackEntry(&di.dni);
di.dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + di.dni.pDns->nSubBlkOfs);
++di.dni.pDns->nEntryIdx;
} while(di.dni.pDns->nEntryIdx > di.dni.pSubBlkHdr->nNumEntries);
pChoiceChar = &di.dni.pSubBlkHdr->aFirstChar[di.dni.pSubBlkHdr->nStrLen + di.dni.pDns->nEntryIdx-1];
if ((unsigned)pChoiceChar[-1] >= (unsigned)*pChoiceChar) {
WFSKrnOutputErrorStr("Choice out of order!");
}
}
nSrcNodeOfs = DirLeafGetIntraBlkOfs(di.dni.pDns->nEntryIdx, di.dni.pSubBlkHdr);
SbaCheckOfs(nSrcNodeOfs);
nResult = DirNodeStackGetEntry(&di.dni);
if (nResult != WFSKRN_RESULT_OK) {
WFSKrnOutputErrorCode(nResult);
break;
}
}
CheckFreeSpace:;
// Next check the free space
u32 nTotalFree = SbaCheckFreeSpace((WFSSubBlkAllocHdr *)pBlkHdr, aUtilization);
if ((nTotalFree + nConnectedSize) != pDi->tba.pAreaInfo->nBlkSize) {
WFSKrnOutputErrorStr("Memory Leak detected within block!");
}
if (nRecIdx != pBlkHdr->nNumRecs) {
WFSKrnOutputErrorStr("NumRecs Error!");
}
DirNodeStackFree(&di.dni, di.ppDnsRootParent);
#if _DEBUG_DIR
if ((nDirTest>=nDirTestBreakPoint-1)&&(nDirTest<=nDirTestBreakPoint)) {
MyOSReport("\n");
}
#endif
#if _DEBUG_DIR_NODE_STACK
bCheckDirNodeStack = bOldCheckDirNodeStack;
#endif
}
void DirNodeCheckBlk(DirItr *pDi) {
#if _DEBUG_DIR
// Checks that all allocated sub blocks of pDi->pBlkHdr are reachable, and all non-allocated blocks are on the free list
if (!bCheckDirBlks) {
return;
}
#endif
#if _DEBUG_DIR_NODE_STACK
bool bOldCheckDirNodeStack = bCheckDirNodeStack;
bCheckDirNodeStack = false;
#endif
DirItr di = *pDi;
DirBlkHdr *pBlkHdr = (DirBlkHdr *)di.pBlkHdr;
u32 nSrcNodeOfs = pBlkHdr->nRootOfs;
utf8 *pChoiceChar;
u32 nConnectedSize=(1<<WFS_NUM_BITS_REQUIRED(sizeof(DirBlkHdr)));
u32 aUtilization[1<<(WFS_LOG2_MEDIUM_BLK_SIZE - SBA_MIN_LOG2_SUB_BLK_SIZE - 5)];
memset(aUtilization, 0, sizeof(aUtilization));
WfsSetBitField((unsigned*)aUtilization, 0, 1<<(WFS_NUM_BITS_REQUIRED(sizeof(DirBlkHdr))-SBA_MIN_LOG2_SUB_BLK_SIZE));
u32 nRecIdx = 0;
u32 nSrcNodeStartDepth = di.dni.nDnsDepth;
WFSKrnResult nResult;
while(1) {
di.dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + nSrcNodeOfs);
WFSSubBlkFreeHdr *pSbfHdr = (WFSSubBlkFreeHdr *)di.dni.pSubBlkHdr;
if (pSbfHdr->nMagic == SBA_FREE_SUB_BLK_MAGIC) {
WFSKrnOutputErrorStr("Pointer to deleted sub block detected!");
}
di.dni.nLog2Size = DirNodeGetSubBlkLog2Size(di.dni.pSubBlkHdr);
di.dni.pDns->nBlkAdr = di.tba.nBlkAdr;
di.dni.pDns->nSubBlkOfs = nSrcNodeOfs;
#if _DEBUG_DIR
if ((nDirTest>=nDirTestBreakPoint-1)&&(nDirTest<=nDirTestBreakPoint)) {
u32 nI;
for(nI=nSrcNodeStartDepth; nI<di.dni.nDnsDepth; nI++) {
MyOSReport(" ");
}
MyOSReport("%03x: ", nSrcNodeOfs);
DirSubBlkDebugPrint(di.dni.pSubBlkHdr);
}
#endif
if (WfsTestAndSetBitField((unsigned*)aUtilization, nSrcNodeOfs>>SBA_MIN_LOG2_SUB_BLK_SIZE, 1<<(di.dni.nLog2Size-SBA_MIN_LOG2_SUB_BLK_SIZE))) {
WFSKrnOutputErrorStr("Overlap!");
}
nConnectedSize += (u32)(1<<di.dni.nLog2Size);
di.dni.pDns->nEntryIdx = 1;
if (di.dni.pSubBlkHdr->nNumEntries == 0) {
if (pBlkHdr->nNumRecs) {
WFSKrnOutputErrorStr("No entries!");
}
}
pChoiceChar = &di.dni.pSubBlkHdr->aFirstChar[di.dni.pSubBlkHdr->nStrLen];
if (*pChoiceChar == 0) {
// String terminator char indicates this is a record, so increment the record count
++nRecIdx;
++di.dni.pDns->nEntryIdx;
} else if (di.dni.pSubBlkHdr->nNumEntries == 1) {
WFSKrnOutputErrorStr("Non-terminating single-choice node!");
}
if (di.dni.pDns->nEntryIdx > di.dni.pSubBlkHdr->nNumEntries) {
do {
if (di.dni.nDnsDepth == nSrcNodeStartDepth) {
// We reached the top of the stack, so this should be the last record
goto CheckFreeSpace;
}
DirPopNodeStackEntry(&di.dni);
di.dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + di.dni.pDns->nSubBlkOfs);
++di.dni.pDns->nEntryIdx;
} while(di.dni.pDns->nEntryIdx > di.dni.pSubBlkHdr->nNumEntries);
pChoiceChar = &di.dni.pSubBlkHdr->aFirstChar[di.dni.pSubBlkHdr->nStrLen + di.dni.pDns->nEntryIdx -1];
if ((unsigned)pChoiceChar[-1] >= (unsigned)*pChoiceChar) {
WFSKrnOutputErrorStr("Choice out of order!");
}
}
nSrcNodeOfs = DirNodeGetIntraBlkOfs(di.dni.pDns->nEntryIdx, di.dni.pSubBlkHdr);
SbaCheckOfs(nSrcNodeOfs);
nResult = DirNodeStackGetEntry(&di.dni);
if (nResult != WFSKRN_RESULT_OK) {
WFSKrnOutputErrorCode(nResult);
break;
}
}
CheckFreeSpace:;
// Next check the free space
u32 nTotalFree = SbaCheckFreeSpace((WFSSubBlkAllocHdr *)pBlkHdr, aUtilization);
if ((nTotalFree + nConnectedSize) != pDi->tba.pAreaInfo->nBlkSize) {
WFSKrnOutputErrorStr("Memory Leak detected within block!");
}
if (nRecIdx != pBlkHdr->nNumRecs) {
WFSKrnOutputErrorStr("NumRecs Error!");
}
#if _DEBUG_DIR
if ((nDirTest>=nDirTestBreakPoint-1)&&(nDirTest<=nDirTestBreakPoint)) {
MyOSReport("\n");
}
#endif
#if _DEBUG_DIR_NODE_STACK
bCheckDirNodeStack = bOldCheckDirNodeStack;
#endif
}
void DirCheckBlk(DirItr *pDi) {
#if _DEBUG_DIR
// Checks that all allocated blocks are reachable, and all non-allocated blocks are on the free list
if (!bCheckDirBlks) {
return;
}
#endif
if (pDi->pBlkHdr->sbah.mdh.nFlags & WFS_MDF_DIR_LEAF_BLK) {
DirLeafCheckBlk(pDi);
} else {
DirNodeCheckBlk(pDi);
}
}
static void SetBit(WFSSrvFileHandle fh, u32 diskAddr)
{
u32 byte = diskAddr / 8;
u32 bit = diskAddr % 8;
u8 flag = (1 << bit);
u8 dst;
WFSResult nResult;
nResult = (WFSResult)WFSSrvReadFile(fh, &dst, byte, 1);
if(nResult < WFS_RESULT_OK){
osTPrintf("SetBit() error %d\n", nResult);
}
ASSERT(0 == (dst & flag));
dst |= flag;
nResult = WFSSrvWriteFile(fh, &dst, byte, 1, true);
}
static void SetBitArrayInternal(WFSSrvFileHandle fh, u8* pBuffer, u32 bufferSize, u32 diskAddr, u32 length){
u32 byte = diskAddr / 8;
u32 bit = diskAddr % 8;
u32 byteLength = (diskAddr + length - 1) / 8 - byte + 1;
WFSResult nResult;
// read
nResult = (WFSResult)WFSSrvReadFile(fh, pBuffer, byte, byteLength);
if(nResult < WFS_RESULT_OK){
osTPrintf("SetBitArray() error %d\n", nResult);
}
// set bits
int i;
for(i=bit; i<bit+length; ++i){
u8 flag = 1 << (i & 0x07);
ASSERT( !(pBuffer[i/8] & flag) );
pBuffer[i/8] |= flag;
}
// write
nResult = WFSSrvWriteFile(fh, pBuffer, byte, byteLength, true);
}
static void SetBitArray(WFSSrvFileHandle fh, u8* pBuffer, u32 bufferSize, u32 diskAddr, u32 length){
while(length > (bufferSize-1)*8){
SetBitArrayInternal(fh, pBuffer, bufferSize, diskAddr, (bufferSize-1)*8);
length -= (bufferSize-1)*8;
diskAddr += (bufferSize-1)*8;
}
SetBitArrayInternal(fh, pBuffer, bufferSize, diskAddr, length);
}
WFSKrnResult DirCheckDisk(WFSBlkAdr rootBlkAdr, DirItr *pDi, WFSSrvFileHandle fh, u8* pBuffer, u32 bufferSize, u32 nFlag) {
DirBlkHdr *pBlkHdr;
pDi->tba.nBlkAdr = rootBlkAdr;
///
//pCheckDiskArray[rootBlkAdr/8] |= 1<<(rootBlkAdr%8);
SetBit(fh, rootBlkAdr);
pDi->nBlkDepth = 0;
WFSKrnReturnOnError(DirGetBlk(pDi, TRANS_FLAG_READ_BLK | BCACHE_FLAG_PINNED, &pBlkHdr));
pDi->dni.nDnsDepth = 0;
WFSKrnReturnOnError(DirNodeStackGetEntry(&pDi->dni));
pDi->ppDnsRootParent = &pDi->dni.pDns->pParent;
pDi->dni.pDns->nBlkAdr = 0; //tba.nBlkAdr;
pDi->dni.pDns->nSubBlkOfs = pBlkHdr->nRootOfs;
SbaCheckOfs(pDi->dni.pDns->nSubBlkOfs);
pDi->dni.pDns->nEntryIdx = 1;
pDi->dni.nEntryIdx = 1;
pDi->dni.pOfs = &pBlkHdr->nRootOfs;
SbaCheckOfs(*pDi->dni.pOfs);
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
if (pBlkHdr->sbah.mdh.nFlags & WFS_MDF_DIR_LEAF_BLK) {
pDi->dni.nLog2Size = DirLeafGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
} else {
pDi->dni.nLog2Size = DirNodeGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
}
while(1){
#if _DEBUG_BREAK_POINT
static int c=0; c++; if(c==0x2b){
int a; a=0;
}
#endif
while (pDi->dni.nEntryIdx > pDi->dni.pSubBlkHdr->nNumEntries) {
if(pDi->dni.pDns->nBlkAdr == 0){
TransUnpinBlk(&pDi->tba);
DirPopNodeStackEntry(&pDi->dni);
pDi->nBlkDepth = 0;
return WFSKRN_RESULT_OK;
}
if(pDi->tba.nBlkAdr != pDi->dni.pDns->nBlkAdr){
TransUnpinBlk(&pDi->tba);
pDi->tba.nBlkAdr = pDi->dni.pDns->nBlkAdr;
WFSKrnReturnOnError( DirGetBlk(pDi, TRANS_FLAG_READ_BLK | BCACHE_FLAG_PINNED, &pBlkHdr) );
}
pDi->dni.nEntryIdx = ++pDi->dni.pDns->nEntryIdx;
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + pDi->dni.pDns->nSubBlkOfs);
if (pDi->dni.nEntryIdx <= pDi->dni.pSubBlkHdr->nNumEntries){
if (pBlkHdr->sbah.mdh.nFlags & WFS_MDF_DIR_LEAF_BLK) {
pDi->dni.nLog2Size = DirLeafGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
pDi->dni.pOfs = DirLeafGetIntraBlkOfsPtr_l2s((s32)pDi->dni.nEntryIdx, pDi->dni.pSubBlkHdr, pDi->dni.nLog2Size);
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
pDi->dni.nLog2Size = DirLeafGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
} else {
pDi->dni.nLog2Size = DirNodeGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
pDi->dni.pOfs = DirNodeGetIntraBlkOfsPtr_l2s((s32)pDi->dni.nEntryIdx, pDi->dni.pSubBlkHdr, pDi->dni.nLog2Size);
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
pDi->dni.nLog2Size = DirNodeGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
}
pDi->dni.nEntryIdx = 1;
} else {
DirPopNodeStackEntry(&pDi->dni);
--pDi->nBlkDepth;
}
}
WFSKrnReturnOnError(DirPushNodeStackEntry(&pDi->dni, pDi->tba.nBlkAdr));
++pDi->nBlkDepth;
pDi->dni.pDns->nUpdateCtr = pDi->nUpdateCtr;
if (pBlkHdr->sbah.mdh.nFlags & WFS_MDF_DIR_LEAF_BLK) {
if(pDi->dni.nEntryIdx == 1 && pDi->dni.pSubBlkHdr->aFirstChar[pDi->dni.pSubBlkHdr->nStrLen] == 0){
u16 nOfs = *DirLeafGetIntraBlkOfsPtr_l2s(1, pDi->dni.pSubBlkHdr, pDi->dni.nLog2Size);
pDi->pAttrHdr = (DirEntryAttrHdr *)((u8*)pBlkHdr + nOfs);
if (pDi->pAttrHdr->nAccessListIdx & WFS_FLAG_IS_A_DIRECTORY) {
TransUnpinBlk(&pDi->tba);
pDi->tba.nBlkAdr = pDi->pAttrHdr->dir.nSubDirBlkAdr;
///
//pCheckDiskArray[pDi->tba.nBlkAdr/8] |= 1<<(pDi->tba.nBlkAdr%8);
SetBit(fh, pDi->tba.nBlkAdr);
WFSKrnReturnOnError( DirGetBlk(pDi, TRANS_FLAG_READ_BLK | BCACHE_FLAG_PINNED, &pBlkHdr) );
pDi->dni.pOfs = &pBlkHdr->nRootOfs;
SbaCheckOfs(*pDi->dni.pOfs);
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
if (pBlkHdr->sbah.mdh.nFlags & WFS_MDF_DIR_LEAF_BLK) {
pDi->dni.nLog2Size = DirLeafGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
} else {
pDi->dni.nLog2Size = DirNodeGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
}
pDi->dni.nEntryIdx = 1;
} else {
if(nFlag == DIR_CHECK_DISK_FOR_DIR_TREE){
switch(pDi->pAttrHdr->nSizeCategory){
case FILE_SIZE_CATEGORY_SMALL:{
u32 nI, nNumSmallBlks = pDi->pAttrHdr->nAllocSize>>pDi->tba.pAreaInfo->ah.nLog2BlkSize;
for(nI=0;nI<nNumSmallBlks;nI++){
WFSFileBlkPtr *pFileBlkPtr = WFSKrnGetFileBlkPtrForCategorySmall(pDi->pAttrHdr, pDi->pAttrHdr->nAttrLog2Size, nI);
//if(pCheckDiskArray[pFileBlkPtr->nBlkAdr/8]&(1<<(pFileBlkPtr->nBlkAdr%8))){
// int a; a=0;
//}
///
//pCheckDiskArray[pFileBlkPtr->nBlkAdr/8] |= 1<<(pFileBlkPtr->nBlkAdr%8);
SetBit(fh, pFileBlkPtr->nBlkAdr);
}
break;
}
case FILE_SIZE_CATEGORY_MEDIUM:{
u32 nI, nNumMediumBlks = pDi->pAttrHdr->nAllocSize>>pDi->tba.pAreaInfo->ah.nLog2MediumBlkSize;
for(nI=0;nI<nNumMediumBlks;nI++){
WFSFileBlkPtr *pFileBlkPtr = WFSKrnGetFileBlkPtrForCategoryMedium(pDi->pAttrHdr, pDi->pAttrHdr->nAttrLog2Size, nI);
//u8 flag = 0xff<<(pFileBlkPtr->nBlkAdr%8);
///
SetBitArray(fh, pBuffer, bufferSize, pFileBlkPtr->nBlkAdr, 8); // array!
/*
pCheckDiskArray[pFileBlkPtr->nBlkAdr/8] |= flag;
if(~flag){
///
pCheckDiskArray[pFileBlkPtr->nBlkAdr/8+1] |= ~flag;
}
*/
}
break;
}
case FILE_SIZE_CATEGORY_LARGE:{
u32 nI, nJ, nNumLargeBlks = pDi->pAttrHdr->nAllocSize>>pDi->tba.pAreaInfo->ah.nLog2LargeBlkSize;
for(nJ=0;nJ<nNumLargeBlks;nJ++){
WFSFileLargeBlkPtr *pFileLargeBlkPtr = WFSKrnGetFileLargeBlkPtrForCategoryLarge(pDi->pAttrHdr, pDi->pAttrHdr->nAttrLog2Size, nJ);
for(nI=0;nI<(1<<pDi->tba.pAreaInfo->nLog2MediumBlkPerLargeBlk);nI++){
WFSFileBlkInfo fileBlkInfo = WFSKrnGetFileBlkInfoForCategoryLarge(pDi->tba.pAreaInfo, pFileLargeBlkPtr, nI);
//u8 flag = 0xff<<(fileBlkInfo.nBlkAdr%8);
SetBitArray(fh, pBuffer, bufferSize, fileBlkInfo.nBlkAdr, 8); // array!
/*
///
pCheckDiskArray[fileBlkInfo.nBlkAdr/8] |= flag;
if(~flag){
///
pCheckDiskArray[fileBlkInfo.nBlkAdr/8+1] |= ~flag;
}*/
}
}
break;
}
case FILE_SIZE_CATEGORY_VERY_LARGE: {
WFSBlkAdr nBlkAdr = pDi->tba.nBlkAdr;
u32 nI, nJ, nK;
u32 nNumLargeBlks = pDi->pAttrHdr->nAllocSize>>pDi->tba.pAreaInfo->ah.nLog2LargeBlkSize;
u32 nNumIndirectBlks = (nNumLargeBlks-1)/pDi->tba.pAreaInfo->nNumLargeBlkPtrsPerBlk+1;
for(nK=0;nK<nNumIndirectBlks;nK++){
u8* pIndirectPtr;
WFSBlkAdr *pBlkAdr = WFSKrnGetBlkAdrPtrFromAttrHdrAndIndirectBlkIdxForCategoryVeryLarge(pDi->tba.pAreaInfo, pDi->pAttrHdr, pDi->pAttrHdr->nAttrLog2Size, nK);
///
//pCheckDiskArray[*pBlkAdr/8] |= 1<<(*pBlkAdr%8);
SetBit(fh, *pBlkAdr);
pDi->tba.nBlkAdr = *pBlkAdr;
WFSKrnReturnOnError( DirGetBlk(pDi, TRANS_FLAG_READ_BLK | BCACHE_FLAG_PINNED, (DirBlkHdr**)&pIndirectPtr) );
for(nJ=0;nJ<pDi->tba.pAreaInfo->nNumLargeBlkPtrsPerBlk;nJ++){
WFSFileLargeBlkPtr *pFileLargeBlkPtr = WFSKrnGetFileLargeBlkPtrFromIndirectBlkForCategoryVeryLarge(pIndirectPtr, nJ);
for(nI=0;nI<(1<<pDi->tba.pAreaInfo->nLog2MediumBlkPerLargeBlk);nI++){
WFSFileBlkInfo fileBlkInfo = WFSKrnGetFileBlkInfoForCategoryLarge(pDi->tba.pAreaInfo, pFileLargeBlkPtr, nI);
//u8 nFlag = 0xff<<(fileBlkInfo.nBlkAdr%8);
SetBitArray(fh, pBuffer, bufferSize, fileBlkInfo.nBlkAdr, 8); // array!
/*
///
pCheckDiskArray[fileBlkInfo.nBlkAdr/8] |= nFlag;
nFlag = ~nFlag;
if(nFlag){
///
pCheckDiskArray[fileBlkInfo.nBlkAdr/8+1] |= nFlag;
}
*/
}
if(--nNumLargeBlks == 0){
break;
}
}
TransUnpinBlk(&pDi->tba);
}
pDi->tba.nBlkAdr = nBlkAdr;
break;
}
}
}
DirPopNodeStackEntry(&pDi->dni);
pDi->dni.nEntryIdx = 2;
}
}
else{
pDi->dni.pOfs = DirLeafGetIntraBlkOfsPtr_l2s((s32)pDi->dni.nEntryIdx, pDi->dni.pSubBlkHdr, pDi->dni.nLog2Size);
SbaCheckOfs(*pDi->dni.pOfs);
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
pDi->dni.nLog2Size = DirLeafGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
pDi->dni.nEntryIdx = 1;
}
} else {
if (pDi->dni.nEntryIdx == 1 && pDi->dni.pSubBlkHdr->aFirstChar[pDi->dni.pSubBlkHdr->nStrLen] == 0){
u32 nNewBlkAdr = DirNodeGetBlkAdr_l2s(pDi->dni.pSubBlkHdr, pDi->dni.nLog2Size);
///
//pCheckDiskArray[nNewBlkAdr/8] |= 1<<(nNewBlkAdr%8);
SetBit(fh, nNewBlkAdr);
TransUnpinBlk(&pDi->tba);
pDi->tba.nBlkAdr = nNewBlkAdr;
WFSKrnReturnOnError( DirGetBlk(pDi, TRANS_FLAG_READ_BLK | BCACHE_FLAG_PINNED, &pBlkHdr) );
pDi->dni.pOfs = &pBlkHdr->nRootOfs;
SbaCheckOfs(*pDi->dni.pOfs);
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
if (pBlkHdr->sbah.mdh.nFlags & WFS_MDF_DIR_LEAF_BLK) {
pDi->dni.nLog2Size = DirLeafGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
} else {
pDi->dni.nLog2Size = DirNodeGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
}
} else {
pDi->dni.pOfs = DirNodeGetIntraBlkOfsPtr_l2s((s32)pDi->dni.nEntryIdx, pDi->dni.pSubBlkHdr, pDi->dni.nLog2Size);
SbaCheckOfs(*pDi->dni.pOfs);
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
pDi->dni.nLog2Size = DirNodeGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
}
pDi->dni.nEntryIdx = 1;
}
}
}

View File

@ -0,0 +1,774 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_DirFind.cpp - Functions for finding
Copyright 2007-2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_DirFind.cpp,v $
Revision 1.15 2008/10/30 04:49:31 kondo_masahiro
Deleted the function of DirItrCheckList
Revision 1.14 2008/10/14 10:27:14 kondo_masahiro
Added #define _DEBUG_BREAK_POINT
Revision 1.13 2008/09/28 23:32:04 kondo_masahiro
Fixed codes to use medium size user block.
Revision 1.12 2008/08/27 09:46:48 paul
Added pAttrHdr->nAttrLog2Size
Revision 1.11 2008/08/05 03:58:43 kondo_masahiro
Added error handling for hash error and detach device.
Revision 1.10 2008/07/28 22:17:10 paul
Improved updateMap processing.
Revision 1.9 2008/07/25 02:51:28 paul
Changed from nTransIdx to *pTransInfo
Revision 1.8 2008/07/09 00:37:03 paul
Changes to make directory code work with block cache.
Revision 1.7 2008/06/09 17:25:31 paul
Fixed a bug in DirFindNext()
Revision 1.6 2008/05/27 18:44:44 paul
Made utf8 variable definitions more consistent, and use (unsigned) for comparisons
Revision 1.5 2008/05/17 03:54:59 paul
Fixed a bug in DirFindNext
Revision 1.4 2008/05/16 18:42:15 paul
Added DirFindNext to allow WFSSrvSearchDirectoryNext to work while adding/deleting files in the directory
Revision 1.3 2008/05/12 19:13:34 paul
Removed dni local variable from DirFind.
Made DirFind add pDi to a list of open iterators.
Revision 1.2 2008/05/10 03:59:44 kondo_masahiro
Merged and fixed code to accept RM compiler
Revision 1.1 2008/04/25 17:29:11 kondo_masahiro
Initial check-in
Revision 1.2 2008/04/22 23:28:12 paul
WfsArea* -> Area*
Revision 1.1 2008/04/21 18:58:31 paul
*** empty log message ***
*---------------------------------------------------------------------------*/
#undef _KRN_FILE_
#define _KRN_FILE_ "DirFind"
#include "wfskrn_SubBlkAlloc.h"
#include "wfskrn_Dir.h"
#include "wfskrn_DirFind.h"
#include "wfskrn_DirNodeStack.h"
#include "wfskrn_DirRxTree.h"
#undef dbg
#if _DEBUG_DIR
#define dbg(s) s
#else
#define dbg(s)
#endif
WFSKrnResult DirFind(WFSFileName *pName, DirItr *pDi, u32 nMaxBlkDepth, u32 nMode) {
// This function searches for a particular named entry in a directory up to a given max depth.
// If the name is found, its location within the appropriate leaf block is returned in pDi, and the function returns WFSKRN_RESULT_DIR_ENTRY_FOUND.
// If the name is not found, the location where it should be inserted within the appropriate leaf block, is returned in pDi, and the function returns ....
// In addition, if the input name is a prefix of one or more entries in the directory, then the characters beyond the end of the input string
// will be filled with the characters of the first matching entry from the directory. This can be used to help implement pattern searches,
// or just to get the first entry in a directory (by searching for "").
#if _DEBUG_BREAK_POINT
static int c=0;++c;if(c>=6979){
int a;a=0;
}
if (nDbgCommandCount==2850){
int a;a=0;
}
#endif
#if _DEBUG_DIR
if (nDirTest == nDirTestBreakPoint) {
int a; a=0;
}
#endif
DirBlkHdr *pBlkHdr;
WFSKrnReturnOnError(DirGetBlk(pDi, TRANS_FLAG_READ_BLK | BCACHE_FLAG_PINNED, &pBlkHdr));
DirNodeItr dniTemp;
utf8 *pStrEnd = pName->sStr + pName->nLen;
u32 nStrIdx, nPrefixStrIdx;
utf8 *pChoiceStrPtr = pName->sStr; // To keep track of how many characters are common between adjacent splitters when we move to a child block, so that it can implement prefix suppression.
utf8 cSubBlkChar, cSearchChar=pChoiceStrPtr[0];
u16 *pOfsTblEnd;
u32 nSubBlkStrLen;
WFSKrnResult nResult = WFSKRN_RESULT_OK;
#if _DEBUG
if ((pDi->dni.nDnsDepth == 0) && (pDi->ppDnsRootParent != 0)) {
WFSKrnOutputErrorStr("Directory Iterator already opened");
}
// Check pDi is not already on the open iterator list
DirItr *pListDi = dirGlobals.openDirItrListAnchor.pNext;
while(pListDi != dirGlobals.pOpenDirItrListAnchor) {
if (pListDi == pDi) {
WFSKrnOutputErrorStr("pDi already on open iterator list");
}
if (pListDi->link.pNext->link.pPrev != pListDi) {
WFSKrnOutputErrorStr("pDi link error");
}
pListDi = pListDi->link.pNext;
}
#endif
//MyOSReport("%d: Open(%p)\n", nDirTest, pDi);
pDi->link.pNext = dirGlobals.openDirItrListAnchor.pNext;
pDi->link.pPrev = dirGlobals.pOpenDirItrListAnchor;
dirGlobals.openDirItrListAnchor.pNext->link.pPrev = pDi;
dirGlobals.openDirItrListAnchor.pNext = pDi;
pDi->dni.nDnsDepth = 0;
WFSKrnReturnOnError(DirNodeStackGetEntry(&pDi->dni));
pDi->ppDnsRootParent = &pDi->dni.pDns->pParent;
pDi->dni.pDns->nBlkAdr = 0; //tba.nBlkAdr;
pDi->dni.pDns->nSubBlkOfs = pBlkHdr->nRootOfs;
dbg(SbaCheckOfs(pDi->dni.pDns->nSubBlkOfs));
pDi->dni.pDns->nEntryIdx = 1;
nPrefixStrIdx=0;
while(1) {
nStrIdx = nPrefixStrIdx-1;
#if DIR_PREFIX_SUPPRESSION
pDi->dni.pStrPtr = pChoiceStrPtr; // This should skip any common prefix shared by all file name key fields or splitters in the block
#else
pDi->dni.pStrPtr = pName->sStr;
#endif
pDi->dni.pOfs = &pBlkHdr->nRootOfs;
dbg(SbaCheckOfs(*pDi->dni.pOfs));
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
if ((pBlkHdr->sbah.mdh.nFlags & WFS_MDF_DIR_LEAF_BLK) || (pDi->nBlkDepth >= nMaxBlkDepth)) {
break;
}
++pDi->nBlkDepth;
pDi->dni.nLog2Size = DirNodeGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
while(1) {
nSubBlkStrLen = pDi->dni.pSubBlkHdr->nStrLen;
nStrIdx += nSubBlkStrLen + 1;
pDi->dni.pNodeStrPtr = pDi->dni.pSubBlkHdr->aFirstChar;
if ((pStrEnd - pDi->dni.pStrPtr) < nSubBlkStrLen) {
do {
cSearchChar = *pDi->dni.pStrPtr++;
cSubBlkChar = *pDi->dni.pNodeStrPtr++;
} while(cSearchChar == cSubBlkChar);
if ((unsigned)cSearchChar < (unsigned)cSubBlkChar) {
goto BackTrack;
}
goto ChooseMaxDescendent;
}
while(nSubBlkStrLen--) {
cSearchChar = *pDi->dni.pStrPtr++;
cSubBlkChar = *pDi->dni.pNodeStrPtr++;
if (cSearchChar != cSubBlkChar) {
if ((unsigned)cSearchChar < (unsigned)cSubBlkChar) {
goto BackTrack;
}
goto ChooseMaxDescendent;
}
}
// matched all the characters from the prefix. pDi->dni.pNodeStrPtr should now be pointing to the array of choices following the prefix.
cSearchChar = *pDi->dni.pStrPtr;
pOfsTblEnd = (u16*)((u8*)pDi->dni.pSubBlkHdr + (1<<pDi->dni.nLog2Size));
WFSBool bFound = DirBinarySplitSearchChoices(pDi->dni.pNodeStrPtr, pDi->dni.pSubBlkHdr->nNumEntries, cSearchChar, &pDi->dni.nEntryIdx);
#if DIR_PREFIX_SUPPRESSION
if ((pDi->dni.nEntryIdx>=1) && (pDi->dni.nEntryIdx < pDi->dni.pSubBlkHdr->nNumEntries)) {
// ToDo: Implement prefix suppression
nPrefixStrIdx = nStrIdx;
}
#endif
WFSKrnExitOnError(DirPushNodeStackEntry(&pDi->dni, pDi->tba.nBlkAdr));
pDi->dni.pDns->nUpdateCtr = pDi->nUpdateCtr;
if (bFound) {
// Found the search character.
pDi->dni.pDns->nStrIdx = (u8)nStrIdx;
if (cSearchChar==0) {
// We matched a 0 .. means the file name matched one of the splitters exactly
// This may still be a valid file name.
// Note: A splitter can be arbitrary. It does not even have to be a prefix of an existing file name.
// (This can happen after deleting the filename which was originally chosen as a split point).
break;
}
if (pDi->dni.pSubBlkHdr->nNumEntries>1) {
if (pDi->dni.nEntryIdx>1) {
// Update the previous record information
dniTemp = pDi->dni;
--dniTemp.nEntryIdx;
}
pChoiceStrPtr = pDi->dni.pStrPtr;
}
pDi->dni.pOfs = DirNodeGetIntraBlkOfsPtr_ote((s32)pDi->dni.nEntryIdx, pDi->dni.pSubBlkHdr, pOfsTblEnd);
dbg(SbaCheckOfs(*pDi->dni.pOfs));
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
pDi->dni.nLog2Size = DirNodeGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
++pDi->dni.pStrPtr;
continue;
}
if (pDi->dni.nEntryIdx==0) {
// The binary split search determined that the search character was smaller than the smallest choice
BackTrack:
while(pDi->dni.pDns != dniTemp.pDns) {
DirPopNodeStackEntry(&pDi->dni);
};
pDi->dni = dniTemp;
pDi->dni.pDns->nEntryIdx = pDi->dni.nEntryIdx;
nStrIdx = (u32)(pDi->dni.pDns->nStrIdx);// + pDi->dni.pSubBlkHdr->nStrLen + 1);
pChoiceStrPtr = pDi->dni.pStrPtr;
pOfsTblEnd = (u16*)((u8*)pDi->dni.pSubBlkHdr + (1<<pDi->dni.nLog2Size));
pDi->dni.pNodeStrPtr = &pDi->dni.pSubBlkHdr->aFirstChar[pDi->dni.pSubBlkHdr->nStrLen];
}
pDi->dni.pDns->nStrIdx = (u8)nStrIdx;
if ((pDi->dni.nEntryIdx==1)&&(pDi->dni.pNodeStrPtr[0]==0)) {
break;
}
// Offset is an intra block offset
pDi->dni.pOfs = DirNodeGetIntraBlkOfsPtr_ote((s32)pDi->dni.nEntryIdx, pDi->dni.pSubBlkHdr, pOfsTblEnd);
dbg(SbaCheckOfs(*pDi->dni.pOfs));
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
nStrIdx += pDi->dni.pSubBlkHdr->nStrLen + 1;
pDi->dni.nLog2Size = DirNodeGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
ChooseMaxDescendent:
// Follow intra block offsets until max splitter end is encountered
if (pDi->dni.pSubBlkHdr->nNumEntries > 1) {
while(1) {
pDi->dni.nEntryIdx = pDi->dni.pSubBlkHdr->nNumEntries;
WFSKrnExitOnError(DirPushNodeStackEntry(&pDi->dni, pDi->tba.nBlkAdr));
pDi->dni.pDns->nUpdateCtr = pDi->nUpdateCtr;
nStrIdx += pDi->dni.pSubBlkHdr->nStrLen;
pDi->dni.pDns->nStrIdx = (u8)nStrIdx;
if (pDi->dni.pSubBlkHdr->nNumEntries == 1) {
break;
}
++nStrIdx;
pDi->dni.pOfs = DirNodeGetIntraBlkOfsPtr_l2s(pDi->dni.nEntryIdx, pDi->dni.pSubBlkHdr, pDi->dni.nLog2Size);
dbg(SbaCheckOfs(*pDi->dni.pOfs));
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
pDi->dni.nLog2Size = DirNodeGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
};
pOfsTblEnd = (u16*)((u8*)pDi->dni.pSubBlkHdr + (1<<pDi->dni.nLog2Size));
break;
}
// we should now be at the end of the line
pOfsTblEnd = (u16*)((u8*)pDi->dni.pSubBlkHdr + (1<<pDi->dni.nLog2Size));
pDi->dni.nEntryIdx = 1;
WFSKrnExitOnError(DirPushNodeStackEntry(&pDi->dni, pDi->tba.nBlkAdr));
pDi->dni.pDns->nUpdateCtr = pDi->nUpdateCtr;
pDi->dni.pDns->nStrIdx = nStrIdx;
break;
}
if (nMode == DIR_FIND_MODE_NODE_SEARCH) {
if (pDi->nBlkDepth >= nMaxBlkDepth) {
goto Exit;
}
}
{
u32 nNewBlkAdr = DirNodeGetBlkAdr_ote(pDi->dni.pSubBlkHdr, pOfsTblEnd);
TransUnpinBlk(&pDi->tba);
pDi->tba.nBlkAdr = nNewBlkAdr;
WFSKrnExitOnError( DirGetBlk(pDi, TRANS_FLAG_READ_BLK | BCACHE_FLAG_PINNED, &pBlkHdr) );
}
}
#if (DIR_PREFIX_SUPPRESSION==0)
// ToDo: Prefix suppression not yet implemented
pDi->dni.pStrPtr = pName->sStr;
#endif
// Search the leaf node
if (pBlkHdr->sbah.mdh.nFlags & WFS_MDF_DIR_LEAF_BLK) {
pDi->dni.nLog2Size = DirLeafGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
} else {
pDi->dni.nLog2Size = DirNodeGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
}
while(1) {
nSubBlkStrLen = pDi->dni.pSubBlkHdr->nStrLen;
nStrIdx += nSubBlkStrLen + 1;
pDi->dni.pNodeStrPtr = pDi->dni.pSubBlkHdr->aFirstChar;
if ((pStrEnd - pDi->dni.pStrPtr) < nSubBlkStrLen) {
while(*pDi->dni.pStrPtr == *pDi->dni.pNodeStrPtr) {
++pDi->dni.pStrPtr; ++pDi->dni.pNodeStrPtr;
}
nSubBlkStrLen -= (pDi->dni.pNodeStrPtr - pDi->dni.pSubBlkHdr->aFirstChar);
nResult = WFSKRN_RESULT_DIR_NODE_STRING_MISMATCH;
break;
}
while((nSubBlkStrLen) && (*pDi->dni.pStrPtr == *pDi->dni.pNodeStrPtr)) {
++pDi->dni.pStrPtr; ++pDi->dni.pNodeStrPtr; --nSubBlkStrLen;
}
if (nSubBlkStrLen) {
nResult = WFSKRN_RESULT_DIR_NODE_STRING_MISMATCH;
break;
}
// matched all the characters from the prefix. pDi->dni.pNodeStrPtr should now be pointing to the array of choices following the prefix.
cSearchChar = *pDi->dni.pStrPtr;
if (!DirBinarySplitSearchChoices(pDi->dni.pNodeStrPtr, pDi->dni.pSubBlkHdr->nNumEntries, cSearchChar, &pDi->dni.nEntryIdx)) {
nResult = WFSKRN_RESULT_DIR_NODE_CHOICE_NOT_FOUND;
break;
}
WFSKrnExitOnError(DirPushNodeStackEntry(&pDi->dni, pDi->tba.nBlkAdr));
pDi->dni.pDns->nUpdateCtr = pDi->nUpdateCtr;
pDi->dni.pDns->nStrIdx = nStrIdx;
// Found the search character.
if (cSearchChar==0) {
// We matched a 0 .. which means we have found the filename
nResult = WFSKRN_RESULT_DIR_ENTRY_FOUND;
break;
}
if (pBlkHdr->sbah.mdh.nFlags & WFS_MDF_DIR_LEAF_BLK) {
pDi->dni.pOfs = DirLeafGetIntraBlkOfsPtr_l2s((s32)pDi->dni.nEntryIdx, pDi->dni.pSubBlkHdr, pDi->dni.nLog2Size);
dbg(SbaCheckOfs(*pDi->dni.pOfs));
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
pDi->dni.nLog2Size = DirLeafGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
} else {
pDi->dni.pOfs = DirNodeGetIntraBlkOfsPtr_l2s((s32)pDi->dni.nEntryIdx, pDi->dni.pSubBlkHdr, pDi->dni.nLog2Size);
dbg(SbaCheckOfs(*pDi->dni.pOfs));
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
pDi->dni.nLog2Size = DirNodeGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
}
++pDi->dni.pStrPtr;
}
// This is the location passed back to the caller
pDi->pBlkHdr = pBlkHdr;
if ((*pDi->dni.pStrPtr) || (pBlkHdr->nNumRecs==0) || (!(pBlkHdr->sbah.mdh.nFlags & WFS_MDF_DIR_LEAF_BLK))) {
goto Done;
}
if (nResult == WFSKRN_RESULT_DIR_ENTRY_FOUND) {
goto GetAttr;
}
if (nMode != DIR_FIND_MODE_PREFIX_SEARCH) {
goto Done;
}
if (nResult == WFSKRN_RESULT_DIR_NODE_STRING_MISMATCH) {
nResult = WFSKRN_RESULT_DIR_NODE_STRING_PREFIX;
} else {
nResult = WFSKRN_RESULT_DIR_CHOICE_PREFIX;
}
// The exact name was not found, but it was a prefix of one or more exising names.
// We continue traversing to find the left-most descendent.
// This is useful for iterating through the directory, and wildcard pattern search.
pDi->dni.nEntryIdx = 1;
while(1) {
while(nSubBlkStrLen--) {
*pDi->dni.pStrPtr++ = *pDi->dni.pNodeStrPtr++;
}
//if (pDi->dni.pSubBlkHdr->nNumEntries > 1) {
WFSKrnExitOnError(DirPushNodeStackEntry(&pDi->dni, pDi->tba.nBlkAdr));
pDi->dni.pDns->nUpdateCtr = pDi->nUpdateCtr;
pDi->dni.pDns->nStrIdx = nStrIdx;
//}
cSubBlkChar = pDi->dni.pSubBlkHdr->aFirstChar[pDi->dni.pSubBlkHdr->nStrLen];
*pDi->dni.pStrPtr++ = cSubBlkChar;
if (cSubBlkChar==0) {
//pDi->dni = pDi->dni;
pName->nLen = nStrIdx;
goto GetAttr;
}
pOfsTblEnd = (u16*)((u8*)pDi->dni.pSubBlkHdr + (1<<pDi->dni.nLog2Size));
pDi->dni.pOfs = &pOfsTblEnd[-1];
dbg(SbaCheckOfs(*pDi->dni.pOfs));
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
pDi->dni.nLog2Size = DirLeafGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
nSubBlkStrLen = pDi->dni.pSubBlkHdr->nStrLen;
nStrIdx += nSubBlkStrLen + 1;
pDi->dni.pNodeStrPtr = pDi->dni.pSubBlkHdr->aFirstChar;
}
GetAttr:
pDi->dni.pOfs = DirLeafGetIntraBlkOfsPtr_l2s(1, pDi->dni.pSubBlkHdr, pDi->dni.nLog2Size);
pDi->pAttrHdr = (DirEntryAttrHdr *)((u8*)pDi->pBlkHdr + *pDi->dni.pOfs);
pDi->dni.nLog2Size = pDi->pAttrHdr->nAttrLog2Size;
Done:
return nResult;
Exit:
pDi->pBlkHdr = pBlkHdr;
return nResult;
}
WFSKrnResult DirFindNext(WFSFileName *pName, DirItr *pDi) {
#if _DEBUG_DIR
if (nDirTest == nDirTestBreakPoint) {
int a; a=0;
}
#endif
DirBlkHdr *pBlkHdr;
WFSKrnReturnOnError( DirGetBlk(pDi, TRANS_FLAG_READ_BLK | BCACHE_FLAG_PINNED, &pBlkHdr) );
DirNodeItr dniPrev, dniNext;
utf8 *pStrEnd = pName->sStr + pName->nLen;
u32 nStrIdx, nPrefixStrIdx;
utf8 *pChoiceStrPtr = pName->sStr; // To keep track of how many characters are common between adjacent splitters when we move to a child block, so that it can implement prefix suppression.
utf8 cSubBlkChar, cSearchChar=pChoiceStrPtr[0];
u16 *pOfsTblEnd;
u32 nSubBlkStrLen;
WFSKrnResult nResult = WFSKRN_RESULT_OK;
#if _DEBUG
if ((pDi->dni.nDnsDepth == 0) && (pDi->ppDnsRootParent != 0)) {
WFSKrnOutputErrorStr("Directory Iterator already opened");
}
// Check pDi is not already on the open iterator list
DirItr *pListDi = dirGlobals.openDirItrListAnchor.pNext;
while(pListDi != dirGlobals.pOpenDirItrListAnchor) {
if (pListDi == pDi) {
WFSKrnOutputErrorStr("pDi already on open iterator list");
}
if (pListDi->link.pNext->link.pPrev != pListDi) {
WFSKrnOutputErrorStr("pDi link error");
}
pListDi = pListDi->link.pNext;
}
#endif
//MyOSReport("%d: Open(%p)\n", nDirTest, pDi);
pDi->link.pNext = dirGlobals.openDirItrListAnchor.pNext;
pDi->link.pPrev = dirGlobals.pOpenDirItrListAnchor;
dirGlobals.openDirItrListAnchor.pNext->link.pPrev = pDi;
dirGlobals.openDirItrListAnchor.pNext = pDi;
pDi->dni.nDnsDepth = 0;
WFSKrnReturnOnError(DirNodeStackGetEntry(&pDi->dni));
pDi->ppDnsRootParent = &pDi->dni.pDns->pParent;
pDi->dni.pDns->nBlkAdr = 0; //tba.nBlkAdr;
pDi->dni.pDns->nSubBlkOfs = pBlkHdr->nRootOfs;
dbg(SbaCheckOfs(pDi->dni.pDns->nSubBlkOfs));
pDi->dni.pDns->nEntryIdx = 1;
nPrefixStrIdx = 0;
dniNext.nEntryIdx = 0;
while(1) {
nStrIdx = nPrefixStrIdx-1;
#if DIR_PREFIX_SUPPRESSION
pDi->dni.pStrPtr = pChoiceStrPtr; // This should skip any common prefix shared by all file name key fields or splitters in the block
#else
pDi->dni.pStrPtr = pName->sStr;
#endif
pDi->dni.pOfs = &pBlkHdr->nRootOfs;
dbg(SbaCheckOfs(*pDi->dni.pOfs));
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
if (pBlkHdr->sbah.mdh.nFlags & WFS_MDF_DIR_LEAF_BLK) {
break;
}
#if _DEBUG_DIR
/*if (nDirTest == nDirTestBreakPoint) {
nDirTest = nDirTestBreakPoint;
pDi->pBlkHdr = pBlkHdr;
DirNodeCheckBlk(pDi);
}*/
#endif
++pDi->nBlkDepth;
pDi->dni.nLog2Size = DirNodeGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
while(1) {
nSubBlkStrLen = pDi->dni.pSubBlkHdr->nStrLen;
nStrIdx += nSubBlkStrLen + 1;
pDi->dni.pNodeStrPtr = pDi->dni.pSubBlkHdr->aFirstChar;
if ((pStrEnd - pDi->dni.pStrPtr) < nSubBlkStrLen) {
do {
cSearchChar = *pDi->dni.pStrPtr++;
cSubBlkChar = *pDi->dni.pNodeStrPtr++;
} while(cSearchChar == cSubBlkChar);
if ((unsigned)cSearchChar < (unsigned)cSubBlkChar) {
goto BackTrackNodePrev;
}
goto ChooseMaxDescendent;
}
while(nSubBlkStrLen--) {
cSearchChar = *pDi->dni.pStrPtr++;
cSubBlkChar = *pDi->dni.pNodeStrPtr++;
if (cSearchChar != cSubBlkChar) {
if ((unsigned)cSearchChar < (unsigned)cSubBlkChar) {
goto BackTrackNodePrev;
}
goto ChooseMaxDescendent;
}
}
// matched all the characters from the prefix. pDi->dni.pNodeStrPtr should now be pointing to the array of choices following the prefix.
cSearchChar = *pDi->dni.pStrPtr;
pOfsTblEnd = (u16*)((u8*)pDi->dni.pSubBlkHdr + (1<<pDi->dni.nLog2Size));
WFSBool bFound = DirBinarySplitSearchChoices(pDi->dni.pNodeStrPtr, pDi->dni.pSubBlkHdr->nNumEntries, cSearchChar, &pDi->dni.nEntryIdx);
#if DIR_PREFIX_SUPPRESSION
if ((pDi->dni.nEntryIdx>=1) && (pDi->dni.nEntryIdx < pDi->dni.pSubBlkHdr->nNumEntries)) {
// ToDo: Implement prefix suppression
nPrefixStrIdx = nStrIdx;
}
#endif
WFSKrnExitOnError(DirPushNodeStackEntry(&pDi->dni, pDi->tba.nBlkAdr));
pDi->dni.pDns->nUpdateCtr = pDi->nUpdateCtr;
if (pDi->dni.nEntryIdx < pDi->dni.pSubBlkHdr->nNumEntries) {
dniNext = pDi->dni;
}
if (bFound) {
// Found the search character.
pDi->dni.pDns->nStrIdx = (u8)nStrIdx;
if (cSearchChar==0) {
// We matched a 0 .. means the file name matched one of the splitters exactly
// This may still be a valid file name.
// Note: A splitter can be arbitrary. It does not even have to be a prefix of an existing file name.
// (This can happen after deleting the filename which was originally chosen as a split point).
break;
}
if (pDi->dni.pSubBlkHdr->nNumEntries>1) {
if (pDi->dni.nEntryIdx>1) {
// Update the previous record information
dniPrev = pDi->dni;
}
pChoiceStrPtr = pDi->dni.pStrPtr;
}
pDi->dni.pOfs = DirNodeGetIntraBlkOfsPtr_ote((s32)pDi->dni.nEntryIdx, pDi->dni.pSubBlkHdr, pOfsTblEnd);
dbg(SbaCheckOfs(*pDi->dni.pOfs));
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
pDi->dni.nLog2Size = DirNodeGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
++pDi->dni.pStrPtr;
continue;
}
if (pDi->dni.nEntryIdx==0) {
// The binary split search determined that the search character was smaller than the smallest choice
BackTrackNodePrev:
while(pDi->dni.pDns != dniPrev.pDns) {
DirPopNodeStackEntry(&pDi->dni);
};
pDi->dni = dniPrev;
pDi->dni.pDns->nEntryIdx = --pDi->dni.nEntryIdx;
dniNext = pDi->dni;
nStrIdx = (u32)(pDi->dni.pDns->nStrIdx);// + pDi->dni.pSubBlkHdr->nStrLen + 1);
pChoiceStrPtr = pDi->dni.pStrPtr;
pOfsTblEnd = (u16*)((u8*)pDi->dni.pSubBlkHdr + (1<<pDi->dni.nLog2Size));
pDi->dni.pNodeStrPtr = &pDi->dni.pSubBlkHdr->aFirstChar[pDi->dni.pSubBlkHdr->nStrLen];
}
pDi->dni.pDns->nStrIdx = (u8)nStrIdx;
if ((pDi->dni.nEntryIdx==1)&&(pDi->dni.pNodeStrPtr[0]==0)) {
break;
}
// Offset is an intra block offset
pDi->dni.pOfs = DirNodeGetIntraBlkOfsPtr_ote((s32)pDi->dni.nEntryIdx, pDi->dni.pSubBlkHdr, pOfsTblEnd);
dbg(SbaCheckOfs(*pDi->dni.pOfs));
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
nStrIdx += pDi->dni.pSubBlkHdr->nStrLen + 1;
pDi->dni.nLog2Size = DirNodeGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
ChooseMaxDescendent:
// Follow intra block offsets until max splitter end is encountered
if (pDi->dni.pSubBlkHdr->nNumEntries > 1) {
while(1) {
pDi->dni.nEntryIdx = pDi->dni.pSubBlkHdr->nNumEntries;
WFSKrnExitOnError(DirPushNodeStackEntry(&pDi->dni, pDi->tba.nBlkAdr));
pDi->dni.pDns->nUpdateCtr = pDi->nUpdateCtr;
nStrIdx += pDi->dni.pSubBlkHdr->nStrLen;
pDi->dni.pDns->nStrIdx = (u8)nStrIdx;
if (pDi->dni.pSubBlkHdr->nNumEntries == 1) {
break;
}
++nStrIdx;
pDi->dni.pOfs = DirNodeGetIntraBlkOfsPtr_l2s(pDi->dni.nEntryIdx, pDi->dni.pSubBlkHdr, pDi->dni.nLog2Size);
dbg(SbaCheckOfs(*pDi->dni.pOfs));
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
pDi->dni.nLog2Size = DirNodeGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
};
pOfsTblEnd = (u16*)((u8*)pDi->dni.pSubBlkHdr + (1<<pDi->dni.nLog2Size));
break;
}
// we should now be at the end of the line
pOfsTblEnd = (u16*)((u8*)pDi->dni.pSubBlkHdr + (1<<pDi->dni.nLog2Size));
pDi->dni.nEntryIdx = 1;
WFSKrnExitOnError(DirPushNodeStackEntry(&pDi->dni, pDi->tba.nBlkAdr));
pDi->dni.pDns->nUpdateCtr = pDi->nUpdateCtr;
pDi->dni.pDns->nStrIdx = nStrIdx;
break;
}
{
u32 nNewBlkAdr = DirNodeGetBlkAdr_ote(pDi->dni.pSubBlkHdr, pOfsTblEnd);
TransUnpinBlk(&pDi->tba);
pDi->tba.nBlkAdr = nNewBlkAdr;
WFSKrnExitOnError( DirGetBlk(pDi, TRANS_FLAG_READ_BLK | BCACHE_FLAG_PINNED, &pBlkHdr) );
}
}
#if (DIR_PREFIX_SUPPRESSION==0)
// ToDo: Prefix suppression not yet implemented
pDi->dni.pStrPtr = pName->sStr;
#endif
#if _DEBUG_DIR
/*if (nDirTest == nDirTestBreakPoint) {
pDi->pBlkHdr = pBlkHdr;
DirLeafCheckBlk(pDi);
}*/
#endif
// Search the leaf node
pDi->dni.nLog2Size = DirLeafGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
while(1) {
nSubBlkStrLen = pDi->dni.pSubBlkHdr->nStrLen;
nStrIdx += nSubBlkStrLen + 1;
pDi->dni.pNodeStrPtr = pDi->dni.pSubBlkHdr->aFirstChar;
if ((pStrEnd - pDi->dni.pStrPtr) < nSubBlkStrLen) {
while(*pDi->dni.pStrPtr == *pDi->dni.pNodeStrPtr) {
++pDi->dni.pStrPtr; ++pDi->dni.pNodeStrPtr;
}
nSubBlkStrLen -= (pDi->dni.pNodeStrPtr - pDi->dni.pSubBlkHdr->aFirstChar);
} else {
while((nSubBlkStrLen) && (*pDi->dni.pStrPtr == *pDi->dni.pNodeStrPtr)) {
++pDi->dni.pStrPtr; ++pDi->dni.pNodeStrPtr; --nSubBlkStrLen;
}
}
if (nSubBlkStrLen) {
if (*pDi->dni.pStrPtr > *pDi->dni.pNodeStrPtr) {
goto BackTrack;
}
pDi->dni.nEntryIdx = 1;
goto ChooseMinDescendentLeaf;
}
// matched all the characters from the prefix. pDi->dni.pNodeStrPtr should now be pointing to the array of choices following the prefix.
WFSKrnExitOnError(DirPushNodeStackEntry(&pDi->dni, pDi->tba.nBlkAdr));
pDi->dni.pDns->nUpdateCtr = pDi->nUpdateCtr;
pDi->dni.pDns->nStrIdx = nStrIdx;
cSearchChar = *pDi->dni.pStrPtr;
if (DirBinarySplitSearchChoices(pDi->dni.pNodeStrPtr, pDi->dni.pSubBlkHdr->nNumEntries, cSearchChar, &pDi->dni.nEntryIdx)) {
pDi->dni.pDns->nEntryIdx = pDi->dni.nEntryIdx;
if (pDi->dni.nEntryIdx < pDi->dni.pSubBlkHdr->nNumEntries) {
dniNext = pDi->dni;
}
} else {
//*pDi->dni.pStrPtr++ = pDi->dni.pNodeStrPtr[pDi->dni.nEntryIdx];
pDi->dni.pNodeStrPtr += pDi->dni.nEntryIdx;
++pDi->dni.nEntryIdx;
if (pDi->dni.nEntryIdx > pDi->dni.pSubBlkHdr->nNumEntries) {
goto BackTrack;
}
goto ChooseMinDescendentLeaf;
}
// Found the search character.
if (cSearchChar==0) {
// We matched a 0 .. which means we have found the filename
// However an exact match is not what we are looking for. We want the next entry.
BackTrack:
if (dniNext.nEntryIdx == 0) {
nResult = WFSKRN_RESULT_NOT_FOUND;
goto Exit;
}
nResult = WFSKRN_RESULT_DIR_ENTRY_FOUND;
//WFSBlkAdr nLeafBlkAdr = pDi->dni.pDns->nBlkAdr;
while(pDi->dni.pDns != dniNext.pDns) {
DirPopNodeStackEntry(&pDi->dni);
}
pDi->dni = dniNext;
if (pDi->tba.nBlkAdr != dniNext.pDns->nBlkAdr) {
// We have back tracked to a previous node
TransUnpinBlk(&pDi->tba);
pDi->tba.nBlkAdr = dniNext.pDns->nBlkAdr;
WFSKrnExitOnError( DirGetBlk(pDi, TRANS_FLAG_READ_BLK | BCACHE_FLAG_PINNED, &pBlkHdr) );
++pDi->dni.pDns->nEntryIdx;
pDi->dni.pOfs = DirNodeGetIntraBlkOfsPtr(pDi->dni.pDns->nEntryIdx, pDi->dni.pSubBlkHdr);
dbg(SbaCheckOfs(*pDi->dni.pOfs));
pDi->dni.nEntryIdx=1;
do {
while(1) {
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
WFSKrnExitOnError(DirPushNodeStackEntry(&pDi->dni, pDi->tba.nBlkAdr));
pDi->dni.pDns->nUpdateCtr = pDi->nUpdateCtr;
if (pDi->dni.pSubBlkHdr->aFirstChar[pDi->dni.pSubBlkHdr->nStrLen] == 0) {
break;
}
pDi->dni.pOfs = DirNodeGetIntraBlkOfsPtr(pDi->dni.nEntryIdx, pDi->dni.pSubBlkHdr);
dbg(SbaCheckOfs(*pDi->dni.pOfs));
}
{
WFSBlkAdr nNewBlkAdr = DirNodeGetBlkAdr(pDi->dni.pSubBlkHdr);
TransUnpinBlk(&pDi->tba);
pDi->tba.nBlkAdr = nNewBlkAdr;
WFSKrnExitOnError( DirGetBlk(pDi, TRANS_FLAG_READ_BLK | BCACHE_FLAG_PINNED, &pBlkHdr) );
}
DirCheckBlk(pDi);
#if _DEBUG_DIR
/*if (nDirTest == nDirTestBreakPoint) {
pDi->pBlkHdr = pBlkHdr;
DirCheckBlk(pDi);
}*/
#endif
pDi->dni.pOfs = &pBlkHdr->nRootOfs;
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
pDi->dni.nEntryIdx = 1;
} while(!(pBlkHdr->sbah.mdh.nFlags & WFS_MDF_DIR_LEAF_BLK));
nStrIdx = (u32)-1;
pDi->dni.pStrPtr = pName->sStr;
} else {
nStrIdx = dniNext.pDns->nStrIdx;
*pDi->dni.pStrPtr++ = pDi->dni.pNodeStrPtr[dniNext.nEntryIdx];
++dniNext.nEntryIdx;
pDi->dni.pOfs = DirLeafGetIntraBlkOfsPtr(dniNext.nEntryIdx, pDi->dni.pSubBlkHdr);
dbg(SbaCheckOfs(*pDi->dni.pOfs));
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
}
nSubBlkStrLen = pDi->dni.pSubBlkHdr->nStrLen;
nStrIdx += nSubBlkStrLen + 1;
pDi->dni.pNodeStrPtr = pDi->dni.pSubBlkHdr->aFirstChar;
pDi->dni.nEntryIdx = 1;
ChooseMinDescendentLeaf:
++nSubBlkStrLen;
while(1) {
memcpy(pDi->dni.pStrPtr, pDi->dni.pNodeStrPtr, nSubBlkStrLen);
pDi->dni.pStrPtr += nSubBlkStrLen;
if(pDi->dni.pDns->nBlkAdr != pDi->tba.nBlkAdr || pDi->dni.pDns->nSubBlkOfs != *pDi->dni.pOfs){
WFSKrnReturnOnError(DirPushNodeStackEntry(&pDi->dni, pDi->tba.nBlkAdr));
} else {
pDi->dni.pDns->nEntryIdx = (u8)pDi->dni.nEntryIdx;
}
//WFSKrnExitOnError(DirPushNodeStackEntry(&pDi->dni, pDi->tba.nBlkAdr));
pDi->dni.pDns->nUpdateCtr = pDi->nUpdateCtr;
pDi->dni.pDns->nStrIdx = (u8)nStrIdx;
pDi->dni.pOfs = DirLeafGetIntraBlkOfsPtr(pDi->dni.nEntryIdx, pDi->dni.pSubBlkHdr);
dbg(SbaCheckOfs(*pDi->dni.pOfs));
if (pDi->dni.pNodeStrPtr[nSubBlkStrLen-1] == 0) {
break;
}
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
pDi->dni.pNodeStrPtr = pDi->dni.pSubBlkHdr->aFirstChar;
nSubBlkStrLen = pDi->dni.pSubBlkHdr->nStrLen + 1;
nStrIdx += nSubBlkStrLen;
pDi->dni.nEntryIdx = 1;
};
break;
}
pDi->dni.pOfs = DirLeafGetIntraBlkOfsPtr_l2s((s32)pDi->dni.nEntryIdx, pDi->dni.pSubBlkHdr, pDi->dni.nLog2Size);
dbg(SbaCheckOfs(*pDi->dni.pOfs));
pDi->dni.pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + *pDi->dni.pOfs);
pDi->dni.nLog2Size = DirLeafGetSubBlkLog2Size(pDi->dni.pSubBlkHdr);
++pDi->dni.pStrPtr;
}
pDi->pAttrHdr = (DirEntryAttrHdr*)((u8*)pBlkHdr + *pDi->dni.pOfs);
pDi->name.nLen = nStrIdx;
Exit:
pDi->pBlkHdr = pBlkHdr;
return nResult;
}

View File

@ -0,0 +1,418 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_DirNodeStack.cpp
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_DirNodeStack.cpp,v $
Revision 1.8 2008/10/16 09:30:39 ooizumi
Fixed definitions for debug build.
Revision 1.7 2008/10/14 10:27:14 kondo_masahiro
Added #define _DEBUG_BREAK_POINT
Revision 1.6 2008/09/28 23:32:04 kondo_masahiro
Fixed codes to use medium size user block.
Revision 1.5 2008/08/05 03:58:31 kondo_masahiro
Added error handling for hash error and detach device.
Revision 1.4 2008/07/09 00:37:52 paul
Changes to make directory code work with block cache.
Revision 1.3 2008/05/10 03:59:44 kondo_masahiro
Merged and fixed code to accept RM compiler
Revision 1.2 2008/04/25 17:29:50 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.1 2008/04/22 04:39:08 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.10 2008/04/23 01:56:07 paul
Fixed bCheckDirNodeStack to be visible from wfskrn_Dir.cpp
Revision 1.9 2008/04/22 22:12:40 paul
Changed WFSArea* to Area*
Revision 1.8 2008/04/19 05:50:51 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.7 2008/04/15 18:45:09 paul
Added some debug code to output calling locations for NodeStack functions
Revision 1.6 2008/04/04 22:53:33 paul
Changed debug triggers to use bCheckDirNodeStack
Revision 1.5 2008/04/04 21:16:33 paul
Fixed loop-detecting code
Revision 1.4 2008/04/03 23:38:31 kondo_masahiro
change name of debug parameter
Revision 1.3 2008/03/05 11:02:13 paul
Changed stack checking functions to not allocate memory
Revision 1.2 2008/02/28 06:31:49 kondo_masahiro
Fixed code to accept PPC compiler
Revision 1.1 2008/02/27 09:46:53 paul
*** empty log message ***
Revision 1.2 2008/02/27 00:38:44 paul
Updated debug code
Revision 1.1 2008/02/21 04:35:34 paul
*** empty log message ***
*---------------------------------------------------------------------------*/
#undef _KRN_FILE_
#define _KRN_FILE_ "DirNS"
#include "wfskrn_DirNodeStack.h"
#include "wfskrn_Mutex.h"
#include "wfskrn_Api.h"
#if _DEBUG_DIR_NODE_STACK
#define dbg_check(s) s
#define dbg_output(s)
#else
#define dbg_check(s)
#define dbg_output(s)
#endif
#if _DEBUG_DIR_NODE_STACK
bool bCheckDirNodeStack = false; // extern
#endif
typedef struct {
WFSKrnMutex mxMutex;
dbg_check(u32 nTotalAllocated;)
dbg_check(u32 nNumUsed;)
u32 nNumFreeDnsPoolEntries;
DirNodeStack *pDnsPoolFreeList;
} DirNodeStackGlobals;
DirNodeStackGlobals dnsg;
#if _DEBUG_DIR
void DebugCheckNumFreeDnsPoolEntries(char *str) {
static u32 nPrev=0;
char *s; s = str; // for warning
if (nPrev != dnsg.nNumFreeDnsPoolEntries) {
nPrev = dnsg.nNumFreeDnsPoolEntries;
dbg_output(MyOSReport("%s: dnsg.nNumFreeDnsPoolEntries=%d\n", str, dnsg.nNumFreeDnsPoolEntries));
if ((dnsg.nNumFreeDnsPoolEntries!=WFS_DIR_NODE_STACK_ENTRY_POOL_ALLOC_UNIT)&&
(dnsg.nNumFreeDnsPoolEntries!=(WFS_DIR_NODE_STACK_ENTRY_POOL_ALLOC_UNIT*2))) {
//int a=0; // for warning
}
}
}
#endif //_DEBUG_DIR
#if _DEBUG_DIR_NODE_STACK
DirNodeStack *pDebugLastNodeStackAlloc;
u32 nDebugCountNodeStackCheckAlloc = 0;
u32 nDebugCountNodeStackCheckFreeList = 0;
static
void DirNodeStackCheckAlloc(DirNodeItr *pDni) {
nDebugCountNodeStackCheckAlloc++;
dbg_output(MyOSReport("%d. ", nDebugCountNodeStackCheckAlloc));
DirNodeStack *pDns = pDni->pDns;
u32 nI;
for(nI=pDni->nDnsDepth; --nI; ) {
//s32 nIdx = pDns-pDebugLastNodeStackAlloc; // unused
dbg_output(MyOSReport("%d,", nIdx));
if ((u32)pDns==0xbaadf00d) {
WFSKrnOutputErrorStr("DirNodeStack Error! Bad entry!\n");
}
DirNodeStack *pDns2 = pDns;
u32 nJ;
for(nJ=nI; --nJ; ) {
pDns2 = pDns2->pParent;
if (pDns2 == pDns) {
WFSKrnOutputErrorStr("DirNodeStack Error! Same entry appears twice!\n");
}
}
//u32 nOfs = pDns->nSubBlkOfs; // unused
//u32 nBlkAdr = pDns->nBlkAdr;
pDns = pDns->pParent;
/*if ((nI>1) && (pDns->nSubBlkOfs == nOfs) && (pDns->nBlkAdr == nBlkAdr)) {
WFSKrnOutputErrorStr("DirNodeStack Error! Same offset repeats!\n");
}*/
}
dbg_output(MyOSReport(": "));
}
void DirNodeStackCheckFreeList() {
nDebugCountNodeStackCheckFreeList++;
DirNodeStack *pDns = dnsg.pDnsPoolFreeList;
u32 nI;
for(nI=0; nI<dnsg.nNumFreeDnsPoolEntries; nI++) {
//s32 nIdx = pDns-pDebugLastNodeStackAlloc; // unused
dbg_output(MyOSReport("%d,", nIdx));
if ((u32)pDns==0xbaadf00d) {
WFSKrnOutputErrorStr("DirNodeStack Error! Bad entry on free list!\n");
}
DirNodeStack *pDns2 = dnsg.pDnsPoolFreeList;
u32 nJ;
for(nJ=0; nJ<nI; nJ++) {
if (pDns2 == pDns) {
WFSKrnOutputErrorStr("DirNodeStack Error! Same entry appears twice on free list!\n");
}
pDns2 = pDns2->pParent;
}
pDns = pDns->pParent;
}
dbg_output(MyOSReport("\n"));
//WFSKrnHeapFree(&wkg.heap, ppDns);
}
#endif //_DEBUG_DIR_NODE_STACK
WFSKrnResult DirAllocateMoreNodeStackEntries() {
dnsg.pDnsPoolFreeList = (DirNodeStack *)WFSKrnHeapAlloc(&wkg.heap, WFS_DIR_NODE_STACK_ENTRY_POOL_ALLOC_UNIT * sizeof(DirNodeStack));
dbg_check(pDebugLastNodeStackAlloc = dnsg.pDnsPoolFreeList);
if (dnsg.pDnsPoolFreeList == 0) {
return WFSKRN_RESULT_OUT_OF_MEMORY;
}
u32 nI;
for(nI=0; nI<WFS_DIR_NODE_STACK_ENTRY_POOL_ALLOC_UNIT-1; nI++) {
dnsg.pDnsPoolFreeList[nI].pParent = &dnsg.pDnsPoolFreeList[nI+1];
}
dbg_check(dnsg.nTotalAllocated += WFS_DIR_NODE_STACK_ENTRY_POOL_ALLOC_UNIT);
dnsg.nNumFreeDnsPoolEntries += WFS_DIR_NODE_STACK_ENTRY_POOL_ALLOC_UNIT;
return WFSKRN_RESULT_OK;
}
#if _DEBUG_DIR_NODE_STACK
static u32 nDebugDirNodeStackGetEntryCount=0;
WFSKrnResult _DirNodeStackGetEntry(char *sFile, u32 nLine, DirNodeItr *pDni) {
++nDebugDirNodeStackGetEntryCount;
++dnsg.nNumUsed;
if (bCheckDirNodeStack)
MyOSReport("Dns:%d, %s Ln:%d GetEntry\n", dnsg.nNumUsed, sFile, nLine);
#else
WFSKrnResult DirNodeStackGetEntry(DirNodeItr *pDni) {
#endif
WFSKrnLockMutex(&dnsg.mxMutex);
if ((s32)dnsg.nNumFreeDnsPoolEntries<=0) {
if ((s32)dnsg.nNumFreeDnsPoolEntries<0) {
WFSKrnOutputErrorStr("nNumFreeDnsPoolEntries < 0");
}
WFSKrnReturnOnError(DirAllocateMoreNodeStackEntries());
}
--dnsg.nNumFreeDnsPoolEntries;
DirNodeStack *pNewDnsEntry = dnsg.pDnsPoolFreeList;
dnsg.pDnsPoolFreeList = dnsg.pDnsPoolFreeList->pParent;
WFSKrnUnlockMutex(&dnsg.mxMutex);
pNewDnsEntry->pParent = pDni->pDns;
pDni->pDns = pNewDnsEntry;
++pDni->nDnsDepth;
#if _DEBUG_DIR_NODE_STACK
if (bCheckDirNodeStack) {
dbg_output(MyOSReport("GetEntry: "));
DirNodeStackCheckAlloc(pDni);
DirNodeStackCheckFreeList();
}
#endif
return WFSKRN_RESULT_OK;
}
#if _DEBUG_DIR_NODE_STACK
void _DirNodeStackFree(char *sFile, u32 nLine, DirNodeItr *pDni, DirNodeStack **ppParent) {
dnsg.nNumUsed -= pDni->nDnsDepth;
if (bCheckDirNodeStack)
MyOSReport("Dns:%d, %s Ln:%d Free\n", dnsg.nNumUsed, sFile, nLine);
if (bCheckDirNodeStack) {
dbg_output(MyOSReport("StackFree(%d) { ", pDni->nDnsDepth));
DirNodeStackCheckAlloc(pDni);
DirNodeStackCheckFreeList();
}
#else
void DirNodeStackFree(DirNodeItr *pDni, DirNodeStack **ppParent) {
#endif
WFSKrnLockMutex(&dnsg.mxMutex);
dnsg.nNumFreeDnsPoolEntries += pDni->nDnsDepth;
*ppParent = dnsg.pDnsPoolFreeList;
dnsg.pDnsPoolFreeList = pDni->pDns;
WFSKrnUnlockMutex(&dnsg.mxMutex);
#if _DEBUG_DIR_NODE_STACK
if (bCheckDirNodeStack) {
dbg_output(MyOSReport("} StackFree: "));
DirNodeStackCheckAlloc(pDni);
DirNodeStackCheckFreeList();
}
#endif
}
#if _DEBUG_DIR_NODE_STACK
WFSKrnResult _DirPushNodeStackEntry(char *sFile, u32 nLine, DirNodeItr *pDni, WFSBlkAdr nBlkAdr) {
++dnsg.nNumUsed;
if (bCheckDirNodeStack)
MyOSReport("Dns:%d, %s Ln:%d Push\n", dnsg.nNumUsed, sFile, nLine);
#if _DEBUG_DIR
if (nDirTest == nDirTestBreakPoint) {
int a; a=0;
}
#endif
#else
WFSKrnResult DirPushNodeStackEntry(DirNodeItr *pDni, WFSBlkAdr nBlkAdr) {
#endif
#if _DEBUG_BREAK_POINT
static int c=0; c++; if(c == 2601){
int a; a=0;
}
if( pDni->pDns->nBlkAdr == nBlkAdr && pDni->pDns->nSubBlkOfs == *pDni->pOfs ){
int a; a=0;
}
#endif
WFSKrnLockMutex(&dnsg.mxMutex);
if (dnsg.nNumFreeDnsPoolEntries==0) {
WFSKrnUnlockMutex(&dnsg.mxMutex);
WFSKrnReturnOnError(DirAllocateMoreNodeStackEntries());
WFSKrnLockMutex(&dnsg.mxMutex);
}
--dnsg.nNumFreeDnsPoolEntries;
DirNodeStack *pNewDnsEntry = dnsg.pDnsPoolFreeList;
#if _WIN32
if ((u32)dnsg.pDnsPoolFreeList == 0xbaadf00d) {
WFSKrnOutputErrorStr("Bad Node Stack Entry");
}
#endif
dnsg.pDnsPoolFreeList = dnsg.pDnsPoolFreeList->pParent;
pNewDnsEntry->pParent = pDni->pDns;
pDni->pDns = pNewDnsEntry;
++pDni->nDnsDepth;
WFSKrnUnlockMutex(&dnsg.mxMutex);
pNewDnsEntry->nBlkAdr = nBlkAdr;
pNewDnsEntry->nSubBlkOfs = *pDni->pOfs;
//}
pNewDnsEntry->nEntryIdx = (u8)pDni->nEntryIdx;
#if _DEBUG_DIR_NODE_STACK
if (bCheckDirNodeStack) {
dbg_output(MyOSReport("PushEntry: "));
DirNodeStackCheckAlloc(pDni);
DirNodeStackCheckFreeList();
}
#endif
return WFSKRN_RESULT_OK;
}
#if _DEBUG_DIR_NODE_STACK
void _DirPopNodeStackEntry(char *sFile, u32 nLine, DirNodeItr *pDni) {
--dnsg.nNumUsed;
if (bCheckDirNodeStack)
MyOSReport("Dns:%d, %s Ln:%d Pop\n", dnsg.nNumUsed, sFile, nLine);
#else
void DirPopNodeStackEntry(DirNodeItr *pDni) {
#endif
WFSKrnLockMutex(&dnsg.mxMutex);
DirNodeStack *pNewFreeEntry = pDni->pDns;
pDni->pDns = pNewFreeEntry->pParent;
pNewFreeEntry->pParent = dnsg.pDnsPoolFreeList;
dnsg.pDnsPoolFreeList = pNewFreeEntry;
--pDni->nDnsDepth;
++dnsg.nNumFreeDnsPoolEntries;
#if _DEBUG_DIR_NODE_STACK
if (bCheckDirNodeStack) {
dbg_output(MyOSReport("PopEntry: "));
DirNodeStackCheckAlloc(pDni);
DirNodeStackCheckFreeList();
}
#endif
WFSKrnUnlockMutex(&dnsg.mxMutex);
}
void DirConstructEntryNameFromNodeStack(WFSFileName *pKey, DirItr *pDi) {
// This function parses the node stack constructing the key name
// ToDo: This function simply concatenates the strings from SubBlks,
// but it should take account of the adjustment needed between blocks
#if (_DEBUG_DIR && _DEBUG_DIR_NODE_STACK)
if (nDirTest == nDirTestBreakPoint) {
int a; a=0;
}
#endif
DirBlkHdr *pBlkHdr = pDi->pBlkHdr;
DirNodeStack *pDns = pDi->dni.pDns;
u32 nI=pDi->dni.nDnsDepth;
pKey->nLen = pDns->nStrIdx;//nStrLen-1;
utf8 *pStr = pKey->sStr;
// Trace back through the leaf
u32 nMinStrIdx = WFS_MAX_FILE_NAME_SIZE;
do {
DirSubBlkHdr *pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + pDns->nSubBlkOfs);
nMinStrIdx = (u32)(pDns->nStrIdx - pSubBlkHdr->nStrLen);
pStr[pDns->nStrIdx] = pSubBlkHdr->aFirstChar[pSubBlkHdr->nStrLen + pDns->nEntryIdx-1];
memcpy(&pStr[nMinStrIdx], pSubBlkHdr->aFirstChar, pSubBlkHdr->nStrLen);
if (0 == --nI) {
return;
}
pDns = pDns->pParent;
} while (pDi->tba.nBlkAdr == pDns->nBlkAdr);
// Trace back through nodes
#if (DIR_PREFIX_SUPPRESSION)
pDi->tba.nBlkAdr = pDns->nBlkAdr;
#if AREA_ENABLE_BLK_CACHE
AreaBlkMap(pDi->tba.pAreaInfo, pDi->tba.nBlkAdr, TRUE, TRUE, TRUE, (void**) &pBlkHdr);
#else
TransGetAndPinBlk(&pDi->tba, &pBlkHdr);
#endif
while(nMinStrIdx) {
DirSubBlkHdr *pSubBlkHdr = (DirSubBlkHdr *)((u8*)pBlkHdr + pDns->nSubBlkOfs);
utf8 cChoiceChar = pSubBlkHdr->aFirstChar[pSubBlkHdr->nStrLen + pDns->nEntryIdx-1];
if (pDns->nStrIdx <= nMinStrIdx) {
if (pDns->nStrIdx < nMinStrIdx) {
pStr[pDns->nStrIdx] = cChoiceChar;
}
memcpy(&pStr[pDns->nStrIdx - pSubBlkHdr->nStrLen], pSubBlkHdr->aFirstChar, pSubBlkHdr->nStrLen);
nMinStrIdx = pDns->nStrIdx;
}
if (0 == --nI) {
return;
}
pDns = pDns->pParent;
if (pDi->tba.nBlkAdr != pDns->nBlkAdr) {
pDi->tba.nBlkAdr = pDns->nBlkAdr;
#if AREA_ENABLE_BLK_CACHE
AreaBlkUnpin(pDi->tba.pAreaInfo, pDi->tba.nBlkAdr);
AreaBlkMap(pDi->tba.pAreaInfo, pDns->nBlkAdr, TRUE, TRUE, TRUE, (void**) &pBlkHdr);
#else
TransGetAndPinBlk(&pDi->tba, &pBlkHdr);
#endif
}
}
#if AREA_ENABLE_BLK_CACHE
AreaBlkUnpin(pDi->tba.pAreaInfo, pDi->tba.nBlkAdr);
#endif
#endif
}
#if _DEBUG_DIR_NODE_STACK
void _DirNodeStackCheckEmpty() {
if (dnsg.nNumUsed != 0) {
WFSKrnOutputErrorStr("Dir Node Stack Not Empty");
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,937 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_EPTree.cpp
Copyright 2007-2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_EPTree.cpp,v $
Revision 1.5 2008/12/18 08:53:11 ueno
Refactoring to avoid recursive call.
Revision 1.4 2008/12/17 05:06:49 ueno
Cleanup.
Revision 1.3 2008/12/15 04:14:40 ueno
Cleanup.
Revision 1.2 2008/12/15 02:40:07 ueno
Added support for multi p-tree.
Revision 1.1 2008/12/02 04:55:13 ueno
Added EPTree to support multi-PTree.
*---------------------------------------------------------------------------*/
#include "wfskrn_Area.h"
#include "wfskrn_FTree.h"
#include "wfskrn_FreeBlkAlloc.h"
#define ROUNDUP32BYTE(val) (((size_t)(val)+31)&~31)
#define ROUNDDOWN(val, unit) ((u32) (val) & ~((unit)-1))
#define ROUNDUP(val, unit) ((u32) ((val) + ((unit)-1)) & ~((unit)-1))
#define FBA_PTREE_MIN_HEIGHT 1
typedef struct _EPTreeChildInfo
{
EPTreeHdr* eptreeHdr;
u32 address;
u32 numEntries;
u32 subTreeType;
u32 firstKey;
} EPTreeChildInfo;
typedef struct _EPTreeSplitInfo
{
EPTreeChildInfo right;
EPTreeChildInfo left;
u32 splitKey;
u32 newChild;
u32 totalNumRecs;
} EPTreeSplitInfo;
EPTreeItr* EPTreeGetLastIter(MEPTreeItr* iter)
{
ASSERT(iter->eptreeHdr[0]);
u8 height = iter->eptreeHdr[0]->height;
EPTreeItr* last = &iter->epti[height-1];
return last;
}
static inline void AllocatorInit(PTreeAllocator* allocator, EPTreeHdr* eptreeHdr)
{
allocator->pBase = GET_BLOCK_HEAD(eptreeHdr);
allocator->fpAllocNode = FTreeAllocEntry;
allocator->fpAllocNodes = FTreeAllocEntries;
allocator->fpFreeNode = FTreeFreeEntry;
}
static WFSKrnResult GetAndPinEPTreeHdr(AreaInfo* area,
MEPTreeItr* iter, u32 level, WFSBlkAdr addr, u32 flags)
{
WFSKrnResult result = WFSKRN_RESULT_OK;
void* block;
if (level == 0)
{
// root ptree block is already pinned.
return WFSKRN_RESULT_OK;
}
if (iter->eptreeHdr[level] &&
iter->eptreeHdr[level]->addr == addr)
{
return WFSKRN_RESULT_OK;
}
if (iter->eptreeHdr[level])
{
ASSERT(iter->eptreeHdr[level]->addr != 0);
FBAUnpinCache(area, iter->eptreeHdr[level]->addr); // unpin old ptree block.
}
result = FBAGetCache(area, addr, flags, &block);
if (result == WFSKRN_RESULT_OK)
{
iter->eptreeHdr[level] = GET_EPTREEHDR(block);
ASSERT(iter->eptreeHdr[level]->addr == addr);
}
else
{
iter->eptreeHdr[level] = 0;
}
return result;
}
EPTreeHdr* EPTreeBlockInit(AreaInfo* area, void* block, WFSBlkAdr addr, u32 offset, u8 height)
{
EPTreeHdr* eptreeHdr;
FTreeSbaInit(area, block, sizeof(EPTreeHdr), offset);
eptreeHdr = GET_EPTREEHDR(block);
eptreeHdr->addr = addr;
eptreeHdr->height = height;
PTreeInit(&eptreeHdr->ptreeHdr, NULL); // 2nd argument is not used in PTreeInit().
return eptreeHdr; // keep pinning.
};
/*
* initial state.
[ToDo] update the figures.
disk address (FBA_ROOT_BLK). (PLeaf in 8kB)
+----------+
| sbaHdr |
+----------+
| PTreeHdr |--->PLeaf
+----------+ +---+---+---+---+
| PLeaf | | 0 | 0 | 0 | 0 |
+----------+ +---+---+---+---+
: : | 1 | ? | ? | ? |
: : +---+---+---+---+
| |
+----------+
disk address (FBA_INITIAL_FTREE_BLK)
+----------+
| sbaHdr |
+- - - - - +
| FTreeHdr |
+----------+
: empty :
: :
| |
+----------+
*/
WFSKrnResult EPTreeInit(AreaInfo* pAreaInfo, u32 offset)
{
WFSKrnResult result;
FTreeHdr* ftreeHdr;
EPTreeHdr* eptreeHdr;
void* cache;
void* eptreeBlock;
// FBA_ROOT_BLK is already pinned.
eptreeBlock = (u8*) pAreaInfo->pAflh - offset; // FBA_ROOT_BLK is already pinned.
eptreeHdr = EPTreeBlockInit(pAreaInfo, eptreeBlock, FBA_ROOT_BLK, ROUNDUP32BYTE(offset), FBA_PTREE_MIN_HEIGHT);
// create an F-tree block.
result = FBAGetCache(pAreaInfo, FBA_INITIAL_FTREE_BLK, BCACHE_FLAG_PINNED | BCACHE_FLAG_DIRTY, &cache);
if (result == WFSKRN_RESULT_OK)
{
PTreeAllocator allocator;
EPTreeItr epti;
ftreeHdr = FTreeBlockInit(pAreaInfo, cache);
BCacheUnpin(pAreaInfo->pVolInfo, pAreaInfo->nAbsStartBlkAdr + FBA_INITIAL_FTREE_BLK);
// +---+---+---+---+
// | 0 | 0 | 0 | 0 |
// +---+---+---+---+
// | 1 | ? | ? | ? |
// +---+---+---+---+
// A
// |
// FBA_INITIAL_FTREE_BLK
AllocatorInit(&allocator, eptreeHdr);
result = PTreeInsert(&eptreeHdr->ptreeHdr, &epti, 0, FBA_INITIAL_FTREE_BLK, &allocator);
WFSKRN_FTREE_ASSERT(result == WFSKRN_RESULT_OK);
}
// the EP-tree block is pinned.
return result;
}
WFSKrnResult EPTreeReinit(AreaInfo* pAreaInfo, u32 offset)
{
WFSKrnResult result;
EPTreeHdr* eptreeHdr;
void* eptreeBlock;
// FBA_ROOT_BLK is already pinned.
eptreeBlock = (u8*) pAreaInfo->pAflh - offset; // FBA_ROOT_BLK is already pinned.
eptreeHdr = EPTreeBlockInit(pAreaInfo, eptreeBlock, FBA_ROOT_BLK, ROUNDUP32BYTE(offset), FBA_PTREE_MIN_HEIGHT);
PTreeAllocator allocator;
EPTreeItr epti;
// +---+---+---+---+
// | 0 | 0 | 0 | 0 |
// +---+---+---+---+
// | 1 | ? | ? | ? |
// +---+---+---+---+
// A
// |
// FBA_INITIAL_FTREE_BLK
// FBA_INITIAL_FTREE_BLK is not initialized, because it may include some freeblocks.
AllocatorInit(&allocator, eptreeHdr);
result = PTreeInsert(&eptreeHdr->ptreeHdr, &epti, 0, FBA_INITIAL_FTREE_BLK, &allocator);
WFSKRN_FTREE_ASSERT(result == WFSKRN_RESULT_OK);
// the EP-tree block is pinned.
return result;
}
// determine the threshold block address.
static u32 GetSplitAddress(PTreeHdr* ptreeHdr, EPTreeItr* iter, PTreeAllocator* allocator)
{
WFSKrnResult result;
u32 halfNumRecs = ptreeHdr->nNumRecs / 2;
result = PTreeFirst(ptreeHdr, iter, allocator);
while (halfNumRecs--)
{
result = PTreeNext(ptreeHdr, iter, allocator);
ASSERT(result == WFSKRN_RESULT_OK);
}
return PTREE_GET_KEY(iter);
}
static WFSKrnResult GetNewControlBlock(AreaInfo* area, WFSBlkAdr nNGBlkAdr1, WFSBlkAdr nNGBlkAdr2, WFSBlkAdr nRefBlkAdr, FTreeExtent* extent, u32* subTreeIdx)
{
WFSKrnResult result = WFSKRN_RESULT_NOT_FOUND;
FBATreeItr iter;
FBAItrOpen(area, &iter);
u32 idx;
for (idx = FTREE_TYPE_A; idx < MAX_SUB_TREE; ++idx)
{
result = FreeBlkFind(area, &iter, nRefBlkAdr, FTreeBlkLog2Ofs[idx]);
while ((result == WFSKRN_RESULT_OK) &&
(nNGBlkAdr1 == FBA_RESULT_KEY(&iter) ||
nNGBlkAdr2 == FBA_RESULT_KEY(&iter)))
{
result = FreeBlkPrev(area, &iter);
}
if (result == WFSKRN_RESULT_OK)
{
extent->start = FBA_RESULT_KEY(&iter);
extent->len = (FBA_RESULT_DATA(&iter) + 1) * (1<<FTreeBlkLog2Ofs[idx]);
*subTreeIdx = idx;
break;
}
}
FBAItrClose(area, &iter);
return result;
}
static EPTreeHdr* ControlBlockInit(AreaInfo* area, u32 addr, u8 height)
{
void* pBlock;
EPTreeHdr* eptreeHdr;
WFSKrnResult result;
result = FBAGetCache(area, addr, BCACHE_FLAG_DIRTY | BCACHE_FLAG_PINNED, &pBlock);
ASSERT(result == WFSKRN_RESULT_OK);
u32 offset = (sizeof(WFSHashCode) + sizeof(WFSMetaDataHdr));
EPTreeBlockInit(area, pBlock, addr, offset, height);
eptreeHdr = GET_EPTREEHDR(pBlock);
eptreeHdr->addr = addr;
return eptreeHdr;
}
// allocate 2 blocks. (must not remove them from FBA tree, because it may cause another p-tree splitting.)
static WFSKrnResult SplitTreeInit(AreaInfo* area, EPTreeHdr* eptreeHdr, EPTreeSplitInfo* info, PTreeAllocator* allocator)
{
EPTreeItr iter;
WFSKrnResult result;
FTreeExtent newCb;
u32 subTreeIdxNewCb;
// choose split key.
info->splitKey = GetSplitAddress(&eptreeHdr->ptreeHdr, &iter, allocator);
result = GetNewControlBlock(area, 0 /* no NG address */, 0 /* no NG address */,
info->splitKey, &newCb, &subTreeIdxNewCb);
ASSERT(result == WFSKRN_RESULT_OK);
info->left.address = newCb.start;
info->left.subTreeType = subTreeIdxNewCb;
if (newCb.len == 1)
{
result = GetNewControlBlock(area, info->left.address, 0, newCb.start + 1, &newCb, &subTreeIdxNewCb);
ASSERT(result == WFSKRN_RESULT_OK);
info->right.address = newCb.start;
}
else
{
info->right.address = info->left.address + 1;
}
info->right.subTreeType = subTreeIdxNewCb;
// height field is only used by root ptree block.
info->left.eptreeHdr = ControlBlockInit(area, info->left.address, eptreeHdr->height);
info->right.eptreeHdr = ControlBlockInit(area, info->right.address, eptreeHdr->height);
return WFSKRN_RESULT_OK;
}
static WFSKrnResult CreateChildBlocks(AreaInfo* area, EPTreeSplitInfo* info, PTreeHdr* ptreeHdr, PTreeAllocator* allocatorParent)
{
WFSKrnResult result;
PTreeAllocator allocator;
PTreeItr ptiSearch;
PTreeItr ptiInsert;
// insert to left child.
result = PTreeFirst(ptreeHdr, &ptiSearch, allocatorParent);
ASSERT(result == WFSKRN_RESULT_OK);
AllocatorInit(&allocator, info->left.eptreeHdr); // [ToDo] single ptree.
info->left.firstKey = PTREE_GET_KEY(&ptiSearch);
int count = ptreeHdr->nNumRecs;
while ((int) (ptreeHdr->nNumRecs - ptreeHdr->nNumRecs / 2) < count)
{
ASSERT(PTREE_GET_KEY(&ptiSearch) < info->splitKey);
result = PTreeInsert(&info->left.eptreeHdr->ptreeHdr, &ptiInsert,
PTREE_GET_KEY(&ptiSearch), PTREE_GET_DATA(&ptiSearch), &allocator);
if (result != WFSKRN_RESULT_OK)
{
ASSERT(result == WFSKRN_RESULT_OK);
goto ERROR_CREATECHILDBLOCKS;
}
result = PTreeNext(ptreeHdr, &ptiSearch, allocatorParent);
if (result != WFSKRN_RESULT_OK)
{
ASSERT(result == WFSKRN_RESULT_OK);
goto ERROR_CREATECHILDBLOCKS;
}
--count;
}
ASSERT(result == WFSKRN_RESULT_OK);
// insert to right child.
info->right.firstKey = PTREE_GET_KEY(&ptiSearch);
AllocatorInit(&allocator, info->right.eptreeHdr); // [ToDo] single ptree.
while (0 < count)
{
ASSERT(info->splitKey <= PTREE_GET_KEY(&ptiSearch));
result = PTreeInsert(&info->right.eptreeHdr->ptreeHdr, &ptiInsert,
PTREE_GET_KEY(&ptiSearch), PTREE_GET_DATA(&ptiSearch), &allocator);
if (result != WFSKRN_RESULT_OK)
{
ASSERT(result == WFSKRN_RESULT_OK);
goto ERROR_CREATECHILDBLOCKS;
}
if (--count == 0)
{
break;
}
ASSERT(result == WFSKRN_RESULT_OK);
result = PTreeNext(ptreeHdr, &ptiSearch, allocatorParent);
if (result != WFSKRN_RESULT_OK)
{
ASSERT(result == WFSKRN_RESULT_OK);
goto ERROR_CREATECHILDBLOCKS;
}
}
ERROR_CREATECHILDBLOCKS:
return result;
}
static inline WFSBool IsRootBlock(AreaInfo* area, EPTreeHdr* eptreeHdr)
{
FBATreeHdr* fbaTreeHdr = GET_FBATREE_HDR(area);
return ((u32) (eptreeHdr->height) == fbaTreeHdr->ptreeHeight);
}
static WFSKrnResult InsertToParentBlocks(AreaInfo* area, EPTreeHdr* eptreeHdr, EPTreeSplitInfo* info)
{
WFSKrnResult result;
EPTreeHdr* tempEptreeHdr;
PTreeItr pti;
PTreeAllocator allocator;
if (IsRootBlock(area, eptreeHdr) == (WFSBool) TRUE)
{
u32 offset;
u32 subTreeIdxTempCb;
u32 originalAddr;
FBATreeHdr* fbaTreeHdr = GET_FBATREE_HDR(area);
FTreeExtent tempCb;
// create a new level.
++fbaTreeHdr->ptreeHeight;
ASSERT(fbaTreeHdr->ptreeHeight <= EPTREE_MAX_HEIGHT);
result = GetNewControlBlock(area, info->left.address, info->right.address,
1, &tempCb, &subTreeIdxTempCb);
ASSERT(result == WFSKRN_RESULT_OK);
tempEptreeHdr = ControlBlockInit(area, tempCb.start, (u8) (fbaTreeHdr->ptreeHeight));
// copy original parent ptree.
memmove((u8*) GET_BLOCK_FROM_EPTREEHDR(tempEptreeHdr), GET_BLOCK_FROM_EPTREEHDR(eptreeHdr), area->nBlkSize);
// clear all entries
offset = eptreeHdr->sbaHdr.offset;
EPTreeBlockInit(area, GET_BLOCK_FROM_EPTREEHDR(tempEptreeHdr), tempCb.start, offset, (u8) (fbaTreeHdr->ptreeHeight));
// insert child blocks into the parent.
AllocatorInit(&allocator, tempEptreeHdr);
result = PTreeInsert(&tempEptreeHdr->ptreeHdr, &pti, info->left.firstKey, info->left.address, &allocator);
ASSERT(result == WFSKRN_RESULT_OK);
result = PTreeInsert(&tempEptreeHdr->ptreeHdr, &pti, info->right.firstKey, info->right.address, &allocator);
ASSERT(result == WFSKRN_RESULT_OK);
originalAddr = eptreeHdr->addr;
memmove(GET_BLOCK_FROM_EPTREEHDR(eptreeHdr), GET_BLOCK_FROM_EPTREEHDR(tempEptreeHdr), area->nBlkSize); // remap
eptreeHdr->addr = originalAddr;
FBAFreeCache(area, tempCb.start); // unpin the temporary parent block.
}
else
{
// insert the split key into the parent block.
AllocatorInit(&allocator, eptreeHdr);
result = PTreeInsert(&eptreeHdr->ptreeHdr, &pti, info->splitKey, 1, &allocator);
}
// remove left and right child blocks from the FBA tree.
return result;
}
static WFSKrnResult EPTreeSplit(AreaInfo* area, MEPTreeItr* iter, EPTreeHdr* eptreeHdr, EPTreeSplitInfo* info)
{
WFSKrnResult result;
PTreeAllocator allocator;
if (EPTREE_MAX_HEIGHT == iter->eptreeHdr[0]->height)
{
return WFSKRN_RESULT_RESOURCE_LIMIT_EXCEEDED;
}
AllocatorInit(&allocator, eptreeHdr);
result = SplitTreeInit(area, eptreeHdr, info, &allocator);
if (result != WFSKRN_RESULT_OK)
{
return result;
}
// split the original block to two children.
result = CreateChildBlocks(area, info, &eptreeHdr->ptreeHdr, &allocator);
FBAUnpinCache(area, info->left.address);
FBAUnpinCache(area, info->right.address);
if (result != WFSKRN_RESULT_OK)
{
return result;
}
// create new parent block and remap it to the original block.
result = InsertToParentBlocks(area, eptreeHdr, info);
if (result == WFSKRN_RESULT_OK)
{
FBATreeItr iterDelete;
FBAItrOpen(area, &iterDelete);
iterDelete.fti.subTree = FTreeSelectSubTree(iterDelete.ftreeHdr, info->left.subTreeType);
// remove child block address from the FBA tree.
result = FreeBlkDelete(area, &iterDelete,
info->left.address, 1, FTreeBlkLog2Ofs[info->left.subTreeType]);
ASSERT(result == WFSKRN_RESULT_OK);
iterDelete.fti.subTree = FTreeSelectSubTree(iterDelete.ftreeHdr, info->right.subTreeType);
result = FreeBlkDelete(area, &iterDelete,
info->right.address, 1, FTreeBlkLog2Ofs[info->right.subTreeType]);
ASSERT(result == WFSKRN_RESULT_OK);
FBAItrClose(area, &iterDelete);
}
return result;
}
WFSKrnResult EPTreeFirst(AreaInfo* area, MEPTreeItr* iter)
{
WFSKrnResult result;
PTreeAllocator allocator;
int level;
u8 ptreeHeight;
AllocatorInit(&allocator, iter->eptreeHdr[0]);
result = PTreeFirst(&iter->eptreeHdr[0]->ptreeHdr, (PTreeItr*) &iter->epti[0], &allocator);
ptreeHeight = iter->eptreeHdr[0]->height;
for (level = 1; level < ptreeHeight; ++level)
{
if (result != WFSKRN_RESULT_OK)
{
break;
}
result = GetAndPinEPTreeHdr(area, iter, level,
EPTREE_GET_DATA(&iter->epti[level-1]), BCACHE_FLAG_READ | BCACHE_FLAG_PINNED);
if (result != WFSKRN_RESULT_OK)
{
break;
}
AllocatorInit(&allocator, iter->eptreeHdr[level]);
result = PTreeFirst(&iter->eptreeHdr[level]->ptreeHdr, (PTreeItr*) &iter->epti[level], &allocator);
}
return result;
}
WFSKrnResult EPTreeLast(AreaInfo* area, MEPTreeItr* iter)
{
WFSKrnResult result;
PTreeAllocator allocator;
int level;
u8 ptreeHeight;
AllocatorInit(&allocator, iter->eptreeHdr[0]);
result = PTreeLast(&iter->eptreeHdr[0]->ptreeHdr, (PTreeItr*) &iter->epti[0], &allocator);
ptreeHeight = iter->eptreeHdr[0]->height;
for (level = 1; level < ptreeHeight; ++level)
{
if (result != WFSKRN_RESULT_OK)
{
break;
}
result = GetAndPinEPTreeHdr(area, iter, level,
EPTREE_GET_DATA(&iter->epti[level-1]), BCACHE_FLAG_READ | BCACHE_FLAG_PINNED);
if (result != WFSKRN_RESULT_OK)
{
break;
}
AllocatorInit(&allocator, iter->eptreeHdr[level]);
result = PTreeLast(&iter->eptreeHdr[level]->ptreeHdr, (PTreeItr*) &iter->epti[level], &allocator);
}
return result;
}
WFSKrnResult EPTreeNext(AreaInfo* area, MEPTreeItr* iter)
{
WFSKrnResult result = WFSKRN_RESULT_PTREE_ENTRY_NOT_FOUND;
PTreeAllocator allocator;
EPTreeHdr* eptreeHdr;
u8 ptreeHeight = iter->eptreeHdr[0]->height;
eptreeHdr = iter->eptreeHdr[ptreeHeight-1];
AllocatorInit(&allocator, eptreeHdr);
result = PTreeNext(&eptreeHdr->ptreeHdr, (PTreeItr*) &iter->epti[ptreeHeight-1], &allocator);
if (result == WFSKRN_RESULT_PTREE_ENTRY_FOUND)
{
return result;
}
// go back and lookup an entry in the next node.
int level = ptreeHeight;
while (result == WFSKRN_RESULT_PTREE_ENTRY_NOT_FOUND && --level)
{
eptreeHdr = iter->eptreeHdr[level-1];
AllocatorInit(&allocator, eptreeHdr);
result = PTreeNext(&eptreeHdr->ptreeHdr, (PTreeItr*) &iter->epti[level-1], &allocator);
}
if (result == WFSKRN_RESULT_OK)
{
for (;level < ptreeHeight; ++level)
{
result = GetAndPinEPTreeHdr(area, iter, level,
EPTREE_GET_DATA(&iter->epti[level-1]), BCACHE_FLAG_READ | BCACHE_FLAG_PINNED);
if (result != WFSKRN_RESULT_OK)
{
break;
}
eptreeHdr = iter->eptreeHdr[level];
AllocatorInit(&allocator, eptreeHdr);
result = PTreeFirst(&eptreeHdr->ptreeHdr, (PTreeItr*) &iter->epti[level], &allocator);
if (result != WFSKRN_RESULT_OK)
{
break;
}
}
}
return result;
}
WFSKrnResult EPTreePrev(AreaInfo* area, MEPTreeItr* iter)
{
WFSKrnResult result = WFSKRN_RESULT_PTREE_ENTRY_NOT_FOUND;
PTreeAllocator allocator;
EPTreeHdr* eptreeHdr;
u8 ptreeHeight = iter->eptreeHdr[0]->height;
eptreeHdr = iter->eptreeHdr[ptreeHeight-1];
AllocatorInit(&allocator, eptreeHdr);
result = PTreePrev(&eptreeHdr->ptreeHdr, (PTreeItr*) &iter->epti[ptreeHeight-1], &allocator);
if (result == WFSKRN_RESULT_PTREE_ENTRY_FOUND)
{
return result;
}
// go back and lookup an entry in the next node.
int level = ptreeHeight;
while (result == WFSKRN_RESULT_PTREE_ENTRY_NOT_FOUND && --level)
{
eptreeHdr = iter->eptreeHdr[level-1];
AllocatorInit(&allocator, eptreeHdr);
result = PTreePrev(&eptreeHdr->ptreeHdr, (PTreeItr*) &iter->epti[level-1], &allocator);
}
if (result == WFSKRN_RESULT_OK)
{
for (;level < ptreeHeight; ++level)
{
result = GetAndPinEPTreeHdr(area, iter, level,
EPTREE_GET_DATA(&iter->epti[level-1]), BCACHE_FLAG_READ | BCACHE_FLAG_PINNED);
if (result != WFSKRN_RESULT_OK)
{
break;
}
eptreeHdr = iter->eptreeHdr[level];
AllocatorInit(&allocator, eptreeHdr);
result = PTreeLast(&eptreeHdr->ptreeHdr, (PTreeItr*) &iter->epti[level], &allocator);
if (result != WFSKRN_RESULT_OK)
{
break;
}
}
}
return result;
}
static WFSKrnResult EPTreeInsertWithoutSplitting(AreaInfo* area, MEPTreeItr* iter, u32 key, u32 data)
{
WFSKrnResult result;
EPTreeHdr* eptreeHdr;
EPTreeItr* epti;
PTreeAllocator allocator;
u8 height;
result = EPTreeFind(area, iter, key);
if (result == WFSKRN_RESULT_OK)
{
return WFSKRN_RESULT_ALREADY_EXISTS;
}
if (result != WFSKRN_RESULT_PTREE_ENTRY_NOT_FOUND)
{
return result;
}
height = iter->eptreeHdr[0]->height;
epti = &iter->epti[height-1];
eptreeHdr = iter->eptreeHdr[height-1];
AllocatorInit(&allocator, eptreeHdr);
result = PTreeInsert(&eptreeHdr->ptreeHdr, (PTreeItr*) epti, key, data, &allocator);
return result;
}
WFSKrnResult EPTreeInsert(AreaInfo* area, MEPTreeItr* iter, u32 key, u32 data)
{
WFSKrnResult result;
while (WFSKRN_RESULT_PTREE_FULL == (result = EPTreeInsertWithoutSplitting(area, iter, key, data)))
{
EPTreeSplitInfo info;
result = EPTreeSplit(area, (MEPTreeItr*) iter, iter->eptreeHdr[0], &info);
if (result != WFSKRN_RESULT_OK)
{
#ifdef _DEBUG
OS_TPrintf("*** EPTreeInsert(): split error (%d) ***\n", result);
#endif // _DEBUG
ASSERT(result == WFSKRN_RESULT_OK ||
result == WFSKRN_RESULT_DIRECTORY_QUOTA);
break;
}
}
return result;
}
static WFSKrnResult DelteEmptyBlocks(AreaInfo* area, MEPTreeItr* iter, WFSBlkAdr* freeBlks)
{
WFSKrnResult result = WFSKRN_RESULT_OK;
EPTreeHdr* eptreeHdr;
EPTreeItr* epti;
PTreeAllocator allocator;
WFSBlkAdr addr;
int level;
int height = (int) iter->eptreeHdr[0]->height;
for (level = height - 2; 0 <= level; --level)
{
eptreeHdr = iter->eptreeHdr[level];
epti = &iter->epti[level];
addr = EPTREE_GET_DATA(epti);
AllocatorInit(&allocator, eptreeHdr);
result = PTreeDelete(&eptreeHdr->ptreeHdr, (PTreeItr*) epti, &allocator);
if (result != WFSKRN_RESULT_OK)
{
break;
}
iter->eptreeHdr[level+1] = 0;
FBAFreeCache(area, addr);
freeBlks[level] = addr; // save to insert it into FBA tree, later.
if (0 < eptreeHdr->ptreeHdr.nNumRecs)
{
break;
}
}
return result;
}
WFSKrnResult EPTreeShrink(AreaInfo* area, MEPTreeItr* iter, WFSBlkAdr* freeBlks)
{
WFSKrnResult result = EPTreeLast(area, iter);
if (result == WFSKRN_RESULT_OK)
{
u32 height = (u32) iter->eptreeHdr[0]->height;
EPTreeItr* epti = EPTreeGetLastIter(iter);
if (EPTREE_GET_DATA(epti) == FBA_INITIAL_FTREE_BLK &&
EPTREE_GET_KEY(epti) == 0)
{
MEPTreeItr iterInsert;
iterInsert.eptreeHdr[0] = GET_EPTREEHDR_FROM_AREAINFO(area);
u32 level;
for (level = 1; level < EPTREE_MAX_HEIGHT; ++level)
{
iterInsert.eptreeHdr[level] = 0;
}
FBATreeHdr* fbaTreeHdr = GET_FBATREE_HDR(area);
fbaTreeHdr->ptreeHeight = 1;
u32 offset = area->nBlkSize - GET_FBATREE_HDR(area)->ofsEPtreeHdr - sizeof(EPTreeHdr);
EPTreeReinit(area, ROUNDUP32BYTE(offset));
for (level = 0; level < (int) height; ++level)
{
u32 addr = iter->epti[level].nData;
if (addr != FBA_INITIAL_FTREE_BLK)
{
FBAFreeCache(area, addr);
freeBlks[level + (EPTREE_MAX_HEIGHT-1)] = addr;
}
}
}
}
return result;
}
WFSKrnResult EPTreeDelete(AreaInfo* area, MEPTreeItr* iter, u32 key, WFSBlkAdr* freeBlks)
{
WFSKrnResult result;
EPTreeHdr* eptreeHdr;
PTreeAllocator allocator;
result = EPTreeFind(area, iter, key);
if (result == WFSKRN_RESULT_OK ||
result == WFSKRN_RESULT_PTREE_ENTRY_NOT_FOUND) // not found?
{
u8 height = iter->eptreeHdr[0]->height;
EPTreeItr* epti = &iter->epti[height-1];
eptreeHdr = iter->eptreeHdr[height-1];
AllocatorInit(&allocator, eptreeHdr);
result = PTreeDelete(&eptreeHdr->ptreeHdr, (PTreeItr*) epti, &allocator);
if (eptreeHdr->ptreeHdr.nNumRecs <= 1 && 2 <= height)
{
if (eptreeHdr->ptreeHdr.nNumRecs == 0)
{
result = DelteEmptyBlocks(area, iter, freeBlks);
if (result == WFSKRN_RESULT_OK)
{
result = EPTreeShrink(area, iter, freeBlks);
}
}
else if (epti->pLeaf->aKey[0] == 0 &&
epti->pLeaf->aData[0] == FBA_INITIAL_FTREE_BLK)
{
// eptreeHdr->ptreeHdr.nNumRecs == 1.
result = EPTreeShrink(area, iter, freeBlks);
}
}
}
return result;
}
// search a P-tree by key.
/*
P-tree node
+-----------------+
| P-Tree |
|key: 100 |
| |
+-----------------+
| |
p-tree leaf V V p-tree leaf
+-----------------+ +-----------------+
| P-Tree | | P-Tree |
|key: 80 96 | |key: 110 116 119 |
| | | |
+-----------------+ +-----------------+
A A A A
| | | |
(1) (2) (3) (4)
key result pPti->nKey
(1) 101 => WFSKRN_RESULT_NOT_FOUND - (no value is set).
(2) 110 => WFSKRN_RESULT_OK 110
(3) 118 => WFSKRN_RESULT_OK 116
(4) 120 => WFSKRN_RESULT_OK 119
*/
WFSKrnResult EPTreeFind(AreaInfo* area, MEPTreeItr* iter, u32 key)
{
WFSKrnResult result = WFSKRN_RESULT_PTREE_ENTRY_NOT_FOUND;
PTreeAllocator allocator;
EPTreeHdr* eptreeHdr;
EPTreeItr* epti;
int level;
u8 ptreeHeight = iter->eptreeHdr[0]->height;
for (level = 0; level < ptreeHeight; ++level)
{
eptreeHdr = iter->eptreeHdr[level];
AllocatorInit(&allocator, eptreeHdr);
result = PTreeFind(&eptreeHdr->ptreeHdr, (PTreeItr*) &iter->epti[level], key, &allocator);
epti = &iter->epti[level];
if (result == WFSKRN_RESULT_PTREE_ENTRY_NOT_FOUND)
{
if (iter->eptreeHdr[level]->ptreeHdr.nNumRecs == 0)
{
result = WFSKRN_RESULT_PTREE_EMPTY;
goto RESULT_EPTREEFIND;
}
else if (epti->aEntryIdx[0] == 0)
{
// the key is smaller than the minimum key in this P-tree.
result = EPTreePrev(area, iter);
if (result != WFSKRN_RESULT_OK)
{
result = WFSKRN_RESULT_NOT_FOUND;
goto RESULT_EPTREEFIND;
}
if (key == EPTREE_GET_KEY(epti))
{
result = WFSKRN_RESULT_PTREE_ENTRY_FOUND;
}
else
{
result = WFSKRN_RESULT_PTREE_ENTRY_NOT_FOUND;
}
}
else
{
// In this case, PTreeFind() saved the nearest key.
--epti->aEntryIdx[0];
}
}
if (result != WFSKRN_RESULT_PTREE_ENTRY_FOUND &&
result != WFSKRN_RESULT_PTREE_ENTRY_NOT_FOUND)
{
break;
}
epti->nKey = epti->pLeaf->aKey[epti->aEntryIdx[0]];
epti->nData = epti->pLeaf->aData[epti->aEntryIdx[0]];
if (level == ptreeHeight - 1)
{
// the bottom of multi EP-Tree.
break;
}
result = GetAndPinEPTreeHdr(area, iter, level + 1, EPTREE_GET_DATA(epti), BCACHE_FLAG_READ | BCACHE_FLAG_PINNED);
if (result != WFSKRN_RESULT_OK)
{
break;
}
}
if (result == WFSKRN_RESULT_PTREE_ENTRY_FOUND)
{
result = WFSKRN_RESULT_OK;
}
RESULT_EPTREEFIND:
return result;
}

View File

@ -0,0 +1,216 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_Errors.cpp
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Errors.cpp,v $
Revision 1.13 2008/09/28 23:32:04 kondo_masahiro
Fixed codes to use medium size user block.
Revision 1.12 2008/09/04 23:53:04 nakanose_jin
wfsdev has no pathcache.
Revision 1.11 2008/08/27 23:23:28 ooizumi
Fixed newline to CR+LF(Windows format).
Revision 1.10 2008/08/27 09:38:04 paul
Added error messages. small change to error output.
Revision 1.9 2008/07/11 18:04:54 paul
Updated to match latest error defs
Revision 1.8 2008/07/09 00:43:54 paul
Renamed some error messages. Added software breakpoint for nDbgCommandCount.
Revision 1.7 2008/07/02 06:34:57 nakanose_jin
temporary edit
Revision 1.6 2008/06/10 20:12:44 kondo_masahiro
Fixed WFSKrnCommandCountBreak.
Revision 1.5 2008/06/09 17:51:14 paul
Added support for logging calls to WFSSrv functions.
Added new error codes.
Revision 1.4 2008/05/10 03:59:34 kondo_masahiro
Merged and fixed code to accept RM compiler
Revision 1.3 2008/04/25 17:35:50 kondo_masahiro
Fixed log information
Revision 1.2 2008/04/25 12:07:44 nakanose_jin
add new errors
Revision 1.1 2008/04/22 04:39:08 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.7 2008/04/25 04:35:37 nakanose_jin
add new errors
Revision 1.6 2008/04/22 23:22:39 paul
Made errors match laters wfskrn_Errors.h
Revision 1.5 2008/04/19 05:50:45 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.4 2008/04/04 21:18:58 paul
Added \n to error message
Revision 1.3 2008/02/27 07:24:29 paul
Updated error strings
Revision 1.2 2008/02/27 00:37:24 paul
Fixed a typo
Revision 1.1 2008/02/21 00:49:14 paul
*** empty log message ***
*---------------------------------------------------------------------------*/
#include "wfskrn_Defs.h"
#include "wfskrn_Errors.h"
#if _DEBUG
u32 nDbgCommandCount = 0;
u32 nDbgCommandOutputStart = 0; //15520; //(u32)-1;
u32 nDbgCommandOutputEnd = (u32)-1;
u32 nDbgCommandCountBreak = (u32)-1;
#if _WIN32
FILE *fpLog;
#endif
#endif //_DEBUG
const char *WFSKrnGetErrorString( WFSKrnResult nResult ) {
const char *p;
switch(nResult) {
case WFSKRN_RESULT_OK :p="OK" ; break;
case WFSKRN_RESULT_BUSY :p="BUSY" ; break;
case WFSKRN_RESULT_OUT_OF_MEMORY :p="OUT_OF_MEMORY" ; break;
case WFSKRN_RESULT_INVALID :p="INVALID" ; break;
case WFSKRN_RESULT_ACCESS :p="ACCESS" ; break;
case WFSKRN_RESULT_LIB_NOT_INITIALIZED :p="LIB_NOT_INITIALIZED" ; break;
case WFSKRN_RESULT_LIB_ALREADY_INITIALIZED :p="LIB_ALREADY_INITIALIZED" ; break;
case WFSKRN_RESULT_FILE_TOO_BIG :p="FILE_TOO_BIG" ; break;
case WFSKRN_RESULT_NO_CHANGE_SIZE :p="NO_CHANGE_SIZE" ; break;
case WFSKRN_RESULT_MEDIA_ERROR :p="MEDIA_ERROR" ; break;
case WFSKRN_RESULT_DEV_UNUSABLE :p="DEV_UNUSABLE" ; break;
case WFSKRN_RESULT_DEV_NOT_INITIALIZED :p="DEV_NOT_INITIALIZED" ; break;
case WFSKRN_RESULT_DEV_IN_USE :p="DEV_IN_USE" ; break;
case WFSKRN_RESULT_VOL_ID_ERROR :p="VOL_ID_ERROR" ; break;
case WFSKRN_RESULT_WRITE_PROTECTED :p="WRITE_PROTECTED" ; break;
case WFSKRN_RESULT_ALREADY_MOUNTED :p="ALREADY_MOUNTED" ; break;
case WFSKRN_RESULT_PERMISSION :p="PERMISSION" ; break;
case WFSKRN_RESULT_PERMISSION_CL :p="PERMISSION_CL" ; break;
case WFSKRN_RESULT_ACL_FULL :p="ACL_FULL" ; break;
case WFSKRN_RESULT_ACL_ENTRY_NOT_FOUND :p="ACL_ENTRY_NOT_FOUND" ; break;
case WFSKRN_RESULT_AUTHENTICATION :p="AUTHENTICATION" ; break;
case WFSKRN_RESULT_CORRUPTION :p="CORRUPTION" ; break;
case WFSKRN_RESULT_DIRECTORY_QUOTA :p="DIRECTORY_QUOTA" ; break;
case WFSKRN_RESULT_MAX_HANDLES :p="MAX_HANDLES" ; break;
case WFSKRN_RESULT_ALREADY_EXISTS :p="ALREADY_EXISTS" ; break;
case WFSKRN_RESULT_NOT_FOUND :p="NOT_FOUND" ; break;
case WFSKRN_RESULT_NOT_EMPTY :p="NOT_EMPTY" ; break;
case WFSKRN_RESULT_NOT_FILE :p="NOT_FILE" ; break;
case WFSKRN_RESULT_NOT_DIRECTORY :p="NOT_DIRECTORY" ; break;
case WFSKRN_RESULT_FILE_OPEN :p="FILE_OPEN" ; break;
case WFSKRN_RESULT_LOCKED :p="LOCKED" ; break;
case WFSKRN_RESULT_RESOURCE_LIMIT_EXCEEDED :p="RESOURCE_LIMIT_EXCEEDED" ; break;
case WFSKRN_RESULT_DIR_ENTRY_FOUND :p="DIR_ENTRY_FOUND" ; break;
case WFSKRN_RESULT_DIR_NODE_STRING_PREFIX :p="DIR_NODE_STRING_PREFIX" ; break;
case WFSKRN_RESULT_DIR_CHOICE_PREFIX :p="DIR_CHOICE_PREFIX" ; break;
case WFSKRN_RESULT_DIR_NODE_STRING_MISMATCH :p="DIR_NODE_STRING_MISMATCH" ; break;
case WFSKRN_RESULT_DIR_NODE_CHOICE_NOT_FOUND :p="DIR_NODE_CHOICE_NOT_FOUND" ; break;
case WFSKRN_RESULT_DIR_BLK_FULL :p="DIR_BLK_FULL" ; break;
case WFSKRN_RESULT_SRV_END_OF_PATH :p="SRV_END_OF_PATH" ; break;
case WFSKRN_RESULT_SRV_PATH_DEPTH_1 :p="SRV_PATH_DEPTH_1" ; break;
case WFSKRN_RESULT_SRV_PATH_DEV :p="SRV_PATH_DEV" ; break;
case WFSKRN_RESULT_SRV_PATH_VOL :p="SRV_PATH_VOL" ; break;
case WFSKRN_RESULT_SRV_PATH_VOL_ROOT :p="SRV_PATH_VOL_ROOT" ; break;
case WFSKRN_RESULT_PTREE_ENTRY_FOUND :p="PTREE_ENTRY_FOUND" ; break;
case WFSKRN_RESULT_PTREE_ENTRY_NOT_FOUND :p="PTREE_ENTRY_NOT_FOUND" ; break;
case WFSKRN_RESULT_PTREE_FULL :p="PTREE_FULL" ; break;
case WFSKRN_RESULT_DEVICE_ERROR :p="DEVICE_ERROR" ; break;
case WFSKRN_RESULT_DEVICE_INVALID_PARAMETER :p="DEVICE_INVALID_PARAMETER" ; break;
case WFSKRN_RESULT_DEVICE_NOT_FOUND :p="DEVICE_INVALID_PARAMETER" ; break;
case WFSKRN_RESULT_BLK_CACHE_ALLOC_FAILED :p="BLK_CACHE_ALLOC_FAILED" ; break;
case WFSKRN_RESULT_BCACHE_ERROR :p="BCACHE_ERROR" ; break;
case WFSKRN_RESULT_BCACHE_RESOURCE_LIMIT :p="BCACHE_RESOURCE_LIMIT" ; break;
case WFSKRN_RESULT_BCACHE_INVALID_PARAMETER :p="BCACHE_INVALID_PARAMETER" ; break;
case WFSKRN_RESULT_BCACHE_NO_MEMORY :p="BCACHE_NO_MEMORY" ; break;
case WFSKRN_RESULT_BCACHE_NOT_FOUND :p="BCACHE_NOT_FOUND" ; break;
case WFSKRN_RESULT_BCACHE_MAX_DEVICES :p="BCACHE_MAX_DEVICES" ; break;
case WFSKRN_RESULT_BCACHE_INVALID_DEVICE :p="BCACHE_INVALID_DEVICE" ; break;
case WFSKRN_RESULT_BCACHE_INVALID_HANDLE :p="BCACHE_INVALID_HANDLE" ; break;
case WFSKRN_RESULT_BCACHE_INVALID_VOLUME :p="BCACHE_INVALID_VOLUME" ; break;
case WFSKRN_RESULT_BCACHE_ALREADY_MAPPED :p="BCACHE_ALREADY_MAPPED" ; break;
case WFSKRN_RESULT_BCACHE_ALLOC :p="BCACHE_ALLOC" ; break;
case WFSKRN_RESULT_BCACHE_HASH_BLK_NOT_MAPPED :p="BCACHE_PMEM" ; break;
case WFSKRN_RESULT_VOLUME_ERROR :p="VOLUME_ERROR" ; break;
case WFSKRN_RESULT_VOLUME_INVALID_PARAMETER :p="VOLUME_INVALID_PARAMETER" ; break;
case WFSKRN_RESULT_VOLUME_BCACHE_ALLOC :p="VOLUME_BCACHE_ALLOC" ; break;
case WFSKRN_RESULT_VOLUME_BCACHE_CONFIG :p="VOLUME_BCACHE_CONFIG" ; break;
//case WFSKRN_RESULT_VOLUME_ID :p="VOLUME_ID" ; break;
//case WFSKRN_RESULT_VOLUME_CORRUPT_MR :p="VOLUME_CORRUPT_MR" ; break;
//case WFSKRN_RESULT_VOLUME_AREA_ALLOC :p="VOLUME_AREA_ALLOC" ; break;
//case WFSKRN_RESULT_VOLUME_DEVICE_PARAMETER :p="VOLUME_DEVICE_PARAMETER" ; break;
//case WFSKRN_RESULT_VOLUME_NOT_MAPPED :p="VOLUME_NOT_MAPPED" ; break;
case WFSKRN_RESULT_TRANSACTION_ERROR :p="TRANSACTION_ERROR" ; break;
case WFSKRN_RESULT_TRANSACTION_INVALID_PARAMETER:p="TRANSACTION_INVALID_PARAMETER"; break;
case WFSKRN_RESULT_ACL_ERROR :p="ACL_ERROR" ; break;
case WFSKRN_RESULT_ACL_INVALID_PARAMETER :p="ACL_INVALID_PARAMETER" ; break;
case WFSKRN_RESULT_ACL_MAX_ENTRIES :p="ACL_MAX_ENTRIES" ; break;
case WFSKRN_RESULT_ACL_CACHE :p="ACL_CACHE" ; break;
case WFSKRN_RESULT_ACL_FILE :p="ACL_FILE" ; break;
case WFSKRN_RESULT_ACL_FILENAME :p="ACL_FILENAME" ; break;
case WFSKRN_RESULT_ACL_HANDLE :p="ACL_HANDLE" ; break;
case WFSKRN_RESULT_AREA_ERROR :p="AREA_ERROR" ; break;
case WFSKRN_RESULT_AREA_INVALID_PARAMETER :p="AREA_INVALID_PARAMETER" ; break;
case WFSKRN_RESULT_AREA_BCACHE_ALLOC :p="AREA_BCACHE_ALLOC" ; break;
case WFSKRN_RESULT_NOT_IMPLEMENTED :p="NOT_IMPLEMENTED" ; break;
case WFSKRN_RESULT_UNKNOWN :p="UNKNOWN" ; break;
case WFSKRN_RESULT_FATAL_ERROR :p="FATAL_ERROR" ; break;
default: p="???" ;break ;
}
return p;
}
WFSKrnResult WFSKrnOutputErrorCode(WFSKrnResult nResult) {
#if _DEBUG
MyOSReport("%d. Error: (%d) WFSKRN_RESULT_%s\n", nDbgCommandCount, nResult, WFSKrnGetErrorString(nResult) );
#endif
if (nResult != WFSKRN_RESULT_PTREE_ENTRY_NOT_FOUND) {
return nResult;
}
WFSKrnDbgOutputClose();
return nResult;
}
void PathCacheDebugOutput();
WFSKrnResult WFSKrnOutputErrorStr(const char *pStr) {
#if _DEBUG
MyOSReport("%d. %s\n", nDbgCommandCount, pStr);
WFSKrnDbgOutputClose();
#endif
return WFSKRN_RESULT_UNKNOWN;
}
void WFSKrnCommandCountBreak() {
#if _DEBUG
if(nDbgCommandCount >= nDbgCommandCountBreak) {
#ifndef WFSDEV
PathCacheDebugOutput();
#endif
int a; a=0;
}
#endif
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,119 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_Handles.cpp - Module for file handles and search directory handles
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Handles.cpp,v $
Revision 1.2 2008/10/07 06:00:57 ueno
Modified WFSKrnFileInfoAlloc() to set WFSKRN_HANDLE_ALLOCATED in order to indicate the handle is allocated.
Revision 1.1 2008/04/25 17:29:06 kondo_masahiro
Initial check-in
Revision 1.1 2008/04/23 00:27:17 paul
Copied and modified from wfscli_Handles.cpp
*---------------------------------------------------------------------------*/
#include "wfskrn_Api.h"
static bool bMutexInitialized = false; // [check]
void WFSKrnInitHandles() {
if (!bMutexInitialized)
{
bMutexInitialized = true;
WFSKrnInitMutex(&wkg.hnd.mxAccessTheFileInfo);
WFSKrnInitMutex(&wkg.hnd.mxAccessTheSearchDirInfo);
}
wkg.hnd.nFileHandleCounter = 0;
wkg.hnd.nSearchDirHandleCounter = 0;
wkg.hnd.nFirstFreeFileHandle = 0;
wkg.hnd.nFirstFreeSearchDirHandle = 0;
wkg.hnd.nNumUsedFileHandles = 0;
wkg.hnd.nNumUsedSearchDirHandles = 0;
//wkg.hnd.nFirstUsedFileHandle = WFSKRN_MAX_FILE_HANDLES; // A value of WFSKRN_MAX_FILE_HANDLES is the list terminator
//wkg.hnd.nFirstUsedSearchDirHandle = WFSKRN_MAX_SEARCH_DIR_HANDLES; // A value of WFSKRN_MAX_SEARCH_DIR_HANDLES is the list terminator
u32 nI;
for(nI=0; nI<WFSKRN_MAX_FILE_HANDLES; nI++) {
wkg.hnd.aFileInfo[nI].nNext = nI+1;
}
for(nI=0; nI<WFSKRN_MAX_SEARCH_DIR_HANDLES; nI++) {
wkg.hnd.aSearchDirInfo[nI].nNext = nI+1;
}
}
WFSKrnResult WFSKrnGetFileInfo(WFSKrnFileInfo **ppFi, WFSSrvFileHandle sfh) {
*ppFi = &wkg.hnd.aFileInfo[sfh&(WFSKRN_MAX_FILE_HANDLES-1)];
return ((*ppFi)->nHandle == sfh)?WFSKRN_RESULT_OK:WFSKRN_RESULT_INVALID;
}
WFSKrnResult WFSKrnGetSearchDirInfo(WFSKrnSearchDirInfo **ppSdi, WFSSrvSearchDirectoryHandle ssdh) {
*ppSdi = &wkg.hnd.aSearchDirInfo[ssdh&(WFSKRN_MAX_SEARCH_DIR_HANDLES-1)];
return ((*ppSdi)->nHandle == ssdh)?WFSKRN_RESULT_OK:WFSKRN_RESULT_INVALID;
}
WFSKrnResult WFSKrnFileInfoAlloc(WFSKrnFileInfo **ppFi) {
WFSKrnLockMutex(&wkg.hnd.mxAccessTheFileInfo);
if (wkg.hnd.nFirstFreeFileHandle == WFSKRN_MAX_FILE_HANDLES) {
WFSKrnUnlockMutex(&wkg.hnd.mxAccessTheFileInfo);
return WFSKRN_RESULT_MAX_HANDLES;
}
wkg.hnd.nNumUsedFileHandles++;
u32 nIdx = wkg.hnd.nFirstFreeFileHandle;
wkg.hnd.nFirstFreeFileHandle = wkg.hnd.aFileInfo[nIdx].nNext;
wkg.hnd.aFileInfo[nIdx].nNext = WFSKRN_HANDLE_ALLOCATED;
*ppFi = &wkg.hnd.aFileInfo[nIdx];
wkg.hnd.aFileInfo[nIdx].nHandle = wkg.hnd.nFileHandleCounter | nIdx;
wkg.hnd.nFileHandleCounter += WFSKRN_FILE_HANDLE_INC;
wkg.hnd.nFileHandleCounter &= WFSKRN_HANDLE_COUNTER_MASK;
WFSKrnUnlockMutex(&wkg.hnd.mxAccessTheFileInfo);
return WFSKRN_RESULT_OK;
}
WFSKrnResult WFSKrnSearchDirInfoAlloc(WFSKrnSearchDirInfo **ppSdi) {
WFSKrnLockMutex(&wkg.hnd.mxAccessTheSearchDirInfo);
if (wkg.hnd.nFirstFreeSearchDirHandle == WFSKRN_MAX_SEARCH_DIR_HANDLES) {
WFSKrnUnlockMutex(&wkg.hnd.mxAccessTheSearchDirInfo);
return WFSKRN_RESULT_MAX_HANDLES;
}
wkg.hnd.nNumUsedSearchDirHandles++;
u32 nIdx = wkg.hnd.nFirstFreeSearchDirHandle;
wkg.hnd.nFirstFreeSearchDirHandle = wkg.hnd.aSearchDirInfo[nIdx].nNext;
wkg.hnd.aSearchDirInfo[nIdx].nNext = WFSKRN_HANDLE_ALLOCATED;
*ppSdi = &wkg.hnd.aSearchDirInfo[nIdx];
wkg.hnd.aSearchDirInfo[nIdx].nHandle = wkg.hnd.nSearchDirHandleCounter | nIdx;
wkg.hnd.nSearchDirHandleCounter += WFSKRN_SEARCH_DIR_HANDLE_INC;
wkg.hnd.nSearchDirHandleCounter &= WFSKRN_HANDLE_COUNTER_MASK;
WFSKrnUnlockMutex(&wkg.hnd.mxAccessTheSearchDirInfo);
return WFSKRN_RESULT_OK;
}
void WFSKrnFileInfoFree(WFSKrnFileInfo *pFi) {
WFSKrnLockMutex(&wkg.hnd.mxAccessTheFileInfo);
u32 nIdx = (u32)(pFi - wkg.hnd.aFileInfo);
pFi->nHandle ^= 0x5555; // ensures the deleted handle is invalid
pFi->nNext = wkg.hnd.nFirstFreeFileHandle;
wkg.hnd.nNumUsedFileHandles--;
wkg.hnd.nFirstFreeFileHandle = nIdx;
WFSKrnUnlockMutex(&wkg.hnd.mxAccessTheFileInfo);
}
void WFSKrnSearchDirInfoFree(WFSKrnSearchDirInfo *pSdi) {
WFSKrnLockMutex(&wkg.hnd.mxAccessTheSearchDirInfo);
u32 nIdx = (u32)(pSdi - wkg.hnd.aSearchDirInfo);
pSdi->nHandle ^= 0x5555; // ensures the deleted handle is invalid
pSdi->nNext = wkg.hnd.nFirstFreeSearchDirHandle;
wkg.hnd.nNumUsedSearchDirHandles--;
wkg.hnd.nFirstFreeSearchDirHandle = nIdx;
WFSKrnUnlockMutex(&wkg.hnd.mxAccessTheSearchDirInfo);
}

View File

@ -0,0 +1,141 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_Heap.cpp
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Heap.cpp,v $
Revision 1.1 2008/04/22 04:39:08 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.3 2008/04/19 05:50:40 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.2 2007/12/27 11:07:04 paul
fixed some copy-paste errors: changed WFS to WFSKrn
Revision 1.1 2007/12/27 11:04:05 paul
similar to wfs_Heap.cpp, but will eventually support IOP, so will eventually be different
*---------------------------------------------------------------------------*/
#include "wfskrn_Heap.h"
#include "firm.h"
#undef dbg
#if _DEBUG_WFSKRN_ALLOC
#define dbg(s) s
#else
#define dbg(s)
#endif
#if _WIN32
dbg(u32 nSizeAvaliable=0;)
void WFSKrnCreateHeap(WFSKrnHeap *pHeap, void *pBase, size_t nSize) {
*pHeap = HeapCreate(0, nSize, nSize);
dbg(nSizeAvaliable = nSize);
}
void *WFSKrnHeapAlloc(WFSKrnHeap *pHeap, size_t nSize) {
void *pAddr = HeapAlloc(*pHeap, 0, nSize);
dbg(nSizeAvaliable -= nSize;
MyOSReport("A:Heap:%d\n", nSizeAvaliable));
return pAddr;
}
void WFSKrnHeapFree(WFSKrnHeap *pHeap, void *pAddr) {
dbg(nSizeAvaliable += HeapSize(pHeap, NULL, pAddr);
MyOSReport("F:Heap:%d\n", nSizeAvaliable));
HeapFree(*pHeap, 0, pAddr);
}
void WFSKrnHeapDestroy(WFSKrnHeap *pHeap) {
dbg(MyOSReport("WFSKrnHeapDestroy()\n"));
HeapDestroy(*pHeap);
}
//-- twl modified
#elif _TWL
void WFSKrnCreateHeap(WFSKrnHeap *pHeap, void *pBase, size_t nSize) {
osTPrintf( "%s needs modify.\n", __FUNCTION__);
//main.cÅ<E2809A>sÁÄ¢é
}
void *WFSKrnHeapAlloc(WFSKrnHeap *pHeap, size_t nSize) {
void *pAddr = osAlloc( nSize);
if( pAddr == NULL) {
osTPrintf( "%s error!\n", __FUNCTION__);
}
// void *pAddr = OS_AllocFromHeap( OS_ARENA_MAIN_SUBPRIV, *pHeap, nSize);
return pAddr;
}
void WFSKrnHeapFree(WFSKrnHeap *pHeap, void *pAddr) {
osFree( pAddr);
// OS_FreeToHeap( OS_ARENA_MAIN_SUBPRIV, *pHeap, pAddr);
}
void WFSKrnHeapDestroy(WFSKrnHeap *pHeap) {
osTPrintf( "%s needs modify.\n", __FUNCTION__);
// OS_DestroyHeap( OS_ARENA_MAIN_SUBPRIV, *pHeap);
}
//-- twl modified
#elif _RVL
void WFSKrnCreateHeap(WFSKrnHeap *pHeap, void *pBase, size_t nSize) {
pHeap->handle = MEMCreateExpHeap(pBase, nSize);
MEMInitAllocatorForExpHeap(&pHeap->allocator, pHeap->handle, WFS_HEAP_DEFAULT_ALIGNMENT);
}
void *WFSKrnHeapAlloc(WFSKrnHeap *pHeap, size_t nSize) {
// osTPrintf("==> %s:%d pHeap: 0x%08x size: %d\n", __FILE__, __LINE__, pHeap->pAllocator, nSize);
void *pAddr = MEMAllocFromAllocator(&pHeap->allocator, nSize);
// osTPrintf("==> %s:%d pAddr: 0x%08x\n", __FILE__, __LINE__, pAddr);
return pAddr;
}
void WFSKrnHeapFree(WFSKrnHeap *pHeap, void *pAddr) {
MEMFreeToAllocator(&pHeap->allocator, pAddr);
}
void WFSKrnHeapDestroy(WFSKrnHeap *pHeap) {
MEMDestroyExpHeap(pHeap->handle);
}
#elif _IOP
void WFSKrnCreateHeap(WFSKrnHeap *pHeap, void *pBase, size_t nSize) {
*pHeap = IOS_CreateHeap(pBase, nSize);
}
void *WFSKrnHeapAlloc(WFSKrnHeap *pHeap, size_t nSize) {
// osTPrintf("==> %s:%d pHeap: 0x%08x size: %d\n", __FILE__, __LINE__, pHeap, nSize);
void *pAddr = IOS_AllocAligned(*pHeap, nSize, 32);
// osTPrintf("==> %s:%d pAddr: 0x%08x\n", __FILE__, __LINE__, pAddr);
return pAddr;
}
void WFSKrnHeapFree(WFSKrnHeap *pHeap, void *pAddr) {
IOS_Free(*pHeap, pAddr);
}
void WFSKrnHeapDestroy(WFSKrnHeap *pHeap) {
IOS_DestroyHeap(*pHeap);
}
#endif

View File

@ -0,0 +1,354 @@
/*---------------------------------------------------------------------------*
Project: wfs
File: wfskrn_Mutex.cpp
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Log: wfskrn_Mutex.cpp,v $
Revision 1.2 2008/04/25 17:28:54 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.1 2008/04/22 04:39:08 kondo_masahiro
Fixed code to transfer the wfskrn project to RM_SDK tree
Revision 1.2 2008/04/19 05:50:34 kondo_masahiro
Fixed code to accept RM compiler
Revision 1.1 2007/12/27 11:11:58 paul
similar to wfs_Mutex.cpp, but will eventually need to support IOP
*---------------------------------------------------------------------------*/
#include "wfskrn_Mutex.h"
#undef dbg
#if _DEBUG_WFSKRN_MUTEX
#define dbg(s) s
#else
#define dbg(s)
#endif
#if _WIN32
dbg(u32 aSignalCounter[0x2000]);
void WFSKrnInitMutex(WFSKrnMutex *pMx) {
pMx->hHandle = CreateMutex(NULL, false, NULL);
ReleaseMutex(pMx->hHandle);
dbg(aSignalCounter[(u32)pMx->hHandle&0x1fff]=1;
MyOSReport("InitMutex(%x:%d)\n", pMx->hHandle, aSignalCounter[(u32)pMx->hHandle&0x1fff]));
}
void WFSKrnLockMutex(WFSKrnMutex *pMx) {
dbg(MyOSReport("Wait(%x:%d)\n", pMx->hHandle, aSignalCounter[(u32)pMx->hHandle&0x1fff]));
WaitForSingleObject(pMx->hHandle, INFINITE);
dbg(aSignalCounter[(u32)pMx->hHandle&0x1fff]--);
}
bool WFSKrnTryLockMutex(WFSKrnMutex *pMx) {
return (WaitForSingleObject(pMx->hHandle, 0) != WAIT_TIMEOUT);
}
void WFSKrnUnlockMutex(WFSKrnMutex *pMx) {
dbg(aSignalCounter[(u32)pMx->hHandle&0x1fff]++;
MyOSReport("Release(%x:%d)\n", pMx->hHandle, aSignalCounter[(u32)pMx->hHandle&0x1fff]));
ReleaseMutex(pMx->hHandle);
}
void WFSKrnInitCond(WFSKrnCond *pCond) {
pCond->hAutoResetEvent = CreateEvent(NULL, false, false, NULL);
dbg(aSignalCounter[(u32)pCond->hAutoResetEvent&0x1fff]=0;
MyOSReport("InitCond(%x:%d)\n", pCond->hAutoResetEvent, aSignalCounter[(u32)pCond->hAutoResetEvent&0x1fff]));
//ResetEvent(pCond->hAutoResetEvent);
//pCond->hManualResetEvent = CreateEvent(NULL, true, false, NULL);
}
void WFSKrnSignalCond(WFSKrnCond *pCond) {
//PulseEvent(pCond->hAutoResetEvent);
dbg(aSignalCounter[(u32)pCond->hAutoResetEvent&0x1fff]++;
MyOSReport("Signal(%x:%d)\n", pCond->hAutoResetEvent, aSignalCounter[(u32)pCond->hAutoResetEvent&0x1fff]));
SetEvent(pCond->hAutoResetEvent);
}
void WFSKrnWaitCond(WFSKrnCond *pCond, WFSKrnMutex* pMx) {
#if 1
dbg(aSignalCounter[(u32)pMx->hHandle&0x1fff]++;
MyOSReport("Signal(%x:%d) And Wait(%x:%d)\n", pMx->hHandle, aSignalCounter[(u32)pMx->hHandle&0x1fff], pCond->hAutoResetEvent, aSignalCounter[(u32)pCond->hAutoResetEvent&0x1fff]));
//DWORD nRet = SignalObjectAndWait(pMx->hHandle, pCond->hAutoResetEvent, INFINITE, false);
dbg(aSignalCounter[(u32)pCond->hAutoResetEvent&0x1fff]--);
#else
ReleaseMutex(pMx->hHandle);
WaitForSingleObject(pCond->hAutoResetEvent, INFINITE);
#endif
dbg(MyOSReport("Wait(%x:%d)\n", pMx->hHandle, aSignalCounter[(u32)pMx->hHandle&0x1fff]));
WaitForSingleObject(pMx->hHandle, INFINITE);
dbg(aSignalCounter[(u32)pMx->hHandle&0x1fff]--);
}
void WFSKrnResetCond(WFSKrnCond *pCond) {
ResetEvent(pCond->hAutoResetEvent);
}
bool WFSKrnCreateThread(WFSKrnThread *pThread,
WFSKrnThreadFunc threadFunc,
void* param,
void* stackBase,
u32 stackSize,
OSPriority priority)
{
pThread->hThread = CreateThread(NULL, stackSize, (LPTHREAD_START_ROUTINE)threadFunc, param, CREATE_SUSPENDED, 0);
SetThreadPriority(pThread->hThread, 16-priority);
return true;
}
s32 WFSKrnResumeThread(WFSKrnThread *pThread) {
return ResumeThread(pThread->hThread);
}
void WFSKrnCancelThread(WFSKrnThread *pThread) {
// Note: On windows, this does not do any cleanup - should avoid using
TerminateThread(pThread->hThread, 0);
}
void WFSKrnExitThread(void *pVal) {
ExitThread((DWORD)pVal);
}
s32 WFSKrnSuspendThread(WFSKrnThread *pThread)
{
return SuspendThread(pThread->hThread);
}
bool WFSKrnIsThreadTerminated(WFSKrnThread *pThread)
{
switch (WaitForSingleObject(pThread->hThread, 0))
{
case WAIT_TIMEOUT:
return false;
case WAIT_OBJECT_0: // the thread has exited.
case WAIT_ABANDONED: // [check]
case WAIT_FAILED: // the thread does not exist. [check] should check error code?
default:
break;
}
return true;
}
bool WFSKrnJoinThread(WFSKrnThread *pThread, void** val)
{
#pragma unused (val) // exit value is not supported.
switch (WaitForSingleObject(pThread->hThread, INFINITE))
{
case WAIT_OBJECT_0:
return true;
case WAIT_TIMEOUT:
case WAIT_ABANDONED:
case WAIT_FAILED:
default:
break;
}
return false;
}
#elif _RVL
bool WFSKrnCreateThread(WFSKrnThread *pThread,
WFSKrnThreadFunc threadFunc,
void* param,
void* stackBase,
u32 stackSize,
OSPriority priority)
{
return OSCreateThread(pThread, threadFunc, param, (void*)((u32)stackBase+stackSize), stackSize, priority, OS_THREAD_ATTR_DETACH);
}
//--- twl modified
#elif _TWL
typedef void (*MyThreadFunc)(void*);
bool WFSKrnCreateThread(WFSKrnThread *pThread,
WFSKrnThreadFunc threadFunc,
void* param,
void* stackBase,
u32 stackSize,
OSPriority priority)
{
osCreateThread( pThread, (MyThreadFunc)threadFunc, param, (void*)((u32)stackBase+stackSize), stackSize, priority);
return true;
}
s32 WFSKrnResumeThread(WFSKrnThread *pThread)
{
osWakeupThreadDirect( pThread);
#if 1
// osTPrintf( "Need TWL modifies.\n");
return 0;
#else
if(WFSKrnIsThreadTerminated(pThread)){
return 0;
}
else if(--pThread->count == 0){
IOS_StartThread(pThread->tid);
}
return pThread->count;
#endif
}
void WFSKrnCancelThread(WFSKrnThread *pThread)
{
osDestroyThread( pThread);
}
void WFSKrnExitThread(void *pVal)
{
osExitThread();
}
s32 WFSKrnSuspendThread(WFSKrnThread *pThread)
{
#if 1
osTPrintf( "Need TWL modifies.\n");
return 0;
#else
if(WFSKrnIsThreadTerminated(pThread)){
return 0;
}
else if(++pThread->count == 1){
IOS_StopThread(pThread->tid);
}
return pThread->count;
#endif
}
bool WFSKrnIsThreadTerminated(WFSKrnThread *pThread)
{
return( osIsThreadTerminated( pThread));
}
bool WFSKrnJoinThread(WFSKrnThread *pThread, void** val)
{
#pragma unused (val) // exit value is not supported.
osJoinThread( pThread);
return true;
}
void WFSKrnInitCond(WFSCond *pCond) {
osInitEvent( pCond);
}
void WFSKrnSignalCond(WFSCond *pCond) {
osSignalEvent( pCond, 1);
}
void WFSKrnWaitCond(WFSCond *pCond, WFSMutex* pMx) {
osUnlockMutex( pMx);
osWaitEventEx( pCond, 1, OS_EVENT_MODE_OR, 1); //イベント待ち後にクリアを伴う
}
void WFSKrnResetCond(WFSCond *pCond) {
osClearAllEvent( pCond);
return;
}
//-- twl modified
#elif _IOP
void WFSKrnInitMutex(WFSKrnMutex *mutex)
{
mutex->mqid = IOS_CreateMessageQueue(mutex->mq, WFSKRN_MUTEX_Q_SIZE);
IOS_SendMessage(mutex->mqid, 0xabcd1234, IOS_MESSAGE_NOBLOCK);
}
void WFSKrnLockMutex(WFSKrnMutex *mutex)
{
IOSMessage msg;
IOS_ReceiveMessage(mutex->mqid, &msg, IOS_MESSAGE_BLOCK);
}
bool WFSKrnTryLockMutex(WFSKrnMutex *mutex)
{
IOSMessage msg;
if(IOS_ReceiveMessage(mutex->mqid, &msg, IOS_MESSAGE_NOBLOCK) == IOS_ERROR_OK )
return true;
else
return false;
}
void WFSKrnUnlockMutex(WFSKrnMutex *mutex)
{
IOS_SendMessage(mutex->mqid, 0xabcd1234, IOS_MESSAGE_NOBLOCK);
}
bool WFSKrnCreateThread(WFSKrnThread *pThread,
WFSKrnThreadFunc threadFunc,
void* param,
void* stackBase,
u32 stackSize,
OSPriority priority)
{
IOSError ie = IOS_CreateThread((IOSEntryProc)threadFunc, param, stackBase, stackSize, (u32)priority, IOS_THREAD_CREATE_JOINABLE);
if(ie < 0) return false;
pThread->tid = ie;
pThread->count = 1;
return true;
}
s32 WFSKrnResumeThread(WFSKrnThread *pThread)
{
if(WFSKrnIsThreadTerminated(pThread)){
return 0;
}
else if(--pThread->count == 0){
IOS_StartThread(pThread->tid);
}
return pThread->count;
}
void WFSKrnCancelThread(WFSKrnThread *pThread)
{
IOS_DestroyThread(pThread->tid, 0);
}
void WFSKrnExitThread(void *pVal)
{
IOS_DestroyThread(IOS_GetThreadId(), pVal);
}
s32 WFSKrnSuspendThread(WFSKrnThread *pThread)
{
if(WFSKrnIsThreadTerminated(pThread)){
return 0;
}
else if(++pThread->count == 1){
IOS_StopThread(pThread->tid);
}
return pThread->count;
}
bool WFSKrnIsThreadTerminated(WFSKrnThread *pThread)
{
if(IOS_GetThreadPriority(pThread->tid) >= 0)
return true;
else
return false;
}
bool WFSKrnJoinThread(WFSKrnThread *pThread, void** val)
{
if(IOS_JoinThread(pThread->tid, val) == IOS_ERROR_OK)
return true;
else
return false;
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More