Skip to content

Commit c8b92ca

Browse files
fs-builder: Add module to create filesystem in hex files
1 parent ee7081d commit c8b92ca

File tree

4 files changed

+461
-20
lines changed

4 files changed

+461
-20
lines changed

src/__tests__/fs-builder.spec.ts

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
import * as fs from 'fs';
2+
3+
import MemoryMap from 'nrf-intel-hex';
4+
5+
import { strToBytes } from '../common';
6+
import { addFileToIntelHex, testResetFileSystem } from '../fs-builder';
7+
8+
describe('Filesystem Builder', () => {
9+
const uPyHexFile = fs.readFileSync('./src/__tests__/upy-v1.0.1.hex', 'utf8');
10+
11+
it('Add files to hex.', () => {
12+
const files = [
13+
{
14+
fileName: 'test_file_1.py',
15+
fileStr: "from microbit import display\r\ndisplay.show('x')",
16+
},
17+
{
18+
fileName: 'test_file_2.py',
19+
fileStr:
20+
'# Lorem Ipsum is simply dummy text of the printing and\r\n' +
21+
"# typesetting industry. Lorem Ipsum has been the industry's\r\n" +
22+
'# standard dummy text ever since the 1500s, when an unknown\r\n' +
23+
'# printer took a galley of type and scrambled it to make a\r\n' +
24+
'# type specimen book. It has survived not only five\r\n' +
25+
'# centuries, but also the leap into electronic typesetting,\r\n' +
26+
'# remaining essentially unchanged. It was popularised in the\r\n' +
27+
'# 1960s with the release of Letraset sheets containing Lorem\r\n' +
28+
'# Ipsum passages, and more recently with desktop publishing\r\n' +
29+
'# software like Aldus PageMaker including versions of Lorem\r\n' +
30+
'# Ipsum.\r\n' +
31+
'# Lorem Ipsum is simply dummy text of the printing and\r\n' +
32+
"# typesetting industry. Lorem Ipsum has been the industry's\r\n" +
33+
'# standard dummy text ever since the 1500s, when an unknown\r\n' +
34+
'# printer took a galley of type and scrambled it to make a\r\n' +
35+
'# type specimen book. It has survived not only five\r\n' +
36+
'# centuries, but also the leap into electronic typesetting,\r\n' +
37+
'# remaining essentially unchanged. It was popularised in the\r\n' +
38+
'# 1960s with the release of Letraset sheets containing Lorem\r\n' +
39+
'# Ipsum passages, and more recently with desktop publishing\r\n' +
40+
'# software like Aldus PageMaker including versions of Lorem\r\n' +
41+
'# Ipsum.',
42+
},
43+
];
44+
const largeFileHex =
45+
':020000040003F7\n' +
46+
':10C98000FE600E746573745F66696C655F322E704D\n' +
47+
':10C990007923204C6F72656D20497073756D206925\n' +
48+
':10C9A000732073696D706C792064756D6D79207476\n' +
49+
':10C9B000657874206F6620746865207072696E7483\n' +
50+
':10C9C000696E6720616E640D0A2320747970657347\n' +
51+
':10C9D000657474696E6720696E6475737472792EFC\n' +
52+
':10C9E000204C6F72656D20497073756D206861739E\n' +
53+
':10C9F000206265656E2074686520696E6475732DAC\n' +
54+
':10CA00002C74727927730D0A23207374616E64612C\n' +
55+
':10CA100072642064756D6D79207465787420657614\n' +
56+
':10CA200065722073696E63652074686520313530E6\n' +
57+
':10CA300030732C207768656E20616E20756E6B6E8A\n' +
58+
':10CA40006F776E0D0A23207072696E7465722074A0\n' +
59+
':10CA50006F6F6B20612067616C6C6579206F662059\n' +
60+
':10CA60007479706520616E6420736372616D626CAD\n' +
61+
':10CA7000656420697420746F206D616B6520612E80\n' +
62+
':10CA80002D0D0A2320747970652073706563696DBC\n' +
63+
':10CA9000656E20626F6F6B2E204974206861732071\n' +
64+
':10CAA0007375727669766564206E6F74206F6E6C34\n' +
65+
':10CAB0007920666976650D0A232063656E74757248\n' +
66+
':10CAC0006965732C2062757420616C736F207468C3\n' +
67+
':10CAD00065206C65617020696E746F20656C65639C\n' +
68+
':10CAE00074726F6E696320747970657365747469AC\n' +
69+
':10CAF0006E672C0D0A232072656D61696E696E2F59\n' +
70+
':10CB00002E6720657373656E7469616C6C7920752E\n' +
71+
':10CB10006E6368616E6765642E2049742077617367\n' +
72+
':10CB200020706F70756C61726973656420696E2026\n' +
73+
':10CB30007468650D0A2320313936307320776974A3\n' +
74+
':10CB400068207468652072656C65617365206F6626\n' +
75+
':10CB5000204C6574726173657420736865657473C5\n' +
76+
':10CB600020636F6E7461696E696E67204C6F7265C9\n' +
77+
':10CB70006D0D0A2320497073756D207061737330D9\n' +
78+
':10CB80002F616765732C20616E64206D6F72652064\n' +
79+
':10CB9000726563656E746C7920776974682064656A\n' +
80+
':10CBA000736B746F70207075626C697368696E67FF\n' +
81+
':10CBB0000D0A2320736F667477617265206C696B50\n' +
82+
':10CBC0006520416C64757320506167654D616B65CC\n' +
83+
':10CBD0007220696E636C7564696E67207665727326\n' +
84+
':10CBE000696F6E73206F66204C6F72656D0D0A233E\n' +
85+
':10CBF00020497073756D2E0D0A23204C6F726531BC\n' +
86+
':10CC0000306D20497073756D2069732073696D7084\n' +
87+
':10CC10006C792064756D6D792074657874206F6609\n' +
88+
':10CC200020746865207072696E74696E6720616E29\n' +
89+
':10CC3000640D0A23207479706573657474696E6776\n' +
90+
':10CC400020696E6475737472792E204C6F72656DF5\n' +
91+
':10CC500020497073756D20686173206265656E2070\n' +
92+
':10CC600074686520696E64757374727927730D0A30\n' +
93+
':10CC700023207374616E646172642064756D6D321B\n' +
94+
':10CC80003179207465787420657665722073696ED9\n' +
95+
':10CC90006365207468652031353030732C207768E7\n' +
96+
':10CCA000656E20616E20756E6B6E6F776E0D0A2358\n' +
97+
':10CCB000207072696E74657220746F6F6B206120D2\n' +
98+
':10CCC00067616C6C6579206F66207479706520618E\n' +
99+
':10CCD0006E6420736372616D626C65642069742098\n' +
100+
':10CCE000746F206D616B6520610D0A23207479706B\n' +
101+
':10CCF000652073706563696D656E20626F6F6B335D\n' +
102+
':10CD0000322E2049742068617320737572766976BB\n' +
103+
':10CD10006564206E6F74206F6E6C7920666976652D\n' +
104+
':10CD20000D0A232063656E7475726965732C206229\n' +
105+
':10CD3000757420616C736F20746865206C65617018\n' +
106+
':10CD400020696E746F20656C656374726F6E6963C1\n' +
107+
':10CD5000207479706573657474696E672C0D0A238D\n' +
108+
':10CD60002072656D61696E696E6720657373656EAB\n' +
109+
':10CD70007469616C6C7920756E6368616E67653487\n' +
110+
':10CD800033642E2049742077617320706F70756C46\n' +
111+
':10CD900061726973656420696E207468650D0A2389\n' +
112+
':10CDA00020313936307320776974682074686520C3\n' +
113+
':10CDB00072656C65617365206F66204C6574726185\n' +
114+
':10CDC0007365742073686565747320636F6E746136\n' +
115+
':10CDD000696E696E67204C6F72656D0D0A2320497C\n' +
116+
':10CDE0007073756D2070617373616765732C20615A\n' +
117+
':10CDF0006E64206D6F726520726563656E746C354C\n' +
118+
':10CE000034792077697468206465736B746F70205F\n' +
119+
':10CE10007075626C697368696E670D0A2320736FA1\n' +
120+
':10CE2000667477617265206C696B6520416C64750E\n' +
121+
':10CE30007320506167654D616B657220696E636C2C\n' +
122+
':10CE40007564696E672076657273696F6E73206FA3\n' +
123+
':10CE500066204C6F72656D0D0A2320497073756DE5\n' +
124+
':10CE60002EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA3\n' +
125+
':00000001FF';
126+
const largeMap = MemoryMap.fromHex(largeFileHex);
127+
const largeData = largeMap.get(0x3c980);
128+
const shortFileHex =
129+
':020000040003F7\n' +
130+
':10C90000FE3F0E746573745F66696C655F312E70EF\n' +
131+
':10C910007966726F6D206D6963726F6269742069E8\n' +
132+
':10C920006D706F727420646973706C61790D0A6444\n' +
133+
':10C930006973706C61792E73686F7728277827295F\n' +
134+
':10C94000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7\n' +
135+
':10C95000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7\n' +
136+
':10C96000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD7\n' +
137+
':10C97000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7\n' +
138+
':00000001FF';
139+
const shortMap = MemoryMap.fromHex(shortFileHex);
140+
const shortData = shortMap.get(0x3c900);
141+
142+
testResetFileSystem();
143+
let fwWithFsOther = addFileToIntelHex(
144+
uPyHexFile,
145+
files[0].fileName,
146+
strToBytes(files[0].fileStr)
147+
);
148+
fwWithFsOther = addFileToIntelHex(
149+
fwWithFsOther,
150+
files[1].fileName,
151+
strToBytes(files[1].fileStr)
152+
);
153+
// fs.writeFileSync('./ignore/output2.hex', fwWithFsOther);
154+
155+
const opMap = MemoryMap.fromHex(fwWithFsOther);
156+
const opLargeData = opMap.slice(0x3a180, 1264).get(0x3a180);
157+
const opShortData = opMap.slice(0x3a100, 128).get(0x3a100);
158+
expect(opShortData).toEqual(shortData);
159+
expect(opLargeData).toEqual(largeData);
160+
});
161+
});

