├── .gitattributes ├── .github └── workflows │ └── CI.yml ├── .gitignore ├── .vscode └── settings.json ├── LICENSE ├── README.MD ├── __bdm_assault ├── Makefile └── src │ ├── bdm │ ├── bdm.h │ ├── bdm_bdm.c │ ├── bdm_main.c │ ├── bdm_part_driver.c │ ├── bdm_part_driver_gpt.c │ ├── bdm_part_driver_mbr.c │ └── include │ │ ├── gpt_types.h │ │ ├── mbr_types.h │ │ ├── module_debug.h │ │ └── part_driver.h │ ├── bdmfs │ ├── bdmfs_diskio.c │ ├── bdmfs_ff.c │ ├── bdmfs_ffsystem.c │ ├── bdmfs_ffunicode.c │ ├── bdmfs_fs_driver.c │ ├── bdmfs_main.c │ └── include │ │ ├── diskio.h │ │ ├── ff.h │ │ ├── ffconf.h │ │ ├── fs_driver.h │ │ └── module_debug.h │ ├── exports.tab │ ├── imports.lst │ └── irx_imports.h ├── __usbd_bd_assault ├── Makefile └── src │ ├── exports.tab │ ├── imports.lst │ ├── irx_imports.h │ ├── usbd │ ├── driver.h │ ├── hcd.h │ ├── hub.h │ ├── irx_imports.h │ ├── mem.h │ ├── usbd_driver.c │ ├── usbd_hcd.c │ ├── usbd_hub.c │ ├── usbd_interface.c │ ├── usbd_mem.c │ ├── usbd_usbd.c │ ├── usbd_usbd_driver.c │ ├── usbd_usbio.c │ ├── usbdpriv.h │ └── usbio.h │ └── usbmass_bd │ ├── include │ ├── module_debug.h │ └── scsi.h │ ├── usbmass_bd_main.c │ ├── usbmass_bd_scsi.c │ └── usbmass_bd_usb_mass.c ├── bdm ├── Makefile ├── include │ └── bdm.h └── src │ ├── bdm.c │ ├── exports.tab │ ├── imports.lst │ ├── include │ ├── gpt_types.h │ ├── mbr_types.h │ ├── module_debug.h │ └── part_driver.h │ ├── irx_imports.h │ ├── main.c │ ├── part_driver.c │ ├── part_driver_gpt.c │ └── part_driver_mbr.c ├── bdmfs_fatfs ├── Makefile └── src │ ├── 00history.txt │ ├── 00readme.txt │ ├── diskio.c │ ├── ff.c │ ├── ffsystem.c │ ├── ffunicode.c │ ├── fs_driver.c │ ├── imports.lst │ ├── include │ ├── diskio.h │ ├── ff.h │ ├── ffconf.h │ ├── fs_driver.h │ └── module_debug.h │ ├── irx_imports.h │ └── main.c ├── global.make ├── libbdm ├── Makefile ├── include │ ├── bd_cache.h │ └── bd_defrag.h └── src │ ├── bd_cache.c │ ├── bd_defrag.c │ └── include │ └── module_debug.h ├── usbd ├── Makefile ├── include │ ├── usbd.h │ └── usbd_macro.h └── src │ ├── driver.c │ ├── driver.h │ ├── exports.tab │ ├── hcd.c │ ├── hcd.h │ ├── hub.c │ ├── hub.h │ ├── imports.lst │ ├── interface.c │ ├── irx_imports.h │ ├── mem.c │ ├── mem.h │ ├── usbd.c │ ├── usbdpriv.h │ ├── usbio.c │ └── usbio.h └── usbmass_bd ├── Makefile └── src ├── imports.lst ├── include ├── module_debug.h └── scsi.h ├── irx_imports.h ├── main.c ├── scsi.c └── usb_mass.c /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/CI.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | repository_dispatch: 5 | types: [Component_update] 6 | push: 7 | branches: 8 | - '*' 9 | tags: 10 | - 'v*' 11 | paths-ignore: 12 | - '**.MD' 13 | - '**.gitkeep' 14 | - '**.gitignore' 15 | workflow_dispatch: 16 | 17 | jobs: 18 | build: 19 | runs-on: ubuntu-latest 20 | container: ps2dev/ps2dev:latest 21 | steps: 22 | 23 | - name: Install dependencies 24 | run: | 25 | apk add build-base git p7zip 26 | 27 | - uses: actions/checkout@v3 28 | - run: | 29 | git config --global --add safe.directory "$GITHUB_WORKSPACE" 30 | git fetch --prune --unshallow 31 | 32 | - name: Compile 33 | run: | 34 | make -C libbdm clean all 35 | make -C __bdm_assault/ clean all 36 | make -C __usbd_bd_assault/ clean all 37 | mkdir -p READY_TO_USE/POPStarter/POPSTARTER/ 38 | mkdir -p READY_TO_USE/FreeMcBoot/SYS-CONF/ 39 | cp bdm_assault.irx READY_TO_USE/POPStarter/POPSTARTER/usbd.irx 40 | cp usbd_bd_assault.irx READY_TO_USE/POPStarter/POPSTARTER/usbhdfsd.irx 41 | cp bdm_assault.irx READY_TO_USE/FreeMcBoot/SYS-CONF/USBD.IRX 42 | cp usbd_bd_assault.irx READY_TO_USE/FreeMcBoot/SYS-CONF/USBHDFSD.IRX 43 | 7z a -t7z BDMAssault.7z *.irx LICENSE README.MD READY_TO_USE/* 44 | 45 | - name: Upload artifacts 46 | if: ${{ success() }} 47 | uses: actions/upload-artifact@v3 48 | with: 49 | name: BDM_ASSAULT 50 | path: | 51 | *.irx 52 | 53 | - name: Create release 54 | if: github.ref == 'refs/heads/main' 55 | uses: marvinpinto/action-automatic-releases@latest 56 | with: 57 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 58 | prerelease: true 59 | automatic_release_tag: "latest" 60 | title: "Latest development build" 61 | files: | 62 | BDMAssault.7z 63 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | # Libraries 7 | *.a 8 | 9 | # Executables 10 | *.irx 11 | *.7z 12 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "part_driver.h": "c", 4 | "module_debug.h": "c", 5 | "mbr_types.h": "c", 6 | "bdm.h": "c", 7 | "gpt_types.h": "c", 8 | "ff.h": "c", 9 | "diskio.h": "c", 10 | "fs_driver.h": "c", 11 | "scsi.h": "c" 12 | } 13 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | The Academic Free License 3 | v. 2.0 4 | 5 | This Academic Free License (the "License") applies to any original work 6 | of authorship (the "Original Work") whose owner (the "Licensor") has 7 | placed the following notice immediately following the copyright notice 8 | for the Original Work: 9 | 10 | *Licensed under the Academic Free License version 2.0* 11 | 12 | 1) *Grant of Copyright License.* Licensor hereby grants You a 13 | world-wide, royalty-free, non-exclusive, perpetual, sublicenseable 14 | license to do the following: 15 | 16 | a) to reproduce the Original Work in copies; 17 | 18 | b) to prepare derivative works ("Derivative Works") based upon the 19 | Original Work; 20 | 21 | c) to distribute copies of the Original Work and Derivative Works to 22 | the public; 23 | 24 | d) to perform the Original Work publicly; and 25 | 26 | e) to display the Original Work publicly. 27 | 28 | 2) *Grant of Patent License.* Licensor hereby grants You a world-wide, 29 | royalty-free, non-exclusive, perpetual, sublicenseable license, under 30 | patent claims owned or controlled by the Licensor that are embodied in 31 | the Original Work as furnished by the Licensor, to make, use, sell and 32 | offer for sale the Original Work and Derivative Works. 33 | 34 | 3) *Grant of Source Code License.* The term "Source Code" means the 35 | preferred form of the Original Work for making modifications to it and 36 | all available documentation describing how to modify the Original Work. 37 | Licensor hereby agrees to provide a machine-readable copy of the Source 38 | Code of the Original Work along with each copy of the Original Work that 39 | Licensor distributes. Licensor reserves the right to satisfy this 40 | obligation by placing a machine-readable copy of the Source Code in an 41 | information repository reasonably calculated to permit inexpensive and 42 | convenient access by You for as long as Licensor continues to distribute 43 | the Original Work, and by publishing the address of that information 44 | repository in a notice immediately following the copyright notice that 45 | applies to the Original Work. 46 | 47 | 4) *Exclusions From License Grant. *Neither the names of Licensor, nor 48 | the names of any contributors to the Original Work, nor any of their 49 | trademarks or service marks, may be used to endorse or promote products 50 | derived from this Original Work without express prior written permission 51 | of the Licensor. Nothing in this License shall be deemed to grant any 52 | rights to trademarks, copyrights, patents, trade secrets or any other 53 | intellectual property of Licensor except as expressly stated herein. No 54 | patent license is granted to make, use, sell or offer to sell 55 | embodiments of any patent claims other than the licensed claims defined 56 | in Section 2. No right is granted to the trademarks of Licensor even if 57 | such marks are included in the Original Work. Nothing in this License 58 | shall be interpreted to prohibit Licensor from licensing under different 59 | terms from this License any Original Work that Licensor otherwise would 60 | have a right to license. 61 | 62 | 5) This section intentionally omitted. 63 | 64 | 6) *Attribution Rights.* You must retain, in the Source Code of any 65 | Derivative Works that You create, all copyright, patent or trademark 66 | notices from the Source Code of the Original Work, as well as any 67 | notices of licensing and any descriptive text identified therein as an 68 | "Attribution Notice." You must cause the Source Code for any Derivative 69 | Works that You create to carry a prominent Attribution Notice reasonably 70 | calculated to inform recipients that You have modified the Original Work. 71 | 72 | 7) *Warranty of Provenance and Disclaimer of Warranty.* Licensor 73 | warrants that the copyright in and to the Original Work and the patent 74 | rights granted herein by Licensor are owned by the Licensor or are 75 | sublicensed to You under the terms of this License with the permission 76 | of the contributor(s) of those copyrights and patent rights. Except as 77 | expressly stated in the immediately proceeding sentence, the Original 78 | Work is provided under this License on an "AS IS" BASIS and WITHOUT 79 | WARRANTY, either express or implied, including, without limitation, the 80 | warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A 81 | PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL 82 | WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential 83 | part of this License. No license to Original Work is granted hereunder 84 | except under this disclaimer. 85 | 86 | 8) *Limitation of Liability.* Under no circumstances and under no legal 87 | theory, whether in tort (including negligence), contract, or otherwise, 88 | shall the Licensor be liable to any person for any direct, indirect, 89 | special, incidental, or consequential damages of any character arising 90 | as a result of this License or the use of the Original Work including, 91 | without limitation, damages for loss of goodwill, work stoppage, 92 | computer failure or malfunction, or any and all other commercial damages 93 | or losses. This limitation of liability shall not apply to liability for 94 | death or personal injury resulting from Licensor's negligence to the 95 | extent applicable law prohibits such limitation. Some jurisdictions do 96 | not allow the exclusion or limitation of incidental or consequential 97 | damages, so this exclusion and limitation may not apply to You. 98 | 99 | 9) *Acceptance and Termination.* If You distribute copies of the 100 | Original Work or a Derivative Work, You must make a reasonable effort 101 | under the circumstances to obtain the express assent of recipients to 102 | the terms of this License. Nothing else but this License (or another 103 | written agreement between Licensor and You) grants You permission to 104 | create Derivative Works based upon the Original Work or to exercise any 105 | of the rights granted in Section 1 herein, and any attempt to do so 106 | except under the terms of this License (or another written agreement 107 | between Licensor and You) is expressly prohibited by U.S. copyright law, 108 | the equivalent laws of other countries, and by international treaty. 109 | Therefore, by exercising any of the rights granted to You in Section 1 110 | herein, You indicate Your acceptance of this License and all of its 111 | terms and conditions. 112 | 113 | 10) *Termination for Patent Action.* This License shall terminate 114 | automatically and You may no longer exercise any of the rights granted 115 | to You by this License as of the date You commence an action, including 116 | a cross-claim or counterclaim, for patent infringement (i) against 117 | Licensor with respect to a patent applicable to software or (ii) against 118 | any entity with respect to a patent applicable to the Original Work (but 119 | excluding combinations of the Original Work with other software or 120 | hardware). 121 | 122 | 11) *Jurisdiction, Venue and Governing Law.* Any action or suit relating 123 | to this License may be brought only in the courts of a jurisdiction 124 | wherein the Licensor resides or in which Licensor conducts its primary 125 | business, and under the laws of that jurisdiction excluding its 126 | conflict-of-law provisions. The application of the United Nations 127 | Convention on Contracts for the International Sale of Goods is expressly 128 | excluded. Any use of the Original Work outside the scope of this License 129 | or after its termination shall be subject to the requirements and 130 | penalties of the U.S. Copyright Act, 17 U.S.C. � 101 et seq., the 131 | equivalent laws of other countries, and international treaty. This 132 | section shall survive the termination of this License. 133 | 134 | 12) *Attorneys Fees.* In any action to enforce the terms of this License 135 | or seeking damages relating thereto, the prevailing party shall be 136 | entitled to recover its costs and expenses, including, without 137 | limitation, reasonable attorneys' fees and costs incurred in connection 138 | with such action, including any appeal of such action. This section 139 | shall survive the termination of this License. 140 | 141 | 13) *Miscellaneous.* This License represents the complete agreement 142 | concerning the subject matter hereof. If any provision of this License 143 | is held to be unenforceable, such provision shall be reformed only to 144 | the extent necessary to make it enforceable. 145 | 146 | 14) *Definition of "You" in This License.* "You" throughout this 147 | License, whether in upper or lower case, means an individual or a legal 148 | entity exercising rights under, and complying with all of the terms of, 149 | this License. For legal entities, "You" includes any entity that 150 | controls, is controlled by, or is under common control with you. For 151 | purposes of this definition, "control" means (i) the power, direct or 152 | indirect, to cause the direction or management of such entity, whether 153 | by contract or otherwise, or (ii) ownership of fifty percent (50%) or 154 | more of the outstanding shares, or (iii) beneficial ownership of such 155 | entity. 156 | 157 | 15) *Right to Use.* You may use the Original Work in all ways not 158 | otherwise restricted or conditioned by this License or by law, and 159 | Licensor promises not to interfere with or be responsible for such uses 160 | by You. 161 | 162 | This license is Copyright (C) 2003 Lawrence E. Rosen. All rights 163 | reserved. Permission is hereby granted to copy and distribute this 164 | license without modification. This license may not be modified without 165 | the express written permission of its copyright owner. 166 | 167 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # BDM Assault 2 | 3 | BDM Assault is a homebrew project for PS2 that aims to bring EXFAT USB support to those old closed source homebrew apps that can load external USB drivers that people still use today (POPStarter, FreeMcBoot). 4 | 5 | ## Usage 6 | 7 | To use this project you have to place the two IRX binaries provided at the [release section](https://github.com/israpps/BDMAssault/releases) into the path that your app looks for 8 | 9 | 10 | ### POPStarter 11 | - `bdm_assault.irx` must be pasted into `mc?:/POPSTARTER/usbd.irx` 12 | - `usbd_bd_assault.irx` must be pasted into `mc?:/POPSTARTER/usbhdfsd.irx` 13 | 14 | ### FreeMcBoot 15 | - `bdm_assault.irx` must be pasted into `mc?:/SYS-CONF/USBD.IRX` 16 | - `usbd_bd_assault.irx` must be pasted into `mc?:/SYS-CONF/USBHDFSD.IRX` 17 | 18 | ### FreeHdBoot 19 | - `bdm_assault.irx` must be pasted into `hdd0:__sysconf/FMCB/USBD.IRX` 20 | - `usbd_bd_assault.irx` must be pasted into `hdd0:__sysconf/FMCB/USBHDFSD.IRX` 21 | 22 | ### old wLaunchELF versions 23 | - `bdm_assault.irx` must be pasted into the path you configured for `USBD.IRX` 24 | - `usbd_bd_assault.irx` must be pasted into the path you configured for `USBHDFSD.IRX` 25 | 26 | ### Any other homebrew 27 | - find out by yourself. I cant remember any other. 28 | 29 | ## Incompatible programs 30 | 31 | - Simple Media System (SMS): incompatible due to usage of custom USB drivers and practices wich are not common amongst the homebrew devs. support not planned (and most likely not even possible) 32 | 33 | ## CREDITS 34 | 35 | the softwares found here were taken and modified from [__PS2SDK__](https://github.com/ps2dev/ps2sdk) 36 | 37 | - krHACKen: for letting me know POPStarter loads external USB drivers (wich ended up in the creation of this project) 38 | - juankytutoriales: for making tests in real hardware 39 | - everyone that collaborated to PS2SDK 40 | -------------------------------------------------------------------------------- /__bdm_assault/Makefile: -------------------------------------------------------------------------------- 1 | 2 | IOP_BIN = ../bdm_assault.irx 3 | 4 | 5 | #bdm 6 | BDM_OBJS = main.o bdm.o part_driver.o part_driver_mbr.o part_driver_gpt.o 7 | IOP_LIBS += ../libbdm/lib/libbdm.a 8 | IOP_CFLAGS += -I../libbdm/include/ -Wno-strict-aliasing 9 | 10 | #bdmfs_fatfs 11 | BDMFS_FATFS_OBJS = ff.o ffsystem.o ffunicode.o fs_driver.o diskio.o main.o 12 | IOP_LIBS += -static-libgcc -lgcc 13 | 14 | IOP_OBJS = $(addprefix bdm_,$(BDM_OBJS)) $(addprefix bdmfs_,$(BDMFS_FATFS_OBJS)) imports.o exports.o 15 | ifeq ($(DEBUG), 1) 16 | IOP_CFLAGS += -DDEBUG -DDEBUG_EXTREME 17 | IOP_BIN = ../bdm_assault_debug.irx 18 | endif 19 | include ../global.make 20 | IOP_SRC_DIR = 21 | vpath %.c src/ 22 | vpath %.lst src/ 23 | vpath %.tab src/ 24 | vpath %.c src/bdm/ 25 | vpath %.c src/bdmfs/ 26 | 27 | 28 | $(IOP_OBJS_DIR)%.o: src/bdm/%.c 29 | $(DIR_GUARD) 30 | $(IOP_C_COMPILE) -c $< -o $@ 31 | $(IOP_OBJS_DIR)%.o: src/bdmfs/%.c 32 | $(DIR_GUARD) 33 | $(IOP_C_COMPILE) -c $< -o $@ -------------------------------------------------------------------------------- /__bdm_assault/src/bdm/bdm.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Licenced under Academic Free License version 2.0 7 | # Review ps2sdk README & LICENSE files for further details. 8 | */ 9 | 10 | /** 11 | * @file 12 | * IOP BDM (Block Device Manager) definitions. 13 | */ 14 | 15 | #ifndef __BDM_H__ 16 | #define __BDM_H__ 17 | 18 | #include 19 | #include 20 | 21 | struct block_device 22 | { 23 | // Private driver data 24 | void *priv; 25 | 26 | // Device name + number + partition number 27 | // Can be used to create device names like: 28 | // - mass0p1 29 | char *name; 30 | unsigned int devNr; 31 | unsigned int parNr; 32 | unsigned char parId; 33 | 34 | unsigned int sectorSize; // Size of a sector in bytes 35 | u64 sectorOffset; // Starting sector number 36 | u64 sectorCount; // Maximum number of sectors usable 37 | 38 | int (*read)(struct block_device *bd, u64 sector, void *buffer, u16 count); 39 | int (*write)(struct block_device *bd, u64 sector, const void *buffer, u16 count); 40 | void (*flush)(struct block_device *bd); 41 | int (*stop)(struct block_device *bd); 42 | }; 43 | 44 | struct file_system 45 | { 46 | // Private driver data 47 | void *priv; 48 | 49 | // Filesystem (/partition) name 50 | char *name; 51 | 52 | // mount / umount block device 53 | int (*connect_bd)(struct block_device *bd); 54 | void (*disconnect_bd)(struct block_device *bd); 55 | }; 56 | 57 | typedef void (*bdm_cb)(int event); 58 | 59 | // Exported functions 60 | void bdm_connect_bd(struct block_device *bd); 61 | void bdm_disconnect_bd(struct block_device *bd); 62 | void bdm_connect_fs(struct file_system *fs); 63 | void bdm_disconnect_fs(struct file_system *fs); 64 | void bdm_get_bd(struct block_device **pbd, unsigned int count); 65 | void bdm_RegisterCallback(bdm_cb cb); 66 | 67 | #define bdm_IMPORTS_start DECLARE_IMPORT_TABLE(bdm, 1, 1) 68 | #define bdm_IMPORTS_end END_IMPORT_TABLE 69 | 70 | #define I_bdm_connect_bd DECLARE_IMPORT(4, bdm_connect_bd) 71 | #define I_bdm_disconnect_bd DECLARE_IMPORT(5, bdm_disconnect_bd) 72 | #define I_bdm_connect_fs DECLARE_IMPORT(6, bdm_connect_fs) 73 | #define I_bdm_disconnect_fs DECLARE_IMPORT(7, bdm_disconnect_fs) 74 | #define I_bdm_get_bd DECLARE_IMPORT(8, bdm_get_bd) 75 | #define I_bdm_RegisterCallback DECLARE_IMPORT(9, bdm_RegisterCallback) 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /__bdm_assault/src/bdm/bdm_bdm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | // #define DEBUG //comment out this line when not debugging 9 | #include "include/module_debug.h" 10 | 11 | struct bdm_mounts 12 | { 13 | struct block_device *bd; // real block device 14 | struct block_device *cbd; // cached block device 15 | struct file_system *fs; 16 | }; 17 | 18 | #define MAX_CONNECTIONS 20 19 | static struct bdm_mounts g_mount[MAX_CONNECTIONS]; 20 | static struct file_system *g_fs[MAX_CONNECTIONS]; 21 | static bdm_cb g_cb = NULL; 22 | static int bdm_event = -1; 23 | static int bdm_thread_id = -1; 24 | 25 | /* Event flag bits */ 26 | #define BDM_EVENT_CB_MOUNT 0x01 27 | #define BDM_EVENT_CB_UMOUNT 0x02 28 | #define BDM_EVENT_MOUNT 0x04 29 | 30 | void bdm_RegisterCallback(bdm_cb cb) 31 | { 32 | int i; 33 | 34 | M_DEBUG("%s\n", __func__); 35 | 36 | g_cb = cb; 37 | 38 | if (g_cb == NULL) 39 | return; 40 | 41 | // Trigger a mount callback if we already have mounts 42 | for (i = 0; i < MAX_CONNECTIONS; ++i) { 43 | if ((g_mount[i].bd != NULL) && (g_mount[i].fs != NULL)) { 44 | SetEventFlag(bdm_event, BDM_EVENT_CB_MOUNT); 45 | break; 46 | } 47 | } 48 | } 49 | 50 | void bdm_connect_bd(struct block_device *bd) 51 | { 52 | int i; 53 | 54 | M_PRINTF("connecting device %s%dp%d id=0x%x\n", bd->name, bd->devNr, bd->parNr, bd->parId); 55 | 56 | for (i = 0; i < MAX_CONNECTIONS; ++i) { 57 | if (g_mount[i].bd == NULL) { 58 | g_mount[i].bd = bd; 59 | // Create cache for entire device only (not for the partitions on it) 60 | g_mount[i].cbd = (bd->parNr == 0) ? bd_cache_create(bd) : NULL; 61 | // New block device, try to mount it to a filesystem 62 | SetEventFlag(bdm_event, BDM_EVENT_MOUNT); 63 | break; 64 | } 65 | } 66 | } 67 | 68 | void bdm_disconnect_bd(struct block_device *bd) 69 | { 70 | int i; 71 | 72 | M_PRINTF("disconnecting device %s%dp%d id=0x%x\n", bd->name, bd->devNr, bd->parNr, bd->parId); 73 | 74 | for (i = 0; i < MAX_CONNECTIONS; ++i) { 75 | if (g_mount[i].bd == bd) { 76 | if (g_mount[i].fs != NULL) { 77 | // Unmount filesystem 78 | g_mount[i].fs->disconnect_bd(g_mount[i].cbd != NULL ? g_mount[i].cbd : g_mount[i].bd); 79 | M_PRINTF("%s%dp%d unmounted from %s\n", bd->name, bd->devNr, bd->parNr, g_mount[i].fs->name); 80 | g_mount[i].fs = NULL; 81 | } 82 | 83 | if (g_mount[i].cbd != NULL) { 84 | bd_cache_destroy(g_mount[i].cbd); 85 | g_mount[i].cbd = NULL; 86 | } 87 | 88 | g_mount[i].bd = NULL; 89 | 90 | if (g_cb != NULL) 91 | SetEventFlag(bdm_event, BDM_EVENT_CB_UMOUNT); 92 | } 93 | } 94 | } 95 | 96 | void bdm_connect_fs(struct file_system *fs) 97 | { 98 | int i; 99 | 100 | M_PRINTF("connecting fs %s\n", fs->name); 101 | 102 | for (i = 0; i < MAX_CONNECTIONS; ++i) { 103 | if (g_fs[i] == NULL) { 104 | g_fs[i] = fs; 105 | break; 106 | } 107 | } 108 | 109 | // New filesystem, try to mount it to the block devices 110 | SetEventFlag(bdm_event, BDM_EVENT_MOUNT); 111 | } 112 | 113 | void bdm_disconnect_fs(struct file_system *fs) 114 | { 115 | int i; 116 | 117 | M_PRINTF("disconnecting fs %s\n", fs->name); 118 | 119 | // Unmount fs from block devices 120 | for (i = 0; i < MAX_CONNECTIONS; ++i) { 121 | if (g_mount[i].fs == fs) { 122 | g_mount[i].fs = NULL; 123 | if (g_cb != NULL) 124 | SetEventFlag(bdm_event, BDM_EVENT_CB_UMOUNT); 125 | } 126 | } 127 | 128 | // Remove fs from list 129 | for (i = 0; i < MAX_CONNECTIONS; ++i) { 130 | if (g_fs[i] == fs) { 131 | g_fs[i] = NULL; 132 | break; 133 | } 134 | } 135 | } 136 | 137 | void bdm_get_bd(struct block_device **pbd, unsigned int count) 138 | { 139 | int i; 140 | 141 | M_DEBUG("%s\n", __func__); 142 | 143 | // Fill pointer array with block device pointers 144 | for (i = 0; (unsigned int)i < count && i < MAX_CONNECTIONS; i++) 145 | pbd[i] = g_mount[i].bd; 146 | } 147 | 148 | static void bdm_try_mount(struct bdm_mounts *mount) 149 | { 150 | int i; 151 | 152 | M_DEBUG("%s(%s%dp%d)\n", __func__, mount->bd->name, mount->bd->devNr, mount->bd->parNr); 153 | 154 | for (i = 0; i < MAX_CONNECTIONS; ++i) { 155 | if (g_fs[i] != NULL) { 156 | if (g_fs[i]->connect_bd(mount->cbd != NULL ? mount->cbd : mount->bd) == 0) { 157 | M_PRINTF("%s%dp%d mounted to %s\n", mount->bd->name, mount->bd->devNr, mount->bd->parNr, g_fs[i]->name); 158 | mount->fs = g_fs[i]; 159 | if (g_cb != NULL) 160 | SetEventFlag(bdm_event, BDM_EVENT_CB_MOUNT); 161 | break; 162 | } 163 | } 164 | } 165 | } 166 | 167 | static void bdm_thread(void *arg) 168 | { 169 | u32 EFBits; 170 | int i; 171 | 172 | (void)arg; 173 | 174 | M_PRINTF("BDM event thread running\n"); 175 | 176 | while (1) { 177 | WaitEventFlag(bdm_event, BDM_EVENT_CB_MOUNT | BDM_EVENT_CB_UMOUNT | BDM_EVENT_MOUNT, WEF_OR | WEF_CLEAR, &EFBits); 178 | 179 | if (EFBits & BDM_EVENT_MOUNT) { 180 | // Try to mount any unmounted block devices 181 | for (i = 0; i < MAX_CONNECTIONS; ++i) { 182 | if ((g_mount[i].bd != NULL) && (g_mount[i].fs == NULL)) 183 | bdm_try_mount(&g_mount[i]); 184 | } 185 | } 186 | 187 | if (EFBits & BDM_EVENT_CB_MOUNT) { 188 | // Notify callback about changes 189 | if (g_cb != NULL) 190 | g_cb(1); 191 | } 192 | 193 | if (EFBits & BDM_EVENT_CB_UMOUNT) { 194 | // Notify callback about changes 195 | if (g_cb != NULL) 196 | g_cb(0); 197 | } 198 | } 199 | } 200 | 201 | int bdm_init() 202 | { 203 | int i, result; 204 | iop_event_t EventFlagData; 205 | iop_thread_t ThreadData; 206 | 207 | M_DEBUG("%s\n", __func__); 208 | 209 | for (i = 0; i < MAX_CONNECTIONS; ++i) { 210 | g_mount[i].bd = NULL; 211 | g_mount[i].cbd = NULL; 212 | g_mount[i].fs = NULL; 213 | g_fs[i] = NULL; 214 | } 215 | 216 | EventFlagData.attr = 0; 217 | EventFlagData.option = 0; 218 | EventFlagData.bits = 0; 219 | result = bdm_event = CreateEventFlag(&EventFlagData); 220 | if (result < 0) { 221 | M_DEBUG("ERROR: CreateEventFlag %d\n", result); 222 | return result; 223 | } 224 | 225 | ThreadData.attr = TH_C; 226 | ThreadData.thread = bdm_thread; 227 | ThreadData.option = 0; 228 | ThreadData.priority = 0x30; // Low priority 229 | ThreadData.stacksize = 0x1000; // 4KiB 230 | result = bdm_thread_id = CreateThread(&ThreadData); 231 | if (result < 0) { 232 | M_DEBUG("ERROR: CreateThread %d\n", result); 233 | DeleteEventFlag(bdm_event); 234 | return result; 235 | } 236 | 237 | result = StartThread(bdm_thread_id, NULL); 238 | if (result < 0) { 239 | M_DEBUG("ERROR: StartThread %d\n", result); 240 | DeleteThread(bdm_thread_id); 241 | DeleteEventFlag(bdm_event); 242 | return result; 243 | } 244 | 245 | return 0; 246 | } 247 | -------------------------------------------------------------------------------- /__bdm_assault/src/bdm/bdm_main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // #define DEBUG //comment out this line when not debugging 7 | #include "include/module_debug.h" 8 | 9 | #define MAJOR_VER 2 10 | #define MINOR_VER 1 11 | 12 | IRX_ID("bdm", MAJOR_VER, MINOR_VER); 13 | 14 | extern struct irx_export_table _exp_bdm; 15 | extern int bdm_init(); 16 | extern void part_init(); 17 | extern int bdmfs_fatfs_start(int argc, char *argv[]); 18 | 19 | int _start(int argc, char *argv[]) 20 | { 21 | (void)argc; 22 | (void)argv; 23 | 24 | printf("Block Device Manager (BDM) v%d.%d\n", MAJOR_VER, MINOR_VER); 25 | 26 | if (RegisterLibraryEntries(&_exp_bdm) != 0) { 27 | M_PRINTF("ERROR: Already registered!\n"); 28 | return MODULE_NO_RESIDENT_END; 29 | } 30 | 31 | // initialize the block device manager 32 | if (bdm_init() < 0) { 33 | M_PRINTF("ERROR: BDM init failed!\n"); 34 | return MODULE_NO_RESIDENT_END; 35 | } 36 | 37 | // initialize the partition driver 38 | part_init(); 39 | 40 | return bdmfs_fatfs_start(argc, argv); //we return this func because both modules must be ready to work 41 | } 42 | -------------------------------------------------------------------------------- /__bdm_assault/src/bdm/bdm_part_driver.c: -------------------------------------------------------------------------------- 1 | #include "include/part_driver.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include "include/mbr_types.h" 9 | #include "include/gpt_types.h" 10 | 11 | #include "include/module_debug.h" 12 | 13 | #define U64_2XU32(val) ((u32*)val)[1], ((u32*)val)[0] 14 | 15 | struct partition g_part[MAX_PARTITIONS]; 16 | struct block_device g_part_bd[MAX_PARTITIONS]; 17 | 18 | static struct file_system g_mbr_fs; 19 | static struct file_system g_gpt_fs; 20 | 21 | int GetNextFreePartitionIndex() 22 | { 23 | // Loop and find the next free partition index. 24 | for (int i = 0; i < MAX_PARTITIONS; i++) 25 | { 26 | if (g_part[i].bd == NULL) 27 | return i; 28 | } 29 | 30 | // No more free partitions. 31 | return -1; 32 | } 33 | 34 | //--------------------------------------------------------------------------- 35 | void part_disconnect(struct block_device *bd) 36 | { 37 | int i; 38 | 39 | M_DEBUG("%s\n", __func__); 40 | 41 | for (i = 0; i < MAX_PARTITIONS; ++i) { 42 | if (g_part[i].bd == bd) { 43 | bdm_disconnect_bd(&g_part_bd[i]); 44 | g_part[i].bd = NULL; 45 | } 46 | } 47 | } 48 | 49 | // 50 | // Block device interface 51 | // 52 | static int part_read(struct block_device *bd, u64 sector, void *buffer, u16 count) 53 | { 54 | struct partition *part = (struct partition *)bd->priv; 55 | 56 | if ((part == NULL) || (part->bd == NULL)) 57 | return -1; 58 | 59 | #ifdef DEBUG 60 | u64 finalSector = sector + bd->sectorOffset; 61 | M_DEBUG("%s (%s %d %d) 0x%08x%08x %d\n", __func__, bd->name, bd->devNr, bd->parNr, U64_2XU32(&finalSector), count); 62 | #endif 63 | 64 | return part->bd->read(part->bd, sector + bd->sectorOffset, buffer, count); 65 | } 66 | 67 | static int part_write(struct block_device *bd, u64 sector, const void *buffer, u16 count) 68 | { 69 | struct partition *part = (struct partition *)bd->priv; 70 | 71 | if ((part == NULL) || (part->bd == NULL)) 72 | return -1; 73 | 74 | #ifdef DEBUG 75 | u64 finalSector = sector + bd->sectorOffset; 76 | M_DEBUG("%s (%s %d %d) 0x%08x%08x %d\n", __func__, bd->name, bd->devNr, bd->parNr, U64_2XU32(&finalSector), count); 77 | #endif 78 | 79 | return part->bd->write(part->bd, sector + bd->sectorOffset, buffer, count); 80 | } 81 | 82 | static void part_flush(struct block_device *bd) 83 | { 84 | struct partition *part = (struct partition *)bd->priv; 85 | 86 | M_DEBUG("%s\n", __func__); 87 | 88 | if ((part == NULL) || (part->bd == NULL)) 89 | return; 90 | 91 | return part->bd->flush(part->bd); 92 | } 93 | 94 | static int part_stop(struct block_device *bd) 95 | { 96 | struct partition *part = (struct partition *)bd->priv; 97 | 98 | M_DEBUG("%s\n", __func__); 99 | 100 | if ((part == NULL) || (part->bd == NULL)) 101 | return -1; 102 | 103 | return part->bd->stop(part->bd); 104 | } 105 | 106 | void part_init() 107 | { 108 | int i; 109 | 110 | M_DEBUG("%s\n", __func__); 111 | 112 | for (i = 0; i < MAX_PARTITIONS; ++i) { 113 | g_part[i].bd = NULL; 114 | 115 | g_part_bd[i].priv = &g_part[i]; 116 | g_part_bd[i].read = part_read; 117 | g_part_bd[i].write = part_write; 118 | g_part_bd[i].flush = part_flush; 119 | g_part_bd[i].stop = part_stop; 120 | } 121 | 122 | // Setup MBR file system driver: 123 | g_mbr_fs.priv = NULL; 124 | g_mbr_fs.name = "MBR"; 125 | g_mbr_fs.connect_bd = part_connect_mbr; 126 | g_mbr_fs.disconnect_bd = part_disconnect; 127 | bdm_connect_fs(&g_mbr_fs); 128 | 129 | // Setup GPT file system driver: 130 | g_gpt_fs.priv = NULL; 131 | g_gpt_fs.name = "GPT"; 132 | g_gpt_fs.connect_bd = part_connect_gpt; 133 | g_gpt_fs.disconnect_bd = part_disconnect; 134 | bdm_connect_fs(&g_gpt_fs); 135 | } 136 | -------------------------------------------------------------------------------- /__bdm_assault/src/bdm/bdm_part_driver_gpt.c: -------------------------------------------------------------------------------- 1 | #include "include/part_driver.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include "include/gpt_types.h" 9 | 10 | #include "include/module_debug.h" 11 | 12 | #define U64_2XU32(val) ((u32*)val)[1], ((u32*)val)[0] 13 | 14 | void GetGPTPartitionNameAscii(gpt_partition_table_entry* pPartition, char* pAsciiBuffer) 15 | { 16 | // Loop and perform the world's worst unicode -> ascii string conversion. 17 | for (int i = 0; i < sizeof(pPartition->partition_name) / sizeof(u16); i++) 18 | pAsciiBuffer[i] = (char)pPartition->partition_name[i]; 19 | } 20 | 21 | int part_connect_gpt(struct block_device *bd) 22 | { 23 | int ret; 24 | void* buffer = NULL; 25 | gpt_partition_table_header* pGptHeader; 26 | gpt_partition_table_entry* pGptPartitionEntry; 27 | int entriesPerSector; 28 | int endOfTable = 0; 29 | char partName[37] = { 0 }; 30 | int partIndex; 31 | int mountCount = 0; 32 | 33 | M_DEBUG("%s\n", __func__); 34 | 35 | // Allocate scratch memory for parsing the partition table. 36 | buffer = AllocSysMemory(ALLOC_FIRST, 512 * 2, NULL); 37 | if (buffer == NULL) 38 | { 39 | M_DEBUG("Failed to allocate memory\n"); 40 | return 0; 41 | } 42 | 43 | pGptHeader = (gpt_partition_table_header*)buffer; 44 | pGptPartitionEntry = (gpt_partition_table_entry*)((u8*)buffer + 512); 45 | 46 | // Read the GPT partition table header from the block device. 47 | ret = bd->read(bd, 1, pGptHeader, 1); 48 | if (ret < 0) 49 | { 50 | // Failed to read gpt partition table header. 51 | M_DEBUG("Failed to read GPT partition table header %d\n", ret); 52 | FreeSysMemory(buffer); 53 | return -1; 54 | } 55 | 56 | // Check the partition table header signature. 57 | if (memcmp(pGptHeader->signature, EFI_PARTITION_SIGNATURE, sizeof(EFI_PARTITION_SIGNATURE)) != 0) 58 | { 59 | // GPT partition table header signature is invalid. 60 | M_DEBUG("GPT partition table header signature is invalid: %s\n", pGptHeader->signature); 61 | FreeSysMemory(buffer); 62 | return -1; 63 | } 64 | 65 | // TODO: we might want to check the header revision and size for compatibility for newer/older GPT layouts. There's 66 | // also a few CRC checksums in the header that may be useful to validate, but is probably not needed. 67 | 68 | // Calculate how many partition entries there are per sector. 69 | entriesPerSector = bd->sectorSize / sizeof(gpt_partition_table_entry); 70 | 71 | // Loop through all the partition table entries and attempt to mount each one. 72 | printf("Found GPT disk '%08x...'\n", *(u32*)&pGptHeader->disk_guid); 73 | for (int i = 0; i < pGptHeader->partition_count && endOfTable == 0; ) 74 | { 75 | // Check if we need to buffer more data, GPT usually uses LBA 2-33 for partition table entries. Typically there will 76 | // only be a couple partitions at most, so we buffer one sector at a time to avoid making needless allocations for all sectors at once. 77 | if (i % entriesPerSector == 0) 78 | { 79 | // Read the next sector from the block device. 80 | ret = bd->read(bd, pGptHeader->partition_table_lba + (i / entriesPerSector), pGptPartitionEntry, 1); 81 | if (ret < 0) 82 | { 83 | // Failed to read the next sector from the drive. 84 | #ifdef DEBUG 85 | u64 lba = pGptHeader->partition_table_lba + (i / entriesPerSector); 86 | M_DEBUG("Failed to read next partition table entry sector lba=0x%08x%08x\n", U64_2XU32(&lba)); 87 | #endif 88 | FreeSysMemory(buffer); 89 | return -1; 90 | } 91 | 92 | // Parse the two partition table entries in the structure. 93 | for (int x = 0; x < entriesPerSector; x++, i++) 94 | { 95 | // Check if the partition type guid is valid, the header will list the maximum number of partitions that can fit into the table, so 96 | // we need to check if the entries are actually valid. 97 | if (memcmp(pGptPartitionEntry[x].partition_type_guid, NULL_GUID, sizeof(NULL_GUID)) == 0) 98 | { 99 | // Stop scanning for partitions. 100 | endOfTable = 1; 101 | break; 102 | } 103 | 104 | // Perform some sanity checks on the partition. 105 | if (pGptPartitionEntry[x].first_lba < pGptHeader->first_lba || pGptPartitionEntry[x].last_lba > pGptHeader->last_lba) 106 | { 107 | // Partition entry data appears to be corrupt. 108 | M_DEBUG("Partition entry %d appears to be corrupt (lba bounds incorrect)\n", i); 109 | continue; 110 | } 111 | 112 | // Print the partition info and create a pseudo block device for it. 113 | GetGPTPartitionNameAscii(&pGptPartitionEntry[x], partName); 114 | printf("Found partition '%s' type=%08x unique=%08x start=0x%08x%08x end=0x%08x%08x attr=0x%08x%08x\n", partName, *(u32*)&pGptPartitionEntry[x].partition_type_guid, 115 | *(u32*)&pGptPartitionEntry[x].partition_unique_guid, U64_2XU32(&pGptPartitionEntry[x].first_lba), U64_2XU32(&pGptPartitionEntry[x].last_lba), U64_2XU32(&pGptPartitionEntry[x].attribute_flags)); 116 | 117 | // Check for specific GPT partition types we should ignore. 118 | if (memcmp(pGptPartitionEntry[x].partition_type_guid, MS_RESERVED_PARTITION_GUID, sizeof(MS_RESERVED_PARTITION_GUID)) == 0 || 119 | memcmp(pGptPartitionEntry[x].partition_type_guid, EFI_SYSTEM_PARTITION, sizeof(EFI_SYSTEM_PARTITION)) == 0) 120 | continue; 121 | 122 | // Check if the partition should be ignored. 123 | if ((pGptPartitionEntry[x].attribute_flags & GPT_PART_ATTR_IGNORE) != 0) 124 | continue; 125 | 126 | // TODO: Check type specific partition flags: read-only, hidden, etc. 127 | 128 | if ((partIndex = GetNextFreePartitionIndex()) == -1) 129 | { 130 | // No more free partition slots. 131 | printf("Can't mount partition, no more free partition slots!\n"); 132 | continue; 133 | } 134 | 135 | // Create the pseudo block device for the partition. 136 | g_part[partIndex].bd = bd; 137 | g_part_bd[partIndex].name = bd->name; 138 | g_part_bd[partIndex].devNr = bd->devNr; 139 | g_part_bd[partIndex].parNr = i + 1; 140 | g_part_bd[partIndex].parId = 0; 141 | g_part_bd[partIndex].sectorSize = bd->sectorSize; 142 | g_part_bd[partIndex].sectorOffset = bd->sectorOffset + pGptPartitionEntry[x].first_lba; 143 | g_part_bd[partIndex].sectorCount = pGptPartitionEntry[x].last_lba - pGptPartitionEntry[x].first_lba; 144 | bdm_connect_bd(&g_part_bd[partIndex]); 145 | mountCount++; 146 | } 147 | } 148 | } 149 | 150 | // Free our scratch buffer. 151 | FreeSysMemory(buffer); 152 | return mountCount > 0 ? 0 : -1; 153 | } -------------------------------------------------------------------------------- /__bdm_assault/src/bdm/bdm_part_driver_mbr.c: -------------------------------------------------------------------------------- 1 | #include "include/part_driver.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include "include/mbr_types.h" 9 | 10 | #include "include/module_debug.h" 11 | 12 | int part_connect_mbr(struct block_device *bd) 13 | { 14 | master_boot_record* pMbrBlock = NULL; 15 | int rval = -1; 16 | int ret; 17 | int mountCount = 0; 18 | int partIndex; 19 | 20 | M_DEBUG("%s\n", __func__); 21 | 22 | // Filter out any block device where sectorOffset != 0, as this will be a block device for a file system partition and not 23 | // the raw device. 24 | if (bd->sectorOffset != 0) 25 | return rval; 26 | 27 | // Allocate memory for MBR partition sector. 28 | pMbrBlock = AllocSysMemory(ALLOC_FIRST, sizeof(master_boot_record), NULL); 29 | if (pMbrBlock == NULL) 30 | { 31 | // Failed to allocate memory for mbr block. 32 | M_DEBUG("Failed to allocate memory for MBR block\n"); 33 | return rval; 34 | } 35 | 36 | // Read the MBR block from the block device. 37 | ret = bd->read(bd, 0, pMbrBlock, 1); 38 | if (ret < 0) 39 | { 40 | // Failed to read MBR block from the block device. 41 | M_DEBUG("Failed to read MBR sector from block device %d\n", ret); 42 | return rval; 43 | } 44 | 45 | // Check the MBR boot signature. 46 | if (pMbrBlock->boot_signature != MBR_BOOT_SIGNATURE) 47 | { 48 | // Boot signature is invalid, device is not valid MBR. 49 | M_DEBUG("MBR boot signature is invalid, device is not MBR\n"); 50 | FreeSysMemory(pMbrBlock); 51 | return rval; 52 | } 53 | 54 | // Check the first primary partition to see if this is a GPT protective MBR. 55 | if (pMbrBlock->primary_partitions[0].partition_type == MBR_PART_TYPE_GPT_PROTECTIVE_MBR) 56 | { 57 | // We explicitly fail to connect GPT protective MBRs in order to let the GPT driver handle it. 58 | FreeSysMemory(pMbrBlock); 59 | return rval; 60 | } 61 | 62 | // Loop and parse the primary partition entries in the MBR block. 63 | printf("Found MBR disk\n"); 64 | for (int i = 0; i < 4; i++) 65 | { 66 | // Check if the partition is active, checking the status bit is not reliable so check if the sector_count is greater than zero instead. 67 | if (pMbrBlock->primary_partitions[i].sector_count == 0) 68 | continue; 69 | 70 | printf("Found partition type 0x%02x\n", pMbrBlock->primary_partitions[i].partition_type); 71 | 72 | // TODO: Filter out unsupported partition types. 73 | 74 | if ((partIndex = GetNextFreePartitionIndex()) == -1) 75 | { 76 | // No more free partition slots. 77 | printf("Can't mount partition, no more free partition slots!\n"); 78 | continue; 79 | } 80 | 81 | // Create the pseudo block device for the partition. 82 | g_part[partIndex].bd = bd; 83 | g_part_bd[partIndex].name = bd->name; 84 | g_part_bd[partIndex].devNr = bd->devNr; 85 | g_part_bd[partIndex].parNr = i + 1; 86 | g_part_bd[partIndex].parId = pMbrBlock->primary_partitions[i].partition_type; 87 | g_part_bd[partIndex].sectorSize = bd->sectorSize; 88 | g_part_bd[partIndex].sectorOffset = bd->sectorOffset + (u64)pMbrBlock->primary_partitions[i].first_lba; 89 | g_part_bd[partIndex].sectorCount = pMbrBlock->primary_partitions[i].sector_count; 90 | bdm_connect_bd(&g_part_bd[partIndex]); 91 | mountCount++; 92 | } 93 | 94 | // If one or more partitions were mounted then return success. 95 | rval = mountCount > 0 ? 0 : -1; 96 | 97 | FreeSysMemory(pMbrBlock); 98 | return rval; 99 | } -------------------------------------------------------------------------------- /__bdm_assault/src/bdm/include/gpt_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Licenced under Academic Free License version 2.0 7 | # Review ps2sdk README & LICENSE files for further details. 8 | */ 9 | 10 | /** 11 | * @file 12 | * GPT partition definitions. 13 | */ 14 | 15 | #ifndef _GPT_TYPES_H 16 | #define _GPT_TYPES_H 17 | 18 | #include 19 | 20 | static const u8 EFI_PARTITION_SIGNATURE[8] = { 'E', 'F', 'I', ' ', 'P', 'A', 'R', 'T' }; 21 | 22 | typedef struct __attribute__((packed)) _gpt_partition_table_header 23 | { 24 | /* 0x00 */ u8 signature[8]; // 'EFI PART' 25 | /* 0x08 */ u32 revision; // Revision 1.0 (00h 00h 01h 00h) for UEFI 2.8 26 | /* 0x0C */ u32 header_size; // Header size in little endian (in bytes, usually 5Ch 00h 00h 00h or 92 bytes) 27 | /* 0x10 */ u32 header_checksum; // CRC32 of header (offset +0 to +0x5b) in little endian, with this field zeroed during calculation 28 | /* 0x14 */ u32 reserved1; // Reserved, must be zero 29 | /* 0x18 */ u64 current_lba; // Current LBA (location of this header copy) 30 | /* 0x20 */ u64 backup_lba; // Backup LBA (location of the other header copy) 31 | /* 0x28 */ u64 first_lba; // First usable LBA for partitions (primary partition table last LBA + 1) 32 | /* 0x30 */ u64 last_lba; // Last usable LBA (secondary partition table first LBA − 1) 33 | /* 0x38 */ u8 disk_guid[16]; // Disk GUID in mixed endian 34 | /* 0x48 */ u64 partition_table_lba; // Starting LBA of array of partition entries (usually 2 for compatibility) 35 | /* 0x50 */ u32 partition_count; // Number of partition entries in array 36 | /* 0x54 */ u32 partition_entry_size; // Size of a single partition entry (usually 80h or 128) 37 | /* 0x58 */ u32 partition_table_checksum; // CRC32 of partition entries array in little endian 38 | } gpt_partition_table_header; 39 | 40 | // Partition type GUIDs: 41 | static const u8 NULL_GUID[16] = { 0 }; 42 | static const u8 MS_RESERVED_PARTITION_GUID[16] = { 0x16, 0xE3, 0xC9, 0xE3, 0x5C, 0x0B, 0xB8, 0x4D, 0x81, 0x7D, 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE }; 43 | static const u8 EFI_SYSTEM_PARTITION[16] = { 0x28, 0x73, 0x2A, 0xC1, 0x1F, 0xF8, 0xD2, 0x11, 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B }; 44 | static const u8 MS_BASIC_DATA_PARTITION_GUID[16] = { 0xA2, 0xA0, 0xD0, 0xEB, 0xE5, 0xB9, 0x33, 0x44, 0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7 }; 45 | 46 | typedef struct __attribute__((packed)) _gpt_partition_table_entry 47 | { 48 | /* 0x00 */ u8 partition_type_guid[16]; // Partition type guid (mixed endian) 49 | /* 0x10 */ u8 partition_unique_guid[16]; // Unique partition id 50 | /* 0x20 */ u64 first_lba; // First LBA (little endian) 51 | /* 0x28 */ u64 last_lba; // Last LBA (inclusive, usually odd) 52 | /* 0x30 */ u64 attribute_flags; // Attribute flags (e.g. bit 60 denotes read-only) 53 | /* 0x38 */ u16 partition_name[36]; // Partition name (36 UTF-16LE code units) 54 | } gpt_partition_table_entry; 55 | 56 | #define GPT_PART_ATTR_PLATFORM_REQUIRED 0x1 // Platform required (required by the computer to function properly, OEM partition for example, disk partitioning utilities must preserve the partition as is) 57 | #define GPT_PART_ATTR_IGNORE 0x2 // EFI firmware should ignore the content of the partition and not try to read from it 58 | #define GPT_PART_ATTR_LEGACY_BOOTABLE 0x4 // Legacy BIOS bootable 59 | 60 | #define GPT_PART_ATTR_TYPE_SHIFT 48 // Number of partition attribute bits reserved for common attribute 61 | #define GPT_PART_ATTR_TYPE_MASK 0xFFFF // Mask for type-specific attribute bits (after shifting) 62 | #define GPT_PART_ATTR_TYPE_SPECIFIC(attr) ((attr >> GPT_PART_ATTR_TYPE_SHIFT) & GPT_PART_ATTR_TYPE_MASK) 63 | 64 | // Basic data partition type-specific attribute flags: 65 | #define GPT_BDP_ATTR_READ_ONLY 0x1000 // Partition is read only 66 | #define GPT_BDP_ATTR_SHADOW_COPY 0x2000 // Shadow copy (of another partition) 67 | #define GPT_BDP_ATTR_HIDDEN 0x4000 // Partition is hidden 68 | #define GPT_BDP_ATTR_NO_DRIVE_LETTER 0x8000 // No drive letter (i.e. do not automount) 69 | 70 | #endif // _GPT_TYPES_H 71 | -------------------------------------------------------------------------------- /__bdm_assault/src/bdm/include/mbr_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Licenced under Academic Free License version 2.0 7 | # Review ps2sdk README & LICENSE files for further details. 8 | */ 9 | 10 | /** 11 | * @file 12 | * MBR partition definitions. 13 | */ 14 | 15 | #ifndef _MBR_TYPES_H 16 | #define _MBR_TYPES_H 17 | 18 | #include 19 | 20 | #define MBR_BOOT_SIGNATURE 0xAA55 21 | 22 | #define MBR_PART_TYPE_GPT_PROTECTIVE_MBR 0xEE // Indicates the MBR is 'protective' only and the actual format is GPT 23 | 24 | // See: https://en.wikipedia.org/wiki/Master_boot_record#PTE 25 | typedef struct __attribute__((packed)) _mbr_partition_entry 26 | { 27 | /* 0x00 */ u8 status; // Status or physical drive (bit 7 set is for active or bootable, old MBRs only accept 0x80, 0x00 means inactive, and 0x01–0x7F stand for invalid) 28 | /* 0x01 */ u8 chs_first_lba[3]; // CHS address of first absolute sector in partition 29 | /* 0x04 */ u8 partition_type; // Type of partition, see: https://en.wikipedia.org/wiki/Partition_type 30 | /* 0x05 */ u8 chs_last_lba[3]; // CHS address of last absolute sector in partition 31 | /* 0x08 */ u32 first_lba; // LBA of first absolute sector in the partition 32 | /* 0x0C */ u32 sector_count; // Number of sectors in partition 33 | } mbr_partition_entry; 34 | 35 | // See: https://en.wikipedia.org/wiki/Master_boot_record 36 | typedef struct __attribute__((packed)) _master_boot_record 37 | { 38 | /* 0x00 */ u8 bootstrap_code1[218]; // Bootstrap code area (part 1) 39 | /* 0xDA */ u8 disk_timestamp[6]; // Disk timestamp (optional; Windows 95B/98/98SE/ME (MS-DOS 7.1–8.0). Alternatively, can serve as OEM loader signature with NEWLDR) 40 | /* 0xE0 */ u8 bootstrap_code2[216]; // Bootstrap code area (part 2, code entry at 0x0000) 41 | /* 0x1B8 */ u32 disk_signature; // Disk signature (optional; UEFI, Linux, Windows NT family and other OSes) 42 | /* 0x1BC */ u16 copy_protection; // 0x0000 (0x5A5A if copy-protected) 43 | /* 0x1BE */ mbr_partition_entry primary_partitions[4]; // Partition table (for primary partitions) 44 | /* 0x1FE */ u16 boot_signature; // 0xAA55 45 | } master_boot_record; 46 | 47 | #endif // _MBR_TYPES_H 48 | -------------------------------------------------------------------------------- /__bdm_assault/src/bdm/include/module_debug.h: -------------------------------------------------------------------------------- 1 | #ifndef _MODULE_DEBUG_H 2 | #define _MODULE_DEBUG_H 3 | 4 | // #define MINI_DRIVER 5 | 6 | #ifndef MINI_DRIVER 7 | #define M_PRINTF(format, args...) printf("BDM: " format, ##args) 8 | #else 9 | #define M_PRINTF(format, args...) \ 10 | do { \ 11 | } while (0) 12 | #endif 13 | 14 | #ifdef DEBUG 15 | #define M_DEBUG M_PRINTF 16 | #else 17 | #define M_DEBUG(format, args...) \ 18 | do { \ 19 | } while (0) 20 | #endif 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /__bdm_assault/src/bdm/include/part_driver.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Licenced under Academic Free License version 2.0 7 | # Review ps2sdk README & LICENSE files for further details. 8 | */ 9 | 10 | /** 11 | * @file 12 | * Common partition driver definitions. 13 | */ 14 | 15 | #ifndef _PART_DRIVER_H 16 | #define _PART_DRIVER_H 17 | 18 | #include 19 | 20 | struct partition 21 | { 22 | struct block_device *bd; 23 | }; 24 | 25 | #define MAX_PARTITIONS 10 26 | extern struct partition g_part[MAX_PARTITIONS]; 27 | extern struct block_device g_part_bd[MAX_PARTITIONS]; 28 | 29 | int GetNextFreePartitionIndex(); 30 | 31 | int part_connect_mbr(struct block_device *bd); 32 | int part_connect_gpt(struct block_device *bd); 33 | 34 | #endif -------------------------------------------------------------------------------- /__bdm_assault/src/bdmfs/bdmfs_diskio.c: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------*/ 2 | /* Low level disk I/O module SKELETON for FatFs (C)ChaN, 2019 */ 3 | /*-----------------------------------------------------------------------*/ 4 | /* If a working storage control module is available, it should be */ 5 | /* attached to the FatFs via a glue function rather than modifying it. */ 6 | /* This is an example of glue functions to attach various exsisting */ 7 | /* storage control modules to the FatFs module with a defined API. */ 8 | /*-----------------------------------------------------------------------*/ 9 | 10 | #include 11 | #include 12 | 13 | #include "include/ff.h" /* Obtains integer types */ 14 | #include "include/diskio.h" /* Declarations of disk functions */ 15 | 16 | #include "include/fs_driver.h" 17 | 18 | /*-----------------------------------------------------------------------*/ 19 | /* Get Drive Status */ 20 | /*-----------------------------------------------------------------------*/ 21 | 22 | DSTATUS disk_status( 23 | BYTE pdrv /* Physical drive number to identify the drive */ 24 | ) 25 | { 26 | int result; 27 | 28 | result = (fatfs_fs_driver_get_mounted_bd_from_index(pdrv) == NULL) ? (STA_NOINIT | STA_NODISK) : 0; 29 | 30 | return result; 31 | } 32 | 33 | 34 | 35 | /*-----------------------------------------------------------------------*/ 36 | /* Inidialize a Drive */ 37 | /*-----------------------------------------------------------------------*/ 38 | 39 | DSTATUS disk_initialize( 40 | BYTE pdrv /* Physical drive nmuber to identify the drive */ 41 | ) 42 | { 43 | int result; 44 | 45 | result = (fatfs_fs_driver_get_mounted_bd_from_index(pdrv) == NULL) ? (STA_NOINIT | STA_NODISK) : 0; 46 | 47 | return result; 48 | } 49 | 50 | 51 | 52 | /*-----------------------------------------------------------------------*/ 53 | /* Read Sector(s) */ 54 | /*-----------------------------------------------------------------------*/ 55 | 56 | DRESULT disk_read( 57 | BYTE pdrv, /* Physical drive nmuber to identify the drive */ 58 | BYTE *buff, /* Data buffer to store read data */ 59 | LBA_t sector, /* Start sector in LBA */ 60 | UINT count /* Number of sectors to read */ 61 | ) 62 | { 63 | DRESULT res; 64 | struct block_device *mounted_bd; 65 | 66 | mounted_bd = fatfs_fs_driver_get_mounted_bd_from_index(pdrv); 67 | 68 | if (mounted_bd == NULL) { 69 | return RES_NOTRDY; 70 | } 71 | 72 | res = mounted_bd->read(mounted_bd, sector, buff, count); 73 | 74 | return (res == count) ? RES_OK : RES_ERROR; 75 | } 76 | 77 | 78 | 79 | /*-----------------------------------------------------------------------*/ 80 | /* Write Sector(s) */ 81 | /*-----------------------------------------------------------------------*/ 82 | 83 | #if FF_FS_READONLY == 0 84 | 85 | DRESULT disk_write( 86 | BYTE pdrv, /* Physical drive nmuber to identify the drive */ 87 | const BYTE *buff, /* Data to be written */ 88 | LBA_t sector, /* Start sector in LBA */ 89 | UINT count /* Number of sectors to write */ 90 | ) 91 | { 92 | DRESULT res; 93 | struct block_device *mounted_bd; 94 | 95 | mounted_bd = fatfs_fs_driver_get_mounted_bd_from_index(pdrv); 96 | 97 | if (mounted_bd == NULL) { 98 | return RES_NOTRDY; 99 | } 100 | 101 | res = mounted_bd->write(mounted_bd, sector, buff, count); 102 | 103 | return (res == count) ? RES_OK : RES_ERROR; 104 | } 105 | 106 | #endif 107 | 108 | 109 | /*-----------------------------------------------------------------------*/ 110 | /* Miscellaneous Functions */ 111 | /*-----------------------------------------------------------------------*/ 112 | 113 | DRESULT disk_ioctl( 114 | BYTE pdrv, /* Physical drive nmuber (0..) */ 115 | BYTE cmd, /* Control code */ 116 | void *buff /* Buffer to send/receive control data */ 117 | ) 118 | { 119 | struct block_device *mounted_bd; 120 | 121 | mounted_bd = fatfs_fs_driver_get_mounted_bd_from_index(pdrv); 122 | 123 | if (mounted_bd == NULL) { 124 | return RES_NOTRDY; 125 | } 126 | 127 | switch (cmd) { 128 | case CTRL_SYNC: 129 | mounted_bd->flush(mounted_bd); 130 | break; 131 | case GET_SECTOR_COUNT: 132 | *(unsigned int *)buff = mounted_bd->sectorCount; 133 | break; 134 | case GET_SECTOR_SIZE: 135 | *(unsigned int *)buff = mounted_bd->sectorSize; 136 | break; 137 | case GET_BLOCK_SIZE: 138 | *(unsigned int *)buff = 0; 139 | break; 140 | } 141 | 142 | return RES_OK; 143 | } 144 | 145 | DWORD get_fattime(void) 146 | { 147 | // ps2 specific routine to get time and date 148 | int year, month, day, hour, minute, sec; 149 | sceCdCLOCK cdtime; 150 | 151 | if (sceCdReadClock(&cdtime) != 0 && cdtime.stat == 0) { 152 | sec = btoi(cdtime.second); 153 | minute = btoi(cdtime.minute); 154 | hour = btoi(cdtime.hour); 155 | day = btoi(cdtime.day); 156 | month = btoi(cdtime.month & 0x7F); // Ignore century bit (when an old CDVDMAN is used). 157 | year = btoi(cdtime.year) + 2000; 158 | } else { 159 | year = 2005; 160 | month = 1; 161 | day = 6; 162 | hour = 14; 163 | minute = 12; 164 | sec = 10; 165 | } 166 | 167 | /* Pack date and time into a DWORD variable */ 168 | return ((DWORD)(year - 1980) << 25) | ((DWORD)month << 21) | ((DWORD)day << 16) | ((DWORD)hour << 11) | ((DWORD)minute << 5) | ((DWORD)sec >> 1); 169 | } -------------------------------------------------------------------------------- /__bdm_assault/src/bdmfs/bdmfs_ffsystem.c: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------*/ 2 | /* Sample Code of OS Dependent Functions for FatFs */ 3 | /* (C)ChaN, 2018 */ 4 | /*------------------------------------------------------------------------*/ 5 | 6 | 7 | #include "include/ff.h" 8 | #include 9 | 10 | 11 | #if FF_USE_LFN == 3 /* Dynamic memory allocation */ 12 | 13 | /*------------------------------------------------------------------------*/ 14 | /* Allocate a memory block */ 15 | /*------------------------------------------------------------------------*/ 16 | 17 | void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */ 18 | UINT msize /* Number of bytes to allocate */ 19 | ) 20 | { 21 | return malloc(msize); /* Allocate a new memory block with POSIX API */ 22 | } 23 | 24 | 25 | /*------------------------------------------------------------------------*/ 26 | /* Free a memory block */ 27 | /*------------------------------------------------------------------------*/ 28 | 29 | void ff_memfree ( 30 | void* mblock /* Pointer to the memory block to free (nothing to do if null) */ 31 | ) 32 | { 33 | free(mblock); /* Free the memory block with POSIX API */ 34 | } 35 | 36 | #endif 37 | 38 | 39 | 40 | #if FF_FS_REENTRANT /* Mutal exclusion */ 41 | 42 | /*------------------------------------------------------------------------*/ 43 | /* Create a Synchronization Object */ 44 | /*------------------------------------------------------------------------*/ 45 | /* This function is called in f_mount() function to create a new 46 | / synchronization object for the volume, such as semaphore and mutex. 47 | / When a 0 is returned, the f_mount() function fails with FR_INT_ERR. 48 | */ 49 | 50 | //const osMutexDef_t Mutex[FF_VOLUMES]; /* Table of CMSIS-RTOS mutex */ 51 | 52 | 53 | int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */ 54 | BYTE vol, /* Corresponding volume (logical drive number) */ 55 | FF_SYNC_t* sobj /* Pointer to return the created sync object */ 56 | ) 57 | { 58 | #if 0 59 | /* Win32 */ 60 | *sobj = CreateMutex(NULL, FALSE, NULL); 61 | return (int)(*sobj != INVALID_HANDLE_VALUE); 62 | 63 | /* uITRON */ 64 | // T_CSEM csem = {TA_TPRI,1,1}; 65 | // *sobj = acre_sem(&csem); 66 | // return (int)(*sobj > 0); 67 | 68 | /* uC/OS-II */ 69 | // OS_ERR err; 70 | // *sobj = OSMutexCreate(0, &err); 71 | // return (int)(err == OS_NO_ERR); 72 | 73 | /* FreeRTOS */ 74 | // *sobj = xSemaphoreCreateMutex(); 75 | // return (int)(*sobj != NULL); 76 | 77 | /* CMSIS-RTOS */ 78 | // *sobj = osMutexCreate(&Mutex[vol]); 79 | // return (int)(*sobj != NULL); 80 | #endif 81 | /* IOP kernel */ 82 | iop_sema_t sp; 83 | 84 | sp.initial = 1; 85 | sp.max = 1; 86 | sp.option = 0; 87 | sp.attr = 0; 88 | if ((*sobj = CreateSema(&sp)) < 0) { 89 | return 0; 90 | } 91 | 92 | return 1; 93 | } 94 | 95 | 96 | /*------------------------------------------------------------------------*/ 97 | /* Delete a Synchronization Object */ 98 | /*------------------------------------------------------------------------*/ 99 | /* This function is called in f_mount() function to delete a synchronization 100 | / object that created with ff_cre_syncobj() function. When a 0 is returned, 101 | / the f_mount() function fails with FR_INT_ERR. 102 | */ 103 | 104 | int ff_del_syncobj ( /* 1:Function succeeded, 0:Could not delete due to an error */ 105 | FF_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */ 106 | ) 107 | { 108 | #if 0 109 | /* Win32 */ 110 | return (int)CloseHandle(sobj); 111 | 112 | /* uITRON */ 113 | // return (int)(del_sem(sobj) == E_OK); 114 | 115 | /* uC/OS-II */ 116 | // OS_ERR err; 117 | // OSMutexDel(sobj, OS_DEL_ALWAYS, &err); 118 | // return (int)(err == OS_NO_ERR); 119 | 120 | /* FreeRTOS */ 121 | // vSemaphoreDelete(sobj); 122 | // return 1; 123 | 124 | /* CMSIS-RTOS */ 125 | // return (int)(osMutexDelete(sobj) == osOK); 126 | #endif 127 | /* IOP kernel */ 128 | if (sobj >= 0) { 129 | DeleteSema(sobj); 130 | return 1; 131 | } 132 | return 0; 133 | } 134 | 135 | 136 | /*------------------------------------------------------------------------*/ 137 | /* Request Grant to Access the Volume */ 138 | /*------------------------------------------------------------------------*/ 139 | /* This function is called on entering file functions to lock the volume. 140 | / When a 0 is returned, the file function fails with FR_TIMEOUT. 141 | */ 142 | 143 | int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */ 144 | FF_SYNC_t sobj /* Sync object to wait */ 145 | ) 146 | { 147 | #if 0 148 | /* Win32 */ 149 | return (int)(WaitForSingleObject(sobj, FF_FS_TIMEOUT) == WAIT_OBJECT_0); 150 | 151 | /* uITRON */ 152 | // return (int)(wai_sem(sobj) == E_OK); 153 | 154 | /* uC/OS-II */ 155 | // OS_ERR err; 156 | // OSMutexPend(sobj, FF_FS_TIMEOUT, &err)); 157 | // return (int)(err == OS_NO_ERR); 158 | 159 | /* FreeRTOS */ 160 | // return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE); 161 | 162 | /* CMSIS-RTOS */ 163 | // return (int)(osMutexWait(sobj, FF_FS_TIMEOUT) == osOK); 164 | #endif 165 | WaitSema(sobj); 166 | return 1; 167 | } 168 | 169 | 170 | /*------------------------------------------------------------------------*/ 171 | /* Release Grant to Access the Volume */ 172 | /*------------------------------------------------------------------------*/ 173 | /* This function is called on leaving file functions to unlock the volume. 174 | */ 175 | 176 | void ff_rel_grant ( 177 | FF_SYNC_t sobj /* Sync object to be signaled */ 178 | ) 179 | { 180 | #if 0 181 | /* Win32 */ 182 | ReleaseMutex(sobj); 183 | 184 | /* uITRON */ 185 | // sig_sem(sobj); 186 | 187 | /* uC/OS-II */ 188 | // OSMutexPost(sobj); 189 | 190 | /* FreeRTOS */ 191 | // xSemaphoreGive(sobj); 192 | 193 | /* CMSIS-RTOS */ 194 | // osMutexRelease(sobj); 195 | #endif 196 | SignalSema(sobj); 197 | } 198 | 199 | #endif 200 | 201 | -------------------------------------------------------------------------------- /__bdm_assault/src/bdmfs/bdmfs_main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "include/ff.h" 10 | #include "include/fs_driver.h" 11 | 12 | //#define DEBUG //comment out this line when not debugging 13 | #include "include/module_debug.h" 14 | 15 | #define MAJOR_VER 1 16 | #define MINOR_VER 4 17 | 18 | // IRX_ID("bdmff", MAJOR_VER, MINOR_VER); //because were fusing two IRX 19 | 20 | static struct file_system g_fs = { 21 | .priv = NULL, 22 | .name = "fatfs", 23 | .connect_bd = connect_bd, 24 | .disconnect_bd = disconnect_bd, 25 | }; 26 | 27 | int bdmfs_fatfs_start(int argc, char *argv[]) 28 | { 29 | (void)argc; 30 | (void)argv; 31 | 32 | printf("BDM_ASSAULT: starting Fatfs side\n"); 33 | 34 | // initialize the file system driver 35 | if (InitFS() != 0) { 36 | M_DEBUG("Error initializing FatFs driver!\n"); 37 | return MODULE_NO_RESIDENT_END; 38 | } 39 | 40 | // Connect to block device manager 41 | bdm_connect_fs(&g_fs); 42 | 43 | // return resident 44 | return MODULE_RESIDENT_END; 45 | } 46 | 47 | void *malloc(int size) 48 | { 49 | void *result; 50 | int OldState; 51 | 52 | CpuSuspendIntr(&OldState); 53 | result = AllocSysMemory(ALLOC_FIRST, size, NULL); 54 | CpuResumeIntr(OldState); 55 | 56 | return result; 57 | } 58 | 59 | void free(void *ptr) 60 | { 61 | int OldState; 62 | 63 | CpuSuspendIntr(&OldState); 64 | FreeSysMemory(ptr); 65 | CpuResumeIntr(OldState); 66 | } 67 | -------------------------------------------------------------------------------- /__bdm_assault/src/bdmfs/include/diskio.h: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------/ 2 | / Low level disk interface modlue include file (C)ChaN, 2019 / 3 | /-----------------------------------------------------------------------*/ 4 | 5 | #ifndef _DISKIO_DEFINED 6 | #define _DISKIO_DEFINED 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | /* Status of Disk Functions */ 13 | typedef BYTE DSTATUS; 14 | 15 | /* Results of Disk Functions */ 16 | typedef enum { 17 | RES_OK = 0, /* 0: Successful */ 18 | RES_ERROR, /* 1: R/W Error */ 19 | RES_WRPRT, /* 2: Write Protected */ 20 | RES_NOTRDY, /* 3: Not Ready */ 21 | RES_PARERR /* 4: Invalid Parameter */ 22 | } DRESULT; 23 | 24 | 25 | /*---------------------------------------*/ 26 | /* Prototypes for disk control functions */ 27 | 28 | 29 | DSTATUS disk_initialize (BYTE pdrv); 30 | DSTATUS disk_status (BYTE pdrv); 31 | DRESULT disk_read (BYTE pdrv, BYTE* buff, LBA_t sector, UINT count); 32 | DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count); 33 | DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); 34 | 35 | 36 | /* Disk Status Bits (DSTATUS) */ 37 | 38 | #define STA_NOINIT 0x01 /* Drive not initialized */ 39 | #define STA_NODISK 0x02 /* No medium in the drive */ 40 | #define STA_PROTECT 0x04 /* Write protected */ 41 | 42 | 43 | /* Command code for disk_ioctrl fucntion */ 44 | 45 | /* Generic command (Used by FatFs) */ 46 | #define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */ 47 | #define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */ 48 | #define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */ 49 | #define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */ 50 | #define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */ 51 | 52 | /* Generic command (Not used by FatFs) */ 53 | #define CTRL_POWER 5 /* Get/Set power status */ 54 | #define CTRL_LOCK 6 /* Lock/Unlock media removal */ 55 | #define CTRL_EJECT 7 /* Eject media */ 56 | #define CTRL_FORMAT 8 /* Create physical format on the media */ 57 | 58 | /* MMC/SDC specific ioctl command */ 59 | #define MMC_GET_TYPE 10 /* Get card type */ 60 | #define MMC_GET_CSD 11 /* Get CSD */ 61 | #define MMC_GET_CID 12 /* Get CID */ 62 | #define MMC_GET_OCR 13 /* Get OCR */ 63 | #define MMC_GET_SDSTAT 14 /* Get SD status */ 64 | #define ISDIO_READ 55 /* Read data form SD iSDIO register */ 65 | #define ISDIO_WRITE 56 /* Write data to SD iSDIO register */ 66 | #define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */ 67 | 68 | /* ATA/CF specific ioctl command */ 69 | #define ATA_GET_REV 20 /* Get F/W revision */ 70 | #define ATA_GET_MODEL 21 /* Get model name */ 71 | #define ATA_GET_SN 22 /* Get serial number */ 72 | 73 | #ifdef __cplusplus 74 | } 75 | #endif 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /__bdm_assault/src/bdmfs/include/fs_driver.h: -------------------------------------------------------------------------------- 1 | #ifndef FS_DRIVER_H 2 | #define FS_DRIVER_H 3 | 4 | #include 5 | #include "ff.h" 6 | 7 | typedef struct fatfs_fs_driver_mount_info_ 8 | { 9 | FATFS fatfs; 10 | struct block_device *mounted_bd; 11 | int mount_status; 12 | } fatfs_fs_driver_mount_info; 13 | 14 | extern fatfs_fs_driver_mount_info fs_driver_mount_info[FF_VOLUMES]; 15 | 16 | extern int InitFS(void); 17 | extern int connect_bd(struct block_device *bd); 18 | extern void disconnect_bd(struct block_device *bd); 19 | extern struct block_device *fatfs_fs_driver_get_mounted_bd_from_index(int mount_info_index); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /__bdm_assault/src/bdmfs/include/module_debug.h: -------------------------------------------------------------------------------- 1 | #ifndef _MODULE_DEBUG_H 2 | #define _MODULE_DEBUG_H 3 | 4 | 5 | #define M_PRINTF(format, args...) printf("FatFs: " format, ##args) 6 | 7 | #ifdef DEBUG 8 | #define M_DEBUG M_PRINTF 9 | #else 10 | #define M_DEBUG(format, args...) 11 | #endif 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /__bdm_assault/src/exports.tab: -------------------------------------------------------------------------------- 1 | /* BDM Export TAB. remains as is since FATFS has no exports*/ 2 | 3 | DECLARE_EXPORT_TABLE(bdm, 1, 1) 4 | DECLARE_EXPORT(_start) 5 | DECLARE_EXPORT(_retonly) 6 | DECLARE_EXPORT(_retonly) 7 | DECLARE_EXPORT(_retonly) 8 | DECLARE_EXPORT(bdm_connect_bd) 9 | DECLARE_EXPORT(bdm_disconnect_bd) 10 | DECLARE_EXPORT(bdm_connect_fs) 11 | DECLARE_EXPORT(bdm_disconnect_fs) 12 | DECLARE_EXPORT(bdm_get_bd) 13 | DECLARE_EXPORT(bdm_RegisterCallback) 14 | END_EXPORT_TABLE 15 | 16 | void _retonly() {} 17 | -------------------------------------------------------------------------------- /__bdm_assault/src/imports.lst: -------------------------------------------------------------------------------- 1 | // BDM and BDMFS_FATS import lists merged into one 2 | loadcore_IMPORTS_start 3 | I_RegisterLibraryEntries 4 | loadcore_IMPORTS_end 5 | 6 | stdio_IMPORTS_start 7 | I_printf 8 | stdio_IMPORTS_end 9 | 10 | sysclib_IMPORTS_start 11 | I_toupper 12 | I_memset 13 | I_memcmp 14 | I_memcpy 15 | I_strlen 16 | I_strcmp 17 | I_strcpy 18 | I_strncpy 19 | I_strtol 20 | I_strchr 21 | I_strrchr 22 | I_sprintf 23 | sysclib_IMPORTS_end 24 | 25 | sysmem_IMPORTS_start 26 | I_AllocSysMemory 27 | I_FreeSysMemory 28 | sysmem_IMPORTS_end 29 | 30 | thbase_IMPORTS_start 31 | I_CreateThread 32 | I_StartThread 33 | I_DeleteThread 34 | thbase_IMPORTS_end 35 | 36 | thevent_IMPORTS_start 37 | I_CreateEventFlag 38 | I_WaitEventFlag 39 | I_SetEventFlag 40 | I_DeleteEventFlag 41 | thevent_IMPORTS_end 42 | 43 | cdvdman_IMPORTS_start 44 | I_sceCdReadClock 45 | cdvdman_IMPORTS_end 46 | 47 | intrman_IMPORTS_start 48 | I_CpuSuspendIntr 49 | I_CpuResumeIntr 50 | intrman_IMPORTS_end 51 | 52 | ioman_IMPORTS_start 53 | I_AddDrv 54 | I_DelDrv 55 | ioman_IMPORTS_end 56 | 57 | thsemap_IMPORTS_start 58 | I_CreateSema 59 | I_SignalSema 60 | I_WaitSema 61 | I_DeleteSema 62 | thsemap_IMPORTS_end 63 | -------------------------------------------------------------------------------- /__bdm_assault/src/irx_imports.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Copyright 2001-2009, ps2dev - http://www.ps2dev.org 7 | # Licenced under Academic Free License version 2.0 8 | # Review ps2sdk README & LICENSE files for further details. 9 | # 10 | # Defines all IRX imports. 11 | */ 12 | 13 | #ifndef IOP_IRX_IMPORTS_H 14 | #define IOP_IRX_IMPORTS_H 15 | 16 | #include 17 | 18 | /* Please keep these in alphabetical order! */ 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #endif /* IOP_IRX_IMPORTS_H */ 32 | -------------------------------------------------------------------------------- /__usbd_bd_assault/Makefile: -------------------------------------------------------------------------------- 1 | 2 | IOP_BIN = ../usbd_bd_assault.irx 3 | 4 | #usbd 5 | USBD_OBJS = hcd.o hub.o interface.o mem.o usbd.o usbio.o driver.o 6 | 7 | #usbdmass_bd 8 | IOP_INCS += -Isrc/usbd/include -I../bdm/include 9 | IOP_CFLAGS += -Wno-strict-aliasing 10 | IOP_LDFLAGS += -lgcc 11 | USBMASS_BD_OBJS = main.o usb_mass.o scsi.o 12 | 13 | IOP_OBJS = $(addprefix usbd_,$(USBD_OBJS)) $(addprefix usbmass_bd_,$(USBMASS_BD_OBJS)) imports.o exports.o 14 | ifeq ($(DEBUG), 1) 15 | IOP_CFLAGS += -DDEBUG -DDEBUG_EXTREME 16 | IOP_BIN = ../usbd_bd_assault_debug.irx 17 | endif 18 | 19 | include ../global.make 20 | $(IOP_OBJS_DIR)%.o: src/usbd/%.c 21 | $(DIR_GUARD) 22 | $(IOP_C_COMPILE) -c $< -o $@ 23 | $(IOP_OBJS_DIR)%.o: src/usbmass_bd/%.c 24 | $(DIR_GUARD) 25 | $(IOP_C_COMPILE) -c $< -o $@ -------------------------------------------------------------------------------- /__usbd_bd_assault/src/exports.tab: -------------------------------------------------------------------------------- 1 | /*USBD_EXPORTS they remain as is because USBMASS_BD has no export*/ 2 | 3 | DECLARE_EXPORT_TABLE(usbd, 1, 1) 4 | DECLARE_EXPORT(_start) 5 | DECLARE_EXPORT(_retonly) 6 | DECLARE_EXPORT(_retonly) 7 | DECLARE_EXPORT(_retonly) 8 | DECLARE_EXPORT(sceUsbdRegisterLdd) 9 | /*05*/ DECLARE_EXPORT(sceUsbdUnregisterLdd) 10 | DECLARE_EXPORT(sceUsbdScanStaticDescriptor) 11 | DECLARE_EXPORT(sceUsbdSetPrivateData) 12 | DECLARE_EXPORT(sceUsbdGetPrivateData) 13 | DECLARE_EXPORT(sceUsbdOpenPipe) 14 | /*10*/ DECLARE_EXPORT(sceUsbdClosePipe) 15 | DECLARE_EXPORT(sceUsbdTransferPipe) 16 | DECLARE_EXPORT(sceUsbdOpenPipeAligned) 17 | DECLARE_EXPORT(sceUsbdGetDeviceLocation) 18 | DECLARE_EXPORT(sceUsbdRegisterAutoloader) 19 | /*15*/ DECLARE_EXPORT(sceUsbdUnregisterAutoloader) 20 | DECLARE_EXPORT(sceUsbdChangeThreadPriority) 21 | END_EXPORT_TABLE 22 | 23 | void _retonly() {} 24 | -------------------------------------------------------------------------------- /__usbd_bd_assault/src/imports.lst: -------------------------------------------------------------------------------- 1 | 2 | loadcore_IMPORTS_start 3 | I_RegisterLibraryEntries 4 | loadcore_IMPORTS_end 5 | 6 | stdio_IMPORTS_start 7 | I_printf 8 | stdio_IMPORTS_end 9 | 10 | sysmem_IMPORTS_start 11 | I_AllocSysMemory 12 | sysmem_IMPORTS_end 13 | 14 | sysclib_IMPORTS_start 15 | I_memcpy 16 | I_memset 17 | I_strtol 18 | sysclib_IMPORTS_end 19 | 20 | intrman_IMPORTS_start 21 | I_DisableIntr 22 | I_EnableIntr 23 | I_RegisterIntrHandler 24 | I_CpuSuspendIntr 25 | I_CpuResumeIntr 26 | intrman_IMPORTS_end 27 | 28 | thsemap_IMPORTS_start 29 | I_CreateSema 30 | I_WaitSema 31 | I_SignalSema 32 | I_DeleteSema 33 | thsemap_IMPORTS_end 34 | 35 | thevent_IMPORTS_start 36 | I_CreateEventFlag 37 | I_SetEventFlag 38 | I_iSetEventFlag 39 | I_WaitEventFlag 40 | thevent_IMPORTS_end 41 | 42 | thbase_IMPORTS_start 43 | I_CreateThread 44 | I_StartThread 45 | I_DeleteThread 46 | I_DelayThread 47 | I_ChangeThreadPriority 48 | thbase_IMPORTS_end 49 | 50 | bdm_IMPORTS_start 51 | I_bdm_connect_bd 52 | I_bdm_disconnect_bd 53 | bdm_IMPORTS_end -------------------------------------------------------------------------------- /__usbd_bd_assault/src/irx_imports.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Copyright 2001-2004, ps2dev - http://www.ps2dev.org 7 | # Licenced under Academic Free License version 2.0 8 | # Review ps2sdk README & LICENSE files for further details. 9 | # 10 | # Defines all IRX imports. 11 | */ 12 | 13 | #ifndef IOP_IRX_IMPORTS_H 14 | #define IOP_IRX_IMPORTS_H 15 | 16 | #include "irx.h" 17 | 18 | /* Please keep these in alphabetical order! */ 19 | #include 20 | #include "intrman.h" 21 | #include "loadcore.h" 22 | #include "stdio.h" 23 | #include "sysclib.h" 24 | #include "sysmem.h" 25 | #include "thbase.h" 26 | #include "thevent.h" 27 | #include "thmsgbx.h" 28 | #include "thsemap.h" 29 | #include "vblank.h" 30 | 31 | #endif /* IOP_IRX_IMPORTS_H */ 32 | -------------------------------------------------------------------------------- /__usbd_bd_assault/src/usbd/driver.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Copyright 2001-2004, ps2dev - http://www.ps2dev.org 7 | # Licenced under Academic Free License version 2.0 8 | # Review ps2sdk README & LICENSE files for further details. 9 | */ 10 | 11 | /** 12 | * @file 13 | * USB Driver function prototypes and constants. 14 | */ 15 | 16 | #ifndef __DRIVER_H__ 17 | #define __DRIVER_H__ 18 | 19 | #include "usbdpriv.h" 20 | 21 | int callUsbDriverFunc(int (*func)(int devId), int devId, void *gp); 22 | int doRegisterDriver(sceUsbdLddOps *drv, void *drvGpSeg); 23 | int doRegisterAutoLoader(sceUsbdLddOps *drv, void *drvGpSeg); 24 | int doUnregisterAutoLoader(void); 25 | int doUnregisterDriver(sceUsbdLddOps *drv); 26 | void signalCallbackThreadFunc(IoRequest *req); 27 | void callbackThreadFunc(void *arg); 28 | void connectNewDevice(Device *dev); 29 | int initCallbackThread(void); 30 | 31 | #endif //__DRIVER_H__ 32 | -------------------------------------------------------------------------------- /__usbd_bd_assault/src/usbd/hcd.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Copyright 2001-2004, ps2dev - http://www.ps2dev.org 7 | # Licenced under Academic Free License version 2.0 8 | # Review ps2sdk README & LICENSE files for further details. 9 | */ 10 | 11 | /** 12 | * @file 13 | * USB Driver function prototypes and constants. 14 | */ 15 | 16 | #ifndef __HCD_H__ 17 | #define __HCD_H__ 18 | 19 | #include "usbdpriv.h" 20 | 21 | int callUsbDriverFunc(int (*func)(int), int devId, void *gp); 22 | Endpoint *openDeviceEndpoint(Device *dev, UsbEndpointDescriptor *endpDesc, u32 alignFlag); 23 | Endpoint *doOpenEndpoint(Device *dev, UsbEndpointDescriptor *endpDesc, u32 alignFlag); 24 | void *doGetDeviceStaticDescriptor(int devId, void *data, u8 type); 25 | int doCloseEndpoint(Endpoint *ep); 26 | int hcdInit(void); 27 | 28 | #endif // __HCD_H__ 29 | -------------------------------------------------------------------------------- /__usbd_bd_assault/src/usbd/hub.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * USB Driver function prototypes and constants. 4 | */ 5 | 6 | #ifndef __HUB_H__ 7 | #define __HUB_H__ 8 | 9 | #include "usbdpriv.h" 10 | 11 | int removeEndpointFromDevice(Device *dev, Endpoint *ep); 12 | int initHubDriver(void); 13 | void flushPort(Device *dev); 14 | int addTimerCallback(TimerCbStruct *arg, TimerCallback func, void *cbArg, u32 delay); 15 | void hubResetDevice(void *devp); 16 | int hubTimedSetFuncAddress(Device *dev); 17 | 18 | 19 | #endif // __HUB_H__ 20 | -------------------------------------------------------------------------------- /__usbd_bd_assault/src/usbd/irx_imports.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Copyright 2001-2004, ps2dev - http://www.ps2dev.org 7 | # Licenced under Academic Free License version 2.0 8 | # Review ps2sdk README & LICENSE files for further details. 9 | # 10 | # Defines all IRX imports. 11 | */ 12 | 13 | #ifndef IOP_IRX_IMPORTS_H 14 | #define IOP_IRX_IMPORTS_H 15 | 16 | #include "irx.h" 17 | 18 | /* Please keep these in alphabetical order! */ 19 | #include "intrman.h" 20 | #include "loadcore.h" 21 | #include "stdio.h" 22 | #include "sysclib.h" 23 | #include "sysmem.h" 24 | #include "thbase.h" 25 | #include "thevent.h" 26 | #include "thmsgbx.h" 27 | #include "thsemap.h" 28 | #include "vblank.h" 29 | 30 | #endif /* IOP_IRX_IMPORTS_H */ 31 | -------------------------------------------------------------------------------- /__usbd_bd_assault/src/usbd/mem.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Copyright 2001-2004, ps2dev - http://www.ps2dev.org 7 | # Licenced under Academic Free License version 2.0 8 | # Review ps2sdk README & LICENSE files for further details. 9 | */ 10 | 11 | /** 12 | * @file 13 | * USB Driver function prototypes and constants. 14 | */ 15 | 16 | #ifndef __MEM_H__ 17 | #define __MEM_H__ 18 | 19 | #include "usbdpriv.h" 20 | 21 | extern MemoryPool memPool; 22 | 23 | HcIsoTD *allocIsoTd(void); 24 | void freeIsoTd(HcIsoTD *argTd); 25 | 26 | HcTD *allocTd(void); 27 | void freeTd(HcTD *argTd); 28 | 29 | Device *attachChildDevice(Device *parent, u32 portNum); 30 | void freeDevice(Device *dev); 31 | 32 | Device *fetchPortElemByNumber(Device *hub, int port); 33 | 34 | void addToHcEndpointList(u8 type, HcED *ed); 35 | void removeHcEdFromList(int type, const HcED *hcEd); 36 | 37 | Endpoint *allocEndpointForDevice(Device *dev, u32 align); 38 | 39 | Device *fetchDeviceById(int devId); 40 | Endpoint *fetchEndpointById(int id); 41 | 42 | IoRequest *allocIoRequest(void); 43 | void freeIoRequest(IoRequest *req); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /__usbd_bd_assault/src/usbd/usbd_driver.c: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Copyright 2001-2004, ps2dev - http://www.ps2dev.org 7 | # Licenced under Academic Free License version 2.0 8 | # Review ps2sdk README & LICENSE files for further details. 9 | */ 10 | 11 | /** 12 | * @file 13 | * USB Driver function prototypes and constants. 14 | */ 15 | 16 | #include "usbdpriv.h" 17 | #include "driver.h" 18 | #include "mem.h" 19 | #include "hub.h" 20 | 21 | #include "defs.h" 22 | #include "stdio.h" 23 | #include "sysclib.h" 24 | #include "thbase.h" 25 | #include "thevent.h" 26 | #include "intrman.h" 27 | 28 | sceUsbdLddOps *drvListStart = NULL, *drvListEnd = NULL; 29 | sceUsbdLddOps *drvAutoLoader = NULL; 30 | IoRequest *cbListStart = NULL, *cbListEnd = NULL; 31 | 32 | int callbackEvent; 33 | int callbackTid = -1; 34 | 35 | int callUsbDriverFunc(int (*func)(int devId), int devId, void *gp) 36 | { 37 | int res; 38 | 39 | if (func) { 40 | usbdUnlock(); 41 | #if USE_GP_REGISTER 42 | ChangeGP(gp); 43 | #else 44 | (void)gp; 45 | #endif 46 | res = func(devId); 47 | #if USE_GP_REGISTER 48 | SetGP(&_gp); 49 | #endif 50 | usbdLock(); 51 | return res; 52 | } else 53 | return 0; 54 | } 55 | 56 | void probeDeviceTree(Device *tree, sceUsbdLddOps *drv) 57 | { 58 | Device *curDevice; 59 | for (curDevice = tree->childListStart; curDevice != NULL; curDevice = curDevice->next) 60 | if (curDevice->deviceStatus == DEVICE_READY) { 61 | if (curDevice->devDriver == NULL) { 62 | if (callUsbDriverFunc(drv->probe, curDevice->id, drv->gp) != 0) { 63 | curDevice->devDriver = drv; 64 | callUsbDriverFunc(drv->connect, curDevice->id, drv->gp); 65 | } 66 | } else if (curDevice->childListStart) 67 | probeDeviceTree(curDevice, drv); 68 | } 69 | } 70 | 71 | int doRegisterDriver(sceUsbdLddOps *drv, void *drvGpSeg) 72 | { 73 | if (drv->next || drv->prev) 74 | return USB_RC_BUSY; 75 | if (drvListStart == drv) 76 | return USB_RC_BUSY; 77 | 78 | if (!drv->name) 79 | return USB_RC_BADDRIVER; 80 | if (drv->reserved1 || drv->reserved2) 81 | return USB_RC_BADDRIVER; 82 | 83 | drv->gp = drvGpSeg; 84 | 85 | drv->prev = drvListEnd; 86 | if (drvListEnd) 87 | drvListEnd->next = drv; 88 | else 89 | drvListStart = drv; 90 | drvListEnd = drv; 91 | 92 | if (drv->probe) 93 | probeDeviceTree(memPool.deviceTreeRoot, drv); 94 | 95 | return 0; 96 | } 97 | 98 | int doRegisterAutoLoader(sceUsbdLddOps *drv, void *drvGpSeg) 99 | { 100 | if (drv->next || drv->prev) 101 | return USB_RC_BADDRIVER; 102 | if (!drv->name) 103 | return USB_RC_BADDRIVER; 104 | if (drv->reserved1 || drv->reserved2) 105 | return USB_RC_BADDRIVER; 106 | 107 | if (drvAutoLoader != NULL) 108 | return USB_RC_BUSY; 109 | 110 | drv->gp = drvGpSeg; 111 | 112 | drvAutoLoader = drv; 113 | 114 | if (drv->probe) 115 | probeDeviceTree(memPool.deviceTreeRoot, drv); 116 | 117 | return 0; 118 | } 119 | 120 | void disconnectDriver(Device *tree, sceUsbdLddOps *drv) 121 | { 122 | Endpoint *ep, *nextEp; 123 | if (tree->devDriver == drv) { 124 | if (tree->endpointListStart) { 125 | ep = tree->endpointListStart->next; 126 | 127 | while (ep) { 128 | nextEp = ep->next; 129 | removeEndpointFromDevice(tree, ep); 130 | ep = nextEp; 131 | } 132 | } 133 | tree->devDriver = NULL; 134 | tree->privDataField = NULL; 135 | } 136 | 137 | for (tree = tree->childListStart; tree != NULL; tree = tree->next) 138 | disconnectDriver(tree, drv); 139 | } 140 | 141 | int doUnregisterAutoLoader(void) 142 | { 143 | drvAutoLoader = NULL; 144 | return 0; 145 | } 146 | 147 | int doUnregisterDriver(sceUsbdLddOps *drv) 148 | { 149 | sceUsbdLddOps *pos; 150 | for (pos = drvListStart; pos != NULL; pos = pos->next) 151 | if (pos == drv) { 152 | if (drv->next) 153 | drv->next->prev = drv->prev; 154 | else 155 | drvListEnd = drv->prev; 156 | 157 | if (drv->prev) 158 | drv->prev->next = drv->next; 159 | else 160 | drvListStart = drv->next; 161 | 162 | disconnectDriver(memPool.deviceTreeRoot, drv); 163 | return 0; 164 | } 165 | return USB_RC_BADDRIVER; 166 | } 167 | 168 | void connectNewDevice(Device *dev) 169 | { 170 | sceUsbdLddOps *drv; 171 | dbg_printf("searching driver for dev %d, FA %02X\n", dev->id, dev->functionAddress); 172 | for (drv = drvListStart; drv != NULL; drv = drv->next) 173 | if (callUsbDriverFunc(drv->probe, dev->id, drv->gp) != 0) { 174 | dev->devDriver = drv; 175 | dbg_printf("Driver found (%s)\n", drv->name); 176 | callUsbDriverFunc(drv->connect, dev->id, drv->gp); 177 | return; 178 | } 179 | 180 | // No driver found yet. Call autoloader. 181 | if (drvAutoLoader != NULL) { 182 | drv = drvAutoLoader; 183 | 184 | if (callUsbDriverFunc(drv->probe, dev->id, drv->gp) != 0) { 185 | dev->devDriver = drv; 186 | dbg_printf("(autoloader) Driver found (%s)\n", drv->name); 187 | callUsbDriverFunc(drv->connect, dev->id, drv->gp); 188 | return; 189 | } 190 | } 191 | 192 | dbg_printf("no driver found\n"); 193 | } 194 | 195 | void signalCallbackThreadFunc(IoRequest *req) 196 | { 197 | int intrStat; 198 | 199 | CpuSuspendIntr(&intrStat); 200 | 201 | req->prev = cbListEnd; 202 | req->next = NULL; 203 | if (cbListEnd) 204 | cbListEnd->next = req; 205 | else 206 | cbListStart = req; 207 | cbListEnd = req; 208 | 209 | CpuResumeIntr(intrStat); 210 | 211 | SetEventFlag(callbackEvent, 1); 212 | } 213 | 214 | void callbackThreadFunc(void *arg) 215 | { 216 | u32 eventRes; 217 | int intrStat; 218 | IoRequest *req; 219 | IoRequest reqCopy; 220 | 221 | (void)arg; 222 | 223 | while (1) { 224 | WaitEventFlag(callbackEvent, 1, WEF_CLEAR | WEF_OR, &eventRes); 225 | do { 226 | CpuSuspendIntr(&intrStat); 227 | 228 | req = cbListStart; 229 | if (req) { 230 | if (req->next) 231 | req->next->prev = req->prev; 232 | else 233 | cbListEnd = req->prev; 234 | 235 | if (req->prev) 236 | req->prev->next = req->next; 237 | else 238 | cbListStart = req->next; 239 | } 240 | CpuResumeIntr(intrStat); 241 | 242 | if (req) { 243 | memcpy(&reqCopy, req, sizeof(IoRequest)); 244 | usbdLock(); 245 | freeIoRequest(req); 246 | usbdUnlock(); 247 | 248 | if (reqCopy.userCallbackProc) { 249 | #if USE_GP_REGISTER 250 | SetGP(req->gpSeg); 251 | #endif 252 | reqCopy.userCallbackProc(reqCopy.resultCode, reqCopy.transferedBytes, reqCopy.userCallbackArg); 253 | #if USE_GP_REGISTER 254 | SetGP(&_gp); 255 | #endif 256 | } 257 | } 258 | } while (req); 259 | } 260 | } 261 | 262 | int initCallbackThread(void) 263 | { 264 | iop_event_t event; 265 | iop_thread_t thread; 266 | 267 | event.attr = event.option = event.bits = 0; 268 | callbackEvent = CreateEventFlag(&event); 269 | 270 | thread.attr = TH_C; 271 | thread.option = 0; 272 | thread.thread = callbackThreadFunc; 273 | #ifndef MINI_DRIVER 274 | thread.stacksize = 0x4000; // 16KiB 275 | #else 276 | thread.stacksize = 0x0800; // 2KiB 277 | #endif 278 | thread.priority = usbConfig.cbThreadPrio; 279 | callbackTid = CreateThread(&thread); 280 | StartThread(callbackTid, NULL); 281 | 282 | return 0; 283 | } 284 | -------------------------------------------------------------------------------- /__usbd_bd_assault/src/usbd/usbd_mem.c: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Copyright 2001-2004, ps2dev - http://www.ps2dev.org 7 | # Licenced under Academic Free License version 2.0 8 | # Review ps2sdk README & LICENSE files for further details. 9 | */ 10 | 11 | /** 12 | * @file 13 | * USB Driver function prototypes and constants. 14 | */ 15 | 16 | #include "usbdpriv.h" 17 | #include "mem.h" 18 | 19 | #include "stdio.h" 20 | 21 | MemoryPool memPool; 22 | 23 | HcIsoTD *allocIsoTd(void) 24 | { 25 | HcIsoTD *newTd = memPool.freeHcIsoTdList; 26 | if (newTd) { 27 | memPool.freeHcIsoTdList = newTd->next; 28 | newTd->next = NULL; 29 | } 30 | return newTd; 31 | } 32 | 33 | void freeIsoTd(HcIsoTD *argTd) 34 | { 35 | HcIsoTD *pos; 36 | if (argTd) { 37 | for (pos = memPool.freeHcIsoTdList; pos != NULL; pos = pos->next) 38 | if (pos == argTd) { 39 | printf("freeIsoTd %p: already free\n", argTd); 40 | return; 41 | } 42 | argTd->next = memPool.freeHcIsoTdList; 43 | memPool.freeHcIsoTdList = argTd; 44 | } 45 | } 46 | 47 | HcTD *allocTd(void) 48 | { 49 | HcTD *res = memPool.freeHcTdList; 50 | if (res) { 51 | memPool.freeHcTdList = res->next; 52 | res->next = NULL; 53 | } 54 | return res; 55 | } 56 | 57 | void freeTd(HcTD *argTd) 58 | { 59 | HcTD *pos; 60 | if (argTd) { 61 | for (pos = memPool.freeHcTdList; pos != NULL; pos = pos->next) 62 | if (pos == argTd) { 63 | printf("FreeTD %p: already free\n", argTd); 64 | return; 65 | } 66 | argTd->next = memPool.freeHcTdList; 67 | memPool.freeHcTdList = argTd; 68 | } 69 | } 70 | 71 | Device *attachChildDevice(Device *parent, u32 portNum) 72 | { 73 | Device *newDev = memPool.freeDeviceListStart; 74 | if (!newDev) { 75 | dbg_printf("Ran out of device handles\n"); 76 | return NULL; 77 | } 78 | 79 | if (newDev->next) 80 | newDev->next->prev = newDev->prev; 81 | else 82 | memPool.freeDeviceListEnd = newDev->prev; 83 | 84 | if (newDev->prev) 85 | newDev->prev->next = newDev->next; 86 | else 87 | memPool.freeDeviceListStart = newDev->next; 88 | 89 | newDev->endpointListEnd = newDev->endpointListStart = NULL; 90 | newDev->devDriver = NULL; 91 | newDev->deviceStatus = DEVICE_NOTCONNECTED; 92 | newDev->resetFlag = 0; 93 | newDev->childListEnd = newDev->childListStart = NULL; 94 | newDev->parent = parent; 95 | newDev->attachedToPortNo = portNum; 96 | newDev->privDataField = NULL; 97 | if (parent) { 98 | newDev->prev = parent->childListEnd; 99 | if (parent->childListEnd) 100 | parent->childListEnd->next = newDev; 101 | else 102 | parent->childListStart = newDev; 103 | newDev->next = NULL; 104 | parent->childListEnd = newDev; 105 | } else 106 | newDev->next = newDev->prev = NULL; 107 | return newDev; 108 | } 109 | 110 | void freeDevice(Device *dev) 111 | { 112 | if (!dev) 113 | return; 114 | 115 | if ((dev < memPool.deviceTreeBuf) || (dev >= memPool.deviceTreeBuf + usbConfig.maxDevices)) { 116 | printf("freeDevice %p: Arg is not part of dev buffer\n", dev); 117 | return; 118 | } 119 | 120 | dev->prev = memPool.freeDeviceListEnd; 121 | if (memPool.freeDeviceListEnd) 122 | memPool.freeDeviceListEnd->next = dev; 123 | else 124 | memPool.freeDeviceListStart = dev; 125 | 126 | dev->next = NULL; 127 | dev->parent = NULL; 128 | memPool.freeDeviceListEnd = dev; 129 | } 130 | 131 | Device *fetchPortElemByNumber(Device *hub, int port) 132 | { 133 | Device *res = hub->childListStart; 134 | while (--port > 0) { 135 | if (!res) 136 | return NULL; 137 | res = res->next; 138 | } 139 | return res; 140 | } 141 | 142 | void addToHcEndpointList(u8 type, HcED *ed) 143 | { 144 | ed->next = memPool.hcEdBuf[type].next; 145 | memPool.hcEdBuf[type].next = ed; 146 | } 147 | 148 | void removeHcEdFromList(int type, const HcED *hcEd) 149 | { 150 | HcED *prev = memPool.hcEdBuf + type; 151 | HcED *pos = prev->next; 152 | while (pos) { 153 | if (pos == hcEd) { 154 | prev->next = pos->next; 155 | return; 156 | } 157 | prev = pos; 158 | pos = pos->next; 159 | } 160 | } 161 | 162 | Endpoint *allocEndpointForDevice(Device *dev, u32 align) 163 | { 164 | Endpoint *newEp = memPool.freeEpListStart; 165 | if (!newEp) 166 | return NULL; 167 | 168 | if (newEp->next) 169 | newEp->next->prev = newEp->prev; 170 | else 171 | memPool.freeEpListEnd = newEp->prev; 172 | 173 | if (newEp->prev) 174 | newEp->prev->next = newEp->next; 175 | else 176 | memPool.freeEpListStart = newEp->next; 177 | 178 | newEp->correspDevice = dev; 179 | newEp->ioReqListStart = newEp->ioReqListEnd = NULL; 180 | newEp->busyNext = newEp->busyPrev = NULL; 181 | newEp->inTdQueue = 0; 182 | newEp->alignFlag = align; 183 | 184 | newEp->next = NULL; 185 | newEp->prev = dev->endpointListEnd; 186 | if (dev->endpointListEnd) 187 | dev->endpointListEnd->next = newEp; 188 | else 189 | dev->endpointListStart = newEp; 190 | 191 | dev->endpointListEnd = newEp; 192 | return newEp; 193 | } 194 | 195 | Device *fetchDeviceById(int devId) 196 | { 197 | if ((devId > 0) && (devId < usbConfig.maxDevices)) { 198 | Device *dev; 199 | 200 | dev = memPool.deviceTreeBuf + devId; 201 | if (dev->parent) 202 | return dev; 203 | } 204 | return NULL; 205 | } 206 | 207 | Endpoint *fetchEndpointById(int id) 208 | { 209 | if ((id >= 0) && (id < usbConfig.maxEndpoints)) { 210 | Endpoint *res; 211 | 212 | res = memPool.endpointBuf + id; 213 | if (res->correspDevice) 214 | return res; 215 | } 216 | return NULL; 217 | } 218 | 219 | IoRequest *allocIoRequest(void) 220 | { 221 | IoRequest *res = memPool.freeIoReqList; 222 | if (res) { 223 | if (res->next) 224 | res->next->prev = res->prev; 225 | else 226 | memPool.freeIoReqListEnd = res->prev; 227 | 228 | if (res->prev) 229 | res->prev->next = res->next; 230 | else 231 | memPool.freeIoReqList = res->next; 232 | res->prev = res->next = NULL; 233 | } else 234 | dbg_printf("ran out of IoReqs\n"); 235 | return res; 236 | } 237 | 238 | void freeIoRequest(IoRequest *req) 239 | { 240 | int num = req - memPool.ioReqBufPtr; 241 | IoRequest *pos; 242 | if (req) { 243 | if ((num >= 0) && (num < usbConfig.maxIoReqs)) { 244 | for (pos = memPool.freeIoReqList; pos != NULL; pos = pos->next) 245 | if (pos == req) { 246 | printf("freeIoRequest %p: already free.\n", req); 247 | return; 248 | } 249 | req->prev = memPool.freeIoReqListEnd; 250 | if (memPool.freeIoReqListEnd) 251 | memPool.freeIoReqListEnd->next = req; 252 | else 253 | memPool.freeIoReqList = req; 254 | req->next = NULL; 255 | memPool.freeIoReqListEnd = req; 256 | } 257 | req->busyFlag = 0; 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /__usbd_bd_assault/src/usbd/usbd_usbd_driver.c: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Copyright 2001-2004, ps2dev - http://www.ps2dev.org 7 | # Licenced under Academic Free License version 2.0 8 | # Review ps2sdk README & LICENSE files for further details. 9 | */ 10 | 11 | /** 12 | * @file 13 | * USB Driver function prototypes and constants. 14 | */ 15 | 16 | #include "usbdpriv.h" 17 | #include "driver.h" 18 | #include "mem.h" 19 | #include "hub.h" 20 | 21 | #include "defs.h" 22 | #include "stdio.h" 23 | #include "sysclib.h" 24 | #include "thbase.h" 25 | #include "thevent.h" 26 | #include "intrman.h" 27 | 28 | sceUsbdLddOps *drvListStart = NULL, *drvListEnd = NULL; 29 | sceUsbdLddOps *drvAutoLoader = NULL; 30 | IoRequest *cbListStart = NULL, *cbListEnd = NULL; 31 | 32 | int callbackEvent; 33 | int callbackTid = -1; 34 | 35 | int callUsbDriverFunc(int (*func)(int devId), int devId, void *gp) 36 | { 37 | int res; 38 | 39 | if (func) { 40 | usbdUnlock(); 41 | #if USE_GP_REGISTER 42 | ChangeGP(gp); 43 | #else 44 | (void)gp; 45 | #endif 46 | res = func(devId); 47 | #if USE_GP_REGISTER 48 | SetGP(&_gp); 49 | #endif 50 | usbdLock(); 51 | return res; 52 | } else 53 | return 0; 54 | } 55 | 56 | void probeDeviceTree(Device *tree, sceUsbdLddOps *drv) 57 | { 58 | Device *curDevice; 59 | for (curDevice = tree->childListStart; curDevice != NULL; curDevice = curDevice->next) 60 | if (curDevice->deviceStatus == DEVICE_READY) { 61 | if (curDevice->devDriver == NULL) { 62 | if (callUsbDriverFunc(drv->probe, curDevice->id, drv->gp) != 0) { 63 | curDevice->devDriver = drv; 64 | callUsbDriverFunc(drv->connect, curDevice->id, drv->gp); 65 | } 66 | } else if (curDevice->childListStart) 67 | probeDeviceTree(curDevice, drv); 68 | } 69 | } 70 | 71 | int doRegisterDriver(sceUsbdLddOps *drv, void *drvGpSeg) 72 | { 73 | if (drv->next || drv->prev) 74 | return USB_RC_BUSY; 75 | if (drvListStart == drv) 76 | return USB_RC_BUSY; 77 | 78 | if (!drv->name) 79 | return USB_RC_BADDRIVER; 80 | if (drv->reserved1 || drv->reserved2) 81 | return USB_RC_BADDRIVER; 82 | 83 | drv->gp = drvGpSeg; 84 | 85 | drv->prev = drvListEnd; 86 | if (drvListEnd) 87 | drvListEnd->next = drv; 88 | else 89 | drvListStart = drv; 90 | drvListEnd = drv; 91 | 92 | if (drv->probe) 93 | probeDeviceTree(memPool.deviceTreeRoot, drv); 94 | 95 | return 0; 96 | } 97 | 98 | int doRegisterAutoLoader(sceUsbdLddOps *drv, void *drvGpSeg) 99 | { 100 | if (drv->next || drv->prev) 101 | return USB_RC_BADDRIVER; 102 | if (!drv->name) 103 | return USB_RC_BADDRIVER; 104 | if (drv->reserved1 || drv->reserved2) 105 | return USB_RC_BADDRIVER; 106 | 107 | if (drvAutoLoader != NULL) 108 | return USB_RC_BUSY; 109 | 110 | drv->gp = drvGpSeg; 111 | 112 | drvAutoLoader = drv; 113 | 114 | if (drv->probe) 115 | probeDeviceTree(memPool.deviceTreeRoot, drv); 116 | 117 | return 0; 118 | } 119 | 120 | void disconnectDriver(Device *tree, sceUsbdLddOps *drv) 121 | { 122 | Endpoint *ep, *nextEp; 123 | if (tree->devDriver == drv) { 124 | if (tree->endpointListStart) { 125 | ep = tree->endpointListStart->next; 126 | 127 | while (ep) { 128 | nextEp = ep->next; 129 | removeEndpointFromDevice(tree, ep); 130 | ep = nextEp; 131 | } 132 | } 133 | tree->devDriver = NULL; 134 | tree->privDataField = NULL; 135 | } 136 | 137 | for (tree = tree->childListStart; tree != NULL; tree = tree->next) 138 | disconnectDriver(tree, drv); 139 | } 140 | 141 | int doUnregisterAutoLoader(void) 142 | { 143 | drvAutoLoader = NULL; 144 | return 0; 145 | } 146 | 147 | int doUnregisterDriver(sceUsbdLddOps *drv) 148 | { 149 | sceUsbdLddOps *pos; 150 | for (pos = drvListStart; pos != NULL; pos = pos->next) 151 | if (pos == drv) { 152 | if (drv->next) 153 | drv->next->prev = drv->prev; 154 | else 155 | drvListEnd = drv->prev; 156 | 157 | if (drv->prev) 158 | drv->prev->next = drv->next; 159 | else 160 | drvListStart = drv->next; 161 | 162 | disconnectDriver(memPool.deviceTreeRoot, drv); 163 | return 0; 164 | } 165 | return USB_RC_BADDRIVER; 166 | } 167 | 168 | void connectNewDevice(Device *dev) 169 | { 170 | sceUsbdLddOps *drv; 171 | dbg_printf("searching driver for dev %d, FA %02X\n", dev->id, dev->functionAddress); 172 | for (drv = drvListStart; drv != NULL; drv = drv->next) 173 | if (callUsbDriverFunc(drv->probe, dev->id, drv->gp) != 0) { 174 | dev->devDriver = drv; 175 | dbg_printf("Driver found (%s)\n", drv->name); 176 | callUsbDriverFunc(drv->connect, dev->id, drv->gp); 177 | return; 178 | } 179 | 180 | // No driver found yet. Call autoloader. 181 | if (drvAutoLoader != NULL) { 182 | drv = drvAutoLoader; 183 | 184 | if (callUsbDriverFunc(drv->probe, dev->id, drv->gp) != 0) { 185 | dev->devDriver = drv; 186 | dbg_printf("(autoloader) Driver found (%s)\n", drv->name); 187 | callUsbDriverFunc(drv->connect, dev->id, drv->gp); 188 | return; 189 | } 190 | } 191 | 192 | dbg_printf("no driver found\n"); 193 | } 194 | 195 | void signalCallbackThreadFunc(IoRequest *req) 196 | { 197 | int intrStat; 198 | 199 | CpuSuspendIntr(&intrStat); 200 | 201 | req->prev = cbListEnd; 202 | req->next = NULL; 203 | if (cbListEnd) 204 | cbListEnd->next = req; 205 | else 206 | cbListStart = req; 207 | cbListEnd = req; 208 | 209 | CpuResumeIntr(intrStat); 210 | 211 | SetEventFlag(callbackEvent, 1); 212 | } 213 | 214 | void callbackThreadFunc(void *arg) 215 | { 216 | u32 eventRes; 217 | int intrStat; 218 | IoRequest *req; 219 | IoRequest reqCopy; 220 | 221 | (void)arg; 222 | 223 | while (1) { 224 | WaitEventFlag(callbackEvent, 1, WEF_CLEAR | WEF_OR, &eventRes); 225 | do { 226 | CpuSuspendIntr(&intrStat); 227 | 228 | req = cbListStart; 229 | if (req) { 230 | if (req->next) 231 | req->next->prev = req->prev; 232 | else 233 | cbListEnd = req->prev; 234 | 235 | if (req->prev) 236 | req->prev->next = req->next; 237 | else 238 | cbListStart = req->next; 239 | } 240 | CpuResumeIntr(intrStat); 241 | 242 | if (req) { 243 | memcpy(&reqCopy, req, sizeof(IoRequest)); 244 | usbdLock(); 245 | freeIoRequest(req); 246 | usbdUnlock(); 247 | 248 | if (reqCopy.userCallbackProc) { 249 | #if USE_GP_REGISTER 250 | SetGP(req->gpSeg); 251 | #endif 252 | reqCopy.userCallbackProc(reqCopy.resultCode, reqCopy.transferedBytes, reqCopy.userCallbackArg); 253 | #if USE_GP_REGISTER 254 | SetGP(&_gp); 255 | #endif 256 | } 257 | } 258 | } while (req); 259 | } 260 | } 261 | 262 | int initCallbackThread(void) 263 | { 264 | iop_event_t event; 265 | iop_thread_t thread; 266 | 267 | event.attr = event.option = event.bits = 0; 268 | callbackEvent = CreateEventFlag(&event); 269 | 270 | thread.attr = TH_C; 271 | thread.option = 0; 272 | thread.thread = callbackThreadFunc; 273 | #ifndef MINI_DRIVER 274 | thread.stacksize = 0x4000; // 16KiB 275 | #else 276 | thread.stacksize = 0x0800; // 2KiB 277 | #endif 278 | thread.priority = usbConfig.cbThreadPrio; 279 | callbackTid = CreateThread(&thread); 280 | StartThread(callbackTid, NULL); 281 | 282 | return 0; 283 | } 284 | -------------------------------------------------------------------------------- /__usbd_bd_assault/src/usbd/usbio.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Copyright 2001-2004, ps2dev - http://www.ps2dev.org 7 | # Licenced under Academic Free License version 2.0 8 | # Review ps2sdk README & LICENSE files for further details. 9 | */ 10 | 11 | /** 12 | * @file 13 | * USB Driver function prototypes and constants. 14 | */ 15 | 16 | #ifndef __USBIO_H__ 17 | #define __USBIO_H__ 18 | 19 | void removeEndpointFromQueue(Endpoint *ep); 20 | void checkTdQueue(int type); 21 | void handleIoReqList(Endpoint *ep); 22 | int doControlTransfer(Endpoint *ep, IoRequest *req, 23 | u8 requestType, u8 request, u16 value, u16 index, u16 length, 24 | void *destdata, void *callback); 25 | int attachIoReqToEndpoint(Endpoint *ep, IoRequest *req, void *destdata, u16 length, void *callback); 26 | void handleIoReqList(Endpoint *ep); 27 | 28 | #endif // __USBIO_H__ 29 | -------------------------------------------------------------------------------- /__usbd_bd_assault/src/usbmass_bd/include/module_debug.h: -------------------------------------------------------------------------------- 1 | #ifndef _MODULE_DEBUG_H 2 | #define _MODULE_DEBUG_H 3 | 4 | #define MODNAME "usbmass_bd" 5 | #ifndef MINI_DRIVER 6 | #define M_PRINTF(format, args...) printf(MODNAME ": " format, ##args) 7 | #else 8 | #define M_PRINTF(format, args...) \ 9 | do { \ 10 | } while (0) 11 | #endif 12 | 13 | #ifdef DEBUG 14 | #define M_DEBUG M_PRINTF 15 | #else 16 | #define M_DEBUG(format, args...) \ 17 | do { \ 18 | } while (0) 19 | #endif 20 | 21 | #define U64_2XU32(val) ((u32*)val)[1], ((u32*)val)[0] 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /__usbd_bd_assault/src/usbmass_bd/include/scsi.h: -------------------------------------------------------------------------------- 1 | #ifndef _SCSI_H 2 | #define _SCSI_H 3 | 4 | struct scsi_interface 5 | { 6 | void *priv; 7 | char *name; 8 | unsigned int max_sectors; 9 | 10 | int (*get_max_lun)(struct scsi_interface *scsi); 11 | int (*queue_cmd)(struct scsi_interface *scsi, const unsigned char *cmd, unsigned int cmd_len, unsigned char *data, unsigned int data_len, unsigned int data_wr); 12 | }; 13 | 14 | int scsi_init(void); 15 | void scsi_connect(struct scsi_interface *scsi); 16 | void scsi_disconnect(struct scsi_interface *scsi); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /__usbd_bd_assault/src/usbmass_bd/usbmass_bd_main.c: -------------------------------------------------------------------------------- 1 | #define MAJOR_VER 1 2 | #define MINOR_VER 1 3 | 4 | #include "include/scsi.h" 5 | #include 6 | #include 7 | #include 8 | 9 | // #define DEBUG //comment out this line when not debugging 10 | #include "include/module_debug.h" 11 | 12 | //IRX_ID(MODNAME, MAJOR_VER, MINOR_VER); 13 | 14 | extern int usb_mass_init(void); 15 | 16 | int usbmass_bd_start(int argc, char *argv[]) 17 | { 18 | (void)argc; 19 | (void)argv; 20 | 21 | M_PRINTF("USBD ASSAULT: starting USBMASS Side\n"); 22 | 23 | // initialize the SCSI driver 24 | if (scsi_init() != 0) { 25 | M_PRINTF("ERROR: initializing SCSI driver!\n"); 26 | return MODULE_NO_RESIDENT_END; 27 | } 28 | 29 | // initialize the USB driver 30 | if (usb_mass_init() != 0) { 31 | M_PRINTF("ERROR: initializing USB driver!\n"); 32 | return MODULE_NO_RESIDENT_END; 33 | } 34 | 35 | // return resident 36 | return MODULE_RESIDENT_END; 37 | } 38 | -------------------------------------------------------------------------------- /bdm/Makefile: -------------------------------------------------------------------------------- 1 | # _____ ___ ____ ___ ____ 2 | # ____| | ____| | | |____| 3 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 4 | #----------------------------------------------------------------------- 5 | # Copyright 2001-2004, ps2dev - http://www.ps2dev.org 6 | # Licenced under Academic Free License version 2.0 7 | # Review ps2sdk README & LICENSE files for further details. 8 | 9 | # IOP_CFLAGS += -DDEBUG 10 | 11 | IOP_BIN = bdm.irx 12 | 13 | IOP_OBJS = main.o bdm.o part_driver.o part_driver_mbr.o part_driver_gpt.o imports.o exports.o 14 | IOP_LIBS = ../libbdm/lib/libbdm.a 15 | IOP_CFLAGS += -I../libbdm/include/ -Wno-strict-aliasing 16 | 17 | include ../global.make 18 | 19 | ../libbdm/lib/libbdm.a: 20 | $(MAKE) ../libbdm -------------------------------------------------------------------------------- /bdm/include/bdm.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Licenced under Academic Free License version 2.0 7 | # Review ps2sdk README & LICENSE files for further details. 8 | */ 9 | 10 | /** 11 | * @file 12 | * IOP BDM (Block Device Manager) definitions. 13 | */ 14 | 15 | #ifndef __BDM_H__ 16 | #define __BDM_H__ 17 | 18 | #include 19 | #include 20 | 21 | struct block_device 22 | { 23 | // Private driver data 24 | void *priv; 25 | 26 | // Device name + number + partition number 27 | // Can be used to create device names like: 28 | // - mass0p1 29 | char *name; 30 | unsigned int devNr; 31 | unsigned int parNr; 32 | unsigned char parId; 33 | 34 | unsigned int sectorSize; // Size of a sector in bytes 35 | u64 sectorOffset; // Starting sector number 36 | u64 sectorCount; // Maximum number of sectors usable 37 | 38 | int (*read)(struct block_device *bd, u64 sector, void *buffer, u16 count); 39 | int (*write)(struct block_device *bd, u64 sector, const void *buffer, u16 count); 40 | void (*flush)(struct block_device *bd); 41 | int (*stop)(struct block_device *bd); 42 | }; 43 | 44 | struct file_system 45 | { 46 | // Private driver data 47 | void *priv; 48 | 49 | // Filesystem (/partition) name 50 | char *name; 51 | 52 | // mount / umount block device 53 | int (*connect_bd)(struct block_device *bd); 54 | void (*disconnect_bd)(struct block_device *bd); 55 | }; 56 | 57 | typedef void (*bdm_cb)(int event); 58 | 59 | // Exported functions 60 | void bdm_connect_bd(struct block_device *bd); 61 | void bdm_disconnect_bd(struct block_device *bd); 62 | void bdm_connect_fs(struct file_system *fs); 63 | void bdm_disconnect_fs(struct file_system *fs); 64 | void bdm_get_bd(struct block_device **pbd, unsigned int count); 65 | void bdm_RegisterCallback(bdm_cb cb); 66 | 67 | #define bdm_IMPORTS_start DECLARE_IMPORT_TABLE(bdm, 1, 1) 68 | #define bdm_IMPORTS_end END_IMPORT_TABLE 69 | 70 | #define I_bdm_connect_bd DECLARE_IMPORT(4, bdm_connect_bd) 71 | #define I_bdm_disconnect_bd DECLARE_IMPORT(5, bdm_disconnect_bd) 72 | #define I_bdm_connect_fs DECLARE_IMPORT(6, bdm_connect_fs) 73 | #define I_bdm_disconnect_fs DECLARE_IMPORT(7, bdm_disconnect_fs) 74 | #define I_bdm_get_bd DECLARE_IMPORT(8, bdm_get_bd) 75 | #define I_bdm_RegisterCallback DECLARE_IMPORT(9, bdm_RegisterCallback) 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /bdm/src/bdm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | // #define DEBUG //comment out this line when not debugging 9 | #include "module_debug.h" 10 | 11 | struct bdm_mounts 12 | { 13 | struct block_device *bd; // real block device 14 | struct block_device *cbd; // cached block device 15 | struct file_system *fs; 16 | }; 17 | 18 | #define MAX_CONNECTIONS 20 19 | static struct bdm_mounts g_mount[MAX_CONNECTIONS]; 20 | static struct file_system *g_fs[MAX_CONNECTIONS]; 21 | static bdm_cb g_cb = NULL; 22 | static int bdm_event = -1; 23 | static int bdm_thread_id = -1; 24 | 25 | /* Event flag bits */ 26 | #define BDM_EVENT_CB_MOUNT 0x01 27 | #define BDM_EVENT_CB_UMOUNT 0x02 28 | #define BDM_EVENT_MOUNT 0x04 29 | 30 | void bdm_RegisterCallback(bdm_cb cb) 31 | { 32 | int i; 33 | 34 | M_DEBUG("%s\n", __func__); 35 | 36 | g_cb = cb; 37 | 38 | if (g_cb == NULL) 39 | return; 40 | 41 | // Trigger a mount callback if we already have mounts 42 | for (i = 0; i < MAX_CONNECTIONS; ++i) { 43 | if ((g_mount[i].bd != NULL) && (g_mount[i].fs != NULL)) { 44 | SetEventFlag(bdm_event, BDM_EVENT_CB_MOUNT); 45 | break; 46 | } 47 | } 48 | } 49 | 50 | void bdm_connect_bd(struct block_device *bd) 51 | { 52 | int i; 53 | 54 | M_PRINTF("connecting device %s%dp%d id=0x%x\n", bd->name, bd->devNr, bd->parNr, bd->parId); 55 | 56 | for (i = 0; i < MAX_CONNECTIONS; ++i) { 57 | if (g_mount[i].bd == NULL) { 58 | g_mount[i].bd = bd; 59 | // Create cache for entire device only (not for the partitions on it) 60 | g_mount[i].cbd = (bd->parNr == 0) ? bd_cache_create(bd) : NULL; 61 | // New block device, try to mount it to a filesystem 62 | SetEventFlag(bdm_event, BDM_EVENT_MOUNT); 63 | break; 64 | } 65 | } 66 | } 67 | 68 | void bdm_disconnect_bd(struct block_device *bd) 69 | { 70 | int i; 71 | 72 | M_PRINTF("disconnecting device %s%dp%d id=0x%x\n", bd->name, bd->devNr, bd->parNr, bd->parId); 73 | 74 | for (i = 0; i < MAX_CONNECTIONS; ++i) { 75 | if (g_mount[i].bd == bd) { 76 | if (g_mount[i].fs != NULL) { 77 | // Unmount filesystem 78 | g_mount[i].fs->disconnect_bd(g_mount[i].cbd != NULL ? g_mount[i].cbd : g_mount[i].bd); 79 | M_PRINTF("%s%dp%d unmounted from %s\n", bd->name, bd->devNr, bd->parNr, g_mount[i].fs->name); 80 | g_mount[i].fs = NULL; 81 | } 82 | 83 | if (g_mount[i].cbd != NULL) { 84 | bd_cache_destroy(g_mount[i].cbd); 85 | g_mount[i].cbd = NULL; 86 | } 87 | 88 | g_mount[i].bd = NULL; 89 | 90 | if (g_cb != NULL) 91 | SetEventFlag(bdm_event, BDM_EVENT_CB_UMOUNT); 92 | } 93 | } 94 | } 95 | 96 | void bdm_connect_fs(struct file_system *fs) 97 | { 98 | int i; 99 | 100 | M_PRINTF("connecting fs %s\n", fs->name); 101 | 102 | for (i = 0; i < MAX_CONNECTIONS; ++i) { 103 | if (g_fs[i] == NULL) { 104 | g_fs[i] = fs; 105 | break; 106 | } 107 | } 108 | 109 | // New filesystem, try to mount it to the block devices 110 | SetEventFlag(bdm_event, BDM_EVENT_MOUNT); 111 | } 112 | 113 | void bdm_disconnect_fs(struct file_system *fs) 114 | { 115 | int i; 116 | 117 | M_PRINTF("disconnecting fs %s\n", fs->name); 118 | 119 | // Unmount fs from block devices 120 | for (i = 0; i < MAX_CONNECTIONS; ++i) { 121 | if (g_mount[i].fs == fs) { 122 | g_mount[i].fs = NULL; 123 | if (g_cb != NULL) 124 | SetEventFlag(bdm_event, BDM_EVENT_CB_UMOUNT); 125 | } 126 | } 127 | 128 | // Remove fs from list 129 | for (i = 0; i < MAX_CONNECTIONS; ++i) { 130 | if (g_fs[i] == fs) { 131 | g_fs[i] = NULL; 132 | break; 133 | } 134 | } 135 | } 136 | 137 | void bdm_get_bd(struct block_device **pbd, unsigned int count) 138 | { 139 | int i; 140 | 141 | M_DEBUG("%s\n", __func__); 142 | 143 | // Fill pointer array with block device pointers 144 | for (i = 0; (unsigned int)i < count && i < MAX_CONNECTIONS; i++) 145 | pbd[i] = g_mount[i].bd; 146 | } 147 | 148 | static void bdm_try_mount(struct bdm_mounts *mount) 149 | { 150 | int i; 151 | 152 | M_DEBUG("%s(%s%dp%d)\n", __func__, mount->bd->name, mount->bd->devNr, mount->bd->parNr); 153 | 154 | for (i = 0; i < MAX_CONNECTIONS; ++i) { 155 | if (g_fs[i] != NULL) { 156 | if (g_fs[i]->connect_bd(mount->cbd != NULL ? mount->cbd : mount->bd) == 0) { 157 | M_PRINTF("%s%dp%d mounted to %s\n", mount->bd->name, mount->bd->devNr, mount->bd->parNr, g_fs[i]->name); 158 | mount->fs = g_fs[i]; 159 | if (g_cb != NULL) 160 | SetEventFlag(bdm_event, BDM_EVENT_CB_MOUNT); 161 | break; 162 | } 163 | } 164 | } 165 | } 166 | 167 | static void bdm_thread(void *arg) 168 | { 169 | u32 EFBits; 170 | int i; 171 | 172 | (void)arg; 173 | 174 | M_PRINTF("BDM event thread running\n"); 175 | 176 | while (1) { 177 | WaitEventFlag(bdm_event, BDM_EVENT_CB_MOUNT | BDM_EVENT_CB_UMOUNT | BDM_EVENT_MOUNT, WEF_OR | WEF_CLEAR, &EFBits); 178 | 179 | if (EFBits & BDM_EVENT_MOUNT) { 180 | // Try to mount any unmounted block devices 181 | for (i = 0; i < MAX_CONNECTIONS; ++i) { 182 | if ((g_mount[i].bd != NULL) && (g_mount[i].fs == NULL)) 183 | bdm_try_mount(&g_mount[i]); 184 | } 185 | } 186 | 187 | if (EFBits & BDM_EVENT_CB_MOUNT) { 188 | // Notify callback about changes 189 | if (g_cb != NULL) 190 | g_cb(1); 191 | } 192 | 193 | if (EFBits & BDM_EVENT_CB_UMOUNT) { 194 | // Notify callback about changes 195 | if (g_cb != NULL) 196 | g_cb(0); 197 | } 198 | } 199 | } 200 | 201 | int bdm_init() 202 | { 203 | int i, result; 204 | iop_event_t EventFlagData; 205 | iop_thread_t ThreadData; 206 | 207 | M_DEBUG("%s\n", __func__); 208 | 209 | for (i = 0; i < MAX_CONNECTIONS; ++i) { 210 | g_mount[i].bd = NULL; 211 | g_mount[i].cbd = NULL; 212 | g_mount[i].fs = NULL; 213 | g_fs[i] = NULL; 214 | } 215 | 216 | EventFlagData.attr = 0; 217 | EventFlagData.option = 0; 218 | EventFlagData.bits = 0; 219 | result = bdm_event = CreateEventFlag(&EventFlagData); 220 | if (result < 0) { 221 | M_DEBUG("ERROR: CreateEventFlag %d\n", result); 222 | return result; 223 | } 224 | 225 | ThreadData.attr = TH_C; 226 | ThreadData.thread = bdm_thread; 227 | ThreadData.option = 0; 228 | ThreadData.priority = 0x30; // Low priority 229 | ThreadData.stacksize = 0x1000; // 4KiB 230 | result = bdm_thread_id = CreateThread(&ThreadData); 231 | if (result < 0) { 232 | M_DEBUG("ERROR: CreateThread %d\n", result); 233 | DeleteEventFlag(bdm_event); 234 | return result; 235 | } 236 | 237 | result = StartThread(bdm_thread_id, NULL); 238 | if (result < 0) { 239 | M_DEBUG("ERROR: StartThread %d\n", result); 240 | DeleteThread(bdm_thread_id); 241 | DeleteEventFlag(bdm_event); 242 | return result; 243 | } 244 | 245 | return 0; 246 | } 247 | -------------------------------------------------------------------------------- /bdm/src/exports.tab: -------------------------------------------------------------------------------- 1 | /**/ 2 | 3 | DECLARE_EXPORT_TABLE(bdm, 1, 1) 4 | DECLARE_EXPORT(_start) 5 | DECLARE_EXPORT(_retonly) 6 | DECLARE_EXPORT(_retonly) 7 | DECLARE_EXPORT(_retonly) 8 | DECLARE_EXPORT(bdm_connect_bd) 9 | DECLARE_EXPORT(bdm_disconnect_bd) 10 | DECLARE_EXPORT(bdm_connect_fs) 11 | DECLARE_EXPORT(bdm_disconnect_fs) 12 | DECLARE_EXPORT(bdm_get_bd) 13 | DECLARE_EXPORT(bdm_RegisterCallback) 14 | END_EXPORT_TABLE 15 | 16 | void _retonly() {} 17 | -------------------------------------------------------------------------------- /bdm/src/imports.lst: -------------------------------------------------------------------------------- 1 | loadcore_IMPORTS_start 2 | I_RegisterLibraryEntries 3 | loadcore_IMPORTS_end 4 | 5 | stdio_IMPORTS_start 6 | I_printf 7 | stdio_IMPORTS_end 8 | 9 | sysclib_IMPORTS_start 10 | I_memcpy 11 | I_memcmp 12 | I_memset 13 | sysclib_IMPORTS_end 14 | 15 | sysmem_IMPORTS_start 16 | I_AllocSysMemory 17 | I_FreeSysMemory 18 | sysmem_IMPORTS_end 19 | 20 | thbase_IMPORTS_start 21 | I_CreateThread 22 | I_StartThread 23 | I_DeleteThread 24 | thbase_IMPORTS_end 25 | 26 | thevent_IMPORTS_start 27 | I_CreateEventFlag 28 | I_WaitEventFlag 29 | I_SetEventFlag 30 | I_DeleteEventFlag 31 | thevent_IMPORTS_end 32 | -------------------------------------------------------------------------------- /bdm/src/include/gpt_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Licenced under Academic Free License version 2.0 7 | # Review ps2sdk README & LICENSE files for further details. 8 | */ 9 | 10 | /** 11 | * @file 12 | * GPT partition definitions. 13 | */ 14 | 15 | #ifndef _GPT_TYPES_H 16 | #define _GPT_TYPES_H 17 | 18 | #include 19 | 20 | static const u8 EFI_PARTITION_SIGNATURE[8] = { 'E', 'F', 'I', ' ', 'P', 'A', 'R', 'T' }; 21 | 22 | typedef struct __attribute__((packed)) _gpt_partition_table_header 23 | { 24 | /* 0x00 */ u8 signature[8]; // 'EFI PART' 25 | /* 0x08 */ u32 revision; // Revision 1.0 (00h 00h 01h 00h) for UEFI 2.8 26 | /* 0x0C */ u32 header_size; // Header size in little endian (in bytes, usually 5Ch 00h 00h 00h or 92 bytes) 27 | /* 0x10 */ u32 header_checksum; // CRC32 of header (offset +0 to +0x5b) in little endian, with this field zeroed during calculation 28 | /* 0x14 */ u32 reserved1; // Reserved, must be zero 29 | /* 0x18 */ u64 current_lba; // Current LBA (location of this header copy) 30 | /* 0x20 */ u64 backup_lba; // Backup LBA (location of the other header copy) 31 | /* 0x28 */ u64 first_lba; // First usable LBA for partitions (primary partition table last LBA + 1) 32 | /* 0x30 */ u64 last_lba; // Last usable LBA (secondary partition table first LBA − 1) 33 | /* 0x38 */ u8 disk_guid[16]; // Disk GUID in mixed endian 34 | /* 0x48 */ u64 partition_table_lba; // Starting LBA of array of partition entries (usually 2 for compatibility) 35 | /* 0x50 */ u32 partition_count; // Number of partition entries in array 36 | /* 0x54 */ u32 partition_entry_size; // Size of a single partition entry (usually 80h or 128) 37 | /* 0x58 */ u32 partition_table_checksum; // CRC32 of partition entries array in little endian 38 | } gpt_partition_table_header; 39 | 40 | // Partition type GUIDs: 41 | static const u8 NULL_GUID[16] = { 0 }; 42 | static const u8 MS_RESERVED_PARTITION_GUID[16] = { 0x16, 0xE3, 0xC9, 0xE3, 0x5C, 0x0B, 0xB8, 0x4D, 0x81, 0x7D, 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE }; 43 | static const u8 EFI_SYSTEM_PARTITION[16] = { 0x28, 0x73, 0x2A, 0xC1, 0x1F, 0xF8, 0xD2, 0x11, 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B }; 44 | static const u8 MS_BASIC_DATA_PARTITION_GUID[16] = { 0xA2, 0xA0, 0xD0, 0xEB, 0xE5, 0xB9, 0x33, 0x44, 0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7 }; 45 | 46 | typedef struct __attribute__((packed)) _gpt_partition_table_entry 47 | { 48 | /* 0x00 */ u8 partition_type_guid[16]; // Partition type guid (mixed endian) 49 | /* 0x10 */ u8 partition_unique_guid[16]; // Unique partition id 50 | /* 0x20 */ u64 first_lba; // First LBA (little endian) 51 | /* 0x28 */ u64 last_lba; // Last LBA (inclusive, usually odd) 52 | /* 0x30 */ u64 attribute_flags; // Attribute flags (e.g. bit 60 denotes read-only) 53 | /* 0x38 */ u16 partition_name[36]; // Partition name (36 UTF-16LE code units) 54 | } gpt_partition_table_entry; 55 | 56 | #define GPT_PART_ATTR_PLATFORM_REQUIRED 0x1 // Platform required (required by the computer to function properly, OEM partition for example, disk partitioning utilities must preserve the partition as is) 57 | #define GPT_PART_ATTR_IGNORE 0x2 // EFI firmware should ignore the content of the partition and not try to read from it 58 | #define GPT_PART_ATTR_LEGACY_BOOTABLE 0x4 // Legacy BIOS bootable 59 | 60 | #define GPT_PART_ATTR_TYPE_SHIFT 48 // Number of partition attribute bits reserved for common attribute 61 | #define GPT_PART_ATTR_TYPE_MASK 0xFFFF // Mask for type-specific attribute bits (after shifting) 62 | #define GPT_PART_ATTR_TYPE_SPECIFIC(attr) ((attr >> GPT_PART_ATTR_TYPE_SHIFT) & GPT_PART_ATTR_TYPE_MASK) 63 | 64 | // Basic data partition type-specific attribute flags: 65 | #define GPT_BDP_ATTR_READ_ONLY 0x1000 // Partition is read only 66 | #define GPT_BDP_ATTR_SHADOW_COPY 0x2000 // Shadow copy (of another partition) 67 | #define GPT_BDP_ATTR_HIDDEN 0x4000 // Partition is hidden 68 | #define GPT_BDP_ATTR_NO_DRIVE_LETTER 0x8000 // No drive letter (i.e. do not automount) 69 | 70 | #endif // _GPT_TYPES_H 71 | -------------------------------------------------------------------------------- /bdm/src/include/mbr_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Licenced under Academic Free License version 2.0 7 | # Review ps2sdk README & LICENSE files for further details. 8 | */ 9 | 10 | /** 11 | * @file 12 | * MBR partition definitions. 13 | */ 14 | 15 | #ifndef _MBR_TYPES_H 16 | #define _MBR_TYPES_H 17 | 18 | #include 19 | 20 | #define MBR_BOOT_SIGNATURE 0xAA55 21 | 22 | #define MBR_PART_TYPE_GPT_PROTECTIVE_MBR 0xEE // Indicates the MBR is 'protective' only and the actual format is GPT 23 | 24 | // See: https://en.wikipedia.org/wiki/Master_boot_record#PTE 25 | typedef struct __attribute__((packed)) _mbr_partition_entry 26 | { 27 | /* 0x00 */ u8 status; // Status or physical drive (bit 7 set is for active or bootable, old MBRs only accept 0x80, 0x00 means inactive, and 0x01–0x7F stand for invalid) 28 | /* 0x01 */ u8 chs_first_lba[3]; // CHS address of first absolute sector in partition 29 | /* 0x04 */ u8 partition_type; // Type of partition, see: https://en.wikipedia.org/wiki/Partition_type 30 | /* 0x05 */ u8 chs_last_lba[3]; // CHS address of last absolute sector in partition 31 | /* 0x08 */ u32 first_lba; // LBA of first absolute sector in the partition 32 | /* 0x0C */ u32 sector_count; // Number of sectors in partition 33 | } mbr_partition_entry; 34 | 35 | // See: https://en.wikipedia.org/wiki/Master_boot_record 36 | typedef struct __attribute__((packed)) _master_boot_record 37 | { 38 | /* 0x00 */ u8 bootstrap_code1[218]; // Bootstrap code area (part 1) 39 | /* 0xDA */ u8 disk_timestamp[6]; // Disk timestamp (optional; Windows 95B/98/98SE/ME (MS-DOS 7.1–8.0). Alternatively, can serve as OEM loader signature with NEWLDR) 40 | /* 0xE0 */ u8 bootstrap_code2[216]; // Bootstrap code area (part 2, code entry at 0x0000) 41 | /* 0x1B8 */ u32 disk_signature; // Disk signature (optional; UEFI, Linux, Windows NT family and other OSes) 42 | /* 0x1BC */ u16 copy_protection; // 0x0000 (0x5A5A if copy-protected) 43 | /* 0x1BE */ mbr_partition_entry primary_partitions[4]; // Partition table (for primary partitions) 44 | /* 0x1FE */ u16 boot_signature; // 0xAA55 45 | } master_boot_record; 46 | 47 | #endif // _MBR_TYPES_H 48 | -------------------------------------------------------------------------------- /bdm/src/include/module_debug.h: -------------------------------------------------------------------------------- 1 | #ifndef _MODULE_DEBUG_H 2 | #define _MODULE_DEBUG_H 3 | 4 | // #define MINI_DRIVER 5 | 6 | #ifndef MINI_DRIVER 7 | #define M_PRINTF(format, args...) printf("BDM: " format, ##args) 8 | #else 9 | #define M_PRINTF(format, args...) \ 10 | do { \ 11 | } while (0) 12 | #endif 13 | 14 | #ifdef DEBUG 15 | #define M_DEBUG M_PRINTF 16 | #else 17 | #define M_DEBUG(format, args...) \ 18 | do { \ 19 | } while (0) 20 | #endif 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /bdm/src/include/part_driver.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Licenced under Academic Free License version 2.0 7 | # Review ps2sdk README & LICENSE files for further details. 8 | */ 9 | 10 | /** 11 | * @file 12 | * Common partition driver definitions. 13 | */ 14 | 15 | #ifndef _PART_DRIVER_H 16 | #define _PART_DRIVER_H 17 | 18 | #include 19 | 20 | struct partition 21 | { 22 | struct block_device *bd; 23 | }; 24 | 25 | #define MAX_PARTITIONS 10 26 | extern struct partition g_part[MAX_PARTITIONS]; 27 | extern struct block_device g_part_bd[MAX_PARTITIONS]; 28 | 29 | int GetNextFreePartitionIndex(); 30 | 31 | int part_connect_mbr(struct block_device *bd); 32 | int part_connect_gpt(struct block_device *bd); 33 | 34 | #endif -------------------------------------------------------------------------------- /bdm/src/irx_imports.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Copyright 2001-2009, ps2dev - http://www.ps2dev.org 7 | # Licenced under Academic Free License version 2.0 8 | # Review ps2sdk README & LICENSE files for further details. 9 | # 10 | # Defines all IRX imports. 11 | */ 12 | 13 | #ifndef IOP_IRX_IMPORTS_H 14 | #define IOP_IRX_IMPORTS_H 15 | 16 | #include 17 | 18 | /* Please keep these in alphabetical order! */ 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #endif /* IOP_IRX_IMPORTS_H */ 28 | -------------------------------------------------------------------------------- /bdm/src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // #define DEBUG //comment out this line when not debugging 7 | #include "module_debug.h" 8 | 9 | #define MAJOR_VER 1 10 | #define MINOR_VER 1 11 | 12 | IRX_ID("bdm", MAJOR_VER, MINOR_VER); 13 | 14 | extern struct irx_export_table _exp_bdm; 15 | extern int bdm_init(); 16 | extern void part_init(); 17 | 18 | int _start(int argc, char *argv[]) 19 | { 20 | (void)argc; 21 | (void)argv; 22 | 23 | printf("Block Device Manager (BDM) v%d.%d\n", MAJOR_VER, MINOR_VER); 24 | 25 | if (RegisterLibraryEntries(&_exp_bdm) != 0) { 26 | M_PRINTF("ERROR: Already registered!\n"); 27 | return MODULE_NO_RESIDENT_END; 28 | } 29 | 30 | // initialize the block device manager 31 | if (bdm_init() < 0) { 32 | M_PRINTF("ERROR: BDM init failed!\n"); 33 | return MODULE_NO_RESIDENT_END; 34 | } 35 | 36 | // initialize the partition driver 37 | part_init(); 38 | 39 | // return resident 40 | return MODULE_RESIDENT_END; 41 | } 42 | -------------------------------------------------------------------------------- /bdm/src/part_driver.c: -------------------------------------------------------------------------------- 1 | #include "part_driver.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include "mbr_types.h" 9 | #include "gpt_types.h" 10 | 11 | #include "module_debug.h" 12 | 13 | #define U64_2XU32(val) ((u32*)val)[1], ((u32*)val)[0] 14 | 15 | struct partition g_part[MAX_PARTITIONS]; 16 | struct block_device g_part_bd[MAX_PARTITIONS]; 17 | 18 | static struct file_system g_mbr_fs; 19 | static struct file_system g_gpt_fs; 20 | 21 | int GetNextFreePartitionIndex() 22 | { 23 | // Loop and find the next free partition index. 24 | for (int i = 0; i < MAX_PARTITIONS; i++) 25 | { 26 | if (g_part[i].bd == NULL) 27 | return i; 28 | } 29 | 30 | // No more free partitions. 31 | return -1; 32 | } 33 | 34 | //--------------------------------------------------------------------------- 35 | void part_disconnect(struct block_device *bd) 36 | { 37 | int i; 38 | 39 | M_DEBUG("%s\n", __func__); 40 | 41 | for (i = 0; i < MAX_PARTITIONS; ++i) { 42 | if (g_part[i].bd == bd) { 43 | bdm_disconnect_bd(&g_part_bd[i]); 44 | g_part[i].bd = NULL; 45 | } 46 | } 47 | } 48 | 49 | // 50 | // Block device interface 51 | // 52 | static int part_read(struct block_device *bd, u64 sector, void *buffer, u16 count) 53 | { 54 | struct partition *part = (struct partition *)bd->priv; 55 | 56 | if ((part == NULL) || (part->bd == NULL)) 57 | return -1; 58 | 59 | #ifdef DEBUG 60 | u64 finalSector = sector + bd->sectorOffset; 61 | M_DEBUG("%s (%s %d %d) 0x%08x%08x %d\n", __func__, bd->name, bd->devNr, bd->parNr, U64_2XU32(&finalSector), count); 62 | #endif 63 | 64 | return part->bd->read(part->bd, sector + bd->sectorOffset, buffer, count); 65 | } 66 | 67 | static int part_write(struct block_device *bd, u64 sector, const void *buffer, u16 count) 68 | { 69 | struct partition *part = (struct partition *)bd->priv; 70 | 71 | if ((part == NULL) || (part->bd == NULL)) 72 | return -1; 73 | 74 | #ifdef DEBUG 75 | u64 finalSector = sector + bd->sectorOffset; 76 | M_DEBUG("%s (%s %d %d) 0x%08x%08x %d\n", __func__, bd->name, bd->devNr, bd->parNr, U64_2XU32(&finalSector), count); 77 | #endif 78 | 79 | return part->bd->write(part->bd, sector + bd->sectorOffset, buffer, count); 80 | } 81 | 82 | static void part_flush(struct block_device *bd) 83 | { 84 | struct partition *part = (struct partition *)bd->priv; 85 | 86 | M_DEBUG("%s\n", __func__); 87 | 88 | if ((part == NULL) || (part->bd == NULL)) 89 | return; 90 | 91 | return part->bd->flush(part->bd); 92 | } 93 | 94 | static int part_stop(struct block_device *bd) 95 | { 96 | struct partition *part = (struct partition *)bd->priv; 97 | 98 | M_DEBUG("%s\n", __func__); 99 | 100 | if ((part == NULL) || (part->bd == NULL)) 101 | return -1; 102 | 103 | return part->bd->stop(part->bd); 104 | } 105 | 106 | void part_init() 107 | { 108 | int i; 109 | 110 | M_DEBUG("%s\n", __func__); 111 | 112 | for (i = 0; i < MAX_PARTITIONS; ++i) { 113 | g_part[i].bd = NULL; 114 | 115 | g_part_bd[i].priv = &g_part[i]; 116 | g_part_bd[i].read = part_read; 117 | g_part_bd[i].write = part_write; 118 | g_part_bd[i].flush = part_flush; 119 | g_part_bd[i].stop = part_stop; 120 | } 121 | 122 | // Setup MBR file system driver: 123 | g_mbr_fs.priv = NULL; 124 | g_mbr_fs.name = "MBR"; 125 | g_mbr_fs.connect_bd = part_connect_mbr; 126 | g_mbr_fs.disconnect_bd = part_disconnect; 127 | bdm_connect_fs(&g_mbr_fs); 128 | 129 | // Setup GPT file system driver: 130 | g_gpt_fs.priv = NULL; 131 | g_gpt_fs.name = "GPT"; 132 | g_gpt_fs.connect_bd = part_connect_gpt; 133 | g_gpt_fs.disconnect_bd = part_disconnect; 134 | bdm_connect_fs(&g_gpt_fs); 135 | } 136 | -------------------------------------------------------------------------------- /bdm/src/part_driver_gpt.c: -------------------------------------------------------------------------------- 1 | #include "part_driver.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include "gpt_types.h" 9 | 10 | #include "module_debug.h" 11 | 12 | #define U64_2XU32(val) ((u32*)val)[1], ((u32*)val)[0] 13 | 14 | void GetGPTPartitionNameAscii(gpt_partition_table_entry* pPartition, char* pAsciiBuffer) 15 | { 16 | // Loop and perform the world's worst unicode -> ascii string conversion. 17 | for (int i = 0; i < sizeof(pPartition->partition_name) / sizeof(u16); i++) 18 | pAsciiBuffer[i] = (char)pPartition->partition_name[i]; 19 | } 20 | 21 | int part_connect_gpt(struct block_device *bd) 22 | { 23 | int ret; 24 | void* buffer = NULL; 25 | gpt_partition_table_header* pGptHeader; 26 | gpt_partition_table_entry* pGptPartitionEntry; 27 | int entriesPerSector; 28 | int endOfTable = 0; 29 | char partName[37] = { 0 }; 30 | int partIndex; 31 | int mountCount = 0; 32 | 33 | M_DEBUG("%s\n", __func__); 34 | 35 | // Allocate scratch memory for parsing the partition table. 36 | buffer = AllocSysMemory(ALLOC_FIRST, 512 * 2, NULL); 37 | if (buffer == NULL) 38 | { 39 | M_DEBUG("Failed to allocate memory\n"); 40 | return 0; 41 | } 42 | 43 | pGptHeader = (gpt_partition_table_header*)buffer; 44 | pGptPartitionEntry = (gpt_partition_table_entry*)((u8*)buffer + 512); 45 | 46 | // Read the GPT partition table header from the block device. 47 | ret = bd->read(bd, 1, pGptHeader, 1); 48 | if (ret < 0) 49 | { 50 | // Failed to read gpt partition table header. 51 | M_DEBUG("Failed to read GPT partition table header %d\n", ret); 52 | FreeSysMemory(buffer); 53 | return -1; 54 | } 55 | 56 | // Check the partition table header signature. 57 | if (memcmp(pGptHeader->signature, EFI_PARTITION_SIGNATURE, sizeof(EFI_PARTITION_SIGNATURE)) != 0) 58 | { 59 | // GPT partition table header signature is invalid. 60 | M_DEBUG("GPT partition table header signature is invalid: %s\n", pGptHeader->signature); 61 | FreeSysMemory(buffer); 62 | return -1; 63 | } 64 | 65 | // TODO: we might want to check the header revision and size for compatibility for newer/older GPT layouts. There's 66 | // also a few CRC checksums in the header that may be useful to validate, but is probably not needed. 67 | 68 | // Calculate how many partition entries there are per sector. 69 | entriesPerSector = bd->sectorSize / sizeof(gpt_partition_table_entry); 70 | 71 | // Loop through all the partition table entries and attempt to mount each one. 72 | printf("Found GPT disk '%08x...'\n", *(u32*)&pGptHeader->disk_guid); 73 | for (int i = 0; i < pGptHeader->partition_count && endOfTable == 0; ) 74 | { 75 | // Check if we need to buffer more data, GPT usually uses LBA 2-33 for partition table entries. Typically there will 76 | // only be a couple partitions at most, so we buffer one sector at a time to avoid making needless allocations for all sectors at once. 77 | if (i % entriesPerSector == 0) 78 | { 79 | // Read the next sector from the block device. 80 | ret = bd->read(bd, pGptHeader->partition_table_lba + (i / entriesPerSector), pGptPartitionEntry, 1); 81 | if (ret < 0) 82 | { 83 | // Failed to read the next sector from the drive. 84 | #ifdef DEBUG 85 | u64 lba = pGptHeader->partition_table_lba + (i / entriesPerSector); 86 | M_DEBUG("Failed to read next partition table entry sector lba=0x%08x%08x\n", U64_2XU32(&lba)); 87 | #endif 88 | FreeSysMemory(buffer); 89 | return -1; 90 | } 91 | 92 | // Parse the two partition table entries in the structure. 93 | for (int x = 0; x < entriesPerSector; x++, i++) 94 | { 95 | // Check if the partition type guid is valid, the header will list the maximum number of partitions that can fit into the table, so 96 | // we need to check if the entries are actually valid. 97 | if (memcmp(pGptPartitionEntry[x].partition_type_guid, NULL_GUID, sizeof(NULL_GUID)) == 0) 98 | { 99 | // Stop scanning for partitions. 100 | endOfTable = 1; 101 | break; 102 | } 103 | 104 | // Perform some sanity checks on the partition. 105 | if (pGptPartitionEntry[x].first_lba < pGptHeader->first_lba || pGptPartitionEntry[x].last_lba > pGptHeader->last_lba) 106 | { 107 | // Partition entry data appears to be corrupt. 108 | M_DEBUG("Partition entry %d appears to be corrupt (lba bounds incorrect)\n", i); 109 | continue; 110 | } 111 | 112 | // Print the partition info and create a pseudo block device for it. 113 | GetGPTPartitionNameAscii(&pGptPartitionEntry[x], partName); 114 | printf("Found partition '%s' type=%08x unique=%08x start=0x%08x%08x end=0x%08x%08x attr=0x%08x%08x\n", partName, *(u32*)&pGptPartitionEntry[x].partition_type_guid, 115 | *(u32*)&pGptPartitionEntry[x].partition_unique_guid, U64_2XU32(&pGptPartitionEntry[x].first_lba), U64_2XU32(&pGptPartitionEntry[x].last_lba), U64_2XU32(&pGptPartitionEntry[x].attribute_flags)); 116 | 117 | // Check for specific GPT partition types we should ignore. 118 | if (memcmp(pGptPartitionEntry[x].partition_type_guid, MS_RESERVED_PARTITION_GUID, sizeof(MS_RESERVED_PARTITION_GUID)) == 0 || 119 | memcmp(pGptPartitionEntry[x].partition_type_guid, EFI_SYSTEM_PARTITION, sizeof(EFI_SYSTEM_PARTITION)) == 0) 120 | continue; 121 | 122 | // Check if the partition should be ignored. 123 | if ((pGptPartitionEntry[x].attribute_flags & GPT_PART_ATTR_IGNORE) != 0) 124 | continue; 125 | 126 | // TODO: Check type specific partition flags: read-only, hidden, etc. 127 | 128 | if ((partIndex = GetNextFreePartitionIndex()) == -1) 129 | { 130 | // No more free partition slots. 131 | printf("Can't mount partition, no more free partition slots!\n"); 132 | continue; 133 | } 134 | 135 | // Create the pseudo block device for the partition. 136 | g_part[partIndex].bd = bd; 137 | g_part_bd[partIndex].name = bd->name; 138 | g_part_bd[partIndex].devNr = bd->devNr; 139 | g_part_bd[partIndex].parNr = i + 1; 140 | g_part_bd[partIndex].parId = 0; 141 | g_part_bd[partIndex].sectorSize = bd->sectorSize; 142 | g_part_bd[partIndex].sectorOffset = bd->sectorOffset + pGptPartitionEntry[x].first_lba; 143 | g_part_bd[partIndex].sectorCount = pGptPartitionEntry[x].last_lba - pGptPartitionEntry[x].first_lba; 144 | bdm_connect_bd(&g_part_bd[partIndex]); 145 | mountCount++; 146 | } 147 | } 148 | } 149 | 150 | // Free our scratch buffer. 151 | FreeSysMemory(buffer); 152 | return mountCount > 0 ? 0 : -1; 153 | } -------------------------------------------------------------------------------- /bdm/src/part_driver_mbr.c: -------------------------------------------------------------------------------- 1 | #include "part_driver.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include "mbr_types.h" 9 | 10 | #include "module_debug.h" 11 | 12 | int part_connect_mbr(struct block_device *bd) 13 | { 14 | master_boot_record* pMbrBlock = NULL; 15 | int rval = -1; 16 | int ret; 17 | int mountCount = 0; 18 | int partIndex; 19 | 20 | M_DEBUG("%s\n", __func__); 21 | 22 | // Filter out any block device where sectorOffset != 0, as this will be a block device for a file system partition and not 23 | // the raw device. 24 | if (bd->sectorOffset != 0) 25 | return rval; 26 | 27 | // Allocate memory for MBR partition sector. 28 | pMbrBlock = AllocSysMemory(ALLOC_FIRST, sizeof(master_boot_record), NULL); 29 | if (pMbrBlock == NULL) 30 | { 31 | // Failed to allocate memory for mbr block. 32 | M_DEBUG("Failed to allocate memory for MBR block\n"); 33 | return rval; 34 | } 35 | 36 | // Read the MBR block from the block device. 37 | ret = bd->read(bd, 0, pMbrBlock, 1); 38 | if (ret < 0) 39 | { 40 | // Failed to read MBR block from the block device. 41 | M_DEBUG("Failed to read MBR sector from block device %d\n", ret); 42 | return rval; 43 | } 44 | 45 | // Check the MBR boot signature. 46 | if (pMbrBlock->boot_signature != MBR_BOOT_SIGNATURE) 47 | { 48 | // Boot signature is invalid, device is not valid MBR. 49 | M_DEBUG("MBR boot signature is invalid, device is not MBR\n"); 50 | FreeSysMemory(pMbrBlock); 51 | return rval; 52 | } 53 | 54 | // Check the first primary partition to see if this is a GPT protective MBR. 55 | if (pMbrBlock->primary_partitions[0].partition_type == MBR_PART_TYPE_GPT_PROTECTIVE_MBR) 56 | { 57 | // We explicitly fail to connect GPT protective MBRs in order to let the GPT driver handle it. 58 | FreeSysMemory(pMbrBlock); 59 | return rval; 60 | } 61 | 62 | // Loop and parse the primary partition entries in the MBR block. 63 | printf("Found MBR disk\n"); 64 | for (int i = 0; i < 4; i++) 65 | { 66 | // Check if the partition is active, checking the status bit is not reliable so check if the sector_count is greater than zero instead. 67 | if (pMbrBlock->primary_partitions[i].sector_count == 0) 68 | continue; 69 | 70 | printf("Found partition type 0x%02x\n", pMbrBlock->primary_partitions[i].partition_type); 71 | 72 | // TODO: Filter out unsupported partition types. 73 | 74 | if ((partIndex = GetNextFreePartitionIndex()) == -1) 75 | { 76 | // No more free partition slots. 77 | printf("Can't mount partition, no more free partition slots!\n"); 78 | continue; 79 | } 80 | 81 | // Create the pseudo block device for the partition. 82 | g_part[partIndex].bd = bd; 83 | g_part_bd[partIndex].name = bd->name; 84 | g_part_bd[partIndex].devNr = bd->devNr; 85 | g_part_bd[partIndex].parNr = i + 1; 86 | g_part_bd[partIndex].parId = pMbrBlock->primary_partitions[i].partition_type; 87 | g_part_bd[partIndex].sectorSize = bd->sectorSize; 88 | g_part_bd[partIndex].sectorOffset = bd->sectorOffset + (u64)pMbrBlock->primary_partitions[i].first_lba; 89 | g_part_bd[partIndex].sectorCount = pMbrBlock->primary_partitions[i].sector_count; 90 | bdm_connect_bd(&g_part_bd[partIndex]); 91 | mountCount++; 92 | } 93 | 94 | // If one or more partitions were mounted then return success. 95 | rval = mountCount > 0 ? 0 : -1; 96 | 97 | FreeSysMemory(pMbrBlock); 98 | return rval; 99 | } -------------------------------------------------------------------------------- /bdmfs_fatfs/Makefile: -------------------------------------------------------------------------------- 1 | # _____ ___ ____ ___ ____ 2 | # ____| | ____| | | |____| 3 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 4 | #----------------------------------------------------------------------- 5 | # Copyright 2001-2004, ps2dev - http://www.ps2dev.org 6 | # Licenced under Academic Free License version 2.0 7 | # Review ps2sdk README & LICENSE files for further details. 8 | 9 | # IOP_CFLAGS += -DDEBUG -DDEBUG_EXTREME 10 | 11 | IOP_BIN = bdmfs_fatfs.irx 12 | 13 | IOP_INCS += -I../bdm/include 14 | IOP_CFLAGS += -Wno-error -Wno-strict-aliasing 15 | 16 | IOP_OBJS = ff.o ffsystem.o ffunicode.o fs_driver.o diskio.o main.o imports.o 17 | IOP_LIBS = -static-libgcc -lgcc 18 | 19 | include ../global.make -------------------------------------------------------------------------------- /bdmfs_fatfs/src/00readme.txt: -------------------------------------------------------------------------------- 1 | FatFs Module Source Files R0.14b 2 | 3 | 4 | FILES 5 | 6 | 00readme.txt This file. 7 | 00history.txt Revision history. 8 | ff.c FatFs module. 9 | ffconf.h Configuration file of FatFs module. 10 | ff.h Common include file for FatFs and application module. 11 | diskio.h Common include file for FatFs and disk I/O module. 12 | diskio.c An example of glue function to attach existing disk I/O module to FatFs. 13 | ffunicode.c Optional Unicode utility functions. 14 | ffsystem.c An example of optional O/S related functions. 15 | 16 | 17 | Low level disk I/O module is not included in this archive because the FatFs 18 | module is only a generic file system layer and it does not depend on any specific 19 | storage device. You need to provide a low level disk I/O module written to 20 | control the storage device that attached to the target system. 21 | 22 | -------------------------------------------------------------------------------- /bdmfs_fatfs/src/diskio.c: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------*/ 2 | /* Low level disk I/O module SKELETON for FatFs (C)ChaN, 2019 */ 3 | /*-----------------------------------------------------------------------*/ 4 | /* If a working storage control module is available, it should be */ 5 | /* attached to the FatFs via a glue function rather than modifying it. */ 6 | /* This is an example of glue functions to attach various exsisting */ 7 | /* storage control modules to the FatFs module with a defined API. */ 8 | /*-----------------------------------------------------------------------*/ 9 | 10 | #include 11 | #include 12 | 13 | #include "ff.h" /* Obtains integer types */ 14 | #include "diskio.h" /* Declarations of disk functions */ 15 | 16 | #include "fs_driver.h" 17 | 18 | /*-----------------------------------------------------------------------*/ 19 | /* Get Drive Status */ 20 | /*-----------------------------------------------------------------------*/ 21 | 22 | DSTATUS disk_status( 23 | BYTE pdrv /* Physical drive number to identify the drive */ 24 | ) 25 | { 26 | int result; 27 | 28 | result = (fatfs_fs_driver_get_mounted_bd_from_index(pdrv) == NULL) ? (STA_NOINIT | STA_NODISK) : 0; 29 | 30 | return result; 31 | } 32 | 33 | 34 | 35 | /*-----------------------------------------------------------------------*/ 36 | /* Inidialize a Drive */ 37 | /*-----------------------------------------------------------------------*/ 38 | 39 | DSTATUS disk_initialize( 40 | BYTE pdrv /* Physical drive nmuber to identify the drive */ 41 | ) 42 | { 43 | int result; 44 | 45 | result = (fatfs_fs_driver_get_mounted_bd_from_index(pdrv) == NULL) ? (STA_NOINIT | STA_NODISK) : 0; 46 | 47 | return result; 48 | } 49 | 50 | 51 | 52 | /*-----------------------------------------------------------------------*/ 53 | /* Read Sector(s) */ 54 | /*-----------------------------------------------------------------------*/ 55 | 56 | DRESULT disk_read( 57 | BYTE pdrv, /* Physical drive nmuber to identify the drive */ 58 | BYTE *buff, /* Data buffer to store read data */ 59 | LBA_t sector, /* Start sector in LBA */ 60 | UINT count /* Number of sectors to read */ 61 | ) 62 | { 63 | DRESULT res; 64 | struct block_device *mounted_bd; 65 | 66 | mounted_bd = fatfs_fs_driver_get_mounted_bd_from_index(pdrv); 67 | 68 | if (mounted_bd == NULL) { 69 | return RES_NOTRDY; 70 | } 71 | 72 | res = mounted_bd->read(mounted_bd, sector, buff, count); 73 | 74 | return (res == count) ? RES_OK : RES_ERROR; 75 | } 76 | 77 | 78 | 79 | /*-----------------------------------------------------------------------*/ 80 | /* Write Sector(s) */ 81 | /*-----------------------------------------------------------------------*/ 82 | 83 | #if FF_FS_READONLY == 0 84 | 85 | DRESULT disk_write( 86 | BYTE pdrv, /* Physical drive nmuber to identify the drive */ 87 | const BYTE *buff, /* Data to be written */ 88 | LBA_t sector, /* Start sector in LBA */ 89 | UINT count /* Number of sectors to write */ 90 | ) 91 | { 92 | DRESULT res; 93 | struct block_device *mounted_bd; 94 | 95 | mounted_bd = fatfs_fs_driver_get_mounted_bd_from_index(pdrv); 96 | 97 | if (mounted_bd == NULL) { 98 | return RES_NOTRDY; 99 | } 100 | 101 | res = mounted_bd->write(mounted_bd, sector, buff, count); 102 | 103 | return (res == count) ? RES_OK : RES_ERROR; 104 | } 105 | 106 | #endif 107 | 108 | 109 | /*-----------------------------------------------------------------------*/ 110 | /* Miscellaneous Functions */ 111 | /*-----------------------------------------------------------------------*/ 112 | 113 | DRESULT disk_ioctl( 114 | BYTE pdrv, /* Physical drive nmuber (0..) */ 115 | BYTE cmd, /* Control code */ 116 | void *buff /* Buffer to send/receive control data */ 117 | ) 118 | { 119 | struct block_device *mounted_bd; 120 | 121 | mounted_bd = fatfs_fs_driver_get_mounted_bd_from_index(pdrv); 122 | 123 | if (mounted_bd == NULL) { 124 | return RES_NOTRDY; 125 | } 126 | 127 | switch (cmd) { 128 | case CTRL_SYNC: 129 | mounted_bd->flush(mounted_bd); 130 | break; 131 | case GET_SECTOR_COUNT: 132 | *(unsigned int *)buff = mounted_bd->sectorCount; 133 | break; 134 | case GET_SECTOR_SIZE: 135 | *(unsigned int *)buff = mounted_bd->sectorSize; 136 | break; 137 | case GET_BLOCK_SIZE: 138 | *(unsigned int *)buff = 0; 139 | break; 140 | } 141 | 142 | return RES_OK; 143 | } 144 | 145 | DWORD get_fattime(void) 146 | { 147 | // ps2 specific routine to get time and date 148 | int year, month, day, hour, minute, sec; 149 | sceCdCLOCK cdtime; 150 | 151 | if (sceCdReadClock(&cdtime) != 0 && cdtime.stat == 0) { 152 | sec = btoi(cdtime.second); 153 | minute = btoi(cdtime.minute); 154 | hour = btoi(cdtime.hour); 155 | day = btoi(cdtime.day); 156 | month = btoi(cdtime.month & 0x7F); // Ignore century bit (when an old CDVDMAN is used). 157 | year = btoi(cdtime.year) + 2000; 158 | } else { 159 | year = 2005; 160 | month = 1; 161 | day = 6; 162 | hour = 14; 163 | minute = 12; 164 | sec = 10; 165 | } 166 | 167 | /* Pack date and time into a DWORD variable */ 168 | return ((DWORD)(year - 1980) << 25) | ((DWORD)month << 21) | ((DWORD)day << 16) | ((DWORD)hour << 11) | ((DWORD)minute << 5) | ((DWORD)sec >> 1); 169 | } -------------------------------------------------------------------------------- /bdmfs_fatfs/src/ffsystem.c: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------*/ 2 | /* Sample Code of OS Dependent Functions for FatFs */ 3 | /* (C)ChaN, 2018 */ 4 | /*------------------------------------------------------------------------*/ 5 | 6 | 7 | #include "ff.h" 8 | #include 9 | 10 | 11 | #if FF_USE_LFN == 3 /* Dynamic memory allocation */ 12 | 13 | /*------------------------------------------------------------------------*/ 14 | /* Allocate a memory block */ 15 | /*------------------------------------------------------------------------*/ 16 | 17 | void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */ 18 | UINT msize /* Number of bytes to allocate */ 19 | ) 20 | { 21 | return malloc(msize); /* Allocate a new memory block with POSIX API */ 22 | } 23 | 24 | 25 | /*------------------------------------------------------------------------*/ 26 | /* Free a memory block */ 27 | /*------------------------------------------------------------------------*/ 28 | 29 | void ff_memfree ( 30 | void* mblock /* Pointer to the memory block to free (nothing to do if null) */ 31 | ) 32 | { 33 | free(mblock); /* Free the memory block with POSIX API */ 34 | } 35 | 36 | #endif 37 | 38 | 39 | 40 | #if FF_FS_REENTRANT /* Mutal exclusion */ 41 | 42 | /*------------------------------------------------------------------------*/ 43 | /* Create a Synchronization Object */ 44 | /*------------------------------------------------------------------------*/ 45 | /* This function is called in f_mount() function to create a new 46 | / synchronization object for the volume, such as semaphore and mutex. 47 | / When a 0 is returned, the f_mount() function fails with FR_INT_ERR. 48 | */ 49 | 50 | //const osMutexDef_t Mutex[FF_VOLUMES]; /* Table of CMSIS-RTOS mutex */ 51 | 52 | 53 | int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */ 54 | BYTE vol, /* Corresponding volume (logical drive number) */ 55 | FF_SYNC_t* sobj /* Pointer to return the created sync object */ 56 | ) 57 | { 58 | #if 0 59 | /* Win32 */ 60 | *sobj = CreateMutex(NULL, FALSE, NULL); 61 | return (int)(*sobj != INVALID_HANDLE_VALUE); 62 | 63 | /* uITRON */ 64 | // T_CSEM csem = {TA_TPRI,1,1}; 65 | // *sobj = acre_sem(&csem); 66 | // return (int)(*sobj > 0); 67 | 68 | /* uC/OS-II */ 69 | // OS_ERR err; 70 | // *sobj = OSMutexCreate(0, &err); 71 | // return (int)(err == OS_NO_ERR); 72 | 73 | /* FreeRTOS */ 74 | // *sobj = xSemaphoreCreateMutex(); 75 | // return (int)(*sobj != NULL); 76 | 77 | /* CMSIS-RTOS */ 78 | // *sobj = osMutexCreate(&Mutex[vol]); 79 | // return (int)(*sobj != NULL); 80 | #endif 81 | /* IOP kernel */ 82 | iop_sema_t sp; 83 | 84 | sp.initial = 1; 85 | sp.max = 1; 86 | sp.option = 0; 87 | sp.attr = 0; 88 | if ((*sobj = CreateSema(&sp)) < 0) { 89 | return 0; 90 | } 91 | 92 | return 1; 93 | } 94 | 95 | 96 | /*------------------------------------------------------------------------*/ 97 | /* Delete a Synchronization Object */ 98 | /*------------------------------------------------------------------------*/ 99 | /* This function is called in f_mount() function to delete a synchronization 100 | / object that created with ff_cre_syncobj() function. When a 0 is returned, 101 | / the f_mount() function fails with FR_INT_ERR. 102 | */ 103 | 104 | int ff_del_syncobj ( /* 1:Function succeeded, 0:Could not delete due to an error */ 105 | FF_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */ 106 | ) 107 | { 108 | #if 0 109 | /* Win32 */ 110 | return (int)CloseHandle(sobj); 111 | 112 | /* uITRON */ 113 | // return (int)(del_sem(sobj) == E_OK); 114 | 115 | /* uC/OS-II */ 116 | // OS_ERR err; 117 | // OSMutexDel(sobj, OS_DEL_ALWAYS, &err); 118 | // return (int)(err == OS_NO_ERR); 119 | 120 | /* FreeRTOS */ 121 | // vSemaphoreDelete(sobj); 122 | // return 1; 123 | 124 | /* CMSIS-RTOS */ 125 | // return (int)(osMutexDelete(sobj) == osOK); 126 | #endif 127 | /* IOP kernel */ 128 | if (sobj >= 0) { 129 | DeleteSema(sobj); 130 | return 1; 131 | } 132 | return 0; 133 | } 134 | 135 | 136 | /*------------------------------------------------------------------------*/ 137 | /* Request Grant to Access the Volume */ 138 | /*------------------------------------------------------------------------*/ 139 | /* This function is called on entering file functions to lock the volume. 140 | / When a 0 is returned, the file function fails with FR_TIMEOUT. 141 | */ 142 | 143 | int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */ 144 | FF_SYNC_t sobj /* Sync object to wait */ 145 | ) 146 | { 147 | #if 0 148 | /* Win32 */ 149 | return (int)(WaitForSingleObject(sobj, FF_FS_TIMEOUT) == WAIT_OBJECT_0); 150 | 151 | /* uITRON */ 152 | // return (int)(wai_sem(sobj) == E_OK); 153 | 154 | /* uC/OS-II */ 155 | // OS_ERR err; 156 | // OSMutexPend(sobj, FF_FS_TIMEOUT, &err)); 157 | // return (int)(err == OS_NO_ERR); 158 | 159 | /* FreeRTOS */ 160 | // return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE); 161 | 162 | /* CMSIS-RTOS */ 163 | // return (int)(osMutexWait(sobj, FF_FS_TIMEOUT) == osOK); 164 | #endif 165 | WaitSema(sobj); 166 | return 1; 167 | } 168 | 169 | 170 | /*------------------------------------------------------------------------*/ 171 | /* Release Grant to Access the Volume */ 172 | /*------------------------------------------------------------------------*/ 173 | /* This function is called on leaving file functions to unlock the volume. 174 | */ 175 | 176 | void ff_rel_grant ( 177 | FF_SYNC_t sobj /* Sync object to be signaled */ 178 | ) 179 | { 180 | #if 0 181 | /* Win32 */ 182 | ReleaseMutex(sobj); 183 | 184 | /* uITRON */ 185 | // sig_sem(sobj); 186 | 187 | /* uC/OS-II */ 188 | // OSMutexPost(sobj); 189 | 190 | /* FreeRTOS */ 191 | // xSemaphoreGive(sobj); 192 | 193 | /* CMSIS-RTOS */ 194 | // osMutexRelease(sobj); 195 | #endif 196 | SignalSema(sobj); 197 | } 198 | 199 | #endif 200 | 201 | -------------------------------------------------------------------------------- /bdmfs_fatfs/src/imports.lst: -------------------------------------------------------------------------------- 1 | bdm_IMPORTS_start 2 | I_bdm_connect_fs 3 | I_bdm_disconnect_fs 4 | bdm_IMPORTS_end 5 | 6 | cdvdman_IMPORTS_start 7 | I_sceCdReadClock 8 | cdvdman_IMPORTS_end 9 | 10 | intrman_IMPORTS_start 11 | I_CpuSuspendIntr 12 | I_CpuResumeIntr 13 | intrman_IMPORTS_end 14 | 15 | ioman_IMPORTS_start 16 | I_AddDrv 17 | I_DelDrv 18 | ioman_IMPORTS_end 19 | 20 | stdio_IMPORTS_start 21 | I_printf 22 | stdio_IMPORTS_end 23 | 24 | sysclib_IMPORTS_start 25 | I_toupper 26 | I_memset 27 | I_memcmp 28 | I_memcpy 29 | I_strlen 30 | I_strcmp 31 | I_strcpy 32 | I_strncpy 33 | I_strtol 34 | I_strchr 35 | I_strrchr 36 | I_sprintf 37 | sysclib_IMPORTS_end 38 | 39 | sysmem_IMPORTS_start 40 | I_AllocSysMemory 41 | I_FreeSysMemory 42 | sysmem_IMPORTS_end 43 | 44 | thsemap_IMPORTS_start 45 | I_CreateSema 46 | I_SignalSema 47 | I_WaitSema 48 | I_DeleteSema 49 | thsemap_IMPORTS_end 50 | -------------------------------------------------------------------------------- /bdmfs_fatfs/src/include/diskio.h: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------/ 2 | / Low level disk interface modlue include file (C)ChaN, 2019 / 3 | /-----------------------------------------------------------------------*/ 4 | 5 | #ifndef _DISKIO_DEFINED 6 | #define _DISKIO_DEFINED 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | /* Status of Disk Functions */ 13 | typedef BYTE DSTATUS; 14 | 15 | /* Results of Disk Functions */ 16 | typedef enum { 17 | RES_OK = 0, /* 0: Successful */ 18 | RES_ERROR, /* 1: R/W Error */ 19 | RES_WRPRT, /* 2: Write Protected */ 20 | RES_NOTRDY, /* 3: Not Ready */ 21 | RES_PARERR /* 4: Invalid Parameter */ 22 | } DRESULT; 23 | 24 | 25 | /*---------------------------------------*/ 26 | /* Prototypes for disk control functions */ 27 | 28 | 29 | DSTATUS disk_initialize (BYTE pdrv); 30 | DSTATUS disk_status (BYTE pdrv); 31 | DRESULT disk_read (BYTE pdrv, BYTE* buff, LBA_t sector, UINT count); 32 | DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count); 33 | DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); 34 | 35 | 36 | /* Disk Status Bits (DSTATUS) */ 37 | 38 | #define STA_NOINIT 0x01 /* Drive not initialized */ 39 | #define STA_NODISK 0x02 /* No medium in the drive */ 40 | #define STA_PROTECT 0x04 /* Write protected */ 41 | 42 | 43 | /* Command code for disk_ioctrl fucntion */ 44 | 45 | /* Generic command (Used by FatFs) */ 46 | #define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */ 47 | #define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */ 48 | #define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */ 49 | #define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */ 50 | #define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */ 51 | 52 | /* Generic command (Not used by FatFs) */ 53 | #define CTRL_POWER 5 /* Get/Set power status */ 54 | #define CTRL_LOCK 6 /* Lock/Unlock media removal */ 55 | #define CTRL_EJECT 7 /* Eject media */ 56 | #define CTRL_FORMAT 8 /* Create physical format on the media */ 57 | 58 | /* MMC/SDC specific ioctl command */ 59 | #define MMC_GET_TYPE 10 /* Get card type */ 60 | #define MMC_GET_CSD 11 /* Get CSD */ 61 | #define MMC_GET_CID 12 /* Get CID */ 62 | #define MMC_GET_OCR 13 /* Get OCR */ 63 | #define MMC_GET_SDSTAT 14 /* Get SD status */ 64 | #define ISDIO_READ 55 /* Read data form SD iSDIO register */ 65 | #define ISDIO_WRITE 56 /* Write data to SD iSDIO register */ 66 | #define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */ 67 | 68 | /* ATA/CF specific ioctl command */ 69 | #define ATA_GET_REV 20 /* Get F/W revision */ 70 | #define ATA_GET_MODEL 21 /* Get model name */ 71 | #define ATA_GET_SN 22 /* Get serial number */ 72 | 73 | #ifdef __cplusplus 74 | } 75 | #endif 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /bdmfs_fatfs/src/include/fs_driver.h: -------------------------------------------------------------------------------- 1 | #ifndef FS_DRIVER_H 2 | #define FS_DRIVER_H 3 | 4 | #include 5 | #include "ff.h" 6 | 7 | typedef struct fatfs_fs_driver_mount_info_ 8 | { 9 | FATFS fatfs; 10 | struct block_device *mounted_bd; 11 | int mount_status; 12 | } fatfs_fs_driver_mount_info; 13 | 14 | extern fatfs_fs_driver_mount_info fs_driver_mount_info[FF_VOLUMES]; 15 | 16 | extern int InitFS(void); 17 | extern int connect_bd(struct block_device *bd); 18 | extern void disconnect_bd(struct block_device *bd); 19 | extern struct block_device *fatfs_fs_driver_get_mounted_bd_from_index(int mount_info_index); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /bdmfs_fatfs/src/include/module_debug.h: -------------------------------------------------------------------------------- 1 | #ifndef _MODULE_DEBUG_H 2 | #define _MODULE_DEBUG_H 3 | 4 | 5 | #define M_PRINTF(format, args...) printf("FatFs: " format, ##args) 6 | 7 | #ifdef DEBUG 8 | #define M_DEBUG M_PRINTF 9 | #else 10 | #define M_DEBUG(format, args...) 11 | #endif 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /bdmfs_fatfs/src/irx_imports.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Copyright 2001-2009, ps2dev - http://www.ps2dev.org 7 | # Licenced under Academic Free License version 2.0 8 | # Review ps2sdk README & LICENSE files for further details. 9 | # 10 | # Defines all IRX imports. 11 | */ 12 | 13 | #ifndef IOP_IRX_IMPORTS_H 14 | #define IOP_IRX_IMPORTS_H 15 | 16 | #include 17 | 18 | /* Please keep these in alphabetical order! */ 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #endif /* IOP_IRX_IMPORTS_H */ 29 | -------------------------------------------------------------------------------- /bdmfs_fatfs/src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "ff.h" 10 | #include "fs_driver.h" 11 | 12 | //#define DEBUG //comment out this line when not debugging 13 | #include "module_debug.h" 14 | 15 | #define MAJOR_VER 1 16 | #define MINOR_VER 4 17 | 18 | IRX_ID("bdmff", MAJOR_VER, MINOR_VER); 19 | 20 | static struct file_system g_fs = { 21 | .priv = NULL, 22 | .name = "fatfs", 23 | .connect_bd = connect_bd, 24 | .disconnect_bd = disconnect_bd, 25 | }; 26 | 27 | int _start(int argc, char *argv[]) 28 | { 29 | (void)argc; 30 | (void)argv; 31 | 32 | printf("BDM FatFs driver (FAT/exFAT) v%d.%d\n", MAJOR_VER, MINOR_VER); 33 | 34 | // initialize the file system driver 35 | if (InitFS() != 0) { 36 | M_DEBUG("Error initializing FatFs driver!\n"); 37 | return MODULE_NO_RESIDENT_END; 38 | } 39 | 40 | // Connect to block device manager 41 | bdm_connect_fs(&g_fs); 42 | 43 | // return resident 44 | return MODULE_RESIDENT_END; 45 | } 46 | 47 | void *malloc(int size) 48 | { 49 | void *result; 50 | int OldState; 51 | 52 | CpuSuspendIntr(&OldState); 53 | result = AllocSysMemory(ALLOC_FIRST, size, NULL); 54 | CpuResumeIntr(OldState); 55 | 56 | return result; 57 | } 58 | 59 | void free(void *ptr) 60 | { 61 | int OldState; 62 | 63 | CpuSuspendIntr(&OldState); 64 | FreeSysMemory(ptr); 65 | CpuResumeIntr(OldState); 66 | } 67 | -------------------------------------------------------------------------------- /global.make: -------------------------------------------------------------------------------- 1 | 2 | all: $(IOP_BIN) $(IOP_LIB) 3 | clean: 4 | rm -rf $(IOP_OBJS_DIR) $(IOP_BIN) $(IOP_LIB) 5 | 6 | rebuild: clean all 7 | .PHONY: all clean rebuild 8 | 9 | IOP_OBJS_DIR := obj/ 10 | IOP_SRC_DIR := src/ 11 | IOP_INC_DIR := $(IOP_SRC_DIR)include/ 12 | IOP_INCS += -I$(IOP_SRC_DIR) 13 | 14 | include $(PS2SDK)/Defs.make 15 | include $(PS2SDK)/samples/Makefile.pref 16 | include $(PS2SDK)/samples/Makefile.iopglobal -------------------------------------------------------------------------------- /libbdm/Makefile: -------------------------------------------------------------------------------- 1 | # _____ ___ ____ ___ ____ 2 | # ____| | ____| | | |____| 3 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 4 | #----------------------------------------------------------------------- 5 | # Copyright 2001-2004, ps2dev - http://www.ps2dev.org 6 | # Licenced under Academic Free License version 2.0 7 | # Review ps2sdk README & LICENSE files for further details. 8 | 9 | # IOP_CFLAGS += -DDEBUG -Wno-strict-aliasing 10 | 11 | IOP_LIB = lib/libbdm.a 12 | 13 | IOP_INCS += -I../bdm/include 14 | IOP_OBJS = bd_defrag.o bd_cache.o 15 | 16 | 17 | include ../global.make 18 | -------------------------------------------------------------------------------- /libbdm/include/bd_cache.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Licenced under Academic Free License version 2.0 7 | # Review ps2sdk README & LICENSE files for further details. 8 | */ 9 | 10 | /** 11 | * @file 12 | * Simple cache for Block Devices 13 | */ 14 | 15 | #ifndef __BDM_CACHE_H__ 16 | #define __BDM_CACHE_H__ 17 | 18 | 19 | #include 20 | #include 21 | 22 | 23 | /* Create a new cached block device */ 24 | struct block_device *bd_cache_create(struct block_device *bd); 25 | 26 | /* Destroy a cached block device */ 27 | void bd_cache_destroy(struct block_device *cbd); 28 | 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /libbdm/include/bd_defrag.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Licenced under Academic Free License version 2.0 7 | # Review ps2sdk README & LICENSE files for further details. 8 | */ 9 | 10 | /** 11 | * @file 12 | * Fragmented Block Device to Block Device 13 | */ 14 | 15 | #ifndef __BDM_DEFRAG_H__ 16 | #define __BDM_DEFRAG_H__ 17 | 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | 24 | int bd_defrag_read(struct block_device* bd, u32 fragcount, struct bd_fragment* fraglist, u64 sector, void* buffer, u16 count); 25 | int bd_defrag_write(struct block_device* bd, u32 fragcount, struct bd_fragment* fraglist, u64 sector, const void* buffer, u16 count); 26 | 27 | // For backwards compatibility: 28 | #define bd_defrag bd_defrag_read 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /libbdm/src/bd_cache.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | //#define DEBUG //comment out this line when not debugging 6 | #include "module_debug.h" 7 | 8 | #define SECTORS_PER_BLOCK 8 // 8 * 512b = 4KiB 9 | #define BLOCK_COUNT 32 // 32 * 4KiB = 128KiB 10 | #define BLOCK_WEIGHT_FACTOR 256 // Fixed point math (24.8) 11 | 12 | struct bd_cache 13 | { 14 | struct block_device *bd; 15 | int weight[BLOCK_COUNT]; 16 | u64 sector[BLOCK_COUNT]; 17 | u8 cache[BLOCK_COUNT][SECTORS_PER_BLOCK*512]; 18 | #ifdef DEBUG 19 | u32 sectors_read; 20 | u32 sectors_cache; 21 | u32 sectors_dev; 22 | #endif 23 | }; 24 | 25 | /* cache overlaps with requested area ? */ 26 | static int _overlaps(u64 csector, u64 sector, u16 count) 27 | { 28 | if ((sector < (csector + SECTORS_PER_BLOCK)) && ((sector + count) > csector)) 29 | return 1; 30 | else 31 | return 0; 32 | } 33 | 34 | /* cache contains requested area ? */ 35 | static int _contains(u64 csector, u64 sector, u16 count) 36 | { 37 | if ((sector >= csector) && ((sector + count) <= (csector + SECTORS_PER_BLOCK))) 38 | return 1; 39 | else 40 | return 0; 41 | } 42 | 43 | static void _invalidate(struct bd_cache *c, u64 sector, u16 count) 44 | { 45 | int blkidx; 46 | 47 | for (blkidx = 0; blkidx < BLOCK_COUNT; blkidx++) { 48 | if (_overlaps(c->sector[blkidx], sector, count)) { 49 | // Invalidate cache entry 50 | c->sector[blkidx] = 0xffffffffffffffff; 51 | } 52 | } 53 | } 54 | 55 | static int _read(struct block_device *bd, u64 sector, void *buffer, u16 count) 56 | { 57 | struct bd_cache *c = bd->priv; 58 | 59 | //M_DEBUG("%s(%d, %d)\n", __FUNCTION__, sector, count); 60 | 61 | if (count >= SECTORS_PER_BLOCK) { 62 | // Do a direct read 63 | return c->bd->read(c->bd, sector, buffer, count); 64 | } 65 | 66 | #ifdef DEBUG 67 | c->sectors_read += count; 68 | #endif 69 | 70 | // Do a cached read 71 | int blkidx; 72 | for (blkidx = 0; blkidx < BLOCK_COUNT; blkidx++) { 73 | if (_contains(c->sector[blkidx], sector, count)) { 74 | #ifdef DEBUG 75 | c->sectors_cache += count; 76 | //M_DEBUG("- CACHE HIT[%d] [block %d] [devread %ds, hit-ratio %d%%]\n", sector, blkidx, c->sectors_dev, (c->sectors_cache * 100) / c->sectors_read); 77 | #endif 78 | // Minimum weight 79 | if (c->weight[blkidx] < 0) 80 | c->weight[blkidx] = 0; 81 | 82 | c->weight[blkidx] += count * BLOCK_WEIGHT_FACTOR; 83 | 84 | // Read from cache 85 | u64 offset = (sector - c->sector[blkidx]) * 512; 86 | memcpy(buffer, &c->cache[blkidx][offset], count * 512); 87 | return count; 88 | } 89 | } 90 | 91 | // Find block with the lowest weight 92 | int blkidx_best_weight = 0x7fffffff; 93 | int blkidx_best = 0; 94 | M_DEBUG("- list: "); 95 | for (blkidx = 0; blkidx < BLOCK_COUNT; blkidx++) { 96 | #ifdef DEBUG 97 | printf("%*d ", 3, c->weight[blkidx] / BLOCK_WEIGHT_FACTOR); 98 | #endif 99 | 100 | // Dynamic aging 101 | c->weight[blkidx] -= (SECTORS_PER_BLOCK * BLOCK_WEIGHT_FACTOR / BLOCK_COUNT) + (c->weight[blkidx] / 32); 102 | 103 | if (c->weight[blkidx] < blkidx_best_weight) { 104 | // Better block found 105 | blkidx_best_weight = c->weight[blkidx]; 106 | blkidx_best = blkidx; 107 | } 108 | } 109 | #ifdef DEBUG 110 | printf(" devread: %*d, evict %*d [%*d], add [%*d]\n", 4, c->sectors_dev, 2, blkidx_best, 8, c->sector[blkidx_best], 8, sector); 111 | c->sectors_dev += SECTORS_PER_BLOCK; 112 | //M_DEBUG("- CACHE READ[%d] -> [block %d] [devread %ds, hit-ratio %d%%]\n", sector, blkidx_best, c->sectors_dev, (c->sectors_cache * 100) / c->sectors_read); 113 | #endif 114 | 115 | // Fill the block 116 | c->bd->read(c->bd, sector, c->cache[blkidx_best], SECTORS_PER_BLOCK); 117 | c->sector[blkidx_best] = sector; 118 | 119 | // Read from cache 120 | u64 offset = (sector - c->sector[blkidx_best]) * 512; 121 | c->weight[blkidx_best] = count * BLOCK_WEIGHT_FACTOR; 122 | memcpy(buffer, &c->cache[blkidx_best][offset], count * 512); 123 | return count; 124 | } 125 | 126 | static int _write(struct block_device *bd, u64 sector, const void *buffer, u16 count) 127 | { 128 | struct bd_cache *c = bd->priv; 129 | 130 | M_DEBUG("%s(%d, %d)\n", __FUNCTION__, sector, count); 131 | 132 | _invalidate(c, sector, count); 133 | 134 | return c->bd->write(c->bd, sector, buffer, count); 135 | } 136 | 137 | static void _flush(struct block_device *bd) 138 | { 139 | struct bd_cache *c = bd->priv; 140 | 141 | M_DEBUG("%s\n", __FUNCTION__); 142 | 143 | return c->bd->flush(c->bd); 144 | } 145 | 146 | static int _stop(struct block_device *bd) 147 | { 148 | struct bd_cache *c = bd->priv; 149 | 150 | M_DEBUG("%s\n", __FUNCTION__); 151 | 152 | return c->bd->stop(c->bd); 153 | } 154 | 155 | struct block_device *bd_cache_create(struct block_device *bd) 156 | { 157 | int blkidx; 158 | 159 | // Create new block device 160 | struct block_device *cbd = AllocSysMemory(ALLOC_FIRST, sizeof(struct block_device), NULL); 161 | // Create new private data 162 | struct bd_cache *c = AllocSysMemory(ALLOC_FIRST, sizeof(struct bd_cache), NULL); 163 | 164 | M_DEBUG("%s\n", __FUNCTION__); 165 | 166 | c->bd = bd; 167 | for (blkidx = 0; blkidx < BLOCK_COUNT; blkidx++) { 168 | c->weight[blkidx] = 0; 169 | c->sector[blkidx] = 0xffffffffffffffff; 170 | } 171 | #ifdef DEBUG 172 | c->sectors_read = 0; 173 | c->sectors_cache = 0; 174 | c->sectors_dev = 0; 175 | #endif 176 | 177 | // copy all parameters becouse we are the same blocks device 178 | // only difference is we are cached. 179 | cbd->priv = c; 180 | cbd->name = bd->name; 181 | cbd->devNr = bd->devNr; 182 | cbd->parNr = bd->parNr; 183 | cbd->parId = bd->parId; 184 | cbd->sectorSize = bd->sectorSize; 185 | cbd->sectorOffset = bd->sectorOffset; 186 | cbd->sectorCount = bd->sectorCount; 187 | 188 | cbd->read = _read; 189 | cbd->write = _write; 190 | cbd->flush = _flush; 191 | cbd->stop = _stop; 192 | 193 | return cbd; 194 | } 195 | 196 | void bd_cache_destroy(struct block_device *cbd) 197 | { 198 | M_DEBUG("%s\n", __FUNCTION__); 199 | 200 | FreeSysMemory(cbd->priv); 201 | FreeSysMemory(cbd); 202 | } 203 | -------------------------------------------------------------------------------- /libbdm/src/bd_defrag.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //#define DEBUG //comment out this line when not debugging 4 | #include "module_debug.h" 5 | 6 | 7 | int bd_defrag_read(struct block_device* bd, u32 fragcount, struct bd_fragment* fraglist, u64 sector, void* buffer, u16 count) 8 | { 9 | u64 sector_start = sector; 10 | u16 count_left = count; 11 | 12 | while (count_left > 0) { 13 | u16 count_read; 14 | u64 offset = 0; // offset of fragment in bd/file 15 | struct bd_fragment *f = NULL; 16 | int i; 17 | 18 | // Locate fragment containing start sector 19 | for (i=0; (u32)icount) > sector_start) { 22 | // Fragment found 23 | break; 24 | } 25 | offset += f->count; 26 | } 27 | 28 | if ((u32)i == fragcount) { 29 | M_PRINTF("%s: ERROR: fragment not found!\n", __FUNCTION__); 30 | return -1; 31 | } 32 | 33 | // Clip to fragment size 34 | count_read = count_left; 35 | if ((sector_start + count_read) > (offset + f->count)) { 36 | count_read = (offset + f->count) - sector_start; 37 | M_DEBUG("%s: clipping sectors %d -> %d\n", __FUNCTION__, count_left, count_read); 38 | } 39 | 40 | // Do the read 41 | if (bd->read(bd, f->sector + (sector_start - offset), buffer, count_read) != count_read) { 42 | M_PRINTF("%s: ERROR: read failed!\n", __FUNCTION__); 43 | return -1; 44 | } 45 | 46 | // Advance to next fragment 47 | sector_start += count_read; 48 | count_left -= count_read; 49 | buffer = (u8*)buffer + (count_read * bd->sectorSize); 50 | } 51 | 52 | return count; 53 | } 54 | 55 | int bd_defrag_write(struct block_device* bd, u32 fragcount, struct bd_fragment* fraglist, u64 sector, const void* buffer, u16 count) 56 | { 57 | u64 sector_start = sector; 58 | u16 count_left = count; 59 | 60 | while (count_left > 0) { 61 | u16 count_write; 62 | u64 offset = 0; // offset of fragment in bd/file 63 | struct bd_fragment *f = NULL; 64 | int i; 65 | 66 | // Locate fragment containing start sector 67 | for (i=0; (u32)icount) > sector_start) { 70 | // Fragment found 71 | break; 72 | } 73 | offset += f->count; 74 | } 75 | 76 | if ((u32)i == fragcount) { 77 | M_PRINTF("%s: ERROR: fragment not found!\n", __FUNCTION__); 78 | return -1; 79 | } 80 | 81 | // Clip to fragment size 82 | count_write = count_left; 83 | if ((sector_start + count_write) > (offset + f->count)) { 84 | count_write = (offset + f->count) - sector_start; 85 | M_DEBUG("%s: clipping sectors %d -> %d\n", __FUNCTION__, count_left, count_write); 86 | } 87 | 88 | // Do the write 89 | if (bd->write(bd, f->sector + (sector_start - offset), buffer, count_write) != count_write) { 90 | M_PRINTF("%s: ERROR: write failed!\n", __FUNCTION__); 91 | return -1; 92 | } 93 | 94 | // Advance to next fragment 95 | sector_start += count_write; 96 | count_left -= count_write; 97 | buffer = (u8*)buffer + (count_write * bd->sectorSize); 98 | } 99 | 100 | return count; 101 | } 102 | -------------------------------------------------------------------------------- /libbdm/src/include/module_debug.h: -------------------------------------------------------------------------------- 1 | #ifndef _MODULE_DEBUG_H 2 | #define _MODULE_DEBUG_H 3 | 4 | //#define MINI_DRIVER 5 | 6 | #ifndef MINI_DRIVER 7 | #include 8 | #define M_PRINTF(format, args...) printf("BDM: " format, ##args) 9 | #else 10 | #define M_PRINTF(format, args...) do { } while(0) 11 | #endif 12 | 13 | #ifdef DEBUG 14 | #define M_DEBUG M_PRINTF 15 | #else 16 | #define M_DEBUG(format, args...) do { } while(0) 17 | #endif 18 | 19 | #define U64_2XU32(val) ((u32*)val)[1], ((u32*)val)[0] 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /usbd/Makefile: -------------------------------------------------------------------------------- 1 | # _____ ___ ____ ___ ____ 2 | # ____| | ____| | | |____| 3 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 4 | #----------------------------------------------------------------------- 5 | # Copyright 2001-2004, ps2dev - http://www.ps2dev.org 6 | # Licenced under Academic Free License version 2.0 7 | # Review ps2sdk README & LICENSE files for further details. 8 | 9 | # IOP_CFLAGS += -DDEBUG 10 | IOP_BIN = usbd.irx 11 | 12 | IOP_OBJS = hcd.o hub.o interface.o mem.o usbd.o usbio.o driver.o imports.o exports.o 13 | IOP_PREFER_GPOPT = 16384 14 | 15 | include ../global.make 16 | -------------------------------------------------------------------------------- /usbd/include/usbd_macro.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Copyright 2001-2004, ps2dev - http://www.ps2dev.org 7 | # Licenced under Academic Free License version 2.0 8 | # Review ps2sdk README & LICENSE files for further details. 9 | */ 10 | 11 | /** 12 | * @file 13 | * USB Driver function prototypes and constants. 14 | */ 15 | 16 | #ifndef __USBD_MACRO_H__ 17 | #define __USBD_MACRO_H__ 18 | 19 | #include 20 | 21 | static int sceUsbdControlTransfer(int epID, int reqtyp, int req, int val, int index, int leng, void *dataptr, void *doneCB, void *arg) 22 | { 23 | UsbDeviceRequest devreq; 24 | devreq.requesttype = reqtyp; 25 | devreq.request = req; 26 | devreq.value = val; 27 | devreq.index = index; 28 | devreq.length = leng; 29 | 30 | return sceUsbdTransferPipe(epID, dataptr, devreq.length, &devreq, doneCB, arg); 31 | } 32 | 33 | #define sceUsbdIsochronousTransfer(epID, dataptr, len, delta, doneCB, arg) \ 34 | sceUsbdTransferPipe((epID), (dataptr), (len), (void *)(delta), (doneCB), (arg)) 35 | 36 | #define sceUsbdBulkTransfer(epID, dataptr, len, doneCB, arg) \ 37 | sceUsbdTransferPipe((epID), (dataptr), (len), NULL, (doneCB), (arg)) 38 | 39 | #define sceUsbdInterruptTransfer(epID, dataptr, len, doneCB, arg) \ 40 | sceUsbdTransferPipe((epID), (dataptr), (len), NULL, (doneCB), (arg)) 41 | 42 | /* standard control transfers */ 43 | 44 | #define sceUsbdClearDeviceFeature(epID, feature, doneCB, arg) \ 45 | sceUsbdControlTransfer((epID), USB_DIR_OUT | USB_RECIP_DEVICE, USB_REQ_CLEAR_FEATURE, \ 46 | (feature), 0, 0, NULL, (doneCB), (arg)) 47 | 48 | #define sceUsbdSetDeviceFeature(epID, feature, doneCB, arg) \ 49 | sceUsbdControlTransfer((epID), USB_DIR_OUT | USB_RECIP_DEVICE, USB_REQ_SET_FEATURE, \ 50 | (feature), 0, 0, NULL, (doneCB), (arg)) 51 | 52 | #define sceUsbdGetConfiguration(epID, dataptr, doneCB, arg) \ 53 | sceUsbdControlTransfer((epID), USB_DIR_IN | USB_RECIP_DEVICE, USB_REQ_GET_CONFIGURATION, \ 54 | 0, 0, 1, (dataptr), (doneCB), (arg)) 55 | 56 | #define sceUsbdSetConfiguration(epID, config, doneCB, arg) \ 57 | sceUsbdControlTransfer((epID), USB_DIR_OUT | USB_RECIP_DEVICE, USB_REQ_SET_CONFIGURATION, (config), 0, 0, NULL, (doneCB), (arg)) 58 | 59 | #define sceUsbdGetDescriptor(epID, type, index, language, dataptr, len, doneCB, arg) \ 60 | sceUsbdControlTransfer((epID), USB_DIR_IN | USB_RECIP_DEVICE, USB_REQ_GET_DESCRIPTOR, \ 61 | ((type) << 8) | (index), (language), (len), (dataptr), (doneCB), (arg)) 62 | 63 | #define sceUsbdSetDeviceDescriptor(epID, type, index, language, dataptr, len, doneCB, arg) \ 64 | sceUsbdControlTransfer((epID), USB_DIR_OUT | USB_RECIP_DEVICE, USB_REQ_SET_DESCRIPTOR, \ 65 | ((type) << 8) | (index), (language), (len), (dataptr), (doneCB), (arg)) 66 | 67 | #define sceUsbdGetDeviceStatus(epID, dataptr, doneCB, arg) \ 68 | sceUsbdControlTransfer((epID), USB_DIR_IN | USB_RECIP_DEVICE, USB_REQ_GET_STATUS, \ 69 | 0, 0, 2, (dataptr), (doneCB), (arg)) 70 | 71 | #define sceUsbdSetAddress(epID, address, doneCB, arg) \ 72 | sceUsbdControlTransfer((epID), USB_DIR_OUT | USB_RECIP_DEVICE, USB_REQ_SET_ADDRESS, \ 73 | (address), 0, 0, NULL, (doneCB), (arg)) 74 | 75 | #define sceUsbdClearInterfaceFeature(epID, feature, interface, doneCB, arg) \ 76 | sceUsbdControlTransfer((epID), USB_DIR_OUT | USB_RECIP_INTERFACE, USB_REQ_CLEAR_FEATURE, \ 77 | (feature), (interface), 0, NULL, (doneCB), (arg)) 78 | 79 | #define sceUsbdSetInterfaceFeature(epID, feature, interface, doneCB, arg) \ 80 | sceUsbdControlTransfer((epID), USB_DIR_OUT | USB_RECIP_INTERFACE, USB_REQ_SET_FEATURE, \ 81 | (feature), (interface), 0, NULL, (doneCB), (arg)) 82 | 83 | #define sceUsbdGetInterface(epID, interface, dataptr, doneCB, arg) \ 84 | sceUsbdControlTransfer((epID), USB_DIR_IN | USB_RECIP_INTERFACE, USB_REQ_GET_INTERFACE, \ 85 | 0, (interface), 1, (dataptr), (doneCB), (arg)) 86 | 87 | #define sceUsbdSetInterface(epID, interface, alt_setting, doneCB, arg) \ 88 | sceUsbdControlTransfer((epID), USB_DIR_OUT | USB_RECIP_INTERFACE, USB_REQ_SET_INTERFACE, \ 89 | (alt_setting), (interface), 0, NULL, (doneCB), (arg)) 90 | 91 | #define sceUsbdGetInterfaceDescriptor(epID, type, index, language, dataptr, len, doneCB, arg) \ 92 | sceUsbdControlTransfer((epID), USB_DIR_IN | USB_RECIP_INTERFACE, USB_REQ_GET_DESCRIPTOR, \ 93 | ((type) << 8) | (index), (language), (len), (dataptr), (doneCB), (arg)) 94 | 95 | #define sceUsbdSetInterfaceDescriptor(epID, type, index, language, dataptr, len, doneCB, arg) \ 96 | sceUsbdControlTransfer((epID), USB_DIR_OUT | USB_RECIP_INTERFACE, USB_REQ_SET_DESCRIPTOR, \ 97 | ((type) << 8) | (index), (language), (len), (dataptr), (doneCB), (arg)) 98 | 99 | #define sceUsbdGetInterfaceStatus(epID, interface, dataptr, doneCB, arg) \ 100 | sceUsbdControlTransfer((epID), USB_DIR_IN | USB_RECIP_INTERFACE, USB_REQ_GET_STATUS, \ 101 | 0, (interface), 2, (dataptr), (doneCB), (arg)) 102 | 103 | #define sceUsbdClearEndpointFeature(epID, feature, endpoint, doneCB, arg) \ 104 | sceUsbdControlTransfer((epID), USB_DIR_OUT | USB_RECIP_ENDPOINT, USB_REQ_CLEAR_FEATURE, \ 105 | (feature), (endpoint), 0, NULL, (doneCB), (arg)) 106 | 107 | #define sceUsbdSetEndpointFeature(epID, feature, endpoint, doneCB, arg) \ 108 | sceUsbdControlTransfer((epID), USB_DIR_OUT | USB_RECIP_ENDPOINT, USB_REQ_SET_FEATURE, \ 109 | (feature), (endpoint), 0, NULL, (doneCB), (arg)) 110 | 111 | #define sceUsbdGetEndpointStatus(epID, endpoint, dataptr, doneCB, arg) \ 112 | sceUsbdControlTransfer((epID), USB_DIR_IN | USB_RECIP_ENDPOINT, USB_REQ_GET_STATUS, \ 113 | 0, (endpoint), 2, (dataptr), (doneCB), (arg)) 114 | 115 | #define sceUsbdGetEndpointDescriptor(epID, type, index, language, dataptr, len, doneCB, arg) \ 116 | sceUsbdControlTransfer((epID), USB_DIR_IN | USB_RECIP_ENDPOINT, USB_REQ_GET_DESCRIPTOR, \ 117 | ((type) << 8) | (index), (language), (len), (dataptr), (doneCB), (arg)) 118 | 119 | #define sceUsbdSetEndpointDescriptor(epID, type, index, language, dataptr, len, doneCB, arg) \ 120 | sceUsbdControlTransfer((epID), USB_DIR_OUT | USB_RECIP_ENDPOINT, USB_REQ_SET_DESCRIPTOR, \ 121 | ((type) << 8) | (index), (language), (len), (dataptr), (doneCB), (arg)) 122 | 123 | #define sceUsbdSynchFrame(epID, endpoint, pfn, doneCB, arg) \ 124 | sceUsbdControlTransfer((epID), USB_DIR_IN | USB_RECIP_ENDPOINT, USB_REQ_SYNCH_FRAME, \ 125 | 0, (endpoint), 2, (pfn), (doneCB), (arg)) 126 | 127 | // For backwards compatibility: 128 | #define UsbControlTransfer sceUsbdControlTransfer 129 | #define UsbIsochronousTransfer sceUsbdIsochronousTransfer 130 | #define UsbBulkTransfer sceUsbdBulkTransfer 131 | #define UsbInterruptTransfer sceUsbdInterruptTransfer 132 | #define UsbClearDeviceFeature sceUsbdClearDeviceFeature 133 | #define UsbSetDeviceFeature sceUsbdSetDeviceFeature 134 | #define UsbGetDeviceConfiguration sceUsbdGetConfiguration 135 | #define UsbSetDeviceConfiguration sceUsbdSetConfiguration 136 | #define UsbGetDeviceDescriptor sceUsbdGetDescriptor 137 | #define UsbSetDeviceDescriptor sceUsbdSetDeviceDescriptor 138 | #define UsbGetDeviceStatus sceUsbdGetDeviceStatus 139 | #define UsbSetDeviceAddress sceUsbdSetAddress 140 | #define UsbClearInterfaceFeature sceUsbdClearInterfaceFeature 141 | #define UsbSetInterfaceFeature sceUsbdSetInterfaceFeature 142 | #define UsbGetInterface sceUsbdGetInterface 143 | #define UsbSetInterface sceUsbdSetInterface 144 | #define UsbGetInterfaceDescriptor sceUsbdGetInterfaceDescriptor 145 | #define UsbSetInterfaceDescriptor sceUsbdSetInterfaceDescriptor 146 | #define UsbGetInterfaceStatus sceUsbdGetInterfaceStatus 147 | #define UsbClearEndpointFeature sceUsbdClearEndpointFeature 148 | #define UsbSetEndpointFeature sceUsbdSetEndpointFeature 149 | #define UsbGetEndpointStatus sceUsbdGetEndpointStatus 150 | #define UsbGetEndpointDescriptor sceUsbdGetEndpointDescriptor 151 | #define UsbSetEndpointDescriptor sceUsbdSetEndpointDescriptor 152 | #define UsbSynchEndpointFrame sceUsbdSynchFrame 153 | 154 | #endif /* __USBD_MACRO_H__ */ 155 | -------------------------------------------------------------------------------- /usbd/src/driver.c: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Copyright 2001-2004, ps2dev - http://www.ps2dev.org 7 | # Licenced under Academic Free License version 2.0 8 | # Review ps2sdk README & LICENSE files for further details. 9 | */ 10 | 11 | /** 12 | * @file 13 | * USB Driver function prototypes and constants. 14 | */ 15 | 16 | #include "usbdpriv.h" 17 | #include "driver.h" 18 | #include "mem.h" 19 | #include "hub.h" 20 | 21 | #include "defs.h" 22 | #include "stdio.h" 23 | #include "sysclib.h" 24 | #include "thbase.h" 25 | #include "thevent.h" 26 | #include "intrman.h" 27 | 28 | sceUsbdLddOps *drvListStart = NULL, *drvListEnd = NULL; 29 | sceUsbdLddOps *drvAutoLoader = NULL; 30 | IoRequest *cbListStart = NULL, *cbListEnd = NULL; 31 | 32 | int callbackEvent; 33 | int callbackTid = -1; 34 | 35 | int callUsbDriverFunc(int (*func)(int devId), int devId, void *gp) 36 | { 37 | int res; 38 | 39 | if (func) { 40 | usbdUnlock(); 41 | #if USE_GP_REGISTER 42 | ChangeGP(gp); 43 | #else 44 | (void)gp; 45 | #endif 46 | res = func(devId); 47 | #if USE_GP_REGISTER 48 | SetGP(&_gp); 49 | #endif 50 | usbdLock(); 51 | return res; 52 | } else 53 | return 0; 54 | } 55 | 56 | void probeDeviceTree(Device *tree, sceUsbdLddOps *drv) 57 | { 58 | Device *curDevice; 59 | for (curDevice = tree->childListStart; curDevice != NULL; curDevice = curDevice->next) 60 | if (curDevice->deviceStatus == DEVICE_READY) { 61 | if (curDevice->devDriver == NULL) { 62 | if (callUsbDriverFunc(drv->probe, curDevice->id, drv->gp) != 0) { 63 | curDevice->devDriver = drv; 64 | callUsbDriverFunc(drv->connect, curDevice->id, drv->gp); 65 | } 66 | } else if (curDevice->childListStart) 67 | probeDeviceTree(curDevice, drv); 68 | } 69 | } 70 | 71 | int doRegisterDriver(sceUsbdLddOps *drv, void *drvGpSeg) 72 | { 73 | if (drv->next || drv->prev) 74 | return USB_RC_BUSY; 75 | if (drvListStart == drv) 76 | return USB_RC_BUSY; 77 | 78 | if (!drv->name) 79 | return USB_RC_BADDRIVER; 80 | if (drv->reserved1 || drv->reserved2) 81 | return USB_RC_BADDRIVER; 82 | 83 | drv->gp = drvGpSeg; 84 | 85 | drv->prev = drvListEnd; 86 | if (drvListEnd) 87 | drvListEnd->next = drv; 88 | else 89 | drvListStart = drv; 90 | drvListEnd = drv; 91 | 92 | if (drv->probe) 93 | probeDeviceTree(memPool.deviceTreeRoot, drv); 94 | 95 | return 0; 96 | } 97 | 98 | int doRegisterAutoLoader(sceUsbdLddOps *drv, void *drvGpSeg) 99 | { 100 | if (drv->next || drv->prev) 101 | return USB_RC_BADDRIVER; 102 | if (!drv->name) 103 | return USB_RC_BADDRIVER; 104 | if (drv->reserved1 || drv->reserved2) 105 | return USB_RC_BADDRIVER; 106 | 107 | if (drvAutoLoader != NULL) 108 | return USB_RC_BUSY; 109 | 110 | drv->gp = drvGpSeg; 111 | 112 | drvAutoLoader = drv; 113 | 114 | if (drv->probe) 115 | probeDeviceTree(memPool.deviceTreeRoot, drv); 116 | 117 | return 0; 118 | } 119 | 120 | void disconnectDriver(Device *tree, sceUsbdLddOps *drv) 121 | { 122 | Endpoint *ep, *nextEp; 123 | if (tree->devDriver == drv) { 124 | if (tree->endpointListStart) { 125 | ep = tree->endpointListStart->next; 126 | 127 | while (ep) { 128 | nextEp = ep->next; 129 | removeEndpointFromDevice(tree, ep); 130 | ep = nextEp; 131 | } 132 | } 133 | tree->devDriver = NULL; 134 | tree->privDataField = NULL; 135 | } 136 | 137 | for (tree = tree->childListStart; tree != NULL; tree = tree->next) 138 | disconnectDriver(tree, drv); 139 | } 140 | 141 | int doUnregisterAutoLoader(void) 142 | { 143 | drvAutoLoader = NULL; 144 | return 0; 145 | } 146 | 147 | int doUnregisterDriver(sceUsbdLddOps *drv) 148 | { 149 | sceUsbdLddOps *pos; 150 | for (pos = drvListStart; pos != NULL; pos = pos->next) 151 | if (pos == drv) { 152 | if (drv->next) 153 | drv->next->prev = drv->prev; 154 | else 155 | drvListEnd = drv->prev; 156 | 157 | if (drv->prev) 158 | drv->prev->next = drv->next; 159 | else 160 | drvListStart = drv->next; 161 | 162 | disconnectDriver(memPool.deviceTreeRoot, drv); 163 | return 0; 164 | } 165 | return USB_RC_BADDRIVER; 166 | } 167 | 168 | void connectNewDevice(Device *dev) 169 | { 170 | sceUsbdLddOps *drv; 171 | dbg_printf("searching driver for dev %d, FA %02X\n", dev->id, dev->functionAddress); 172 | for (drv = drvListStart; drv != NULL; drv = drv->next) 173 | if (callUsbDriverFunc(drv->probe, dev->id, drv->gp) != 0) { 174 | dev->devDriver = drv; 175 | dbg_printf("Driver found (%s)\n", drv->name); 176 | callUsbDriverFunc(drv->connect, dev->id, drv->gp); 177 | return; 178 | } 179 | 180 | // No driver found yet. Call autoloader. 181 | if (drvAutoLoader != NULL) { 182 | drv = drvAutoLoader; 183 | 184 | if (callUsbDriverFunc(drv->probe, dev->id, drv->gp) != 0) { 185 | dev->devDriver = drv; 186 | dbg_printf("(autoloader) Driver found (%s)\n", drv->name); 187 | callUsbDriverFunc(drv->connect, dev->id, drv->gp); 188 | return; 189 | } 190 | } 191 | 192 | dbg_printf("no driver found\n"); 193 | } 194 | 195 | void signalCallbackThreadFunc(IoRequest *req) 196 | { 197 | int intrStat; 198 | 199 | CpuSuspendIntr(&intrStat); 200 | 201 | req->prev = cbListEnd; 202 | req->next = NULL; 203 | if (cbListEnd) 204 | cbListEnd->next = req; 205 | else 206 | cbListStart = req; 207 | cbListEnd = req; 208 | 209 | CpuResumeIntr(intrStat); 210 | 211 | SetEventFlag(callbackEvent, 1); 212 | } 213 | 214 | void callbackThreadFunc(void *arg) 215 | { 216 | u32 eventRes; 217 | int intrStat; 218 | IoRequest *req; 219 | IoRequest reqCopy; 220 | 221 | (void)arg; 222 | 223 | while (1) { 224 | WaitEventFlag(callbackEvent, 1, WEF_CLEAR | WEF_OR, &eventRes); 225 | do { 226 | CpuSuspendIntr(&intrStat); 227 | 228 | req = cbListStart; 229 | if (req) { 230 | if (req->next) 231 | req->next->prev = req->prev; 232 | else 233 | cbListEnd = req->prev; 234 | 235 | if (req->prev) 236 | req->prev->next = req->next; 237 | else 238 | cbListStart = req->next; 239 | } 240 | CpuResumeIntr(intrStat); 241 | 242 | if (req) { 243 | memcpy(&reqCopy, req, sizeof(IoRequest)); 244 | usbdLock(); 245 | freeIoRequest(req); 246 | usbdUnlock(); 247 | 248 | if (reqCopy.userCallbackProc) { 249 | #if USE_GP_REGISTER 250 | SetGP(req->gpSeg); 251 | #endif 252 | reqCopy.userCallbackProc(reqCopy.resultCode, reqCopy.transferedBytes, reqCopy.userCallbackArg); 253 | #if USE_GP_REGISTER 254 | SetGP(&_gp); 255 | #endif 256 | } 257 | } 258 | } while (req); 259 | } 260 | } 261 | 262 | int initCallbackThread(void) 263 | { 264 | iop_event_t event; 265 | iop_thread_t thread; 266 | 267 | event.attr = event.option = event.bits = 0; 268 | callbackEvent = CreateEventFlag(&event); 269 | 270 | thread.attr = TH_C; 271 | thread.option = 0; 272 | thread.thread = callbackThreadFunc; 273 | #ifndef MINI_DRIVER 274 | thread.stacksize = 0x4000; // 16KiB 275 | #else 276 | thread.stacksize = 0x0800; // 2KiB 277 | #endif 278 | thread.priority = usbConfig.cbThreadPrio; 279 | callbackTid = CreateThread(&thread); 280 | StartThread(callbackTid, NULL); 281 | 282 | return 0; 283 | } 284 | -------------------------------------------------------------------------------- /usbd/src/driver.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Copyright 2001-2004, ps2dev - http://www.ps2dev.org 7 | # Licenced under Academic Free License version 2.0 8 | # Review ps2sdk README & LICENSE files for further details. 9 | */ 10 | 11 | /** 12 | * @file 13 | * USB Driver function prototypes and constants. 14 | */ 15 | 16 | #ifndef __DRIVER_H__ 17 | #define __DRIVER_H__ 18 | 19 | #include "usbdpriv.h" 20 | 21 | int callUsbDriverFunc(int (*func)(int devId), int devId, void *gp); 22 | int doRegisterDriver(sceUsbdLddOps *drv, void *drvGpSeg); 23 | int doRegisterAutoLoader(sceUsbdLddOps *drv, void *drvGpSeg); 24 | int doUnregisterAutoLoader(void); 25 | int doUnregisterDriver(sceUsbdLddOps *drv); 26 | void signalCallbackThreadFunc(IoRequest *req); 27 | void callbackThreadFunc(void *arg); 28 | void connectNewDevice(Device *dev); 29 | int initCallbackThread(void); 30 | 31 | #endif //__DRIVER_H__ 32 | -------------------------------------------------------------------------------- /usbd/src/exports.tab: -------------------------------------------------------------------------------- 1 | /**/ 2 | 3 | DECLARE_EXPORT_TABLE(usbd, 1, 1) 4 | DECLARE_EXPORT(_start) 5 | DECLARE_EXPORT(_retonly) 6 | DECLARE_EXPORT(_retonly) 7 | DECLARE_EXPORT(_retonly) 8 | DECLARE_EXPORT(sceUsbdRegisterLdd) 9 | /*05*/ DECLARE_EXPORT(sceUsbdUnregisterLdd) 10 | DECLARE_EXPORT(sceUsbdScanStaticDescriptor) 11 | DECLARE_EXPORT(sceUsbdSetPrivateData) 12 | DECLARE_EXPORT(sceUsbdGetPrivateData) 13 | DECLARE_EXPORT(sceUsbdOpenPipe) 14 | /*10*/ DECLARE_EXPORT(sceUsbdClosePipe) 15 | DECLARE_EXPORT(sceUsbdTransferPipe) 16 | DECLARE_EXPORT(sceUsbdOpenPipeAligned) 17 | DECLARE_EXPORT(sceUsbdGetDeviceLocation) 18 | DECLARE_EXPORT(sceUsbdRegisterAutoloader) 19 | /*15*/ DECLARE_EXPORT(sceUsbdUnregisterAutoloader) 20 | DECLARE_EXPORT(sceUsbdChangeThreadPriority) 21 | END_EXPORT_TABLE 22 | 23 | void _retonly() {} 24 | -------------------------------------------------------------------------------- /usbd/src/hcd.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Copyright 2001-2004, ps2dev - http://www.ps2dev.org 7 | # Licenced under Academic Free License version 2.0 8 | # Review ps2sdk README & LICENSE files for further details. 9 | */ 10 | 11 | /** 12 | * @file 13 | * USB Driver function prototypes and constants. 14 | */ 15 | 16 | #ifndef __HCD_H__ 17 | #define __HCD_H__ 18 | 19 | #include "usbdpriv.h" 20 | 21 | int callUsbDriverFunc(int (*func)(int), int devId, void *gp); 22 | Endpoint *openDeviceEndpoint(Device *dev, UsbEndpointDescriptor *endpDesc, u32 alignFlag); 23 | Endpoint *doOpenEndpoint(Device *dev, UsbEndpointDescriptor *endpDesc, u32 alignFlag); 24 | void *doGetDeviceStaticDescriptor(int devId, void *data, u8 type); 25 | int doCloseEndpoint(Endpoint *ep); 26 | int hcdInit(void); 27 | 28 | #endif // __HCD_H__ 29 | -------------------------------------------------------------------------------- /usbd/src/hub.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * USB Driver function prototypes and constants. 4 | */ 5 | 6 | #ifndef __HUB_H__ 7 | #define __HUB_H__ 8 | 9 | #include "usbdpriv.h" 10 | 11 | int removeEndpointFromDevice(Device *dev, Endpoint *ep); 12 | int initHubDriver(void); 13 | void flushPort(Device *dev); 14 | int addTimerCallback(TimerCbStruct *arg, TimerCallback func, void *cbArg, u32 delay); 15 | void hubResetDevice(void *devp); 16 | int hubTimedSetFuncAddress(Device *dev); 17 | 18 | 19 | #endif // __HUB_H__ 20 | -------------------------------------------------------------------------------- /usbd/src/imports.lst: -------------------------------------------------------------------------------- 1 | 2 | loadcore_IMPORTS_start 3 | I_RegisterLibraryEntries 4 | loadcore_IMPORTS_end 5 | 6 | stdio_IMPORTS_start 7 | I_printf 8 | stdio_IMPORTS_end 9 | 10 | sysmem_IMPORTS_start 11 | I_AllocSysMemory 12 | sysmem_IMPORTS_end 13 | 14 | sysclib_IMPORTS_start 15 | I_memcpy 16 | I_memset 17 | I_strtol 18 | sysclib_IMPORTS_end 19 | 20 | intrman_IMPORTS_start 21 | I_DisableIntr 22 | I_EnableIntr 23 | I_RegisterIntrHandler 24 | I_CpuSuspendIntr 25 | I_CpuResumeIntr 26 | intrman_IMPORTS_end 27 | 28 | thsemap_IMPORTS_start 29 | I_CreateSema 30 | I_WaitSema 31 | I_SignalSema 32 | I_DeleteSema 33 | thsemap_IMPORTS_end 34 | 35 | thevent_IMPORTS_start 36 | I_CreateEventFlag 37 | I_SetEventFlag 38 | I_iSetEventFlag 39 | I_WaitEventFlag 40 | thevent_IMPORTS_end 41 | 42 | thbase_IMPORTS_start 43 | I_CreateThread 44 | I_StartThread 45 | I_DeleteThread 46 | I_DelayThread 47 | I_ChangeThreadPriority 48 | thbase_IMPORTS_end 49 | -------------------------------------------------------------------------------- /usbd/src/irx_imports.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Copyright 2001-2004, ps2dev - http://www.ps2dev.org 7 | # Licenced under Academic Free License version 2.0 8 | # Review ps2sdk README & LICENSE files for further details. 9 | # 10 | # Defines all IRX imports. 11 | */ 12 | 13 | #ifndef IOP_IRX_IMPORTS_H 14 | #define IOP_IRX_IMPORTS_H 15 | 16 | #include "irx.h" 17 | 18 | /* Please keep these in alphabetical order! */ 19 | #include "intrman.h" 20 | #include "loadcore.h" 21 | #include "stdio.h" 22 | #include "sysclib.h" 23 | #include "sysmem.h" 24 | #include "thbase.h" 25 | #include "thevent.h" 26 | #include "thmsgbx.h" 27 | #include "thsemap.h" 28 | #include "vblank.h" 29 | 30 | #endif /* IOP_IRX_IMPORTS_H */ 31 | -------------------------------------------------------------------------------- /usbd/src/mem.c: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Copyright 2001-2004, ps2dev - http://www.ps2dev.org 7 | # Licenced under Academic Free License version 2.0 8 | # Review ps2sdk README & LICENSE files for further details. 9 | */ 10 | 11 | /** 12 | * @file 13 | * USB Driver function prototypes and constants. 14 | */ 15 | 16 | #include "usbdpriv.h" 17 | #include "mem.h" 18 | 19 | #include "stdio.h" 20 | 21 | MemoryPool memPool; 22 | 23 | HcIsoTD *allocIsoTd(void) 24 | { 25 | HcIsoTD *newTd = memPool.freeHcIsoTdList; 26 | if (newTd) { 27 | memPool.freeHcIsoTdList = newTd->next; 28 | newTd->next = NULL; 29 | } 30 | return newTd; 31 | } 32 | 33 | void freeIsoTd(HcIsoTD *argTd) 34 | { 35 | HcIsoTD *pos; 36 | if (argTd) { 37 | for (pos = memPool.freeHcIsoTdList; pos != NULL; pos = pos->next) 38 | if (pos == argTd) { 39 | printf("freeIsoTd %p: already free\n", argTd); 40 | return; 41 | } 42 | argTd->next = memPool.freeHcIsoTdList; 43 | memPool.freeHcIsoTdList = argTd; 44 | } 45 | } 46 | 47 | HcTD *allocTd(void) 48 | { 49 | HcTD *res = memPool.freeHcTdList; 50 | if (res) { 51 | memPool.freeHcTdList = res->next; 52 | res->next = NULL; 53 | } 54 | return res; 55 | } 56 | 57 | void freeTd(HcTD *argTd) 58 | { 59 | HcTD *pos; 60 | if (argTd) { 61 | for (pos = memPool.freeHcTdList; pos != NULL; pos = pos->next) 62 | if (pos == argTd) { 63 | printf("FreeTD %p: already free\n", argTd); 64 | return; 65 | } 66 | argTd->next = memPool.freeHcTdList; 67 | memPool.freeHcTdList = argTd; 68 | } 69 | } 70 | 71 | Device *attachChildDevice(Device *parent, u32 portNum) 72 | { 73 | Device *newDev = memPool.freeDeviceListStart; 74 | if (!newDev) { 75 | dbg_printf("Ran out of device handles\n"); 76 | return NULL; 77 | } 78 | 79 | if (newDev->next) 80 | newDev->next->prev = newDev->prev; 81 | else 82 | memPool.freeDeviceListEnd = newDev->prev; 83 | 84 | if (newDev->prev) 85 | newDev->prev->next = newDev->next; 86 | else 87 | memPool.freeDeviceListStart = newDev->next; 88 | 89 | newDev->endpointListEnd = newDev->endpointListStart = NULL; 90 | newDev->devDriver = NULL; 91 | newDev->deviceStatus = DEVICE_NOTCONNECTED; 92 | newDev->resetFlag = 0; 93 | newDev->childListEnd = newDev->childListStart = NULL; 94 | newDev->parent = parent; 95 | newDev->attachedToPortNo = portNum; 96 | newDev->privDataField = NULL; 97 | if (parent) { 98 | newDev->prev = parent->childListEnd; 99 | if (parent->childListEnd) 100 | parent->childListEnd->next = newDev; 101 | else 102 | parent->childListStart = newDev; 103 | newDev->next = NULL; 104 | parent->childListEnd = newDev; 105 | } else 106 | newDev->next = newDev->prev = NULL; 107 | return newDev; 108 | } 109 | 110 | void freeDevice(Device *dev) 111 | { 112 | if (!dev) 113 | return; 114 | 115 | if ((dev < memPool.deviceTreeBuf) || (dev >= memPool.deviceTreeBuf + usbConfig.maxDevices)) { 116 | printf("freeDevice %p: Arg is not part of dev buffer\n", dev); 117 | return; 118 | } 119 | 120 | dev->prev = memPool.freeDeviceListEnd; 121 | if (memPool.freeDeviceListEnd) 122 | memPool.freeDeviceListEnd->next = dev; 123 | else 124 | memPool.freeDeviceListStart = dev; 125 | 126 | dev->next = NULL; 127 | dev->parent = NULL; 128 | memPool.freeDeviceListEnd = dev; 129 | } 130 | 131 | Device *fetchPortElemByNumber(Device *hub, int port) 132 | { 133 | Device *res = hub->childListStart; 134 | while (--port > 0) { 135 | if (!res) 136 | return NULL; 137 | res = res->next; 138 | } 139 | return res; 140 | } 141 | 142 | void addToHcEndpointList(u8 type, HcED *ed) 143 | { 144 | ed->next = memPool.hcEdBuf[type].next; 145 | memPool.hcEdBuf[type].next = ed; 146 | } 147 | 148 | void removeHcEdFromList(int type, const HcED *hcEd) 149 | { 150 | HcED *prev = memPool.hcEdBuf + type; 151 | HcED *pos = prev->next; 152 | while (pos) { 153 | if (pos == hcEd) { 154 | prev->next = pos->next; 155 | return; 156 | } 157 | prev = pos; 158 | pos = pos->next; 159 | } 160 | } 161 | 162 | Endpoint *allocEndpointForDevice(Device *dev, u32 align) 163 | { 164 | Endpoint *newEp = memPool.freeEpListStart; 165 | if (!newEp) 166 | return NULL; 167 | 168 | if (newEp->next) 169 | newEp->next->prev = newEp->prev; 170 | else 171 | memPool.freeEpListEnd = newEp->prev; 172 | 173 | if (newEp->prev) 174 | newEp->prev->next = newEp->next; 175 | else 176 | memPool.freeEpListStart = newEp->next; 177 | 178 | newEp->correspDevice = dev; 179 | newEp->ioReqListStart = newEp->ioReqListEnd = NULL; 180 | newEp->busyNext = newEp->busyPrev = NULL; 181 | newEp->inTdQueue = 0; 182 | newEp->alignFlag = align; 183 | 184 | newEp->next = NULL; 185 | newEp->prev = dev->endpointListEnd; 186 | if (dev->endpointListEnd) 187 | dev->endpointListEnd->next = newEp; 188 | else 189 | dev->endpointListStart = newEp; 190 | 191 | dev->endpointListEnd = newEp; 192 | return newEp; 193 | } 194 | 195 | Device *fetchDeviceById(int devId) 196 | { 197 | if ((devId > 0) && (devId < usbConfig.maxDevices)) { 198 | Device *dev; 199 | 200 | dev = memPool.deviceTreeBuf + devId; 201 | if (dev->parent) 202 | return dev; 203 | } 204 | return NULL; 205 | } 206 | 207 | Endpoint *fetchEndpointById(int id) 208 | { 209 | if ((id >= 0) && (id < usbConfig.maxEndpoints)) { 210 | Endpoint *res; 211 | 212 | res = memPool.endpointBuf + id; 213 | if (res->correspDevice) 214 | return res; 215 | } 216 | return NULL; 217 | } 218 | 219 | IoRequest *allocIoRequest(void) 220 | { 221 | IoRequest *res = memPool.freeIoReqList; 222 | if (res) { 223 | if (res->next) 224 | res->next->prev = res->prev; 225 | else 226 | memPool.freeIoReqListEnd = res->prev; 227 | 228 | if (res->prev) 229 | res->prev->next = res->next; 230 | else 231 | memPool.freeIoReqList = res->next; 232 | res->prev = res->next = NULL; 233 | } else 234 | dbg_printf("ran out of IoReqs\n"); 235 | return res; 236 | } 237 | 238 | void freeIoRequest(IoRequest *req) 239 | { 240 | int num = req - memPool.ioReqBufPtr; 241 | IoRequest *pos; 242 | if (req) { 243 | if ((num >= 0) && (num < usbConfig.maxIoReqs)) { 244 | for (pos = memPool.freeIoReqList; pos != NULL; pos = pos->next) 245 | if (pos == req) { 246 | printf("freeIoRequest %p: already free.\n", req); 247 | return; 248 | } 249 | req->prev = memPool.freeIoReqListEnd; 250 | if (memPool.freeIoReqListEnd) 251 | memPool.freeIoReqListEnd->next = req; 252 | else 253 | memPool.freeIoReqList = req; 254 | req->next = NULL; 255 | memPool.freeIoReqListEnd = req; 256 | } 257 | req->busyFlag = 0; 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /usbd/src/mem.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Copyright 2001-2004, ps2dev - http://www.ps2dev.org 7 | # Licenced under Academic Free License version 2.0 8 | # Review ps2sdk README & LICENSE files for further details. 9 | */ 10 | 11 | /** 12 | * @file 13 | * USB Driver function prototypes and constants. 14 | */ 15 | 16 | #ifndef __MEM_H__ 17 | #define __MEM_H__ 18 | 19 | #include "usbdpriv.h" 20 | 21 | extern MemoryPool memPool; 22 | 23 | HcIsoTD *allocIsoTd(void); 24 | void freeIsoTd(HcIsoTD *argTd); 25 | 26 | HcTD *allocTd(void); 27 | void freeTd(HcTD *argTd); 28 | 29 | Device *attachChildDevice(Device *parent, u32 portNum); 30 | void freeDevice(Device *dev); 31 | 32 | Device *fetchPortElemByNumber(Device *hub, int port); 33 | 34 | void addToHcEndpointList(u8 type, HcED *ed); 35 | void removeHcEdFromList(int type, const HcED *hcEd); 36 | 37 | Endpoint *allocEndpointForDevice(Device *dev, u32 align); 38 | 39 | Device *fetchDeviceById(int devId); 40 | Endpoint *fetchEndpointById(int id); 41 | 42 | IoRequest *allocIoRequest(void); 43 | void freeIoRequest(IoRequest *req); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /usbd/src/usbio.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Copyright 2001-2004, ps2dev - http://www.ps2dev.org 7 | # Licenced under Academic Free License version 2.0 8 | # Review ps2sdk README & LICENSE files for further details. 9 | */ 10 | 11 | /** 12 | * @file 13 | * USB Driver function prototypes and constants. 14 | */ 15 | 16 | #ifndef __USBIO_H__ 17 | #define __USBIO_H__ 18 | 19 | void removeEndpointFromQueue(Endpoint *ep); 20 | void checkTdQueue(int type); 21 | void handleIoReqList(Endpoint *ep); 22 | int doControlTransfer(Endpoint *ep, IoRequest *req, 23 | u8 requestType, u8 request, u16 value, u16 index, u16 length, 24 | void *destdata, void *callback); 25 | int attachIoReqToEndpoint(Endpoint *ep, IoRequest *req, void *destdata, u16 length, void *callback); 26 | void handleIoReqList(Endpoint *ep); 27 | 28 | #endif // __USBIO_H__ 29 | -------------------------------------------------------------------------------- /usbmass_bd/Makefile: -------------------------------------------------------------------------------- 1 | # _____ ___ ____ ___ ____ 2 | # ____| | ____| | | |____| 3 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 4 | #----------------------------------------------------------------------- 5 | # Copyright 2001-2004, ps2dev - http://www.ps2dev.org 6 | # Licenced under Academic Free License version 2.0 7 | # Review ps2sdk README & LICENSE files for further details. 8 | 9 | # IOP_CFLAGS += -DDEBUG 10 | 11 | IOP_BIN = usbmass_bd.irx 12 | 13 | IOP_INCS += -I../usbd/include 14 | IOP_INCS += -I../bdm/include 15 | 16 | IOP_CFLAGS += -Wno-strict-aliasing 17 | 18 | IOP_LDFLAGS = -lgcc 19 | 20 | IOP_OBJS = main.o usb_mass.o scsi.o imports.o 21 | 22 | include ../global.make 23 | -------------------------------------------------------------------------------- /usbmass_bd/src/imports.lst: -------------------------------------------------------------------------------- 1 | bdm_IMPORTS_start 2 | I_bdm_connect_bd 3 | I_bdm_disconnect_bd 4 | bdm_IMPORTS_end 5 | 6 | #ifndef MINI_DRIVER 7 | stdio_IMPORTS_start 8 | I_printf 9 | stdio_IMPORTS_end 10 | #endif 11 | 12 | sysclib_IMPORTS_start 13 | I_memset 14 | I_memcpy 15 | sysclib_IMPORTS_end 16 | 17 | thbase_IMPORTS_start 18 | I_CreateThread 19 | I_StartThread 20 | I_DeleteThread 21 | I_DelayThread 22 | thbase_IMPORTS_end 23 | 24 | thsemap_IMPORTS_start 25 | I_CreateSema 26 | I_SignalSema 27 | I_WaitSema 28 | I_DeleteSema 29 | thsemap_IMPORTS_end 30 | 31 | usbd_IMPORTS_start 32 | I_sceUsbdScanStaticDescriptor 33 | I_sceUsbdOpenPipe 34 | I_sceUsbdOpenPipeAligned 35 | I_sceUsbdClosePipe 36 | I_sceUsbdSetPrivateData 37 | I_sceUsbdTransferPipe 38 | I_sceUsbdRegisterLdd 39 | usbd_IMPORTS_end 40 | -------------------------------------------------------------------------------- /usbmass_bd/src/include/module_debug.h: -------------------------------------------------------------------------------- 1 | #ifndef _MODULE_DEBUG_H 2 | #define _MODULE_DEBUG_H 3 | 4 | #define MODNAME "usbmass_bd" 5 | #ifndef MINI_DRIVER 6 | #define M_PRINTF(format, args...) printf(MODNAME ": " format, ##args) 7 | #else 8 | #define M_PRINTF(format, args...) \ 9 | do { \ 10 | } while (0) 11 | #endif 12 | 13 | #ifdef DEBUG 14 | #define M_DEBUG M_PRINTF 15 | #else 16 | #define M_DEBUG(format, args...) \ 17 | do { \ 18 | } while (0) 19 | #endif 20 | 21 | #define U64_2XU32(val) ((u32*)val)[1], ((u32*)val)[0] 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /usbmass_bd/src/include/scsi.h: -------------------------------------------------------------------------------- 1 | #ifndef _SCSI_H 2 | #define _SCSI_H 3 | 4 | struct scsi_interface 5 | { 6 | void *priv; 7 | char *name; 8 | unsigned int max_sectors; 9 | 10 | int (*get_max_lun)(struct scsi_interface *scsi); 11 | int (*queue_cmd)(struct scsi_interface *scsi, const unsigned char *cmd, unsigned int cmd_len, unsigned char *data, unsigned int data_len, unsigned int data_wr); 12 | }; 13 | 14 | int scsi_init(void); 15 | void scsi_connect(struct scsi_interface *scsi); 16 | void scsi_disconnect(struct scsi_interface *scsi); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /usbmass_bd/src/irx_imports.h: -------------------------------------------------------------------------------- 1 | /* 2 | # _____ ___ ____ ___ ____ 3 | # ____| | ____| | | |____| 4 | # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. 5 | #----------------------------------------------------------------------- 6 | # Copyright 2001-2009, ps2dev - http://www.ps2dev.org 7 | # Licenced under Academic Free License version 2.0 8 | # Review ps2sdk README & LICENSE files for further details. 9 | # 10 | # Defines all IRX imports. 11 | */ 12 | 13 | #ifndef IOP_IRX_IMPORTS_H 14 | #define IOP_IRX_IMPORTS_H 15 | 16 | #include 17 | 18 | /* Please keep these in alphabetical order! */ 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #endif /* IOP_IRX_IMPORTS_H */ 27 | -------------------------------------------------------------------------------- /usbmass_bd/src/main.c: -------------------------------------------------------------------------------- 1 | #define MAJOR_VER 1 2 | #define MINOR_VER 1 3 | 4 | #include "scsi.h" 5 | #include 6 | #include 7 | #include 8 | 9 | // #define DEBUG //comment out this line when not debugging 10 | #include "module_debug.h" 11 | 12 | IRX_ID(MODNAME, MAJOR_VER, MINOR_VER); 13 | 14 | extern int usb_mass_init(void); 15 | 16 | int _start(int argc, char *argv[]) 17 | { 18 | (void)argc; 19 | (void)argv; 20 | 21 | M_PRINTF("USB MASS Driver v%d.%d\n", MAJOR_VER, MINOR_VER); 22 | 23 | // initialize the SCSI driver 24 | if (scsi_init() != 0) { 25 | M_PRINTF("ERROR: initializing SCSI driver!\n"); 26 | return MODULE_NO_RESIDENT_END; 27 | } 28 | 29 | // initialize the USB driver 30 | if (usb_mass_init() != 0) { 31 | M_PRINTF("ERROR: initializing USB driver!\n"); 32 | return MODULE_NO_RESIDENT_END; 33 | } 34 | 35 | // return resident 36 | return MODULE_RESIDENT_END; 37 | } 38 | --------------------------------------------------------------------------------