├── .gitignore
├── DriveCom
├── DriveCom.sln
├── DriveCom.v11.suo
└── DriveCom
│ ├── App.config
│ ├── DriveCom.csproj
│ ├── DriveCom.csproj.user
│ ├── PhisonDevice.cs
│ ├── PhisonDo.csproj.user
│ ├── Properties
│ └── AssemblyInfo.cs
│ └── Startup.cs
├── EmbedPayload
├── EmbedPayload.exe.config
├── EmbedPayload.sln
├── EmbedPayload.v11.suo
├── EmbedPayload.vshost.exe.config
└── EmbedPayload
│ ├── App.config
│ ├── EmbedPayload.csproj
│ ├── Properties
│ └── AssemblyInfo.cs
│ └── Startup.cs
├── Injector
├── Injector.sln
├── Injector.v11.suo
└── Injector
│ ├── App.config
│ ├── DoPatch.csproj.user
│ ├── FirmwareImage.cs
│ ├── FirmwareSection.cs
│ ├── Injector.csproj
│ ├── Injector.csproj.user
│ ├── Properties
│ └── AssemblyInfo.cs
│ └── Startup.cs
├── LICENSE
├── README.md
├── docs
└── PinsToShortUponPlugInForBootMode.jpg
├── firmware
├── build.bat
├── control.c
├── defs.h
├── main.c
├── scsi.c
├── test.bat
├── timers.c
├── timers.h
├── usb.c
└── usb.h
├── patch
├── base.c
├── build.bat
└── defs.h
├── templates
├── BNdummy.bin
└── FWdummy.bin
└── tools
├── hex2bin.exe
└── sfk.exe
/.gitignore:
--------------------------------------------------------------------------------
1 | **/bin/Debug/*
2 | **/obj/Debug/*
3 | **/bin/Release/*
4 | **/obj/Release/*
5 | firmware/bin/*
6 | patch/bin/*
7 | patch/equates.h
8 | tools/*
9 |
--------------------------------------------------------------------------------
/DriveCom/DriveCom.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Express 2012 for Windows Desktop
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DriveCom", "DriveCom\DriveCom.csproj", "{25CF4003-4DF8-4F3C-B9B5-50252C2CD2C2}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Any CPU = Debug|Any CPU
9 | Release|Any CPU = Release|Any CPU
10 | EndGlobalSection
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 | {25CF4003-4DF8-4F3C-B9B5-50252C2CD2C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
13 | {25CF4003-4DF8-4F3C-B9B5-50252C2CD2C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
14 | {25CF4003-4DF8-4F3C-B9B5-50252C2CD2C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
15 | {25CF4003-4DF8-4F3C-B9B5-50252C2CD2C2}.Release|Any CPU.Build.0 = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | EndGlobal
21 |
--------------------------------------------------------------------------------
/DriveCom/DriveCom.v11.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brandonlw/Psychson/4522989aac27aada5f522675b33a2bde63a13b30/DriveCom/DriveCom.v11.suo
--------------------------------------------------------------------------------
/DriveCom/DriveCom/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/DriveCom/DriveCom/DriveCom.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {25CF4003-4DF8-4F3C-B9B5-50252C2CD2C2}
8 | Exe
9 | Properties
10 | DriveCom
11 | DriveCom
12 | v4.0
13 | 512
14 |
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | ..\..\tools\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 | true
26 |
27 |
28 | AnyCPU
29 | pdbonly
30 | true
31 | ..\..\tools\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
61 |
--------------------------------------------------------------------------------
/DriveCom/DriveCom/DriveCom.csproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | /drive=E /burner=C:\Users\Brandon\Documents\GitHub\PS2251-03\BINs\BN03V104M.BIN /firmware=C:\Users\Brandon\Documents\GitHub\PS2251-03\BINs\FW03FF01V10353M.BIN
5 |
6 |
7 | /drive=E
8 |
9 |
--------------------------------------------------------------------------------
/DriveCom/DriveCom/PhisonDevice.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32.SafeHandles;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Runtime.InteropServices;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace DriveCom
11 | {
12 | public class PhisonDevice
13 | {
14 | private char _driveLetter;
15 | private SafeFileHandle _handle;
16 |
17 | public enum RunMode
18 | {
19 | Unknown,
20 | BootMode,
21 | Burner,
22 | HardwareVerify,
23 | Firmware
24 | }
25 |
26 | [Flags]
27 | public enum EFileAttributes : uint
28 | {
29 | Readonly = 0x00000001,
30 | Hidden = 0x00000002,
31 | System = 0x00000004,
32 | Directory = 0x00000010,
33 | Archive = 0x00000020,
34 | Device = 0x00000040,
35 | Normal = 0x00000080,
36 | Temporary = 0x00000100,
37 | SparseFile = 0x00000200,
38 | ReparsePoint = 0x00000400,
39 | Compressed = 0x00000800,
40 | Offline = 0x00001000,
41 | NotContentIndexed = 0x00002000,
42 | Encrypted = 0x00004000,
43 | Write_Through = 0x80000000,
44 | Overlapped = 0x40000000,
45 | NoBuffering = 0x20000000,
46 | RandomAccess = 0x10000000,
47 | SequentialScan = 0x08000000,
48 | DeleteOnClose = 0x04000000,
49 | BackupSemantics = 0x02000000,
50 | PosixSemantics = 0x01000000,
51 | OpenReparsePoint = 0x00200000,
52 | OpenNoRecall = 0x00100000,
53 | FirstPipeInstance = 0x00080000
54 | }
55 |
56 | [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
57 | public static extern SafeFileHandle CreateFile(
58 | string fileName,
59 | [MarshalAs(UnmanagedType.U4)] FileAccess fileAccess,
60 | [MarshalAs(UnmanagedType.U4)] FileShare fileShare,
61 | IntPtr securityAttributes,
62 | [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
63 | [MarshalAs(UnmanagedType.U4)] EFileAttributes flags,
64 | IntPtr template);
65 |
66 | [DllImport("kernel32.dll")]
67 | static public extern int CloseHandle(SafeFileHandle hObject);
68 |
69 | public const byte SCSI_IOCTL_DATA_OUT = 0;
70 | public const byte SCSI_IOCTL_DATA_IN = 1;
71 |
72 | [StructLayout(LayoutKind.Sequential)]
73 | class SCSI_PASS_THROUGH_DIRECT
74 | {
75 | private const int _CDB_LENGTH = 16;
76 |
77 | public short Length;
78 | public byte ScsiStatus;
79 | public byte PathId;
80 | public byte TargetId;
81 | public byte Lun;
82 | public byte CdbLength;
83 | public byte SenseInfoLength;
84 | public byte DataIn;
85 | public int DataTransferLength;
86 | public int TimeOutValue;
87 | public IntPtr DataBuffer;
88 | public uint SenseInfoOffset;
89 |
90 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = _CDB_LENGTH)]
91 | public byte[] Cdb;
92 |
93 | public SCSI_PASS_THROUGH_DIRECT()
94 | {
95 | Cdb = new byte[_CDB_LENGTH];
96 | }
97 | };
98 |
99 | [StructLayout(LayoutKind.Sequential)]
100 | class SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER
101 | {
102 | private const int _SENSE_LENGTH = 32;
103 | internal SCSI_PASS_THROUGH_DIRECT sptd = new SCSI_PASS_THROUGH_DIRECT();
104 |
105 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = _SENSE_LENGTH)]
106 | internal byte[] sense;
107 |
108 | public SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER()
109 | {
110 | sense = new byte[_SENSE_LENGTH];
111 | }
112 | };
113 |
114 | [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
115 | static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode,
116 | IntPtr lpInBuffer, uint nInBufferSize,
117 | IntPtr lpOutBuffer, uint nOutBufferSize,
118 | out uint lpBytesReturned, IntPtr lpOverlapped);
119 |
120 | ///
121 | /// Creates a reference to a device with a Phison USB controller.
122 | ///
123 | /// The Windows drive letter representing the device.
124 | public PhisonDevice(char driveLetter)
125 | {
126 | _driveLetter = driveLetter;
127 | }
128 |
129 | ///
130 | /// Opens a connection to the device.
131 | ///
132 | public void Open()
133 | {
134 | _handle = CreateFile(string.Format("\\\\.\\{0}:", _driveLetter), FileAccess.ReadWrite, FileShare.ReadWrite,
135 | IntPtr.Zero, FileMode.Open, EFileAttributes.NoBuffering, IntPtr.Zero);
136 | }
137 |
138 | public byte[] RequestVendorInfo()
139 | {
140 | var data = SendCommand(new byte[] { 0x06, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
141 | 512 + 16);
142 | byte[] ret = null;
143 |
144 | if (data != null)
145 | {
146 | ret = data.Take(512).ToArray();
147 | }
148 |
149 | return ret;
150 | }
151 |
152 | public string GetChipID()
153 | {
154 | var response = SendCommand(new byte[] { 0x06, 0x56, 0x00, 0x00, 0x00,
155 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 512);
156 |
157 | return BitConverter.ToString(response, 0, 6);
158 | }
159 |
160 | public string GetFirmwareVersion()
161 | {
162 | var info = RequestVendorInfo();
163 |
164 | return info[0x94] + "." + info[0x95].ToString("X02") + "." + info[0x96].ToString("X02");
165 | }
166 |
167 | public ushort? GetChipType()
168 | {
169 | ushort? ret = null;
170 | var info = RequestVendorInfo();
171 |
172 | if (info != null)
173 | {
174 | if (info[0x17A] == (byte)'V' && info[0x17B] == (byte)'R')
175 | {
176 | var data = info.Skip(0x17E).Take(2).ToArray();
177 | ret = (ushort)((data[0] << 8) | data[1]);
178 | }
179 | }
180 |
181 | return ret;
182 | }
183 |
184 | public RunMode GetRunMode()
185 | {
186 | var ret = RunMode.Unknown;
187 | var info = RequestVendorInfo();
188 |
189 | if (info != null)
190 | {
191 | if (info[0x17A] == (byte)'V' && info[0x17B] == (byte)'R')
192 | {
193 | //TODO: Fix this, this is a dumb way of detecting it
194 | switch (ASCIIEncoding.ASCII.GetString(info.Skip(0xA0).Take(8).ToArray()))
195 | {
196 | case " PRAM ":
197 | ret = RunMode.BootMode;
198 | break;
199 | case " FW BURN":
200 | ret = RunMode.Burner;
201 | break;
202 | case " HV TEST":
203 | ret = RunMode.HardwareVerify;
204 | break;
205 | default:
206 | ret = RunMode.Firmware;
207 | break;
208 | }
209 | }
210 | }
211 |
212 | return ret;
213 | }
214 |
215 | public ulong GetNumLBAs()
216 | {
217 | var response = SendCommand(new byte[] { 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 8);
218 | ulong ret = response[3];
219 | ret |= (ulong)((ulong)(response[2] << 8) & 0x0000FF00);
220 | ret |= (ulong)((ulong)(response[1] << 16) & 0x00FF0000);
221 | ret |= (ulong)((ulong)(response[0] << 24) & 0xFF000000);
222 |
223 | return ret + 1;
224 | }
225 |
226 | public void JumpToPRAM()
227 | {
228 | SendCommand(new byte[] { 0x06, 0xB3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
229 | }
230 |
231 | public void JumpToBootMode()
232 | {
233 | SendCommand(new byte[] { 0x06, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
234 | }
235 |
236 | public void TransferFile(byte[] data)
237 | {
238 | TransferFile(data, 0x03, 0x02);
239 | }
240 |
241 | public void TransferFile(byte[] data, byte header, byte body)
242 | {
243 | var size = data.Length - 1024;
244 |
245 | //Send header
246 | SendCommand(new byte[] { 0x06, 0xB1, header, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, data.Take(0x200).ToArray());
247 |
248 | //Get response
249 | var response = SendCommand(new byte[] { 0x06, 0xB0, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 8);
250 | if (response == null || response[0] != 0x55)
251 | {
252 | throw new InvalidOperationException("Header not accepted");
253 | }
254 |
255 | //Send body
256 | int address = 0;
257 | while (size > 0)
258 | {
259 | int chunkSize;
260 | if (size > 0x8000)
261 | {
262 | chunkSize = 0x8000;
263 | }
264 | else
265 | {
266 | chunkSize = size;
267 | }
268 |
269 | int cmdAddress = address >> 9;
270 | int cmdChunk = chunkSize >> 9;
271 | SendCommand(new byte[] { 0x06, 0xB1, body, (byte)((cmdAddress >> 8) & 0xFF), (byte)(cmdAddress & 0xFF),
272 | 0x00, 0x00, (byte)((cmdChunk >> 8) & 0xFF), (byte)(cmdChunk & 0xFF), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
273 | data.Skip(address + 0x200).Take(chunkSize).ToArray());
274 |
275 | //Get response
276 | var r = SendCommand(new byte[] { 0x06, 0xB0, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 8);
277 | if (r == null || r[0] != 0xA5)
278 | {
279 | throw new InvalidOperationException("Body not accepted");
280 | }
281 |
282 | address += chunkSize;
283 | size -= chunkSize;
284 | }
285 | }
286 |
287 | ///
288 | /// Sends command with no attached data and returns expected response.
289 | ///
290 | ///
291 | ///
292 | ///
293 | public byte[] SendCommand(byte[] cmd, int bytesExpected)
294 | {
295 | return _SendCommand(_handle, cmd, null, bytesExpected);
296 | }
297 |
298 | ///
299 | /// Sends command with no attached data and no response.
300 | ///
301 | ///
302 | public void SendCommand(byte[] cmd)
303 | {
304 | SendCommand(cmd, null);
305 | }
306 |
307 | ///
308 | /// Sends command with attached data and no response.
309 | ///
310 | ///
311 | ///
312 | public void SendCommand(byte[] cmd, byte[] data)
313 | {
314 | _SendCommand(_handle, cmd, data, 0);
315 | }
316 |
317 | ///
318 | /// Closes the connection to the device.
319 | ///
320 | public void Close()
321 | {
322 | if (_handle != null && !_handle.IsClosed)
323 | {
324 | _handle.Close();
325 | }
326 | }
327 |
328 | private static byte[] _SendCommand(SafeFileHandle handle, byte[] cmd, byte[] data, int bytesExpected)
329 | {
330 | const int IOCTL_SCSI_PASS_THROUGH_DIRECT = 0x4D014;
331 | const int TIMEOUT_SECS = 30;
332 | SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER scsi = null;
333 | IntPtr inBuffer = IntPtr.Zero;
334 | byte[] ret = null;
335 |
336 | try
337 | {
338 | scsi = new SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER();
339 | scsi.sptd.Length = (short)Marshal.SizeOf(scsi.sptd);
340 | scsi.sptd.TimeOutValue = TIMEOUT_SECS;
341 | scsi.sptd.SenseInfoOffset = (uint)Marshal.OffsetOf(typeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER), "sense");
342 | scsi.sptd.SenseInfoLength = (byte)scsi.sense.Length;
343 | scsi.sptd.CdbLength = (byte)cmd.Length;
344 | Array.Copy(cmd, scsi.sptd.Cdb, cmd.Length);
345 | scsi.sptd.DataIn = data != null && data.Length > 0 ? SCSI_IOCTL_DATA_OUT : SCSI_IOCTL_DATA_IN;
346 | scsi.sptd.DataTransferLength = data != null && data.Length > 0 ? data.Length : bytesExpected;
347 | scsi.sptd.DataBuffer = Marshal.AllocHGlobal(scsi.sptd.DataTransferLength);
348 | if (data != null && data.Length > 0)
349 | {
350 | Marshal.Copy(data, 0, scsi.sptd.DataBuffer, data.Length);
351 | }
352 |
353 | uint bytesReturned;
354 | inBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(scsi));
355 | var size = (uint)Marshal.SizeOf(scsi);
356 | Marshal.StructureToPtr(scsi, inBuffer, false);
357 | if (!DeviceIoControl(handle.DangerousGetHandle(), IOCTL_SCSI_PASS_THROUGH_DIRECT,
358 | inBuffer, size, inBuffer, size, out bytesReturned, IntPtr.Zero))
359 | {
360 | //Whoops, do something with the error code
361 | int last = Marshal.GetLastWin32Error();
362 | throw new InvalidOperationException("DeviceIoControl failed: " + last.ToString("X04"));
363 | }
364 | else
365 | {
366 | if (scsi.sptd.ScsiStatus != 0)
367 | {
368 | //Whoops, do something with the error code
369 | throw new InvalidOperationException("SCSI command failed: " + scsi.sptd.ScsiStatus.ToString("X02"));
370 | }
371 | else
372 | {
373 | //Success, marshal back any data we received
374 | if (scsi.sptd.DataTransferLength > 0)
375 | {
376 | ret = new byte[scsi.sptd.DataTransferLength];
377 | Marshal.Copy(scsi.sptd.DataBuffer, ret, 0, ret.Length);
378 | }
379 | }
380 | }
381 | }
382 | finally
383 | {
384 | /* Free any unmanaged resources */
385 |
386 | if (scsi != null && scsi.sptd.DataBuffer != IntPtr.Zero)
387 | {
388 | Marshal.FreeHGlobal(scsi.sptd.DataBuffer);
389 | }
390 |
391 | if (inBuffer != IntPtr.Zero)
392 | {
393 | Marshal.FreeHGlobal(inBuffer);
394 | }
395 | }
396 |
397 | return ret;
398 | }
399 | }
400 | }
401 |
--------------------------------------------------------------------------------
/DriveCom/DriveCom/PhisonDo.csproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | /drive=E /burner="C:\\Users\\Brandon\\Documents\GitHub\\PS2251-03\\BINs\BN03V104M.bin" /firmware="C:\\Users\\Brandon\\Documents\\GitHub\\PS2251-03\\patch\\bin\\patched.bin"
5 |
6 |
--------------------------------------------------------------------------------
/DriveCom/DriveCom/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("PhisonDo")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("PhisonDo")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("ebfd9a94-1fd1-4595-a864-a3525ff4c875")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/DriveCom/DriveCom/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32.SafeHandles;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.IO;
5 | using System.Runtime.InteropServices;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading;
9 | using System.Threading.Tasks;
10 |
11 | namespace DriveCom
12 | {
13 | class Startup
14 | {
15 | private const int _WAIT_TIME_MS = 2000;
16 | private static PhisonDevice _device = null;
17 | private static string _burner;
18 | private static string _firmware;
19 | private static string _password;
20 |
21 | public enum Action
22 | {
23 | None,
24 | GetInfo,
25 | SetPassword,
26 | DumpFirmware,
27 | SetBootMode,
28 | SendExecutable,
29 | SendFirmware,
30 | GetNumLBAs
31 | }
32 |
33 | public enum ExitCode
34 | {
35 | Success = 0,
36 | Failure = 1
37 | }
38 |
39 | static void Main(string[] args)
40 | {
41 | try
42 | {
43 | Environment.ExitCode = (int)ExitCode.Success;
44 |
45 | var action = Action.None;
46 | string drive = string.Empty;
47 |
48 | foreach (var arg in args)
49 | {
50 | var parts = arg.TrimStart(new char[] { '/' }).Split(new char[] { '=' },
51 | StringSplitOptions.RemoveEmptyEntries);
52 | switch (parts[0].ToLower())
53 | {
54 | case "action":
55 | {
56 | action = (Action)Enum.Parse(typeof(Action), parts[1]);
57 | break;
58 | }
59 | case "drive":
60 | {
61 | drive = parts[1];
62 | break;
63 | }
64 | case "burner":
65 | {
66 | _burner = parts[1];
67 | break;
68 | }
69 | case "firmware":
70 | {
71 | _firmware = parts[1];
72 | break;
73 | }
74 | case "password":
75 | {
76 | _password = parts[1];
77 | break;
78 | }
79 | default:
80 | {
81 | break;
82 | }
83 | }
84 | }
85 |
86 | if (!string.IsNullOrEmpty(drive))
87 | {
88 | _OpenDrive(drive);
89 | }
90 |
91 | if (action != Action.None)
92 | {
93 | Console.WriteLine("Action specified: " + action.ToString());
94 |
95 | switch (action)
96 | {
97 | case Action.DumpFirmware:
98 | {
99 | _DumpFirmware(_firmware);
100 | break;
101 | }
102 | case Action.GetInfo:
103 | {
104 | _GetInfo();
105 | break;
106 | }
107 | case Action.SendExecutable:
108 | {
109 | _ExecuteImage(_burner);
110 | break;
111 | }
112 | case Action.SendFirmware:
113 | {
114 | _SendFirmware();
115 | break;
116 | }
117 | case Action.GetNumLBAs:
118 | {
119 | _DisplayLBAs();
120 | break;
121 | }
122 | case Action.SetBootMode:
123 | {
124 | _device.JumpToBootMode();
125 | Thread.Sleep(_WAIT_TIME_MS);
126 | break;
127 | }
128 | case Action.SetPassword:
129 | {
130 | _SendPassword(_password);
131 | break;
132 | }
133 | default:
134 | {
135 | throw new ArgumentException("No/invalid action specified");
136 | }
137 | }
138 | }
139 | else
140 | {
141 | Console.WriteLine("No action specified, entering console.");
142 |
143 | bool exiting = false;
144 | while (!exiting)
145 | {
146 | Console.Write(">");
147 | var line = Console.ReadLine();
148 | var @params = line.Split(new char[] { ' ' });
149 |
150 | try
151 | {
152 | switch (@params[0].ToLower())
153 | {
154 | case "open":
155 | {
156 | _OpenDrive(@params[1]);
157 | break;
158 | }
159 | case "close":
160 | {
161 | _CloseDrive();
162 | break;
163 | }
164 | case "mode":
165 | {
166 | _GetInfo();
167 | break;
168 | }
169 | case "info":
170 | {
171 | var data = _device.RequestVendorInfo();
172 | Console.WriteLine(string.Format("Info: {0}...", BitConverter.ToString(data, 0, 16)));
173 | break;
174 | }
175 | case "get_num_lbas":
176 | {
177 | _DisplayLBAs();
178 | break;
179 | }
180 | case "password":
181 | {
182 | _SendPassword(@params[1]);
183 | break;
184 | }
185 | case "dump_xram":
186 | {
187 | var address = 0;
188 | var data = new byte[0xF000];
189 | for (int i = 0; i < data.Length; i++)
190 | {
191 | var result = _device.SendCommand(new byte[] { 0x06, 0x06,
192 | (byte)((address >> 8) & 0xFF), (byte)(address & 0xFF), 0x00, 0x00, 0x00, 0x00 }, 1);
193 | data[address] = result[0];
194 | address++;
195 | }
196 |
197 | File.WriteAllBytes(@params[1], data);
198 | break;
199 | }
200 | case "dump_firmware":
201 | {
202 | _DumpFirmware(@params[1]);
203 | break;
204 | }
205 | case "nand_read":
206 | {
207 | var address = Convert.ToInt32(@params[1], 16);
208 | var size = Convert.ToInt32(@params[2], 16);
209 | var result = _device.SendCommand(new byte[] { 0x06, 0xB2, 0x10,
210 | (byte)((address >> 8) & 0xFF), (byte)(address & 0xFF), 0x00, 0x00,
211 | (byte)((size >> 8) & 0xFF), (byte)(size & 0xFF) }, size * 512);
212 | Console.WriteLine(string.Format("Data: {0}...", BitConverter.ToString(result, 0, 16)));
213 | break;
214 | }
215 | case "boot":
216 | {
217 | _device.JumpToBootMode();
218 | Thread.Sleep(_WAIT_TIME_MS);
219 | break;
220 | }
221 | case "set_burner":
222 | {
223 | _burner = @params[1];
224 | break;
225 | }
226 | case "set_firmware":
227 | {
228 | _firmware = @params[1];
229 | break;
230 | }
231 | case "burner":
232 | {
233 | _ExecuteImage(_burner);
234 | break;
235 | }
236 | case "firmware":
237 | {
238 | _SendFirmware();
239 | break;
240 | }
241 | case "peek":
242 | {
243 | var address = Convert.ToInt32(@params[1], 16);
244 | var result = _device.SendCommand(new byte[] { 0x06, 0x06,
245 | (byte)((address >> 8) & 0xFF), (byte)(address & 0xFF), 0x00, 0x00, 0x00, 0x00 }, 1);
246 | Console.WriteLine("Value: " + result[0].ToString("X02"));
247 | break;
248 | }
249 | case "poke":
250 | {
251 | var address = Convert.ToInt32(@params[1], 16);
252 | var value = Convert.ToInt32(@params[2], 16);
253 | _device.SendCommand(new byte[] { 0x06, 0x07,
254 | (byte)((address >> 8) & 0xFF), (byte)(address & 0xFF), (byte)value, 0x00, 0x00 }, 1);
255 | break;
256 | }
257 | case "ipeek":
258 | {
259 | var address = Convert.ToInt32(@params[1], 16);
260 | var result = _device.SendCommand(new byte[] { 0x06, 0x08,
261 | (byte)(address & 0xFF), 0x00, 0x00, 0x00, 0x00 }, 1);
262 | Console.WriteLine("Value: " + result[0].ToString("X02"));
263 | break;
264 | }
265 | case "ipoke":
266 | {
267 | var address = Convert.ToInt32(@params[1], 16);
268 | var value = Convert.ToInt32(@params[2], 16);
269 | _device.SendCommand(new byte[] { 0x06, 0x09,
270 | (byte)(address & 0xFF), (byte)value, 0x00, 0x00 }, 1);
271 | break;
272 | }
273 | case "quit":
274 | case "exit":
275 | {
276 | exiting = true;
277 | break;
278 | }
279 | default:
280 | Console.WriteLine("Invalid command: " + @params[0]);
281 | break;
282 | }
283 | }
284 | catch (Exception ex)
285 | {
286 | Console.WriteLine("ERROR: " + ex.ToString());
287 | }
288 | }
289 |
290 | Console.WriteLine("Done.");
291 | }
292 | }
293 | catch (Exception ex)
294 | {
295 | Environment.ExitCode = (int)ExitCode.Failure;
296 |
297 | Console.WriteLine("FATAL: " + ex.ToString());
298 | }
299 | finally
300 | {
301 | if (_device != null)
302 | {
303 | _device.Close();
304 | }
305 | }
306 | }
307 |
308 | private static void _OpenDrive(string drive)
309 | {
310 | _CloseDrive();
311 |
312 | _device = new PhisonDevice(drive[0]);
313 | _device.Open();
314 | }
315 |
316 | private static void _CloseDrive()
317 | {
318 | if (_device != null)
319 | {
320 | _device.Close();
321 | _device = null;
322 | }
323 | }
324 |
325 | private static void _DisplayLBAs()
326 | {
327 | Console.WriteLine("Number of LBAs: 0x" + _device.GetNumLBAs().ToString("X08"));
328 | }
329 |
330 | private static void _DumpFirmware(string fileName)
331 | {
332 | var address = 0;
333 | var data = new byte[0x32400];
334 | var header = new byte[] { 0x42, 0x74, 0x50, 0x72, 0x61, 0x6D, 0x43, 0x64,
335 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x10, 0x0B, 0x18 };
336 | Array.Copy(header, 0, data, 0, header.Length);
337 | while (address * 0x200 < data.Length)
338 | {
339 | var length = Math.Min(0x40 * 512, (data.Length - 0x400) - (address * 0x200));
340 | var temp = length / 512;
341 | var result = _device.SendCommand(new byte[] { 0x06, 0xB2, 0x10,
342 | (byte)((address >> 8) & 0xFF), (byte)(address & 0xFF), 0x00, 0x00,
343 | (byte)((temp >> 8) & 0xFF), (byte)(temp & 0xFF) }, length);
344 | Array.Copy(result.Take(length).ToArray(), 0, data, 0x200 + address * 512, length);
345 | address += 0x40;
346 | }
347 |
348 | var footer = new byte[] { 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6D,
349 | 0x70, 0x20, 0x6D, 0x61, 0x72, 0x6B, 0x00, 0x03, 0x01, 0x00, 0x10, 0x01, 0x04, 0x10, 0x42 };
350 | Array.Copy(footer, 0, data, data.Length - 0x200, footer.Length);
351 | File.WriteAllBytes(fileName, data);
352 | }
353 |
354 | private static void _SendPassword(string password)
355 | {
356 | var data = new byte[0x200];
357 | var pw = ASCIIEncoding.ASCII.GetBytes(password);
358 | Array.Copy(pw, 0, data, 0x10, pw.Length);
359 | _device.SendCommand(new byte[] { 0x0E, 0x00, 0x01, 0x55, 0xAA,
360 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, data);
361 | }
362 |
363 | private static void _SendFirmware()
364 | {
365 | var mode = _GetInfo();
366 | if (mode != PhisonDevice.RunMode.Burner)
367 | {
368 | if (mode != PhisonDevice.RunMode.BootMode)
369 | {
370 | Console.WriteLine("Switching to boot mode...");
371 | _device.JumpToBootMode();
372 | Thread.Sleep(_WAIT_TIME_MS);
373 | }
374 |
375 | _ExecuteImage(_burner);
376 | }
377 |
378 | _RunFirmware(_firmware);
379 | }
380 |
381 | private static PhisonDevice.RunMode _GetInfo()
382 | {
383 | Console.WriteLine("Gathering information...");
384 | Console.WriteLine("Reported chip type: " + _device.GetChipType().GetValueOrDefault().ToString("X04"));
385 | Console.WriteLine("Reported chip ID: " + _device.GetChipID());
386 | Console.WriteLine("Reported firmware version: " + _device.GetFirmwareVersion());
387 |
388 | var ret = _device.GetRunMode();
389 | Console.WriteLine("Mode: " + ret.ToString());
390 |
391 | return ret;
392 | }
393 |
394 | private static void _ExecuteImage(string fileName)
395 | {
396 | //Read image
397 | var file = new FileStream(fileName, FileMode.Open);
398 | var fileData = new byte[file.Length];
399 | file.Read(fileData, 0, fileData.Length);
400 | file.Close();
401 |
402 | //Load it
403 | _device.TransferFile(fileData);
404 | _device.JumpToPRAM();
405 |
406 | //Wait a little bit
407 | Thread.Sleep(_WAIT_TIME_MS);
408 | }
409 |
410 | private static void _RunFirmware(string fileName)
411 | {
412 | //Get file data
413 | var fw = new FileStream(fileName, FileMode.Open);
414 | var data = new byte[fw.Length];
415 | fw.Read(data, 0, data.Length);
416 | fw.Close();
417 |
418 | //TODO: Find out what this actually does...
419 | //Console.WriteLine("Sending scary B7 command (takes several seconds)...");
420 | //_device.SendCommand(new byte[] { 0x06, 0xB7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
421 |
422 | Console.WriteLine("Rebooting...");
423 | _device.JumpToBootMode();
424 | Thread.Sleep(_WAIT_TIME_MS);
425 |
426 | Console.WriteLine("Sending firmware...");
427 | _device.TransferFile(data, 0x01, 0x00);
428 | var ret = _device.SendCommand(new byte[] { 0x06, 0xEE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 64 + 8);
429 | Thread.Sleep(_WAIT_TIME_MS);
430 | _device.TransferFile(data, 0x03, 0x02);
431 | ret = _device.SendCommand(new byte[] { 0x06, 0xEE, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }, 64 + 8);
432 | Thread.Sleep(_WAIT_TIME_MS);
433 | ret = _device.SendCommand(new byte[] { 0x06, 0xEE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 64 + 8);
434 | Thread.Sleep(_WAIT_TIME_MS);
435 | ret = _device.SendCommand(new byte[] { 0x06, 0xEE, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }, 64 + 8);
436 | Thread.Sleep(_WAIT_TIME_MS);
437 |
438 | Console.WriteLine("Executing...");
439 | _device.JumpToPRAM();
440 | Thread.Sleep(_WAIT_TIME_MS);
441 |
442 | //Display new mode, if we can actually get it
443 | Console.WriteLine("Mode: " + _device.GetRunMode().ToString());
444 | }
445 | }
446 | }
447 |
--------------------------------------------------------------------------------
/EmbedPayload/EmbedPayload.exe.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/EmbedPayload/EmbedPayload.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Express 2012 for Windows Desktop
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmbedPayload", "EmbedPayload\EmbedPayload.csproj", "{E2381629-180B-44DE-8702-B63B4699A587}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Any CPU = Debug|Any CPU
9 | Release|Any CPU = Release|Any CPU
10 | EndGlobalSection
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 | {E2381629-180B-44DE-8702-B63B4699A587}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
13 | {E2381629-180B-44DE-8702-B63B4699A587}.Debug|Any CPU.Build.0 = Debug|Any CPU
14 | {E2381629-180B-44DE-8702-B63B4699A587}.Release|Any CPU.ActiveCfg = Release|Any CPU
15 | {E2381629-180B-44DE-8702-B63B4699A587}.Release|Any CPU.Build.0 = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | EndGlobal
21 |
--------------------------------------------------------------------------------
/EmbedPayload/EmbedPayload.v11.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brandonlw/Psychson/4522989aac27aada5f522675b33a2bde63a13b30/EmbedPayload/EmbedPayload.v11.suo
--------------------------------------------------------------------------------
/EmbedPayload/EmbedPayload.vshost.exe.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/EmbedPayload/EmbedPayload/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/EmbedPayload/EmbedPayload/EmbedPayload.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {E2381629-180B-44DE-8702-B63B4699A587}
8 | Exe
9 | Properties
10 | EmbedPayload
11 | EmbedPayload
12 | v4.5
13 | 512
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | ..\..\tools\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | ..\..\tools\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
58 |
--------------------------------------------------------------------------------
/EmbedPayload/EmbedPayload/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("EmbedPayload")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Toshiba")]
12 | [assembly: AssemblyProduct("EmbedPayload")]
13 | [assembly: AssemblyCopyright("Copyright © Toshiba 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("5cd1f91a-6190-490e-a5c8-6d200a7e00db")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/EmbedPayload/EmbedPayload/Startup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace EmbedPayload
9 | {
10 | class Startup
11 | {
12 | public enum ExitCode
13 | {
14 | Success = 0,
15 | Failure = 1
16 | }
17 |
18 | static void Main(string[] args)
19 | {
20 | if (args.Length != 2)
21 | {
22 | Console.WriteLine("Usage: [payload BIN] [firmware image]");
23 | return;
24 | }
25 |
26 | try
27 | {
28 | //Assume success at first
29 | Environment.ExitCode = (int)ExitCode.Success;
30 |
31 | //Read all bytes from input file
32 | var payload = File.ReadAllBytes(args[0]);
33 |
34 | //Read all bytes from output file:
35 | var stream = new FileStream(args[1], FileMode.Open, FileAccess.ReadWrite);
36 | var header = new byte[0x200];
37 | stream.Read(header, 0, header.Length);
38 | var data = new byte[0x6000];
39 | stream.Read(data, 0, data.Length);
40 |
41 | // Look for 0x12345678
42 | var signature = new byte[] { 0x12, 0x34, 0x56, 0x78 };
43 | int? address = null;
44 | for (int i = 0; i < data.Length; i++)
45 | {
46 | bool match = true;
47 | for (int j = 0; j < signature.Length; j++)
48 | {
49 | if (data[i + j] != signature[j])
50 | {
51 | match = false;
52 | break;
53 | }
54 | }
55 |
56 | if (match)
57 | {
58 | address = i;
59 | break;
60 | }
61 | }
62 |
63 | // When found, overwrite with input data
64 | if (address.HasValue)
65 | {
66 | if ((0x200 + address.Value) >= 0x6000)
67 | {
68 | throw new InvalidOperationException("Insufficient memory to inject file!");
69 | }
70 |
71 | stream.Seek(0x200 + address.Value, SeekOrigin.Begin);
72 | stream.Write(payload, 0, payload.Length);
73 |
74 | //Save output file back out
75 | stream.Close();
76 | Console.WriteLine("File updated.");
77 | }
78 | else
79 | {
80 | Console.WriteLine("Signature not found!");
81 | }
82 | }
83 | catch (Exception ex)
84 | {
85 | //Uh-oh
86 | Environment.ExitCode = (int)ExitCode.Failure;
87 |
88 | Console.WriteLine("FATAL: " + ex.ToString());
89 | }
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/Injector/Injector.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Express 2012 for Windows Desktop
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Injector", "Injector\Injector.csproj", "{41480B6F-9051-43D1-9484-30A265D09D5D}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Any CPU = Debug|Any CPU
9 | Release|Any CPU = Release|Any CPU
10 | EndGlobalSection
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 | {41480B6F-9051-43D1-9484-30A265D09D5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
13 | {41480B6F-9051-43D1-9484-30A265D09D5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
14 | {41480B6F-9051-43D1-9484-30A265D09D5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
15 | {41480B6F-9051-43D1-9484-30A265D09D5D}.Release|Any CPU.Build.0 = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | EndGlobal
21 |
--------------------------------------------------------------------------------
/Injector/Injector.v11.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brandonlw/Psychson/4522989aac27aada5f522675b33a2bde63a13b30/Injector/Injector.v11.suo
--------------------------------------------------------------------------------
/Injector/Injector/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Injector/Injector/DoPatch.csproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | /firmware="C:\\Users\\Brandon\\Documents\\GitHub\\PS2251-03\\BINs\\FW03FF01V10353M.BIN" /basecode="C:\\Users\\Brandon\\Documents\\GitHub\\PS2251-03\\patch\\bin\\output.bin" /action=FindFreeBlocks /output="C:\\Users\\Brandon\\Documents\\GitHub\\PS2251-03\\patch\\bin\\patched.bin" /baserst="C:\\Users\\Brandon\\Documents\\GitHub\\PS2251-03\\patch\\bin\\main.rst"
5 |
6 |
--------------------------------------------------------------------------------
/Injector/Injector/FirmwareImage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Injector
9 | {
10 | public class FirmwareImage
11 | {
12 | private string _fileName;
13 | private byte[] _header;
14 | private Dictionary _sections;
15 | private byte[] _footer;
16 |
17 | public FirmwareImage(string fileName)
18 | {
19 | _fileName = fileName;
20 | _header = new byte[0x200];
21 | _sections = new Dictionary();
22 | _sections.Add(FirmwareSection.Base, new byte[0x6000]);
23 | }
24 |
25 | public byte[] GetSection(FirmwareSection section)
26 | {
27 | byte[] ret = null;
28 |
29 | if (_sections.ContainsKey(section))
30 | {
31 | ret = _sections[section];
32 | }
33 |
34 | return ret;
35 | }
36 |
37 | public void Open()
38 | {
39 | FirmwareSection i = 0;
40 |
41 | //Get the header and base page
42 | var stream = new FileStream(_fileName, FileMode.Open);
43 | var @base = GetSection(FirmwareSection.Base);
44 | stream.Read(_header, 0, _header.Length);
45 | stream.Read(@base, 0, @base.Length);
46 |
47 | //Read in all the sections
48 | while ((stream.Length - stream.Position) > 0x200)
49 | {
50 | var data = new byte[0x4000];
51 | stream.Read(data, 0, data.Length);
52 | _sections.Add(i++, data);
53 | }
54 |
55 | //If we have a footer, read it in
56 | if ((stream.Length - stream.Position) == 0x200)
57 | {
58 | _footer = new byte[0x200];
59 | stream.Read(_footer, 0, _footer.Length);
60 | }
61 |
62 | //All done
63 | stream.Close();
64 | }
65 |
66 | public bool FindPattern(byte?[] pattern, out FirmwareSection section, out int address)
67 | {
68 | return FindPattern(pattern, 0, out section, out address);
69 | }
70 |
71 | public bool FindPattern(byte?[] pattern, int startingOffset, out FirmwareSection section, out int address)
72 | {
73 | bool ret = false;
74 | section = FirmwareSection.Base;
75 | address = 0;
76 |
77 | foreach (var s in _sections)
78 | {
79 | for (int i = startingOffset; i < s.Value.Length; i++)
80 | {
81 | bool match = true;
82 | for (int j = 0; j < pattern.Length; j++)
83 | {
84 | if (((i + j) >= s.Value.Length) ||
85 | ((s.Value[i + j] != pattern[j]) && (pattern[j].HasValue)))
86 | {
87 | match = false;
88 | break;
89 | }
90 | }
91 |
92 | if (match)
93 | {
94 | section = s.Key;
95 | address = i;
96 | ret = true;
97 | break;
98 | }
99 | }
100 |
101 | if (ret)
102 | {
103 | break;
104 | }
105 | }
106 |
107 | return ret;
108 | }
109 |
110 | public int FindLastFreeChunk(FirmwareSection section)
111 | {
112 | int ret = -1;
113 |
114 | if (_sections.ContainsKey(section))
115 | {
116 | var data = _sections[section];
117 | var repeating = data[data.Length - 1];
118 | ret = data.Length - 2;
119 |
120 | while (data[ret] == repeating)
121 | {
122 | ret--;
123 | if (ret < 0)
124 | {
125 | break;
126 | }
127 | }
128 | }
129 |
130 | return ++ret;
131 | }
132 |
133 | public void Save(string fileName)
134 | {
135 | var output = new FileStream(fileName, FileMode.Create);
136 | output.Write(_header, 0, _header.Length);
137 | foreach (var section in _sections.OrderBy(t => t.Key))
138 | {
139 | output.Write(section.Value, 0, section.Value.Length);
140 | }
141 |
142 | if (_footer != null)
143 | {
144 | output.Write(_footer, 0, _footer.Length);
145 | }
146 |
147 | output.Close();
148 | }
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/Injector/Injector/FirmwareSection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Injector
8 | {
9 | public enum FirmwareSection
10 | {
11 | None = -2,
12 | Base = -1,
13 | Section0 = 0x00,
14 | Section1 = 0x01,
15 | Section2 = 0x02,
16 | Section3 = 0x03,
17 | Section4 = 0x04,
18 | Section5 = 0x05,
19 | Section6 = 0x06,
20 | Section7 = 0x07,
21 | Section8 = 0x08,
22 | Section9 = 0x09,
23 | SectionA = 0x0A,
24 | SectionB = 0x0B,
25 | SectionC = 0x0C,
26 | SectionD = 0x0D,
27 | SectionE = 0x0E,
28 | SectionF = 0x0F
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Injector/Injector/Injector.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {41480B6F-9051-43D1-9484-30A265D09D5D}
8 | Exe
9 | Properties
10 | Injector
11 | Injector
12 | v4.0
13 | 512
14 |
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | ..\..\tools\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | ..\..\tools\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
61 |
--------------------------------------------------------------------------------
/Injector/Injector/Injector.csproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | /firmware=C:\Users\Brandon\Documents\GitHub\PS2251-03\BINs\FW03FF01V10353M.BIN /output=free.txt /action=FindFreeBlock
5 |
6 |
--------------------------------------------------------------------------------
/Injector/Injector/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("DoPatch")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Toshiba")]
12 | [assembly: AssemblyProduct("DoPatch")]
13 | [assembly: AssemblyCopyright("Copyright © Toshiba 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("16a14751-01cb-4cb0-a3d1-7835d24f4711")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Injector/Injector/Startup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Reflection;
6 | using System.Security.Cryptography;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace Injector
11 | {
12 | class Startup
13 | {
14 | private static string _firmwareImage;
15 | private static string _outputFile;
16 | private static FirmwareSection _section = FirmwareSection.None;
17 | private static Dictionary _codeFiles;
18 | private static Dictionary _rstFiles;
19 |
20 | internal enum Action
21 | {
22 | None,
23 | GenerateHFile,
24 | FindFreeBlock,
25 | ApplyPatches
26 | }
27 |
28 | internal enum ExitCode
29 | {
30 | Success = 0,
31 | Failure = 1
32 | }
33 |
34 | static void Main(string[] args)
35 | {
36 | try
37 | {
38 | _codeFiles = new Dictionary();
39 | _rstFiles = new Dictionary();
40 |
41 | //Assume success to start with
42 | Environment.ExitCode = (int)ExitCode.Success;
43 |
44 | var action = Action.None;
45 |
46 | //Parse command line arguments
47 | foreach (var arg in args)
48 | {
49 | var parts = arg.TrimStart(new char[] { '/' }).Split(new char[] { '=' },
50 | StringSplitOptions.RemoveEmptyEntries);
51 | switch (parts[0].ToLower())
52 | {
53 | case "action":
54 | {
55 | action = (Action)Enum.Parse(typeof(Action), parts[1]);
56 | Console.WriteLine("Action: " + action.ToString());
57 | break;
58 | }
59 | case "section":
60 | {
61 | _section = (FirmwareSection)Enum.Parse(typeof(FirmwareSection), parts[1]);
62 | Console.WriteLine("Section: " + _section.ToString());
63 | break;
64 | }
65 | case "firmware":
66 | {
67 | _firmwareImage = parts[1];
68 | Console.WriteLine("Firmware image: " + _firmwareImage);
69 | _CheckFirmwareImage();
70 | break;
71 | }
72 | case "output":
73 | {
74 | _outputFile = parts[1];
75 | Console.WriteLine("Output file: " + _outputFile);
76 | break;
77 | }
78 | default:
79 | {
80 | _ParseFileNames(ref _codeFiles, "code", parts[0], parts[1]);
81 | _ParseFileNames(ref _rstFiles, "rst", parts[0], parts[1]);
82 | break;
83 | }
84 | }
85 | }
86 |
87 | //Firmware image file name is always required
88 | if (string.IsNullOrEmpty(_firmwareImage))
89 | {
90 | throw new ArgumentException("No/Invalid firmware image file name specified");
91 | }
92 |
93 | switch (action)
94 | {
95 | case Action.GenerateHFile:
96 | {
97 | if (string.IsNullOrEmpty(_outputFile))
98 | {
99 | throw new ArgumentException("No/Invalid output file name specified");
100 | }
101 |
102 | Console.WriteLine("Generating .h file...");
103 |
104 | _GenerateHFile();
105 | break;
106 | }
107 | case Action.ApplyPatches:
108 | {
109 | //Check required arguments for this action
110 |
111 | if (string.IsNullOrEmpty(_outputFile))
112 | {
113 | throw new ArgumentException("No/Invalid output file name specified");
114 | }
115 |
116 | if (_codeFiles.Count == 0)
117 | {
118 | throw new ArgumentException("No code file name(s) specified");
119 | }
120 |
121 | if (_rstFiles.Count == 0)
122 | {
123 | throw new ArgumentException("No/Invalid RST file name specified");
124 | }
125 |
126 | Console.WriteLine("Applying patches...");
127 | _ApplyPatches();
128 | break;
129 | }
130 | case Action.FindFreeBlock:
131 | {
132 | //Check required arguments for this action
133 | if (_section == FirmwareSection.None)
134 | {
135 | throw new ArgumentException("No/Invalid section specified");
136 | }
137 |
138 | Console.WriteLine("Retriving free space...");
139 | _GetFreeSpaceToFile();
140 | break;
141 | }
142 | default:
143 | throw new ArgumentException("No/Invalid action specified");
144 | }
145 |
146 | Console.WriteLine("Done.");
147 | }
148 | catch (Exception ex)
149 | {
150 | //Uh-oh...
151 | Environment.ExitCode = (int)ExitCode.Failure;
152 |
153 | var asm = System.Reflection.Assembly.GetExecutingAssembly();
154 | var asmName = asm.GetName();
155 | Console.WriteLine(asmName.Name + " v" + asmName.Version.ToString(3));
156 | Console.WriteLine("Actions:");
157 | Console.WriteLine("\tGenerateHFile\tGenerates C .h file of common XRAM & function equates.");
158 | Console.WriteLine("\tFindFreeBlock\tWrites amount of free space for a section to file.");
159 | Console.WriteLine("\tApplyPatches\tApplies available patches from code into firmware image.");
160 | Console.WriteLine();
161 | Console.WriteLine("FATAL: " + ex.ToString());
162 | }
163 | }
164 |
165 | private static void _CheckFirmwareImage()
166 | {
167 | var md5 = new MD5CryptoServiceProvider();
168 | var verified = new List();
169 | verified.Add("4C4C0001EC83102C4627D271FF8362A2");
170 |
171 | var hash = BitConverter.ToString(md5.ComputeHash(File.ReadAllBytes(_firmwareImage)))
172 | .Replace("-", string.Empty);
173 | if (!verified.Contains(hash))
174 | {
175 | Console.WriteLine("WARNING! This firmware version has not been " +
176 | "verified to work with these patches.");
177 | }
178 | }
179 |
180 | private static void _ParseFileNames(ref Dictionary files,
181 | string suffix, string name, string value)
182 | {
183 | if (name.ToLower().EndsWith(suffix))
184 | {
185 | var section = FirmwareSection.Base;
186 | int s;
187 |
188 | if (int.TryParse(name.Substring(0, name.Length - suffix.Length), out s))
189 | {
190 | section = (FirmwareSection)s;
191 | }
192 |
193 | files.Add(section, value);
194 | Console.WriteLine(suffix + " " + section.ToString() + " file: " + value);
195 | }
196 | }
197 |
198 | private static Dictionary _GetAddressMap(string fileName)
199 | {
200 | //Read in RST file and its label<->address map
201 | var addressMap = new Dictionary();
202 | var ret = new Dictionary();
203 | var rst = new StreamReader(fileName, ASCIIEncoding.ASCII);
204 |
205 | while (true)
206 | {
207 | var line = rst.ReadLine();
208 | if (line == null)
209 | {
210 | break;
211 | }
212 |
213 | if (line.EndsWith(":"))
214 | {
215 | var parts = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
216 | var label = parts[parts.Length - 1].TrimEnd(':');
217 | var address = parts[0];
218 |
219 | if (label.StartsWith("_"))
220 | {
221 | ret.Add(label, Convert.ToInt32(address, 16));
222 | }
223 | }
224 | }
225 |
226 | rst.Close();
227 |
228 | return ret;
229 | }
230 |
231 | private static void _GenerateHFile()
232 | {
233 | var stream = new StreamWriter(_outputFile);
234 |
235 | //Read in firmware image
236 | var image = new FirmwareImage(_firmwareImage);
237 | image.Open();
238 |
239 | var pattern = new byte?[] { 0x90, 0xF0, 0xB8, 0xE0, //mov DPTR, #0xF0B8 \ movx a, @DPTR
240 | 0x90, null, null, 0xF0, //mov DPTR, #0x???? \ movx @DPTR, a
241 | 0x90, 0xF0, 0xB9, 0xE0 }; //mov DPTR, #0xF0B9 \ movx a, @DPTR \ movx DPTR, #0x????
242 | FirmwareSection section;
243 | int address;
244 | if (image.FindPattern(pattern, out section, out address))
245 | {
246 | var a = image.GetSection(section)[address + 5] << 8;
247 | a |= image.GetSection(section)[address + 6];
248 |
249 | stream.WriteLine(string.Format("__xdata __at 0x{0} BYTE {1};", a.ToString("X04"), "bmRequestType"));
250 | stream.WriteLine(string.Format("__xdata __at 0x{0} BYTE {1};", (a + 1).ToString("X04"), "bRequest"));
251 | }
252 |
253 | pattern = new byte?[] { 0x90, null, null, 0xE0, //mov DPTR, #0x???? \ movx a, @DPTR
254 | 0xB4, 0x28 }; //cjne A, #0x28, ????
255 | if (image.FindPattern(pattern, out section, out address))
256 | {
257 | var a = image.GetSection(section)[address + 1] << 8;
258 | a |= image.GetSection(section)[address + 2];
259 | stream.WriteLine(string.Format("__xdata __at 0x{0} BYTE {1}[16];", a.ToString("X04"), "scsi_cdb"));
260 |
261 | stream.WriteLine(string.Format("#define {0} 0x{1}", "DEFAULT_READ_SECTOR_HANDLER", (address + 7).ToString("X04")));
262 | pattern = new byte?[] { 0x90, (byte)((a >> 8) & 0xFF), (byte)(a & 0xFF), //mov DPTR, #scsi_tag
263 | 0xE0, 0x12 }; //mvox A, @DPTR \ lcall 0x????
264 | if (image.FindPattern(pattern, address, out section, out address))
265 | {
266 | stream.WriteLine(string.Format("#define {0} 0x{1}", "DEFAULT_CDB_HANDLER", address.ToString("X04")));
267 | }
268 | }
269 |
270 | pattern = new byte?[] { 0x90, 0xF2, 0x1C, //mov DPTR, #0xF21C
271 | 0x74, 0x55, 0xF0, //mov A, #0x55 \ movx @DPTR, A
272 | 0x74, 0x53, 0xF0, //mov A, #0x53 \ movx @DPTR, A
273 | 0x74, 0x42, 0xF0, //mov A, #0x42 \ movx @DPTR, A
274 | 0x74, 0x53, 0xF0, //mov A, #0x53 \ movx @DPTR, A
275 | 0x90 }; //mov DPTR, #0x????
276 | if (image.FindPattern(pattern, out section, out address))
277 | {
278 | var a = image.GetSection(section)[address + pattern.Length] << 8;
279 | a |= image.GetSection(section)[address + pattern.Length + 1];
280 |
281 | stream.WriteLine(string.Format("__xdata __at 0x{0} BYTE {1}[4];", (a - 3).ToString("X04"), "scsi_tag"));
282 | }
283 |
284 | pattern = new byte?[] { 0xC0, 0xE0, 0xC0, 0x83, 0xC0, 0x82, //push ACC \ push DPH \ push DPL
285 | 0x90, 0xF0, 0x20, 0xE0, //mov DPTR, #0xF020 \ movx A, @DPTR
286 | 0x30, 0xE1, null, //jnb ACC.1, ????
287 | 0x12, null, null, 0x90 }; //lcall ???? \ mov DPTR, #0x????
288 | if (image.FindPattern(pattern, out section, out address))
289 | {
290 | var a = image.GetSection(section)[address + 17] << 8;
291 | a |= image.GetSection(section)[address + 18];
292 |
293 | stream.WriteLine(string.Format("__xdata __at 0x{0} BYTE {1};", a.ToString("X04"), "FW_EPIRQ"));
294 | }
295 |
296 | stream.WriteLine(string.Format("__xdata __at 0x{0} BYTE {1}[1024];", "B000", "EPBUF"));
297 |
298 | stream.Close();
299 | }
300 |
301 | private static void _GetFreeSpaceToFile()
302 | {
303 | //Read in firmware image
304 | var image = new FirmwareImage(_firmwareImage);
305 | image.Open();
306 |
307 | File.WriteAllText(_outputFile, "0x" + image.FindLastFreeChunk(_section).ToString("X04"));
308 | }
309 |
310 | private static void _ApplyPatches()
311 | {
312 | //Read in firmware image
313 | var image = new FirmwareImage(_firmwareImage);
314 | image.Open();
315 |
316 | //Read in the RST files
317 | var maps = new Dictionary>();
318 | foreach (var file in _rstFiles)
319 | {
320 | maps.Add(file.Key, _GetAddressMap(file.Value));
321 | }
322 |
323 | //Find how much free space is left on each page
324 | var emptyStart = new Dictionary();
325 | for (FirmwareSection i = FirmwareSection.Base; i < FirmwareSection.SectionF; i++)
326 | {
327 | emptyStart.Add(i, image.FindLastFreeChunk(i));
328 | }
329 |
330 | //Embed our code files into the firmware image
331 | foreach (var file in _codeFiles)
332 | {
333 | var code = File.ReadAllBytes(file.Value);
334 | Array.Copy(code, 0, image.GetSection(file.Key), emptyStart[file.Key], code.Length);
335 | emptyStart[file.Key] += code.Length;
336 | }
337 |
338 | //Find the off-page call stubs
339 | var stubs = new Dictionary();
340 | int saddr = 0;
341 | var spattern = new byte?[] { 0xC0, 0x5B, 0x74, 0x08, //push RAM_5B \ mov A, #8
342 | 0xC0, 0xE0, 0xC0, 0x82, 0xC0, 0x83, //push ACC \ push DPL \ push DPH
343 | 0x75, 0x5B }; //mov RAM_5B, #0x??
344 | FirmwareSection fs;
345 | for (FirmwareSection i = FirmwareSection.Section0; i <= FirmwareSection.SectionF; i++)
346 | {
347 | if (image.FindPattern(spattern, saddr, out fs, out saddr))
348 | {
349 | stubs.Add(i, saddr);
350 | saddr += spattern.Length; //move ahead so we can find the next stub
351 | }
352 | }
353 |
354 | //Hook into control request handling
355 | foreach (var map in maps)
356 | {
357 | if (map.Value.ContainsKey("_HandleControlRequest"))
358 | {
359 | var address = map.Value["_HandleControlRequest"];
360 | var pattern = new byte?[] { 0x12, null, null, //lcall #0x????
361 | 0x90, 0xFE, 0x82, 0xE0, //mov DPTR, #0xFE82 \ movx A, @DPTR
362 | 0x54, 0xEF, 0xF0 }; //anl A, #0xEF \ movx @DPTR, A
363 | FirmwareSection s;
364 | int a;
365 | if (image.FindPattern(pattern, out s, out a))
366 | {
367 | a = (image.GetSection(s)[a + 1] << 8) | image.GetSection(s)[a + 2];
368 |
369 | image.GetSection(s)[a + 1] = (byte)((address >> 8) & 0xFF);
370 | image.GetSection(s)[a + 2] = (byte)(address & 0xFF);
371 | if (map.Key != FirmwareSection.Base)
372 | {
373 | image.GetSection(s)[a + 4] = (byte)((stubs[map.Key] >> 8) & 0xFF);
374 | image.GetSection(s)[a + 5] = (byte)(stubs[map.Key] & 0xFF);
375 | }
376 | }
377 | break;
378 | }
379 | }
380 |
381 | //Replace the EP interrupt vector, handling all incoming and outgoing non-control data
382 | foreach (var map in maps)
383 | {
384 | //This part must be on the base page
385 | if (map.Value.ContainsKey("_EndpointInterrupt"))
386 | {
387 | var address = map.Value["_EndpointInterrupt"];
388 | var s = image.GetSection(FirmwareSection.Base);
389 | s[0x0014] = (byte)((address >> 8) & 0xFF);
390 | s[0x0015] = (byte)(address & 0xFF);
391 | }
392 |
393 | if (map.Value.ContainsKey("_HandleEndpointInterrupt"))
394 | {
395 | //Find the base page location to patch
396 | var pattern = new byte?[] { 0x30, 0xE1, null, //jnb ACC.1, #0x????
397 | 0x12, null, null, //lcall #0x????
398 | 0x90, 0xFE, 0x82, 0xE0, //mov DPTR, #0xFE82 \ movx A, @DPTR
399 | 0x54, 0xEF, 0xF0 }; //anl A, #0xEF \ movx @DPTR, A
400 | FirmwareSection ps;
401 | int pa;
402 | if (image.FindPattern(pattern, out ps, out pa))
403 | {
404 | //Create off-page stub for this if necessary
405 | var address = map.Value["_HandleEndpointInterrupt"];
406 | var stubAddress = address;
407 | if (map.Key != FirmwareSection.Base)
408 | {
409 | stubAddress = emptyStart[FirmwareSection.Base];
410 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = 0x90;
411 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = (byte)((address >> 8) & 0xFF);
412 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = (byte)(address & 0xFF);
413 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = 0x02;
414 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = (byte)((stubs[map.Key] >> 8) & 0xFF);
415 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = (byte)(stubs[map.Key] & 0xFF);
416 | }
417 |
418 | //Apply the patch
419 | var s = image.GetSection(ps);
420 | s[pa + 0] = 0x60;
421 | s[pa + 1] = 0x0B;
422 | s[pa + 2] = 0x00;
423 | s[pa + 4] = (byte)((stubAddress >> 8) & 0xFF);
424 | s[pa + 5] = (byte)(stubAddress & 0xFF);
425 | for (int i = 0; i < 7; i++)
426 | {
427 | s[pa + 6 + i] = 0x00;
428 | }
429 | }
430 | }
431 | }
432 |
433 | //Apply CDB-handling code
434 | foreach (var map in maps)
435 | {
436 | if (map.Value.ContainsKey("_HandleCDB"))
437 | {
438 | var pattern = new byte?[] { 0x90, null, null, 0xE0, //mov DPTR, #0x???? \ movx a, @DPTR
439 | 0xB4, 0x28 }; //cjne A, #0x28, ????
440 | FirmwareSection ps;
441 | int pa;
442 | if (image.FindPattern(pattern, out ps, out pa))
443 | {
444 | //Create off-page stub for this if necessary
445 | var address = map.Value["_HandleCDB"];
446 | var stubAddress = address;
447 | if (map.Key != FirmwareSection.Base)
448 | {
449 | stubAddress = emptyStart[FirmwareSection.Base];
450 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = 0x90;
451 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = (byte)((address >> 8) & 0xFF);
452 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = (byte)(address & 0xFF);
453 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = 0x02;
454 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = (byte)((stubs[map.Key] >> 8) & 0xFF);
455 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = (byte)(stubs[map.Key] & 0xFF);
456 | }
457 |
458 | //Apply the patch
459 | var s = image.GetSection(FirmwareSection.Base);
460 | s[pa + 0] = 0x02;
461 | s[pa + 1] = (byte)((stubAddress >> 8) & 0xFF);
462 | s[pa + 2] = (byte)(stubAddress & 0xFF);
463 | }
464 | }
465 | }
466 |
467 | //Add our own code to the infinite loop
468 | foreach (var map in maps)
469 | {
470 | if (map.Value.ContainsKey("_LoopDo"))
471 | {
472 | var pattern = new byte?[] { 0x90, null, null, 0xE0, //mov DPTR, #0x???? \ movx A, @DPTR
473 | 0xB4, 0x01, null, //cjne A, #1, #0x????
474 | 0x90, 0xF0, 0x79 }; //mov DPTR, #0xF079
475 | FirmwareSection ps;
476 | int pa;
477 | if (image.FindPattern(pattern, out ps, out pa))
478 | {
479 | //Create off-page stub for this if necessary
480 | var address = map.Value["_LoopDo"];
481 | var stubAddress = address;
482 | if (map.Key != FirmwareSection.Base)
483 | {
484 | stubAddress = emptyStart[FirmwareSection.Base];
485 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = 0x90;
486 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = (byte)((address >> 8) & 0xFF);
487 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = (byte)(address & 0xFF);
488 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = 0x02;
489 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = (byte)((stubs[map.Key] >> 8) & 0xFF);
490 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = (byte)(stubs[map.Key] & 0xFF);
491 | }
492 |
493 | var s = image.GetSection(ps);
494 | var loopDoStart = emptyStart[FirmwareSection.Base];
495 | s[emptyStart[FirmwareSection.Base]++] = 0x12;
496 | s[emptyStart[FirmwareSection.Base]++] = (byte)((stubAddress >> 8) & 0xFF);
497 | s[emptyStart[FirmwareSection.Base]++] = (byte)(stubAddress & 0xFF);
498 | s[emptyStart[FirmwareSection.Base]++] = 0x90;
499 | s[emptyStart[FirmwareSection.Base]++] = image.GetSection(ps)[pa + 1];
500 | s[emptyStart[FirmwareSection.Base]++] = image.GetSection(ps)[pa + 2];
501 | s[emptyStart[FirmwareSection.Base]++] = 0x22;
502 | s[pa + 0] = 0x12;
503 | s[pa + 1] = (byte)((loopDoStart >> 8) & 0xFF);
504 | s[pa + 2] = (byte)(loopDoStart & 0xFF);
505 | }
506 | }
507 | }
508 |
509 | //Apply password patch code
510 | foreach (var map in maps)
511 | {
512 | if (map.Value.ContainsKey("_PasswordReceived"))
513 | {
514 | var pattern = new byte?[] { 0x90, 0xF2, 0x4C, 0xF0, 0xA3, //mov DPTR, #0xF24C \ movx @DPTR, A \ inc DPTR
515 | 0xC0, 0x83, 0xC0, 0x82, 0x12, //push DPH \ push DPL
516 | null, null, 0xD0, 0x82, 0xD0, 0x83, 0xF0, //lcall #0x???? \ pop DPL \ pop DPH \ movx @DPTR, A
517 | 0x90, 0xF2, 0x53, 0x74, 0x80, 0xF0, //mov DPTR, #0xF253 \ mov A, #0x80 \ movx @DPTR, A
518 | 0x90, 0xF2, 0x53, 0xE0, //mov DPTR, #0xF253 \ movx A, @DPTR
519 | 0x30, 0xE7, null, //jnb ACC.7, #0x????
520 | 0x12, null, null, 0x40, null, //lcall #0x???? \ jc #0x????
521 | 0x12, null, null, 0x7F, 0x00, 0x22 }; //lcall #0x???? \ mov R7, #0 \ ret
522 | FirmwareSection ps;
523 | int pa;
524 | if (image.FindPattern(pattern, out ps, out pa))
525 | {
526 | //Create off-page stub for this if necessary
527 | var address = map.Value["_PasswordReceived"];
528 | var stubAddress = address;
529 | if (map.Key != FirmwareSection.Base)
530 | {
531 | stubAddress = emptyStart[FirmwareSection.Base];
532 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = 0x90;
533 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = (byte)((address >> 8) & 0xFF);
534 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = (byte)(address & 0xFF);
535 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = 0x02;
536 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = (byte)((stubs[map.Key] >> 8) & 0xFF);
537 | image.GetSection(FirmwareSection.Base)[emptyStart[FirmwareSection.Base]++] = (byte)(stubs[map.Key] & 0xFF);
538 | }
539 |
540 | //Apply the patch
541 | pa += 0x24;
542 | var passRecvdStart = emptyStart[ps] + (ps == FirmwareSection.Base ? 0x0000 : 0x5000);
543 | image.GetSection(ps)[emptyStart[ps]++] = 0x12;
544 | image.GetSection(ps)[emptyStart[ps]++] = image.GetSection(ps)[pa + 0];
545 | image.GetSection(ps)[emptyStart[ps]++] = image.GetSection(ps)[pa + 1];
546 | image.GetSection(ps)[emptyStart[ps]++] = 0x02;
547 | image.GetSection(ps)[emptyStart[ps]++] = (byte)((stubAddress >> 8) & 0xFF);
548 | image.GetSection(ps)[emptyStart[ps]++] = (byte)(stubAddress & 0xFF);
549 | image.GetSection(ps)[pa + 0] = (byte)((passRecvdStart >> 8) & 0xFF);
550 | image.GetSection(ps)[pa + 1] = (byte)(passRecvdStart & 0xFF);
551 | }
552 | }
553 | }
554 |
555 | //Write the resulting file out
556 | image.Save(_outputFile);
557 | }
558 | }
559 | }
560 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Adam Caudill, Brandon Wilson
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Phison 2251-03 (2303) Custom Firmware & Existing Firmware Patches
2 | ========
3 |
4 | This repository contains the following items:
5 | - `DriveCom` -- PC C# application to communicate with Phison drives.
6 | - `EmbedPayload` -- PC C# application to embed Rubber Ducky inject.bin key scripts into custom firmware for execution on the drive.
7 | - `Injector` -- PC C# application to extract addresses/equates from firmware as well as embed patching code into the firmware.
8 | - `firmware` -- this is 8051 custom firmware written in C.
9 | - `patch` -- this is a collection of 8051 patch code written in C.
10 |
11 | Releases have the following items:
12 | - `patch` -- this is a collection of 8051 patch code written in C.
13 | - `tools` -- these are the compiled binaries of all the tools.
14 | - `CFW.bin` -- this is custom firmware set up to send an embedded HID payload.
15 |
16 | Take note that the firmware patches have only been tested against PS2251-03 firmware version _1.03.53_ (which is for an 8K eD3 NAND flash chip). They may work for others, but be careful.
17 |
18 | As long as you are using the correct firmware image for your controller version and NAND chip, there is no harm in downgrading to an earlier version (such as from 1.10.53).
19 |
20 | **WARNING: This is experimental software. Use on unsupported devices, or even on supported devices, may cause loss of data, or even permananent damage to devices. Use at your own risk.**
21 |
22 | ## Getting Started
23 | *See [Known Supported Devices](https://github.com/adamcaudill/Psychson/wiki/Known-Supported-Devices) for information on supported devices; use on an unsupported device may cause permanent damage to the device.*
24 |
25 | To get started, you'll need to obtain a burner image, which is the 8051 executable responsible for flashing firmware to the drive.
26 |
27 | See [Obtaining a Burner Image](https://github.com/adamcaudill/Psychson/wiki/Obtaining-a-Burner-Image) on the wiki for more information.
28 |
29 | ## Build Environment
30 | To patch or modify existing firmware, you must first set up a build environment. See [Setting Up the Environment](https://github.com/adamcaudill/Psychson/wiki/Setting-Up-the-Environment) on the wiki for more information.
31 |
32 | At a minimum, SDCC needs to be installed to `C:\Program Files\SDCC`.
33 |
34 | ## Dumping Firmware
35 | Run DriveCom, passing in the drive letter representing the drive you want to flash, the path of the burner image you obtained, and the destination path for the firmware image:
36 |
37 | tools\DriveCom.exe /drive=E /action=DumpFirmware /burner=BN03V104M.BIN /firmware=fw.bin
38 |
39 | where `E` is the drive letter, `BN03V104M.BIN` is the path to the burner image, and `fw.bin` is the resulting firmware dump.
40 |
41 | Currently, only 200KB firmware images can be dumped (which is what the [Patriot 8GB Supersonic Xpress](http://www.amazon.com/gp/product/B005EWB15W/) drive uses).
42 |
43 | ## Flashing Custom Firmware
44 | Run `DriveCom`, passing in the drive letter representing the drive you want to flash, the path of the burner image you obtained, and the path of the firmware image you want to flash:
45 |
46 | tools\DriveCom.exe /drive=E /action=SendFirmware /burner=BN03V104M.BIN /firmware=fw.bin
47 |
48 | where `E` is the drive letter, `BN03V104M.BIN` is the path to the burner image, and `fw.bin` is the path to the firmware image.
49 |
50 | ## Running Demo 1 (HID Payload)
51 | Create a key script in [Rubber Ducky format](https://github.com/hak5darren/USB-Rubber-Ducky/wiki/Payloads), then use [Duckencoder](https://code.google.com/p/ducky-decode/downloads/detail?name=DuckEncoder_2.6.3.zip&can=2&q=) to create an `inject.bin` version of it:
52 |
53 | java -jar duckencoder.java -i keys.txt -o inject.bin
54 |
55 | where `keys.txt` is the path to your key script.
56 |
57 | You may notice the delays are not quite the same between the Rubber Ducky and the drive -- you may need to adjust your scripts to compensate.
58 |
59 | (These tools are available from https://code.google.com/p/ducky-decode/.)
60 |
61 | Once you have an `inject.bin` file, embed it into the custom firmware with:
62 |
63 | copy CFW.bin hid.bin
64 | tools\EmbedPayload.exe inject.bin hid.bin
65 |
66 | where `inject.bin` is the path to your inject.bin file, and `hid.bin` is the path to the HID payload custom firmware.
67 |
68 | (Notice that the firmware image is copied, and the payload is embedded into the copy -- this is because the payload can only be embedded once, so the original `CFW.bin` must remain intact.)
69 |
70 | You can now flash the firmware to your drive with:
71 |
72 | tools\DriveCom.exe /drive=E /action=SendFirmware /burner=BN03V104M.BIN /firmware=hid.bin
73 |
74 | where `E` is the drive letter representing your drive, `BN03V104M.BIN` is the path to your burner image, and `hid.bin` is the path to the HID payload custom firmware.
75 |
76 | *Huge thanks to the [Hak5](http://hak5.org/) team for their work on the excellent [USB Rubber Ducky](https://hakshop.myshopify.com/collections/usb-rubber-ducky/products/usb-rubber-ducky-deluxe)!*
77 |
78 | ## Running Demo 2 (Hidden Partition Patch)
79 | First, determine the number of logical blocks (sectors) your drive has with the following command:
80 |
81 | tools\DriveCom.exe /drive=E /action=GetNumLBAs
82 |
83 | Go into the `patch` directory and modify `base.c` to disable all other patches, and enable the hidden partition patch:
84 |
85 | //#define FEATURE_CHANGE_PASSWORD
86 |
87 | #define FEATURE_EXPOSE_HIDDEN_PARTITION
88 |
89 | Then modify the `NUM_LBAS` define to the number of logical blocks on your drive:
90 |
91 | #define NUM_LBAS 0xE6C980UL //this needs to be even! (round down)
92 |
93 | Make sure you round down to an even number, and it couldn't hurt to subtract a few first, in case a few blocks go bad over time. (For example, if the number of LBAs was `0xE6C981`, you might reduce it to `0xE6C940`.)
94 |
95 | Place the firmware image you want to patch into the `patch` directory and name it `fw.bin`.
96 |
97 | Go to the `patch` directory and run `build.bat`. It will produce a file at `patch\bin\fw.bin` -- this is the modified firmware image.
98 |
99 | You can now flash this file to your drive.
100 |
101 | After flashing, Windows may be confused, as it now only sees half of the partition it once did -- it may ask you to format the first time you view either the public or hidden halves of the drive. This is normal.
102 |
103 | ## Running Demo 3 (Password Patch)
104 | Go into the `patch` directory and modify `base.c` to disable all other patches, and enable the password patch:
105 |
106 | #define FEATURE_CHANGE_PASSWORD
107 |
108 | //#define FEATURE_EXPOSE_HIDDEN_PARTITION
109 |
110 | Place the firmware image you want to patch into the `patch` directory and name it `fw.bin`.
111 |
112 | Go to the `patch` directory and run `build.bat`. It will produce a file at `patch\bin\fw.bin` -- this is the modified firmware image.
113 |
114 | You can now flash this file to your drive.
115 |
116 | ## Running No Boot Mode Patch
117 | Go into the `patch` directory and modify `base.c` to disable all other patches, and enable the no boot patch:
118 |
119 | //#define FEATURE_CHANGE_PASSWORD
120 | //#define FEATURE_EXPOSE_HIDDEN_PARTITION
121 | #define FEATURE_PREVENT_BOOT
122 |
123 | Place the firmware image you want to patch into the `patch` directory and name it `fw.bin`.
124 |
125 | Go to the `patch` directory and run `build.bat`. It will produce a file at `patch\bin\fw.bin` -- this is the modified firmware image.
126 |
127 | You can now flash this file to your drive. Once flashed to your device, it will no longer act on the command to jump to boot mode. To update the firmware again will require [shorting pins](https://github.com/adamcaudill/Psychson/blob/master/docs/PinsToShortUponPlugInForBootMode.jpg) on the controller. To make it impossible* to update, after flashing this patch coat the device with epoxy.
128 |
129 | * *Within reason; it may be possible to get to boot mode via an exploit or other non-standard method.*
130 |
131 | #### Converting to Mode 7
132 | You can run the `ModeConverterFF01.exe` application (see [Useful Links](https://github.com/adamcaudill/Psychson/wiki/Useful-Links)) to split the drive into public and secure partitions, or restore the original (mode 3) functionality.
133 |
134 | After converting to mode 7, you should be able to set, change, or disable the secure partition password with the `USB DISK Pro LOCK` utility.
135 |
136 | ## Building From Source
137 | Modify the C files in the `firmware` directory for custom firmware, or the `patch` directory for the firmware patches, then run the `build.bat` file in the appropriate directory.
138 |
139 | Once it has built successfully, use DriveCom to flash the resulting file (`bin\fw.bin`) to your drive:
140 |
141 | tools\DriveCom.exe /drive=E /action=SendFirmware /burner=BN03V104M.BIN /firmware=firmware\bin\fw.bin
142 |
143 | ...or...
144 |
145 | tools\DriveCom.exe /drive=E /action=SendFirmware /burner=BN03V104M.BIN /firmware=patch\bin\fw.bin
146 |
147 | ## Questions? Comments? Complaints?
148 |
149 | Unfortunately this isn't the most straightforward process at the moment, so if you have questions, open an [issue](https://github.com/adamcaudill/Psychson/issues) and we'll do our best to help (and update the readme/wiki).
150 |
--------------------------------------------------------------------------------
/docs/PinsToShortUponPlugInForBootMode.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brandonlw/Psychson/4522989aac27aada5f522675b33a2bde63a13b30/docs/PinsToShortUponPlugInForBootMode.jpg
--------------------------------------------------------------------------------
/firmware/build.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | REM Set things up and create bin directory if necessary.
4 | SETLOCAL ENABLEDELAYEDEXPANSION
5 | SET BUILD_FILES=
6 | IF NOT EXIST bin\NUL MKDIR bin
7 |
8 | REM Build each file in the list.
9 | FOR %%A IN (
10 | main
11 | timers
12 | usb
13 | control
14 | scsi
15 | ) DO (
16 | ECHO *** Building %%A.c...
17 | sdcc --model-small -mmcs51 -pdefcpu -c -obin\%%A.rel %%A.c
18 | IF ERRORLEVEL 1 GOTO ERRORS
19 | SET "BUILD_FILES=!BUILD_FILES! bin\%%A.rel"
20 | )
21 |
22 | REM Build Intel Hex and BIN versions of combined file.
23 | sdcc --xram-loc 0x6000 -o bin\output.hex %BUILD_FILES%
24 | IF ERRORLEVEL 1 GOTO ERRORS
25 | makebin -p bin\output.hex bin\output.bin
26 |
27 | REM Create firmware and burner images from templates.
28 | copy /y ..\templates\FWdummy.bin bin\fw.bin > NUL
29 | copy /y ..\templates\BNdummy.bin bin\bn.bin > NUL
30 | ..\tools\sfk partcopy bin\output.bin -fromto 0 -1 bin\fw.bin 512 -yes > NUL
31 | ..\tools\sfk partcopy bin\output.bin -fromto 0 -1 bin\bn.bin 512 -yes > NUL
32 |
33 | GOTO END
34 |
35 | :ERRORS
36 | ECHO *** There were errors^^! ***
37 |
38 | :END
39 | ECHO *** Done.
40 |
41 | ENDLOCAL
42 |
--------------------------------------------------------------------------------
/firmware/control.c:
--------------------------------------------------------------------------------
1 | #include "defs.h"
2 | #include "usb.h"
3 | #include "timers.h"
4 |
5 | static const BYTE deviceDescriptor[] = { 0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
6 | 0xFE, 0x13, 0x01, 0x52, 0x10, 0x01, 0x00, 0x00, 0x00, 0x01 };
7 | static const BYTE configDescriptor[] = { 0x09, 0x02, sizeof(configDescriptor) & 0xFF, sizeof(configDescriptor) >> 8, 0x02, 0x01, 0x00, 0x80, 0x4B,
8 | 0x09, 0x04, 0x00, 0x00, 0x03, 0x08, 0x06, 0x50, 0x00,
9 | 0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00,
10 | 0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00,
11 | 0x07, 0x05, 0x83, 0x03, 0x08, 0x00, 0x00,
12 | 0x09, 0x04, 0x01, 0x00, 0x02, 0x03, 0x01, 0x01, 0x00,
13 | 0x09, 0x21, 0x01, 0x01, 0x00, 0x01, 0x22,
14 | sizeof(HIDreportDescriptor) & 0xFF,
15 | sizeof(HIDreportDescriptor) >> 8,
16 | 0x07, 0x05, 0x83, 0x03, 0x08, 0x00, 0x01,
17 | //This is a dummy endpoint to make the descriptor != 0x40, because the controller is stupid.
18 | 0x07, 0x05, 0x04, 0x03, 0x08, 0x00, 0x01 };
19 | static const BYTE HIDreportDescriptor[] = { 0x05, 0x01, 0x09, 0x06, 0xA1, 0x01, 0x05, 0x07,
20 | 0x19, 0xE0, 0x29, 0xE7, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01,
21 | 0x95, 0x08, 0x81, 0x02, 0x95, 0x01, 0x75, 0x08, 0x81, 0x01,
22 | 0x95, 0x05, 0x75, 0x01, 0x05, 0x08, 0x19, 0x01, 0x29, 0x05,
23 | 0x91, 0x02, 0x95, 0x01, 0x75, 0x03, 0x91, 0x01, 0x95, 0x06,
24 | 0x75, 0x08, 0x15, 0x00, 0x25, 0x65, 0x05, 0x07, 0x19, 0x00,
25 | 0x29, 0x65, 0x81, 0x00, 0xC0 };
26 | static const BYTE deviceQualifierDescriptor[] = { 0x0A, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00 };
27 |
28 | void EP0ACK()
29 | {
30 | EP0CS = bmEP0ACK;
31 | }
32 |
33 | static BYTE SetAddress()
34 | {
35 | BYTE ret = FALSE;
36 |
37 | if (wValue < 0x7F)
38 | {
39 | EP0ACK();
40 | ret = TRUE;
41 | }
42 |
43 | return ret;
44 | }
45 |
46 | static BYTE GetDescriptor()
47 | {
48 | BYTE type = (wValue >> 8) & 0xFF;
49 | BYTE i, total;
50 | BYTE ret = FALSE;
51 |
52 | switch (type)
53 | {
54 | case 0x01:
55 | {
56 | for (i = 0; i < 0x12; i++)
57 | {
58 | EP0.fifo = deviceDescriptor[i];
59 | }
60 |
61 | SendControlResponse(wLength < 0x12 ? wLength : 0x12);
62 | ret = TRUE;
63 |
64 | break;
65 | }
66 | case 0x02:
67 | {
68 | total = wLength < sizeof(configDescriptor) ? wLength : sizeof(configDescriptor);
69 | for (i = 0; i < total; i++)
70 | {
71 | EP0.fifo = configDescriptor[i];
72 | }
73 |
74 | SendControlResponse(total);
75 | ret = TRUE;
76 |
77 | break;
78 | }
79 | case 0x06:
80 | {
81 | for (i = 0; i < sizeof(deviceQualifierDescriptor); i++)
82 | {
83 | EP0.fifo = deviceQualifierDescriptor[i];
84 | }
85 |
86 | SendControlResponse(wLength < sizeof(deviceQualifierDescriptor) ? wLength : sizeof(deviceQualifierDescriptor));
87 | ret = TRUE;
88 |
89 | break;
90 | }
91 | case 0x22:
92 | {
93 | for (i = 0; i < sizeof(HIDreportDescriptor); i++)
94 | {
95 | EP0.fifo = HIDreportDescriptor[i];
96 | }
97 |
98 | SendControlResponse(wLength < sizeof(HIDreportDescriptor) ? wLength : sizeof(HIDreportDescriptor));
99 | ret = TRUE;
100 |
101 | break;
102 | }
103 | default:
104 | {
105 | break;
106 | }
107 | }
108 |
109 | return ret;
110 | }
111 |
112 | static BYTE SetConfiguration()
113 | {
114 | BYTE ret = FALSE;
115 |
116 | if (wValue <= 1)
117 | {
118 | EP0ACK();
119 | ret = TRUE;
120 | }
121 |
122 | return ret;
123 | }
124 |
125 | BYTE HandleStandardRequest()
126 | {
127 | switch(bRequest)
128 | {
129 | case 0x05:
130 | {
131 | return SetAddress();
132 | }
133 | case 0x06:
134 | {
135 | return GetDescriptor();
136 | }
137 | case 0x09:
138 | {
139 | return SetConfiguration();
140 | }
141 | default:
142 | {
143 | return FALSE;
144 | }
145 | }
146 | }
147 |
148 | static BYTE GetMaxLUN()
149 | {
150 | EP0.fifo = 0x00;
151 | SendControlResponse(wLength < 0x01 ? wLength : 0x01);
152 |
153 | return TRUE;
154 | }
155 |
156 | BYTE HandleClassRequest()
157 | {
158 | switch(bRequest)
159 | {
160 | case 0x09:
161 | {
162 | EP0CS = 0x05;
163 | return TRUE;
164 | }
165 | case 0x0A:
166 | {
167 | EP0ACK();
168 | return TRUE;
169 | }
170 | case 0xFE:
171 | {
172 | return GetMaxLUN();
173 | }
174 | default:
175 | {
176 | return FALSE;
177 | }
178 | }
179 | }
180 |
181 | BYTE HandleVendorRequest()
182 | {
183 | return FALSE;
184 | }
185 |
--------------------------------------------------------------------------------
/firmware/defs.h:
--------------------------------------------------------------------------------
1 | #ifndef DEFS_H
2 | #define DEFS_H
3 |
4 | #define MSB(word) (BYTE)(((WORD)(word) >> 8) & 0xff)
5 | #define LSB(word) (BYTE)((WORD)(word) & 0xff)
6 |
7 | #define XVAL(addr) (*( __xdata volatile unsigned char *)(addr))
8 | #define IVAL(addr) (*( __idata volatile unsigned char *)(addr))
9 |
10 | typedef unsigned char BYTE;
11 | typedef unsigned short WORD;
12 | typedef unsigned long DWORD;
13 | #define TRUE 1
14 | #define FALSE 0
15 |
16 | #define BANK0_PA 0x008000UL
17 | #define BANK1_VA 0x4000U
18 | #define BANK1_PA 0x00C000UL
19 | #define BANK2_VA 0x6000U
20 | #define BANK2_PA 0x00E000UL
21 |
22 | #define usb_buffer_PA 0x008000UL
23 | #define usb_buffer_VA 0x0000U
24 |
25 | #define USB_VECT 0
26 | #define TMR0_VECT 1
27 | #define EP_VECT 2
28 | #define TMR1_VECT 3
29 | #define COM0_VECT 4
30 |
31 | #define bmAttach 0x80
32 | #define bmSpeed 7
33 | #define bmSuperSpeed 4
34 | #define bmHighSpeed 0
35 | #define bmFullSpeed 1
36 | #define bmSpeedChange 0x80
37 | #define bmEP2IRQ 2
38 | #define bmEP4IRQ 8
39 | #define bmEP0ACK 1
40 | #define bmEP0NAK 2
41 | #define bmEP0IN 4
42 | #define bmEP0STALL 8
43 | #define bmSUDAV 0x80
44 | #define bmSTALL 2
45 |
46 | #define bmNandReady 1
47 |
48 | #define bmNandDma0 0
49 | #define bmNandDma1 0x80
50 | #define bmNandDmaRead 0
51 | #define bmNandDmaWrite 0x40
52 |
53 | #define bmDmaCmd 7
54 | #define bmDmaCopy 2
55 | #define bmDmaFill 4
56 | #define bmDmaWidth8 0
57 | #define bmDmaWidth16 0x40
58 | #define bmDmaWidth32 0x80
59 |
60 | #define bmPRAM 1
61 |
62 | __sfr __at (0x80) P0 ;
63 | __sfr __at (0x90) P1 ;
64 | __sfr __at (0xA0) P2 ;
65 | __sfr __at (0xB0) P3 ;
66 | __sfr __at (0xD0) PSW ;
67 | __sfr __at (0xE0) ACC ;
68 | __sfr __at (0xF0) B ;
69 | __sfr __at (0x81) SP ;
70 | __sfr __at (0x82) DPL ;
71 | __sfr __at (0x83) DPH ;
72 | __sfr __at (0x87) PCON;
73 | __sfr __at (0x88) TCON;
74 | __sfr __at (0x89) TMOD;
75 | __sfr __at (0x8A) TL0 ;
76 | __sfr __at (0x8B) TL1 ;
77 | __sfr __at (0x8C) TH0 ;
78 | __sfr __at (0x8D) TH1 ;
79 | __sfr __at (0xA8) IE ;
80 | __sfr __at (0xB8) IP ;
81 | __sfr __at (0x98) SCON;
82 | __sfr __at (0x99) SBUF;
83 |
84 | /* BIT Register */
85 | /* PSW */
86 | __sbit __at (0xD7) CY ;
87 | __sbit __at (0xD6) AC ;
88 | __sbit __at (0xD5) F0 ;
89 | __sbit __at (0xD4) RS1 ;
90 | __sbit __at (0xD3) RS0 ;
91 | __sbit __at (0xD2) OV ;
92 | __sbit __at (0xD0) P ;
93 |
94 | /* TCON */
95 | __sbit __at (0x8F) TF1 ;
96 | __sbit __at (0x8E) TR1 ;
97 | __sbit __at (0x8D) TF0 ;
98 | __sbit __at (0x8C) TR0 ;
99 | __sbit __at (0x8B) IE1 ;
100 | __sbit __at (0x8A) IT1 ;
101 | __sbit __at (0x89) IE0 ;
102 | __sbit __at (0x88) IT0 ;
103 |
104 | /* IE */
105 | __sbit __at (0xAF) EA ;
106 | __sbit __at (0xAC) ES ;
107 | __sbit __at (0xAB) ET1 ;
108 | __sbit __at (0xAA) EX1 ;
109 | __sbit __at (0xA9) ET0 ;
110 | __sbit __at (0xA8) EX0 ;
111 |
112 | /* IP */
113 | __sbit __at (0xBC) PS ;
114 | __sbit __at (0xBB) PT1 ;
115 | __sbit __at (0xBA) PX1 ;
116 | __sbit __at (0xB9) PT0 ;
117 | __sbit __at (0xB8) PX0 ;
118 |
119 | /* P3 */
120 | __sbit __at (0xB7) RD ;
121 | __sbit __at (0xB6) WR ;
122 | __sbit __at (0xB5) T1 ;
123 | __sbit __at (0xB4) T0 ;
124 | __sbit __at (0xB3) INT1;
125 | __sbit __at (0xB2) INT0;
126 | __sbit __at (0xB1) TXD ;
127 | __sbit __at (0xB0) RXD ;
128 |
129 | /* SCON */
130 | __sbit __at (0x9F) SM0 ;
131 | __sbit __at (0x9E) SM1 ;
132 | __sbit __at (0x9D) SM2 ;
133 | __sbit __at (0x9C) REN ;
134 | __sbit __at (0x9B) TB8 ;
135 | __sbit __at (0x9A) RB8 ;
136 | __sbit __at (0x99) TI ;
137 | __sbit __at (0x98) RI ;
138 |
139 | __xdata __at 0xF000 volatile BYTE REGBANK;
140 | __xdata __at 0xF008 volatile BYTE USBCTL;
141 | __xdata __at 0xF009 volatile BYTE USBSTAT;
142 | __xdata __at 0xF027 volatile BYTE USBIRQ;
143 | __xdata __at 0xF020 volatile BYTE EPIRQ;
144 | __xdata __at 0xF030 volatile BYTE EPIE;
145 | __xdata __at 0xF048 volatile BYTE EP0CS;
146 | __xdata __at 0xF0B8 volatile BYTE SETUPDAT[8];
147 |
148 | typedef struct
149 | {
150 | BYTE r0, r1, r2, r3, r4;
151 | BYTE ptr_l, ptr_m, ptr_h;
152 | BYTE r8, r9;
153 | BYTE offset;
154 | BYTE rB;
155 | BYTE len_l, len_m, len_h;
156 | BYTE rF, r10, r11, r12;
157 | BYTE cs;
158 | BYTE r14, r15, r16, r17, r18, r19;
159 | BYTE fifo_count;
160 | BYTE r1B;
161 | BYTE fifo;
162 | } EPREGS;
163 |
164 | __xdata __at 0xF1C0 volatile EPREGS EP0;
165 | __xdata __at 0xF200 volatile EPREGS EP1;
166 | __xdata __at 0xF240 volatile EPREGS EP2;
167 | __xdata __at 0xF280 volatile EPREGS EP3;
168 | __xdata __at 0xF2C0 volatile EPREGS EP4;
169 |
170 | __xdata __at 0xF608 volatile BYTE NANDCSOUT;
171 | __xdata __at 0xF618 volatile BYTE NANDCSDIR;
172 |
173 | __xdata __at 0xF900 volatile BYTE DMASRCL;
174 | __xdata __at 0xF901 volatile BYTE DMASRCM;
175 | __xdata __at 0xF902 volatile BYTE DMASRCH;
176 | __xdata __at 0xF904 volatile BYTE DMADSTL;
177 | __xdata __at 0xF905 volatile BYTE DMADSTM;
178 | __xdata __at 0xF906 volatile BYTE DMADSTH;
179 | __xdata __at 0xF908 volatile BYTE DMASIZEL;
180 | __xdata __at 0xF909 volatile BYTE DMASIZEM;
181 | __xdata __at 0xF90A volatile BYTE DMASIZEH;
182 | __xdata __at 0xF90C volatile BYTE DMAFILL0;
183 | __xdata __at 0xF90D volatile BYTE DMAFILL1;
184 | __xdata __at 0xF90E volatile BYTE DMAFILL2;
185 | __xdata __at 0xF90F volatile BYTE DMAFILL3;
186 | __xdata __at 0xF930 volatile BYTE DMACMD;
187 |
188 | __xdata __at 0xFA14 volatile BYTE GPIO0DIR;
189 | __xdata __at 0xFA15 volatile BYTE GPIO0OUT;
190 | __xdata __at 0xFA38 volatile BYTE WARMSTATUS;
191 |
192 | __xdata __at 0xFA40 volatile BYTE BANK0PAL;
193 | __xdata __at 0xFA41 volatile BYTE BANK0PAH;
194 | __xdata __at 0xFA42 volatile BYTE BANK1VA;
195 | __xdata __at 0xFA43 volatile BYTE BANK1PAL;
196 | __xdata __at 0xFA44 volatile BYTE BANK1PAH;
197 | __xdata __at 0xFA45 volatile BYTE BANK2VA;
198 | __xdata __at 0xFA46 volatile BYTE BANK2PAL;
199 | __xdata __at 0xFA47 volatile BYTE BANK2PAH;
200 | __xdata __at 0xFA48 volatile BYTE PRAMCTL; //bit 0 set means run from PRAM
201 |
202 | #endif
203 |
--------------------------------------------------------------------------------
/firmware/main.c:
--------------------------------------------------------------------------------
1 | #include "defs.h"
2 | #include "timers.h"
3 | #include "usb.h"
4 |
5 | extern void usb_isr(void) __interrupt USB_VECT;
6 | extern void ep_isr(void) __interrupt EP_VECT;
7 | extern void tmr0isr(void) __interrupt TMR0_VECT;
8 | extern void tmr1isr(void) __interrupt TMR1_VECT;
9 |
10 | #define KEY_DELAY 8192
11 | #define KEY_BUFFER_SIZE 0x2000
12 | static const BYTE keyData[KEY_BUFFER_SIZE] = { /*0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00,
13 | 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xC3,
14 | 0x15, 0x08, 0x00, 0xFF, 0x00, 0xF5, 0x11, 0x00, 0x12, 0x00, 0x17, 0x00, 0x08, 0x00, 0x13,
15 | 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0xFF, 0x00, 0xF5, 0x28, 0x00, 0x00, 0xFF, 0x00, 0xFF,
16 | 0x00, 0xF0, 0x0B, 0x02, 0x08, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0x12, 0x00, 0x2C, 0x00, 0x1A,
17 | 0x02, 0x12, 0x00, 0x15, 0x00, 0x0F, 0x00, 0x07, 0x00, 0x1E, 0x02, 0x1E, 0x02, 0x1E, 0x02,
18 | 0x28, 0x00*/ 0x12, 0x34, 0x56, 0x78 };
19 | int key_index = 0;
20 | volatile BYTE send_keys_enabled = 0;
21 | DWORD wait_counter = KEY_DELAY;
22 | DWORD wait_tick;
23 |
24 | void InitHardware()
25 | {
26 | //Set up RAM mapping just beyond our own code
27 | BANK0PAL = BANK0_PA>>9;
28 | BANK0PAH = BANK0_PA>>17;
29 | BANK1VA = BANK1_VA>>8;
30 | BANK1PAL = BANK1_PA>>9;
31 | BANK1PAH = BANK1_PA>>17;
32 | BANK2VA = BANK2_VA>>8;
33 | BANK2PAL = BANK2_PA>>9;
34 | BANK2PAH = BANK2_PA>>17;
35 |
36 | XVAL(0xF809) = 7;
37 | XVAL(0xF80A) = 0x1F;
38 | XVAL(0xF810) = 0x60;
39 | XVAL(0xF811) = 0;
40 | XVAL(0xF08F) = 0;
41 |
42 | XVAL(0xFA6F) = 0x1F;
43 | XVAL(0xFA60) = 2;
44 | XVAL(0xFA61) = 0;
45 | XVAL(0xFA64) = 0;
46 | XVAL(0xFA65) = 0;
47 | XVAL(0xFA66) = 0;
48 | XVAL(0xFA67) = 0;
49 | XVAL(0xFA62) = 0x0F;
50 | XVAL(0xFA6F) = 0x1F;
51 |
52 | GPIO0DIR &= 0xFD;
53 | GPIO0OUT |= 2;
54 |
55 | XVAL(0xFA21) = 7;
56 | XVAL(0xFA21) &= 0xFB;
57 |
58 | XVAL(0xFA68) &= 0xF7;
59 | XVAL(0xFA69) &= 0xF7;
60 | XVAL(0xFA6A) &= 0xF7;
61 | XVAL(0xFA6B) &= 0xF7;
62 |
63 | XVAL(0xFE00) = 0;
64 | XVAL(0xFE00) = 0x80;
65 |
66 | XVAL(0xFA50) = 0x20;
67 |
68 | XVAL(0xFE01) = 0;
69 | XVAL(0xFE02) = 0x45;
70 |
71 | TMOD = 0x11;
72 | TH0 = 0xF0;
73 | TL0 = 0x5F;
74 | TH1 = 0xF0;
75 | TL1 = 0x5F;
76 | IP = 1;
77 | TCON = 0x10;
78 | SCON = 0;
79 | IE = 0x80;
80 | }
81 |
82 | void DoUSBRelatedInit()
83 | {
84 | if (WARMSTATUS & 2)
85 | {
86 | return;
87 | }
88 |
89 | REGBANK = 5;
90 | XVAL(0xF210) = 0xFF;
91 | XVAL(0xF211) = 2;
92 | XVAL(0xF212) = 3;
93 | XVAL(0xF213) = 0x24;
94 | REGBANK = 0;
95 | XVAL(0xFA6B) = 0xFF;
96 | while((XVAL(0xF014) & 3)==0);
97 | }
98 |
99 | void SendKey(BYTE code, BYTE modifiers)
100 | {
101 | int i;
102 |
103 | EP3.cs = 0;
104 | while (EP3.cs & 0x40);
105 |
106 | EP3.fifo = modifiers;
107 | EP3.fifo = 0;
108 | EP3.fifo = code;
109 | for (i = 0; i < 5; i++)
110 | {
111 | EP3.fifo = 0;
112 | }
113 |
114 | EP3.len_l = 8;
115 | EP3.len_m = 0;
116 | EP3.len_h = 0;
117 | EP3.cs = 0x40;
118 | }
119 |
120 | void main()
121 | {
122 | InitHardware();
123 | DoUSBRelatedInit();
124 | InitUSB();
125 | InitTicks();
126 | InitLED();
127 | LEDBlink();
128 |
129 | while (1)
130 | {
131 | HandleUSBEvents();
132 |
133 | if (wait_tick++ >= KEY_DELAY)
134 | {
135 | if (wait_counter < KEY_DELAY)
136 | {
137 | wait_counter++;
138 | }
139 | }
140 |
141 | if (send_keys_enabled && wait_counter >= KEY_DELAY)
142 | {
143 | if (keyData[key_index])
144 | {
145 | //Send this key, with some padding before, since something's wonky with endpoint 3
146 | SendKey(0x00, 0x00);
147 | SendKey(0x00, 0x00);
148 | SendKey(0x00, 0x00);
149 | SendKey(0x00, 0x00);
150 | SendKey(keyData[key_index], keyData[key_index + 1]);
151 | SendKey(0x00, 0x00);
152 | }
153 | else
154 | {
155 | //Wait a while
156 | wait_counter = 0;
157 | wait_tick = 0;
158 | }
159 |
160 | //Move to next key
161 | key_index += 2;
162 |
163 | //Are we done?
164 | if (key_index >= sizeof(keyData))
165 | {
166 | send_keys_enabled = 0;
167 | }
168 | }
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/firmware/scsi.c:
--------------------------------------------------------------------------------
1 | #include "defs.h"
2 | #include "string.h"
3 | #include "usb.h"
4 |
5 | #define PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E
6 | #define TEST_UNIT_READY 0x00
7 | #define INQUIRY 0x12
8 | #define READ_FORMAT_CAPACITIES 0x23
9 | #define MODE_SENSE 0x1A
10 | #define REQUEST_SENSE 0x03
11 |
12 | #define VENDOR_BOOT 0xBF
13 | #define VENDOR_INFO 0x05
14 | #define VENDOR_CHIPID 0x56
15 | #define CUSTOM_XPEEK 0x06
16 | #define CUSTOM_XPOKE 0x07
17 | #define CUSTOM_IPEEK 0x08
18 | #define CUSTOM_IPOKE 0x09
19 |
20 | BYTE scsi_status;
21 | DWORD scsi_data_residue;
22 | DWORD scsi_transfer_size;
23 | BYTE scsi_tag[4];
24 | BYTE scsi_dir_in;
25 | BYTE scsi_lun;
26 | BYTE scsi_cdb[16];
27 | BYTE scsi_cdb_size;
28 |
29 | BYTE HandleCDB()
30 | {
31 | //Default to returning a bad status
32 | scsi_status = 1;
33 |
34 | switch(scsi_cdb[0])
35 | {
36 | case PREVENT_ALLOW_MEDIUM_REMOVAL:
37 | {
38 | scsi_status = 0;
39 | return 1;
40 | }
41 | case TEST_UNIT_READY:
42 | {
43 | return 1;
44 | }
45 | case INQUIRY:
46 | {
47 | memset(usb_buffer, 0, 36);
48 | usb_buffer[1] = 0x80; //removable media
49 | usb_buffer[3] = 0x01; //because the UFI spec says so
50 | usb_buffer[4] = 0x1F; //additional length
51 | SendData1(36, 0);
52 | scsi_status = 0;
53 | return 1;
54 | }
55 | case READ_FORMAT_CAPACITIES:
56 | {
57 | memset(usb_buffer, 0, 12);
58 | usb_buffer[3] = 0x08; //capacity list length
59 | usb_buffer[6] = 0x10; //number of blocks (sectors) (dummy 2MB)
60 | usb_buffer[8] = 0x03;
61 | usb_buffer[10] = 0x02; //block length (512 bytes/sector)
62 | SendData1(12, 0);
63 | scsi_status = 0;
64 | return 1;
65 | }
66 | case MODE_SENSE:
67 | {
68 | memset(usb_buffer, 0, 8);
69 | usb_buffer[0] = 0x03;
70 | usb_buffer[2] = 0x80;
71 | SendData1(4, 0);
72 | scsi_status = 0;
73 | return 1;
74 | }
75 | case REQUEST_SENSE:
76 | {
77 | memset(usb_buffer, 0, 18);
78 | usb_buffer[0] = 0x70;
79 | usb_buffer[2] = 0x02;
80 | usb_buffer[7] = 10;
81 | usb_buffer[12] = 0x3A;
82 | SendData1(18, 0);
83 | scsi_status = 0;
84 | return 1;
85 | }
86 | //Vendor-specific requests
87 | case 0x06:
88 | case 0xC6:
89 | case 0xC7:
90 | {
91 | switch(scsi_cdb[1])
92 | {
93 | case CUSTOM_XPEEK:
94 | {
95 | usb_buffer[0] = XVAL((scsi_cdb[2] << 8) | scsi_cdb[3]);
96 | SendData1(1, 0);
97 | break;
98 | }
99 | case CUSTOM_XPOKE:
100 | {
101 | XVAL((scsi_cdb[2] << 8) | scsi_cdb[3]) = scsi_cdb[4];
102 | SendData1(1, 0);
103 | break;
104 | }
105 | case CUSTOM_IPEEK:
106 | {
107 | usb_buffer[0] = IVAL(scsi_cdb[2]);
108 | SendData1(1, 0);
109 | break;
110 | }
111 | case CUSTOM_IPOKE:
112 | {
113 | IVAL(scsi_cdb[2]) = scsi_cdb[3];
114 | SendData1(1, 0);
115 | break;
116 | }
117 | case VENDOR_CHIPID:
118 | {
119 | int i;
120 | memset(usb_buffer, 0x00, 0x200);
121 |
122 | //Set raw command mode
123 | XVAL(0xF480) = 0x00;
124 | XVAL(0xF618) = 0xFF;
125 |
126 | //Select chip 0
127 | XVAL(0xF608) = 0xFE;
128 |
129 | //Reset it
130 | XVAL(0xF400) = 0xFF;
131 | while (!(XVAL(0xF41E) & 0x01));
132 |
133 | //Send read chip ID command
134 | XVAL(0xF400) = 0x90;
135 | XVAL(0xF404) = 0x00;
136 | for (i = 0; i < 6; i++)
137 | {
138 | usb_buffer[i] = XVAL(0xF408);
139 | }
140 |
141 | SendData1(0x200, 0);
142 | scsi_status = 0;
143 | return 1;
144 | }
145 | case VENDOR_INFO: //get info
146 | {
147 | int i;
148 |
149 | memset(usb_buffer, 0x00, 0x210);
150 | usb_buffer[0x094] = 0x00;
151 | usb_buffer[0x095] = 0x99;
152 | usb_buffer[0x096] = 0x53;
153 | usb_buffer[0x17A] = 'V';
154 | usb_buffer[0x17B] = 'R';
155 | usb_buffer[0x17E] = 0x23;
156 | usb_buffer[0x17F] = 0x03;
157 | usb_buffer[0x200] = 'I';
158 | usb_buffer[0x201] = 'F';
159 | SendData1(0x210, 0);
160 | scsi_status = 0;
161 | return 1;
162 | }
163 | case VENDOR_BOOT:
164 | {
165 | //This transfers control to boot mode and will not return.
166 | XVAL(0xFA14) = 0x07;
167 | XVAL(0xF747) &= 0xEF;
168 | XVAL(0xFA15) = 0x06;
169 | XVAL(0xFA38) |= 0x01;
170 | XVAL(0xF08F) = 0x00;
171 | XVAL(0xFA68) &= 0xF7;
172 | XVAL(0xFA6A) &= 0xF7;
173 | XVAL(0xFA48) &= 0xFE;
174 | break;
175 | }
176 | default:
177 | {
178 | //Not handling it, then
179 | return 0;
180 | }
181 | }
182 | }
183 | default:
184 | {
185 | //Not handling it, then
186 | return 0;
187 | }
188 | }
189 | }
190 |
--------------------------------------------------------------------------------
/firmware/test.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 | ..\tools\DriveCom /action=SendFirmware /drive=E /burner=..\BINs\BN03V104M.BIN /firmware=bin\fw.bin
3 |
--------------------------------------------------------------------------------
/firmware/timers.c:
--------------------------------------------------------------------------------
1 | #include "defs.h"
2 | #include "timers.h"
3 |
4 | static BYTE tmr0count, led_ticks, led_timer, led_tick_threshold;
5 | static BYTE tmr1count;
6 | static WORD tmr1reload;
7 |
8 | void tmr1isr(void) __interrupt TMR1_VECT
9 | {
10 | TR1 = 0;
11 | TH1 = MSB(tmr1reload);
12 | TL1 = LSB(tmr1reload);
13 | tmr1count++;
14 | TR1 = 1;
15 | }
16 |
17 | void InitTicks()
18 | {
19 | if (XVAL(0xFA60) == 0x0F)
20 | {
21 | tmr1reload = 0xF63C;
22 | }
23 | else
24 | {
25 | tmr1reload = 0-(2500/(XVAL(0xFA60)+2));
26 | }
27 |
28 | tmr1count = 0;
29 | TR1 = 0;
30 | ET1 = 1;
31 | TMOD = TMOD & 0x0F | 0x10;
32 | }
33 |
34 | BYTE GetTickCount(void)
35 | {
36 | return tmr1count;
37 | }
38 |
39 | void tmr0isr(void) __interrupt TMR0_VECT
40 | {
41 | //approx. 10 times per second
42 | TR0 = 0;
43 | TL0 = 0xE6;
44 | TH0 = 0x96;
45 | TR0 = 1;
46 |
47 | if ((GPIO0OUT & 2) == 0) //turned off
48 | {
49 | return;
50 | }
51 |
52 | tmr0count++;
53 | led_ticks++;
54 | if (led_ticks < led_tick_threshold)
55 | {
56 | return;
57 | }
58 |
59 | led_ticks = 0;
60 | if (led_timer >= 31)
61 | {
62 | GPIO0OUT = 1;
63 | led_timer = 0;
64 | return;
65 | }
66 |
67 | if (led_timer >= 10)
68 | {
69 | GPIO0OUT = ~GPIO0OUT;
70 | led_timer++;
71 | return;
72 | }
73 |
74 | if (led_timer == 0)
75 | {
76 | return;
77 | }
78 |
79 | if (GPIO0OUT & 1)
80 | {
81 | GPIO0OUT &= 0xFE;
82 | }
83 | else
84 | {
85 | GPIO0OUT |= 1;
86 | }
87 | }
88 |
89 | void SetLEDThreshold(int threshold)
90 | {
91 | led_tick_threshold = threshold;
92 | }
93 |
94 | void InitLED(void)
95 | {
96 | led_tick_threshold = 100;
97 | tmr0count = 0;
98 | GPIO0OUT = 3;
99 | led_ticks = 0;
100 | led_timer = 0;
101 | EA = 1;
102 | ET0 = 1;
103 | TR0 = 1;
104 | }
105 |
106 | void LEDBlink(void)
107 | {
108 | GPIO0OUT = 2;
109 | led_timer = 1;
110 | }
111 |
112 | void LEDOff(void)
113 | {
114 | GPIO0OUT = 3;
115 | led_timer = 0;
116 | }
117 |
--------------------------------------------------------------------------------
/firmware/timers.h:
--------------------------------------------------------------------------------
1 | #ifndef _TIMERS_H_INCLUDED
2 | #define _TIMERS_H_INCLUDED
3 |
4 | void InitLED(void);
5 | void SetLEDThreshold(int threshold);
6 | void LEDBlink(void);
7 | void LEDOff(void);
8 |
9 | void InitTicks();
10 | BYTE GetTickCount(void);
11 |
12 | #endif
13 |
--------------------------------------------------------------------------------
/firmware/usb.c:
--------------------------------------------------------------------------------
1 | #include "defs.h"
2 | #include "string.h"
3 | #include "timers.h"
4 |
5 | __xdata __at usb_buffer_VA volatile BYTE usb_buffer[1024];
6 |
7 | BYTE bmRequestType;
8 | BYTE bRequest;
9 | WORD wValue;
10 | WORD wIndex;
11 | WORD wLength;
12 |
13 | static __xdata BYTE usb_irq;
14 | static __xdata BYTE UsbIntStsF080, UsbIntStsF082, UsbIntStsF086, UsbIntStsF087;
15 |
16 | BYTE usb_speed;
17 | __xdata volatile BYTE usb_received_data_ready, usb_have_csw_ready;
18 |
19 | extern BYTE scsi_status;
20 | extern DWORD scsi_data_residue;
21 | extern DWORD scsi_transfer_size;
22 | extern BYTE scsi_tag[4];
23 | extern BYTE scsi_dir_in;
24 | extern BYTE scsi_cdb[16];
25 | extern BYTE scsi_lun;
26 | extern BYTE scsi_cdb_size;
27 | extern BYTE HandleCDB(void);
28 | extern volatile BYTE send_keys_enabled;
29 |
30 | extern BYTE HandleStandardRequest(void);
31 | extern BYTE HandleClassRequest(void);
32 | extern BYTE HandleVendorRequest(void);
33 |
34 | void SetDMA(BYTE p5, BYTE p3, BYTE px)
35 | {
36 | XVAL(0xF80B) = 0;
37 | XVAL(0xF80C) = p5-1;
38 |
39 | switch(px)
40 | {
41 | case 0:
42 | {
43 | XVAL(0xF80D) = p3;
44 | XVAL(0xF80E) = p3;
45 | break;
46 | }
47 | case 1:
48 | {
49 | XVAL(0xF80D) = p3;
50 | break;
51 | }
52 | case 2:
53 | {
54 | XVAL(0xF80E) = p3;
55 | break;
56 | }
57 | default:
58 | {
59 | break;
60 | }
61 | }
62 | }
63 |
64 | void SendControlResponse(int size)
65 | {
66 | EP0.len_l = LSB(size);
67 | EP0.len_m = MSB(size);
68 | EP0.len_h = 0;
69 | EP0.cs = 0x40;
70 | while (EP0.cs & 0x40);
71 | EP0CS = 0x05;
72 | }
73 |
74 | void SendData0(WORD size, BYTE offset)
75 | {
76 | if (size > 0)
77 | {
78 | SetDMA(0x20, 0, 0);
79 | SetDMA(0x20, 0x80, 1);
80 | EP0.ptr_l = usb_buffer_PA>>8;
81 | EP0.ptr_m = usb_buffer_PA>>16;
82 | EP0.ptr_h = usb_buffer_PA>>24;
83 | EP0.offset = offset;
84 | EP0.len_l = LSB(size);
85 | EP0.len_m = MSB(size);
86 | EP0.len_h = 0;
87 | EP0.cs = 0x88;
88 |
89 | while(EP0.cs & 0x80);
90 | }
91 | }
92 |
93 | void SendData1(WORD size, BYTE offset)
94 | {
95 | if (size > 0)
96 | {
97 | SetDMA(0x20, 0, 0);
98 | SetDMA(0x20, 0x80, 1);
99 | EP1.ptr_l = usb_buffer_PA>>8;
100 | EP1.ptr_m = usb_buffer_PA>>16;
101 | EP1.ptr_h = usb_buffer_PA>>24;
102 | EP1.offset = offset;
103 | EP1.len_l = LSB(size);
104 | EP1.len_m = MSB(size);
105 | EP1.len_h = 0;
106 | EP1.cs = 0x88;
107 |
108 | while(EP1.cs & 0x80);
109 | }
110 | }
111 |
112 | static void SendCSW()
113 | {
114 | usb_buffer[0] = 'U';
115 | usb_buffer[1] = 'S';
116 | usb_buffer[2] = 'B';
117 | usb_buffer[3] = 'S';
118 | usb_buffer[4] = scsi_tag[0];
119 | usb_buffer[5] = scsi_tag[1];
120 | usb_buffer[6] = scsi_tag[2];
121 | usb_buffer[7] = scsi_tag[3];
122 | usb_buffer[8] = scsi_data_residue;
123 | usb_buffer[9] = scsi_data_residue>>8;
124 | usb_buffer[10] = scsi_data_residue>>16;
125 | usb_buffer[11] = scsi_data_residue>>24;
126 | usb_buffer[12] = scsi_status;
127 |
128 | SendData1(13, 0);
129 | usb_have_csw_ready = 0;
130 | scsi_data_residue = 0;
131 | }
132 |
133 | static void SendCSW2()
134 | {
135 | while(EP1.cs & bmSTALL);
136 | while((EP1.r17 & 0x80)==0)
137 | {
138 | if ((XVAL(0xF010) & 0x20)==0)
139 | {
140 | usb_have_csw_ready = 0;
141 | return;
142 | }
143 | }
144 |
145 | while(EP1.cs & 0x40);
146 | while(EP2.cs & 0x40);
147 | while(EP3.cs & 0x40);
148 | while(EP4.cs & 0x40);
149 |
150 | EP1.fifo = 'U';
151 | EP1.fifo = 'S';
152 | EP1.fifo = 'B';
153 | EP1.fifo = 'S';
154 | EP1.fifo = scsi_tag[0];
155 | EP1.fifo = scsi_tag[1];
156 | EP1.fifo = scsi_tag[2];
157 | EP1.fifo = scsi_tag[3];
158 | EP1.fifo = scsi_data_residue;
159 | EP1.fifo = scsi_data_residue>>8;
160 | EP1.fifo = scsi_data_residue>>16;
161 | EP1.fifo = scsi_data_residue>>24;
162 | EP1.fifo = scsi_status;
163 | EP1.len_l = 13;
164 | EP1.len_m = 0;
165 | EP1.len_h = 0;
166 | EP1.cs = 0x40;
167 | usb_have_csw_ready = 0;
168 | scsi_data_residue = 0;
169 | }
170 |
171 | void InitUSB(void)
172 | {
173 | BYTE b;
174 |
175 | usb_irq = 0;
176 | usb_received_data_ready = 0;
177 | usb_have_csw_ready = 0;
178 | usb_speed = 0;
179 | EP1.ptr_l = usb_buffer_PA>>8;
180 | EP1.ptr_m = usb_buffer_PA>>16;
181 | EP1.ptr_h = usb_buffer_PA>>24;
182 | EP1.r8 = 0x10;
183 | EP1.offset = 0;
184 | EP2.ptr_l = usb_buffer_PA>>8;
185 | EP2.ptr_m = usb_buffer_PA>>16;
186 | EP2.ptr_h = usb_buffer_PA>>24;
187 | EP2.r8 = 0x10;
188 | EP2.offset = 0;
189 |
190 | if (WARMSTATUS & 2) //USB warm start
191 | {
192 | if ((USBSTAT & bmSpeed) == bmSuperSpeed)
193 | {
194 | usb_speed = bmSuperSpeed;
195 | }
196 | else if ((USBSTAT & bmSpeed) == bmHighSpeed)
197 | {
198 | usb_speed = bmHighSpeed;
199 | }
200 | else if ((USBSTAT & bmSpeed) == bmFullSpeed)
201 | {
202 | usb_speed = bmFullSpeed;
203 | }
204 | else
205 | {
206 | usb_speed = 0;
207 | }
208 |
209 | EX1 = 1;
210 | EX0 = 1;
211 | EPIE = bmEP2IRQ | bmEP4IRQ;
212 | scsi_data_residue = 0;
213 | scsi_status = 0;
214 | SendCSW();
215 | }
216 | else
217 | {
218 | //USB cold start
219 | REGBANK = 6;
220 | XVAL(0xF240) = 2;
221 | XVAL(0xF28C) = 0x36;
222 | XVAL(0xF28D) = 0xD0;
223 | XVAL(0xF28E) = 0x98;
224 | REGBANK = 0;
225 | EPIE = bmEP2IRQ | bmEP4IRQ;
226 | USBCTL = bmAttach | bmSuperSpeed;
227 |
228 | XVAL(0xFA38) |= 2;
229 |
230 | EX1 = 1;
231 | EX0 = 1;
232 | for (b = 0; b < 250; b++);
233 | }
234 | }
235 |
236 | void usb_isr(void) __interrupt USB_VECT
237 | {
238 | usb_irq = USBIRQ;
239 |
240 | if (usb_irq & 0x20)
241 | {
242 | USBIRQ = 0x20;
243 | }
244 |
245 | if (usb_irq & 0x10)
246 | {
247 | USBIRQ = 0x10;
248 | }
249 |
250 | if (usb_irq & bmSpeedChange)
251 | {
252 | USBIRQ = bmSpeedChange;
253 | if ((USBSTAT & bmSpeed) == bmSuperSpeed)
254 | {
255 | usb_speed = bmSuperSpeed;
256 | }
257 | else if ((USBSTAT & bmSpeed) == bmHighSpeed)
258 | {
259 | usb_speed = bmHighSpeed;
260 | }
261 | else if ((USBSTAT & bmSpeed) == bmFullSpeed)
262 | {
263 | usb_speed = bmFullSpeed;
264 | }
265 | else
266 | {
267 | usb_speed = 0;
268 | }
269 | }
270 |
271 | if (usb_irq & 0x40)
272 | {
273 | USBIRQ = 0x40;
274 | }
275 |
276 | UsbIntStsF087 = XVAL(0xF087);
277 | UsbIntStsF086 = XVAL(0xF086);
278 | UsbIntStsF082 = XVAL(0xF082);
279 | UsbIntStsF080 = XVAL(0xF080);
280 |
281 | if (UsbIntStsF082 & 0x80)
282 | {
283 | XVAL(0xF082) = 0x80;
284 | }
285 |
286 | if (UsbIntStsF082 & 0x40)
287 | {
288 | XVAL(0xF082) = 0x40;
289 | }
290 |
291 | if (UsbIntStsF080 & 1)
292 | {
293 | XVAL(0xF080) = 1;
294 | if (EP0CS & bmSUDAV)
295 | {
296 | bmRequestType = SETUPDAT[0];
297 | bRequest = SETUPDAT[1];
298 | wValue = SETUPDAT[2] | (SETUPDAT[3] << 8);
299 | wIndex = SETUPDAT[4] | (SETUPDAT[5] << 8);
300 | wLength = SETUPDAT[6] | (SETUPDAT[7] << 8);
301 | }
302 | }
303 |
304 | if (XVAL(0xF082) & 0x20)
305 | {
306 | XVAL(0xF082) = 0x20;
307 | }
308 |
309 | if (XVAL(0xF081) & 0x10)
310 | {
311 | XVAL(0xF081) = 0x10;
312 | }
313 |
314 | if (XVAL(0xF081) & 0x20)
315 | {
316 | XVAL(0xF081) = 0x20;
317 | }
318 |
319 | if (UsbIntStsF080 | UsbIntStsF082 | UsbIntStsF086 | UsbIntStsF087 | usb_irq)
320 | {
321 | EX0 = 0;
322 | }
323 | }
324 |
325 | void ep_isr(void) __interrupt EP_VECT
326 | {
327 | BYTE interrupts = (EPIRQ & (bmEP2IRQ | bmEP4IRQ));
328 | if (interrupts & bmEP2IRQ)
329 | {
330 | EPIE &= ~bmEP2IRQ; //disable this
331 | EPIRQ = bmEP2IRQ; //acknowledge it
332 | usb_received_data_ready |= bmEP2IRQ;
333 | }
334 |
335 | if (interrupts & bmEP4IRQ)
336 | {
337 | EPIE &= ~bmEP4IRQ; //disable this
338 | EPIRQ = bmEP4IRQ; //acknowledge it
339 | usb_received_data_ready |= bmEP4IRQ;
340 | }
341 | }
342 |
343 | static void ResetEPs()
344 | {
345 | EPIE = bmEP2IRQ | bmEP4IRQ;
346 | EP1.cs = 0;
347 | EP2.cs = 0;
348 | EP3.cs = 0;
349 | EP4.cs = 0;
350 | }
351 |
352 | static void HandleControlRequest(void)
353 | {
354 | BYTE res;
355 | switch(bmRequestType & 0x60)
356 | {
357 | case 0:
358 | res = HandleStandardRequest();
359 | break;
360 | case 0x20:
361 | res = HandleClassRequest();
362 | break;
363 | case 0x40:
364 | res = HandleVendorRequest();
365 | break;
366 | default:
367 | res = FALSE;
368 | }
369 |
370 | if (!res)
371 | {
372 | EP0CS = wLength ? bmEP0STALL : bmEP0NAK;
373 | }
374 | }
375 |
376 | void HandleUSBEvents(void)
377 | {
378 | if (UsbIntStsF080 | UsbIntStsF082 | UsbIntStsF086 | UsbIntStsF087 | usb_irq)
379 | {
380 | if (usb_irq)
381 | {
382 | if (usb_irq & 0x40)
383 | {
384 | USBCTL &= ~bmAttach;
385 | ResetEPs();
386 | XVAL(0xFE88) = 0;
387 | XVAL(0xFE82) = 0x10;
388 | while(XVAL(0xFE88)!=2);
389 | USBCTL = bmAttach;
390 | }
391 |
392 | if (usb_irq & bmSpeedChange)
393 | {
394 | ResetEPs();
395 | }
396 |
397 | usb_irq = 0;
398 | }
399 | else
400 | {
401 | if (UsbIntStsF082 & 0xC0)
402 | {
403 | ResetEPs();
404 | XVAL(0xF092) = 0;
405 | XVAL(0xF096) = 0;
406 | if (UsbIntStsF082 & 0x40)
407 | {
408 | XVAL(0xF07A) = 1;
409 | }
410 | }
411 | else
412 | {
413 | if (UsbIntStsF080 & 1)
414 | {
415 | HandleControlRequest();
416 | }
417 | }
418 |
419 | UsbIntStsF080 = 0;
420 | UsbIntStsF082 = 0;
421 | UsbIntStsF086 = 0;
422 | UsbIntStsF087 = 0;
423 | }
424 |
425 | EX0 = 1;
426 | }
427 |
428 | //WHY DOESN'T THIS INTERRUPT FIRE?!
429 | if (1)//usb_received_data_ready)
430 | {
431 | if (1)//usb_received_data_ready & bmEP4IRQ)
432 | {
433 | if (EP4.fifo_count > 0)
434 | {
435 | EP4.cs = 0x40;
436 |
437 | send_keys_enabled = 1;
438 | usb_received_data_ready &= ~bmEP4IRQ;
439 | EPIE |= bmEP4IRQ;
440 | }
441 | }
442 |
443 | if (usb_received_data_ready & bmEP2IRQ)
444 | {
445 | if (EP2.fifo_count == 31) //CBW size
446 | {
447 | BYTE a, b, c, d;
448 |
449 | scsi_data_residue = 0;
450 | /*while(EP1.cs & 0x40);
451 | while(EP2.cs & 0x40);
452 | while(EP3.cs & 0x40);
453 | while(EP4.cs & 0x40);*/
454 |
455 | a = EP2.fifo;
456 | b = EP2.fifo;
457 | c = EP2.fifo;
458 | d = EP2.fifo;
459 | if ((a=='U') && (b=='S') && (c=='B') && (d=='C'))
460 | {
461 | scsi_tag[0] = EP2.fifo;
462 | scsi_tag[1] = EP2.fifo;
463 | scsi_tag[2] = EP2.fifo;
464 | scsi_tag[3] = EP2.fifo;
465 | scsi_transfer_size = EP2.fifo;
466 | scsi_transfer_size |= ((DWORD)EP2.fifo)<<8;
467 | scsi_transfer_size |= ((DWORD)EP2.fifo)<<16;
468 | scsi_transfer_size |= ((DWORD)EP2.fifo)<<24;
469 | scsi_dir_in = EP2.fifo & 0x80;
470 | scsi_lun = EP2.fifo;
471 | scsi_cdb_size = EP2.fifo;
472 | for(a = 0; a < 16; a++)
473 | {
474 | scsi_cdb[a] = EP2.fifo;
475 | }
476 |
477 | EP2.cs = 0x40;
478 | if (!HandleCDB())
479 | {
480 | scsi_status = 1;
481 | if (scsi_transfer_size == 0)
482 | {
483 | EP1.cs = bmSTALL;
484 | }
485 | else if (scsi_dir_in)
486 | {
487 | EP1.cs = bmSTALL;
488 | }
489 | else
490 | {
491 | EP2.cs = bmSTALL;
492 | }
493 | }
494 |
495 | usb_have_csw_ready = 1;
496 | }
497 | else
498 | {
499 | EP2.cs = 0x40;
500 | EP2.cs = 4;
501 | }
502 | }
503 | else
504 | {
505 | EP2.cs = 0x40;
506 | EP2.cs = 4;
507 | }
508 |
509 | usb_received_data_ready &= ~bmEP2IRQ;
510 | EPIE |= bmEP2IRQ;
511 | }
512 | }
513 |
514 | if (usb_have_csw_ready)
515 | {
516 | SendCSW2();
517 | }
518 | }
519 |
--------------------------------------------------------------------------------
/firmware/usb.h:
--------------------------------------------------------------------------------
1 | #ifndef _USB_H_INCLUDED
2 | #define _USB_H_INCLUDED
3 |
4 | void InitUSB(void);
5 | void HandleUSBEvents(void);
6 | void SendControlResponse(int size);
7 | void SendData0(WORD size, BYTE offset);
8 | void SendData1(WORD size, BYTE offset);
9 | void SetDMA(BYTE p5, BYTE p3, BYTE px);
10 |
11 | extern BYTE bmRequestType;
12 | extern BYTE bRequest;
13 | extern WORD wValue;
14 | extern WORD wIndex;
15 | extern WORD wLength;
16 |
17 | extern BYTE usb_speed;
18 | extern __xdata __at usb_buffer_VA volatile BYTE usb_buffer[1024];
19 | extern __xdata volatile BYTE usb_received_data_ready;
20 | extern __xdata volatile BYTE usb_have_csw_ready;
21 |
22 | #endif
23 |
--------------------------------------------------------------------------------
/patch/base.c:
--------------------------------------------------------------------------------
1 | #include "defs.h"
2 | #include "equates.h"
3 |
4 | #define FEATURE_CHANGE_PASSWORD
5 | //#define FEATURE_EXPOSE_HIDDEN_PARTITION
6 | //#define FEATURE_PREVENT_BOOT
7 |
8 | #define NUM_LBAS 0xE6EA40UL //this needs to be even! (round down)
9 |
10 | //SCSI command codes
11 | #define SCSI_06 0x06
12 | #define SCSI_06_XPEEK 0x06
13 | #define SCSI_06_XPOKE 0x07
14 | #define SCSI_06_IPEEK 0x08
15 | #define SCSI_06_IPOKE 0x09
16 | #define SCSI_06_BOOT 0xBF
17 | #define SCSI_START_STOP_UNIT 0x1B
18 | #define SCSI_READ_FORMAT_CAPACITIES 0x23
19 | #define SCSI_READ_CAPACITY 0x25
20 | #define SCSI_READ_SECTOR 0x28
21 | #define SCSI_WRITE_SECTOR 0x2A
22 |
23 | void memset(BYTE* s, BYTE c, int size)
24 | {
25 | int i;
26 | for (i = 0; i < size; i++)
27 | {
28 | *s = c;
29 | s++;
30 | }
31 | }
32 |
33 | void SendData(int size)
34 | {
35 | int i;
36 |
37 | while(EP1.cs & bmSTALL);
38 | while((EP1.r17 & 0x80)==0)
39 | {
40 | if ((XVAL(0xF010) & 0x20)==0)
41 | {
42 | return;
43 | }
44 | }
45 |
46 | while(EP1.cs & 0x40);
47 | while(EP2.cs & 0x40);
48 | while(EP3.cs & 0x40);
49 | while(EP4.cs & 0x40);
50 |
51 | for (i = 0; i < size; i++)
52 | {
53 | EP1.fifo = EPBUF[i];
54 | }
55 |
56 | EP1.len_l = size & 0xFF;
57 | EP1.len_m = (size >> 8) & 0xFF;
58 | EP1.len_h = 0;
59 | EP1.cs = 0x40;
60 | }
61 |
62 | void SendCSW(void)
63 | {
64 | memset(EPBUF, 0, 13);
65 | EPBUF[0] = 'U';
66 | EPBUF[1] = 'S';
67 | EPBUF[2] = 'B';
68 | EPBUF[3] = 'S';
69 | EPBUF[4] = scsi_tag[3];
70 | EPBUF[5] = scsi_tag[2];
71 | EPBUF[6] = scsi_tag[1];
72 | EPBUF[7] = scsi_tag[0];
73 | SendData(13);
74 | }
75 |
76 | //Disconnects and then re-enumerates.
77 | void RecycleUSBConnection(void)
78 | {
79 | USBCTL &= ~bmAttach;
80 | EPIE = bmEP2IRQ;
81 | EP1.cs = 0;
82 | EP2.cs = 0;
83 | XVAL(0xFE88) = 0;
84 | XVAL(0xFE82) = 0x10;
85 | while (XVAL(0xFE88) != 2);
86 | USBCTL = bmAttach;
87 | }
88 |
89 | #ifdef FEATURE_EXPOSE_HIDDEN_PARTITION
90 |
91 | //HACK: We're using an unused bit of SYSTEM register 0xFA38 to hold the hidden status,
92 | // since we don't yet know what RAM is safe to use.
93 | BOOL IsHiddenAreaVisible(void)
94 | {
95 | return WARMSTATUS & 0x80;
96 | }
97 |
98 | //HACK: We're using an unused bit of SYSTEM register 0xFA38 to hold the hidden status,
99 | // since we don't yet know what RAM is safe to use.
100 | void SetHiddenAreaVisibility(BOOL visible)
101 | {
102 | if (visible)
103 | {
104 | WARMSTATUS |= 0x80;
105 | }
106 | else
107 | {
108 | WARMSTATUS &= 0x7F;
109 | }
110 | }
111 |
112 | void WaitTenSeconds(void)
113 | {
114 | WORD i, j;
115 |
116 | for (i = 0; i < 65535; i++)
117 | {
118 | for (j = 0; j < 1000; j++)
119 | {
120 | //Do nothing
121 | }
122 | }
123 | }
124 |
125 | #endif
126 |
127 | /*
128 | void HandleControlRequest(void)
129 | {
130 | if (bmRequestType & 0x20)
131 | {
132 | //Handle class request
133 | }
134 | else if (bmRequestType & 0x40)
135 | {
136 | //Handle vendor request
137 | }
138 | else
139 | {
140 | //Handle standard request
141 | }
142 | }
143 | */
144 |
145 | /*
146 | void EndpointInterrupt(void)
147 | {
148 | __asm
149 | push ACC
150 | push DPH
151 | push DPL
152 | //If no interrupts fired, get out
153 | mov DPTR, #EPIRQ
154 | movx A, @DPTR
155 | jz 000001$
156 | //Let the firmware know these events happened, so it can handle them
157 | mov B, A
158 | mov DPTR, #FW_EPIRQ
159 | movx A, @DPTR
160 | orl A, B
161 | movx @DPTR, A
162 | //Disable those interrupts so they don't fire again until we're done with them
163 | mov A, #0xFF
164 | xrl A, B
165 | mov DPTR, #EPIE
166 | movx @DPTR, A
167 | //Acknowledge the interrupts
168 | mov A, B
169 | mov DPTR, #EPIRQ
170 | movx @DPTR, A
171 | 000001$:pop DPL
172 | pop DPH
173 | pop ACC
174 | reti
175 | __endasm;
176 | }
177 |
178 | void HandleEndpointInterrupt(void)
179 | {
180 | //Handle incoming endpoint data
181 | }
182 | */
183 |
184 | #if defined(FEATURE_EXPOSE_HIDDEN_PARTITION) || defined(FEATURE_PREVENT_BOOT)
185 |
186 | void HandleCDB(void)
187 | {
188 | unsigned long lba;
189 |
190 | switch(scsi_cdb[0])
191 | {
192 | case SCSI_06:
193 | {
194 | switch (scsi_cdb[1])
195 | {
196 | case SCSI_06_XPEEK:
197 | {
198 | EPBUF[0] = XVAL((scsi_cdb[2] << 8) | scsi_cdb[3]);
199 | SendData(1);
200 | break;
201 | }
202 | case SCSI_06_XPOKE:
203 | {
204 | XVAL((scsi_cdb[2] << 8) | scsi_cdb[3]) = scsi_cdb[4];
205 | SendData(1);
206 | break;
207 | }
208 | case SCSI_06_IPEEK:
209 | {
210 | EPBUF[0] = IVAL(scsi_cdb[2]);
211 | SendData(1);
212 | break;
213 | }
214 | case SCSI_06_IPOKE:
215 | {
216 | IVAL(scsi_cdb[2]) = scsi_cdb[3];
217 | SendData(1);
218 | break;
219 | }
220 | #ifdef FEATURE_PREVENT_BOOT
221 | case SCSI_06_BOOT:
222 | {
223 | break;
224 | }
225 | #endif
226 | default:
227 | {
228 | __asm
229 | ljmp #DEFAULT_CDB_HANDLER
230 | __endasm;
231 | }
232 | }
233 | break;
234 | }
235 | case SCSI_READ_SECTOR: //TODO: we should handle the other READ(X) commands as well
236 | {
237 | #ifdef FEATURE_EXPOSE_HIDDEN_PARTITION
238 | //Get the passed-in LBA
239 | lba = ((unsigned long)(scsi_cdb[2]) << 24) & 0xFF000000;
240 | lba |= ((unsigned long)(scsi_cdb[3]) << 16) & 0xFF0000;
241 | lba |= (scsi_cdb[4] << 8) & 0xFF00;
242 | lba |= scsi_cdb[5];
243 |
244 | //Shift it if necessary
245 | if (IsHiddenAreaVisible())
246 | {
247 | lba += NUM_LBAS / 2;
248 | }
249 |
250 | //Save it
251 | scsi_cdb[2] = (lba >> 24) & 0xFF;
252 | scsi_cdb[3] = (lba >> 16) & 0xFF;
253 | scsi_cdb[4] = (lba >> 8) & 0xFF;
254 | scsi_cdb[5] = lba & 0xFF;
255 | #endif
256 | //Let the firmware do its thing
257 | __asm
258 | ljmp #DEFAULT_READ_SECTOR_HANDLER
259 | __endasm;
260 | }
261 | #ifdef FEATURE_EXPOSE_HIDDEN_PARTITION
262 | case SCSI_START_STOP_UNIT:
263 | {
264 | //Are we being stopped?
265 | if (scsi_cdb[4] == 0x02)
266 | {
267 | //Yes, set the other section as the visible one
268 | SetHiddenAreaVisibility(!IsHiddenAreaVisible());
269 |
270 | //Send the CSW
271 | SendCSW();
272 |
273 | //Wait and re-enumerate
274 | WaitTenSeconds();
275 | RecycleUSBConnection();
276 | }
277 | else
278 | {
279 | //No, let things continue normally
280 | __asm
281 | ljmp #DEFAULT_CDB_HANDLER
282 | __endasm;
283 | }
284 | break;
285 | }
286 | case SCSI_READ_FORMAT_CAPACITIES:
287 | {
288 | lba = NUM_LBAS / 2;
289 |
290 | memset(EPBUF, 0, 12);
291 | EPBUF[3] = 0x08; //capacity list length
292 | EPBUF[4] = lba >> 24;
293 | EPBUF[5] = lba >> 16;
294 | EPBUF[6] = lba >> 8;
295 | EPBUF[7] = lba & 0xFF;
296 | EPBUF[8] = 0x02; //descriptor code (formatted media)
297 | EPBUF[10] = 0x02; //block length (512 bytes/sector)
298 | SendData(12);
299 | break;
300 | }
301 | case SCSI_READ_CAPACITY:
302 | {
303 | lba = (NUM_LBAS / 2) - 1;
304 |
305 | memset(EPBUF, 0, 8);
306 | EPBUF[0] = lba >> 24;
307 | EPBUF[1] = lba >> 16;
308 | EPBUF[2] = lba >> 8;
309 | EPBUF[3] = lba & 0xFF;
310 | EPBUF[6] = 0x02; //block length (512 bytes/sector)
311 | SendData(8);
312 | break;
313 | }
314 | case SCSI_WRITE_SECTOR: //TODO: we should handle the other WRITE(x) commands as well
315 | {
316 | //Get the passed-in LBA
317 | lba = ((unsigned long)(scsi_cdb[2]) << 24) & 0xFF000000;
318 | lba |= ((unsigned long)(scsi_cdb[3]) << 16) & 0xFF0000;
319 | lba |= (scsi_cdb[4] << 8) & 0xFF00;
320 | lba |= scsi_cdb[5];
321 |
322 | //Shift it if necessary
323 | if (IsHiddenAreaVisible())
324 | {
325 | lba += NUM_LBAS / 2;
326 | }
327 |
328 | //Save it
329 | scsi_cdb[2] = (lba >> 24) & 0xFF;
330 | scsi_cdb[3] = (lba >> 16) & 0xFF;
331 | scsi_cdb[4] = (lba >> 8) & 0xFF;
332 | scsi_cdb[5] = lba & 0xFF;
333 |
334 | //Let the firmware do its thing
335 | __asm
336 | ljmp #DEFAULT_CDB_HANDLER
337 | __endasm;
338 | }
339 | #endif
340 | default:
341 | __asm
342 | ljmp #DEFAULT_CDB_HANDLER
343 | __endasm;
344 | }
345 | }
346 |
347 | #endif
348 |
349 | //Called in the firmware's infinite loop.
350 | /*
351 | void LoopDo(void)
352 | {
353 | }
354 | */
355 |
356 | #ifdef FEATURE_CHANGE_PASSWORD
357 |
358 | void SetPassword(BYTE* address)
359 | {
360 | int i;
361 | for (i = 0; i < 16; i++)
362 | {
363 | *(address + i) = 'A';
364 | }
365 | }
366 |
367 | void PasswordReceived()
368 | {
369 | if (EPBUF[0])
370 | {
371 | SetPassword(EPBUF);
372 |
373 | }
374 |
375 | if (EPBUF[0x10])
376 | {
377 | SetPassword(EPBUF + 0x10);
378 | }
379 | }
380 |
381 | #endif
382 |
--------------------------------------------------------------------------------
/patch/build.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | REM Set things up and create bin directory if necessary.
4 | SETLOCAL ENABLEDELAYEDEXPANSION
5 | SET BUILD_FILES=
6 | IF NOT EXIST bin\NUL MKDIR bin
7 |
8 | REM Generate .h C file for compilation.
9 | ECHO *** Generating C .h file...
10 | ..\tools\Injector.exe /action=GenerateHFile /firmware=fw.bin /output=equates.h
11 | IF ERRORLEVEL 1 GOTO ERRORS
12 |
13 | REM Build each file in the list.
14 | REM NOTE: This needs to change if more code files or sections are added.
15 | FOR %%A IN (
16 | base
17 | ) DO (
18 | ECHO *** Building %%A.c...
19 | sdcc --model-small -mmcs51 -pdefcpu -c -obin\%%A.rel %%A.c
20 | IF ERRORLEVEL 1 GOTO ERRORS
21 | SET "BUILD_FILES=!BUILD_FILES! bin\%%A.rel"
22 | )
23 |
24 | REM Retrieve free space for each section in the image.
25 | ECHO *** Retrieving free space in image...
26 | ..\tools\Injector.exe /action=FindFreeBlock /firmware=fw.bin /section=Base /output=bin\free.txt
27 | SET BASE_FREE_ADDR=
28 | FOR /F "delims=" %%i IN (bin\free.txt) DO SET BASE_FREE_ADDR=!BASE_FREE_ADDR! %%i
29 | DEL bin\free.txt
30 |
31 | REM Build Intel Hex and BIN versions of combined file.
32 | ECHO *** Linking...
33 | sdcc --model-small --code-loc %BASE_FREE_ADDR% --xram-size 0x400 --xram-loc 0x7C00 -o bin\output.hex %BUILD_FILES%
34 | ..\tools\hex2bin bin\output.hex
35 |
36 | REM Build patched image from assembled image.
37 | REM NOTE: This needs to change if more code files or sections are added.
38 | ECHO *** Injecting...
39 | ..\tools\Injector.exe /action=ApplyPatches /firmware=fw.bin /basecode=bin\output.bin /baserst=bin\base.rst /output=bin\fw.bin
40 | IF ERRORLEVEL 1 GOTO ERRORS
41 |
42 | GOTO END
43 |
44 | :ERRORS
45 | ECHO *** There were errors^^! ***
46 |
47 | :END
48 | ECHO *** Done.
49 |
50 | ENDLOCAL
51 |
--------------------------------------------------------------------------------
/patch/defs.h:
--------------------------------------------------------------------------------
1 | #ifndef DEFS_H
2 | #define DEFS_H
3 |
4 | #define MSB(word) (BYTE)(((WORD)(word) >> 8) & 0xff)
5 | #define LSB(word) (BYTE)((WORD)(word) & 0xff)
6 |
7 | #define XVAL(addr) (*( __xdata volatile unsigned char *)(addr))
8 | #define IVAL(addr) (*( __idata volatile unsigned char *)(addr))
9 |
10 | typedef unsigned char BYTE;
11 | typedef unsigned short WORD;
12 | typedef unsigned long DWORD;
13 | typedef __bit BOOL;
14 | typedef __bit bit;
15 | #define TRUE 1
16 | #define FALSE 0
17 |
18 | #define USB_VECT 0
19 | #define TMR0_VECT 1
20 | #define EP_VECT 2
21 | #define TMR1_VECT 3
22 | #define COM0_VECT 4
23 |
24 | #define bmAttach 0x80
25 | #define bmSpeed 7
26 | #define bmSuperSpeed 4
27 | #define bmHighSpeed 0
28 | #define bmFullSpeed 1
29 | #define bmSpeedChange 0x80
30 | #define bmEP2IRQ 2
31 | #define bmEP0ACK 1
32 | #define bmEP0NAK 2
33 | #define bmEP0IN 4
34 | #define bmEP0STALL 8
35 | #define bmSUDAV 0x80
36 | #define bmSTALL 2
37 |
38 | #define bmNandReady 1
39 |
40 | #define bmNandDma0 0
41 | #define bmNandDma1 0x80
42 | #define bmNandDmaRead 0
43 | #define bmNandDmaWrite 0x40
44 |
45 | #define bmDmaCmd 7
46 | #define bmDmaCopy 2
47 | #define bmDmaFill 4
48 | #define bmDmaWidth8 0
49 | #define bmDmaWidth16 0x40
50 | #define bmDmaWidth32 0x80
51 |
52 | #define bmPRAM 1
53 |
54 | // ------------------------------------------------------------------------------------------------
55 | // * SFRs
56 | // * ------------------------------------------------------------------------------------------------
57 | // BYTE Register
58 | __sfr __at (0x80) P0 ;
59 | __sfr __at (0x90) P1 ;
60 | __sfr __at (0xA0) P2 ;
61 | __sfr __at (0xB0) P3 ;
62 | __sfr __at (0xD0) PSW ;
63 | __sfr __at (0xE0) ACC ;
64 | __sfr __at (0xF0) B ;
65 | __sfr __at (0x81) SP ;
66 | __sfr __at (0x82) DPL ;
67 | __sfr __at (0x83) DPH ;
68 | __sfr __at (0x87) PCON;
69 | __sfr __at (0x88) TCON;
70 | __sfr __at (0x89) TMOD;
71 | __sfr __at (0x8A) TL0 ;
72 | __sfr __at (0x8B) TL1 ;
73 | __sfr __at (0x8C) TH0 ;
74 | __sfr __at (0x8D) TH1 ;
75 | __sfr __at (0xA8) IE ;
76 | __sfr __at (0xB8) IP ;
77 | __sfr __at (0x98) SCON;
78 | __sfr __at (0x99) SBUF;
79 |
80 | /* BIT Register */
81 | /* PSW */
82 | __sbit __at (0xD7) CY ;
83 | __sbit __at (0xD6) AC ;
84 | __sbit __at (0xD5) F0 ;
85 | __sbit __at (0xD4) RS1 ;
86 | __sbit __at (0xD3) RS0 ;
87 | __sbit __at (0xD2) OV ;
88 | __sbit __at (0xD0) P ;
89 |
90 | /* TCON */
91 | __sbit __at (0x8F) TF1 ;
92 | __sbit __at (0x8E) TR1 ;
93 | __sbit __at (0x8D) TF0 ;
94 | __sbit __at (0x8C) TR0 ;
95 | __sbit __at (0x8B) IE1 ;
96 | __sbit __at (0x8A) IT1 ;
97 | __sbit __at (0x89) IE0 ;
98 | __sbit __at (0x88) IT0 ;
99 |
100 | /* IE */
101 | __sbit __at (0xAF) EA ;
102 | __sbit __at (0xAC) ES ;
103 | __sbit __at (0xAB) ET1 ;
104 | __sbit __at (0xAA) EX1 ;
105 | __sbit __at (0xA9) ET0 ;
106 | __sbit __at (0xA8) EX0 ;
107 |
108 | /* IP */
109 | __sbit __at (0xBC) PS ;
110 | __sbit __at (0xBB) PT1 ;
111 | __sbit __at (0xBA) PX1 ;
112 | __sbit __at (0xB9) PT0 ;
113 | __sbit __at (0xB8) PX0 ;
114 |
115 | /* P3 */
116 | __sbit __at (0xB7) RD ;
117 | __sbit __at (0xB6) WR ;
118 | __sbit __at (0xB5) T1 ;
119 | __sbit __at (0xB4) T0 ;
120 | __sbit __at (0xB3) INT1;
121 | __sbit __at (0xB2) INT0;
122 | __sbit __at (0xB1) TXD ;
123 | __sbit __at (0xB0) RXD ;
124 |
125 | /* SCON */
126 | __sbit __at (0x9F) SM0 ;
127 | __sbit __at (0x9E) SM1 ;
128 | __sbit __at (0x9D) SM2 ;
129 | __sbit __at (0x9C) REN ;
130 | __sbit __at (0x9B) TB8 ;
131 | __sbit __at (0x9A) RB8 ;
132 | __sbit __at (0x99) TI ;
133 | __sbit __at (0x98) RI ;
134 |
135 | // ------------------------------------------------------------------------------------------------
136 | // Xdata F000-F3FF USB Registers
137 | // ------------------------------------------------------------------------------------------------
138 | // some banking registers switching
139 | // value: 0-7, default: 0
140 | __xdata __at 0xF000 volatile BYTE REGBANK;
141 | __xdata __at 0xF008 volatile BYTE USBCTL;
142 | __xdata __at 0xF009 volatile BYTE USBSTAT;
143 | __xdata __at 0xF027 volatile BYTE USBIRQ;
144 | __xdata __at 0xF020 volatile BYTE EPIRQ;
145 | __xdata __at 0xF030 volatile BYTE EPIE;
146 | __xdata __at 0xF048 volatile BYTE EP0CS;
147 | __xdata __at 0xF0B8 volatile BYTE SETUPDAT[8];
148 |
149 | typedef struct
150 | {
151 | BYTE r0,r1,r2,r3,r4;
152 | BYTE ptr_l, ptr_m, ptr_h; //buffer ptr = buf_pa>>8
153 | BYTE r8,r9;
154 | BYTE ofs; // buffer offset, data addr will be ptr<<8 + ofs*0x200
155 | BYTE rB;
156 | BYTE len_l, len_m, len_h; //C,D,E
157 | BYTE rF,r10,r11,r12;
158 | BYTE cs; //13
159 | BYTE r14,r15,r16,r17,r18,r19;
160 | BYTE fifo_count;
161 | BYTE r1B;
162 | BYTE fifo; //1C
163 | } EPREGS;
164 |
165 | __xdata __at 0xF1C0 volatile EPREGS EP0;
166 | __xdata __at 0xF200 volatile EPREGS EP1;
167 | __xdata __at 0xF240 volatile EPREGS EP2;
168 | __xdata __at 0xF280 volatile EPREGS EP3;
169 | __xdata __at 0xF2C0 volatile EPREGS EP4;
170 |
171 | typedef struct
172 | {
173 | BYTE raw_cmd;
174 | BYTE u1[3];
175 | BYTE raw_addr;
176 | BYTE u5[3];
177 | BYTE raw_data;
178 | BYTE r9;
179 | BYTE uA[2];
180 | BYTE rC;
181 | BYTE uD[3];
182 | BYTE r10;
183 | BYTE u11[7];
184 | BYTE r18;
185 | BYTE u19[5];
186 | BYTE status; // .0 - R/nB
187 | BYTE u1F[0x19];
188 | BYTE r38, r39, r3A;
189 | BYTE u3B;
190 | BYTE r3C, r3D;
191 | BYTE u3E[2];
192 | BYTE r40;
193 | BYTE dma_size; // DMA size in KB
194 | BYTE r42;
195 | BYTE dma_mode; // DMA modes
196 | BYTE u44[3];
197 | BYTE r47;
198 | BYTE u48[0x14];
199 | BYTE r5C; // nand command
200 | // DMA command. |=1 to go, wait until .0 cleared
201 | BYTE dma_cmd;
202 | BYTE u61[0x0B];
203 | BYTE dma1_page; // DMA1 start page. Autoincrements
204 | BYTE u6D[3];
205 | BYTE dma0_page; // DMA0 start page. Autoincrements
206 | BYTE u71[3];
207 | // DMA1 PA. This pseudo reg sets dma1_page actually. RAZ
208 | BYTE dma1_ptr0, dma1_ptr1, dma1_ptr2, dma1_ptr3;
209 | // DMA0 PA. This pseudo reg sets w_dma_page actually. RAZ
210 | BYTE dma0_ptr0, dma0_ptr1, dma0_ptr2, dma0_ptr3;
211 | BYTE u7C[4];
212 | BYTE r80;
213 | BYTE u81[0x1B];
214 | BYTE page_size_l, page_size_h; // 9C full page size with spare
215 | BYTE r9E, r9F;
216 | BYTE uA0[0x4C];
217 | BYTE rEC;
218 | BYTE uED[0x13];
219 | } NANDREGS;
220 |
221 | __xdata __at 0xF400 volatile NANDREGS NFC0;
222 | __xdata __at 0xF500 volatile NANDREGS NFC1;
223 |
224 | __xdata __at 0xF608 volatile BYTE NANDCSOUT;
225 | __xdata __at 0xF618 volatile BYTE NANDCSDIR;
226 | //F638, F639 - scrambler control
227 | //F638 | 18 & 7F - turn off descrambler
228 | __xdata __at 0xF700 volatile NANDREGS NFCX;
229 |
230 | // DMA copy source / fill destination physical address
231 | __xdata __at 0xF900 volatile BYTE DMASRCL;
232 | __xdata __at 0xF901 volatile BYTE DMASRCM;
233 | __xdata __at 0xF902 volatile BYTE DMASRCH;
234 |
235 | // DMA copy destination physical address
236 | __xdata __at 0xF904 volatile BYTE DMADSTL;
237 | __xdata __at 0xF905 volatile BYTE DMADSTM;
238 | __xdata __at 0xF906 volatile BYTE DMADSTH;
239 |
240 | // DMA copy size in bytes (always in bytes, regardless of cmd width)
241 | __xdata __at 0xF908 volatile BYTE DMASIZEL;
242 | __xdata __at 0xF909 volatile BYTE DMASIZEM;
243 | __xdata __at 0xF90A volatile BYTE DMASIZEH;
244 |
245 | // DMA fill value
246 | __xdata __at 0xF90C volatile BYTE DMAFILL0;
247 | __xdata __at 0xF90D volatile BYTE DMAFILL1;
248 | __xdata __at 0xF90E volatile BYTE DMAFILL2;
249 | __xdata __at 0xF90F volatile BYTE DMAFILL3;
250 |
251 | // DMA command
252 | __xdata __at 0xF930 volatile BYTE DMACMD;
253 |
254 | // ------------------------------------------------------------------------------------------------
255 | // Xdata FA00-FAFF SYSTEM Registers
256 | // ------------------------------------------------------------------------------------------------
257 | __xdata __at 0xFA14 volatile BYTE GPIO0DIR;
258 | __xdata __at 0xFA15 volatile BYTE GPIO0OUT;
259 | __xdata __at 0xFA38 volatile BYTE WARMSTATUS;
260 |
261 | // XDATA banking
262 | // XDATA consists of 3 mapped areas: BANK0,1,2
263 | // BANK0 start is fixed at 0000, BANK1,2 starts at variable addresses
264 | // in case of overlapped addresses a bank with higher number has higher priority
265 |
266 | // xdata BANK0 mapping registers
267 | // maps XDATA VA 0000 to PA=BANK0PAH:L<<9, size - up to BANK1/2
268 | __xdata __at 0xFA40 volatile BYTE BANK0PAL;
269 | __xdata __at 0xFA41 volatile BYTE BANK0PAH;
270 |
271 | // xdata BANK1 mapping registers
272 | // maps XDATA VA=(BANK1VA & 0xFE)<<8 to PA=BANK1PAH:L<<9, size - up to BANK2
273 | __xdata __at 0xFA42 volatile BYTE BANK1VA;
274 | __xdata __at 0xFA43 volatile BYTE BANK1PAL;
275 | __xdata __at 0xFA44 volatile BYTE BANK1PAH;
276 |
277 | // xdata BANK2 mapping registers
278 | // maps XDATA VA=(BANK2VA & 0xFE)<<8 to PA=BANK2PAH:L<<9, size - up to F000
279 | __xdata __at 0xFA45 volatile BYTE BANK2VA;
280 | __xdata __at 0xFA46 volatile BYTE BANK2PAL;
281 | __xdata __at 0xFA47 volatile BYTE BANK2PAH;
282 |
283 | // PRAM/PROM switching with restart
284 | // value: bit0 =0 - run from PROM, =1 - run from PRAM. Changing this bit causes CPU restart!
285 | __xdata __at 0xFA48 volatile BYTE PRAMCTL;
286 |
287 | #endif
288 |
--------------------------------------------------------------------------------
/templates/BNdummy.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brandonlw/Psychson/4522989aac27aada5f522675b33a2bde63a13b30/templates/BNdummy.bin
--------------------------------------------------------------------------------
/templates/FWdummy.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brandonlw/Psychson/4522989aac27aada5f522675b33a2bde63a13b30/templates/FWdummy.bin
--------------------------------------------------------------------------------
/tools/hex2bin.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brandonlw/Psychson/4522989aac27aada5f522675b33a2bde63a13b30/tools/hex2bin.exe
--------------------------------------------------------------------------------
/tools/sfk.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brandonlw/Psychson/4522989aac27aada5f522675b33a2bde63a13b30/tools/sfk.exe
--------------------------------------------------------------------------------