src/appended-script.ts

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*/
44
import MemoryMap from 'nrf-intel-hex';
55

6-
import { bytesToStr, strToBytes } from './common';
6+
import { bytesToStr, cleanseOldHexFormat, strToBytes } from './common';
77

88
const enum UserCodeBlock {
99
/** User script located at specific flash address. */
@@ -23,22 +23,9 @@ const enum UserCodeBlock {
2323
HeaderStartByte1 = 80, // 'P'
2424
}
2525

26-
/**
27-
* String placed inside the MicroPython hex string to indicate where to
28-
* paste the Python Code
29-
*/
30-
const HEX_INSERTION_POINT = ':::::::::::::::::::::::::::::::::::::::::::\n';
26+
/** How many bytes per Intel Hex record line. */
3127
const HEX_RECORD_DATA_LEN = 16;
3228

33-
/**
34-
* Removes the old insertion line the input Intel Hex string contains it.
35-
* @param intelHex String with the intel hex lines.
36-
* @returns The Intel Hex string without insertion line.
37-
*/
38-
function cleanseOldHexFormat(intelHex: string): string {
39-
return intelHex.replace(HEX_INSERTION_POINT, '');
40-
}
41-
4229
/**
4330
* Parses through an Intel Hex string to find the Python code at the
4431
* allocated address and extracts it.
@@ -111,4 +98,22 @@ function appendScriptToIntelHex(intelHex: string, pyCode: string): string {
11198
return intelHexMap.asHexString() + '\n';
11299
}
113100

114-
export { appendScriptToIntelHex, getScriptFromIntelHex };
101+
/**
102+
* Checks the Intel Hex memory map to see if there is an appended script.
103+
*
104+
* TODO: Actually implement this.
105+
* At the moment this is only used in the fs-builder and we are not yet
106+
* implementing this feature.
107+
* @param intelHex
108+
* @returns True if present.
109+
*/
110+
function isAppendedScriptPresent(intelHexMap: object): boolean {
111+
return false;
112+
}
113+
114+
export {
115+
UserCodeBlock,
116+
appendScriptToIntelHex,
117+
getScriptFromIntelHex,
118+
isAppendedScriptPresent,
119+
};

src/common.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,28 @@
22
* General utilities.
33
*/
44

5+
/**
6+
* String placed inside the MicroPython hex string to indicate where to
7+
* paste the Python Code
8+
*/
9+
const HEX_INSERTION_POINT = ':::::::::::::::::::::::::::::::::::::::::::\n';
10+
11+
/**
12+
* Removes the old insertion line the input Intel Hex string contains it.
13+
* @param intelHex String with the intel hex lines.
14+
* @returns The Intel Hex string without insertion line.
15+
*/
16+
export function cleanseOldHexFormat(intelHex: string): string {
17+
return intelHex.replace(HEX_INSERTION_POINT, '');
18+
}
19+
520
/**
621
* Converts a string into a byte array of characters.
722
* TODO: Update to encode to UTF-8 correctly.
823
* @param str - String to convert to bytes.
924
* @returns A byte array with the encoded data.
1025
*/
11-
function strToBytes(str: string): Uint8Array {
26+
export function strToBytes(str: string): Uint8Array {
1227
const data: Uint8Array = new Uint8Array(str.length);
1328
for (let i: number = 0; i < str.length; i++) {
1429
// TODO: This will only keep the LSB from the UTF-16 code points
@@ -24,10 +39,8 @@ function strToBytes(str: string): Uint8Array {
2439
* @param byteArray - Array of bytes to convert.
2540
* @returns String output from the conversion.
2641
*/
27-
function bytesToStr(byteArray: Uint8Array): string {
42+
export function bytesToStr(byteArray: Uint8Array): string {
2843
const result: string[] = [];
2944
byteArray.forEach((element) => result.push(String.fromCharCode(element)));
3045
return result.join('');
3146
}
32-
33-
export { strToBytes, bytesToStr };

0 commit comments

Comments
 (0)