BlTools.Mod 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. MODULE BlTools;
  2. (**
  3. AUTHOR Timothée Martiel, 01/2016
  4. PURPOSE Command interface to Bootloader
  5. *)
  6. IMPORT
  7. Commands, Files, Streams, Strings,
  8. CryptoHashes, CryptoUtils,
  9. TFTPServer,
  10. BlCommands;
  11. CONST
  12. ArgError * = 1;
  13. ExecError * = 2;
  14. TYPE
  15. Resource = POINTER TO RECORD
  16. file, resource: ARRAY 256 OF CHAR;
  17. next: Resource
  18. END;
  19. VAR
  20. session: BlCommands.Session;
  21. resources: Resource;
  22. (** StartSession (ip address | 'UART') *)
  23. PROCEDURE StartSession * (context: Commands.Context);
  24. VAR
  25. udp: BlCommands.UdpSession;
  26. uart: BlCommands.UartSession;
  27. arg: ARRAY 32 OF CHAR;
  28. uartPort: LONGINT;
  29. BEGIN
  30. IF context.arg.GetString(arg) THEN
  31. IF arg = 'UART' THEN
  32. IF ~context.arg.GetInteger(uartPort, FALSE) THEN
  33. context.error.String("Error: expected COM port number");
  34. context.error.Ln;
  35. context.result := 1;
  36. RETURN
  37. END;
  38. NEW(uart, uartPort);
  39. session := uart;
  40. context.out.String("Session established");
  41. context.out.Ln
  42. ELSE
  43. TFTPServer.Stop;
  44. NEW(udp, arg);
  45. IF udp # NIL THEN
  46. TRACE(udp);
  47. session := udp;
  48. resources := NIL;
  49. context.out.String("Session established");
  50. context.out.Ln
  51. ELSE
  52. context.error.String("Error: invalid IP address");
  53. context.error.Ln;
  54. context.result := ArgError
  55. END
  56. END
  57. ELSE
  58. context.error.String("Error: expected IP address or 'UART'");
  59. context.error.Ln;
  60. context.result := ArgError
  61. END
  62. END StartSession;
  63. PROCEDURE StopSession * (context : Commands.Context);
  64. BEGIN
  65. session.Close;
  66. context.out.String("Session stopped");
  67. context.out.Ln
  68. END StopSession;
  69. (** Load filename resourcename ~ *)
  70. PROCEDURE Load * (context : Commands.Context);
  71. VAR
  72. file, resource: ARRAY 256 OF CHAR;
  73. r: Resource;
  74. BEGIN
  75. IF session = NIL THEN
  76. context.error.String("Error: no session started yet. Please call BlTools.SelectBoard first");
  77. context.error.Ln;
  78. RETURN
  79. END;
  80. IF context.arg.GetString(file) THEN
  81. IF context.arg.GetString(resource) THEN
  82. IF session.Load(file, resource) THEN
  83. context.out.String(resource);
  84. NEW(r);
  85. COPY(file, r.file);
  86. COPY(resource, r.resource);
  87. r.next := resources;
  88. resources := r;
  89. context.out.String(" loaded");
  90. context.out.Ln
  91. ELSE
  92. context.error.String(session.ack);
  93. context.error.Ln;
  94. context.result := ExecError
  95. END
  96. ELSE
  97. context.error.String("Error: expected resource name");
  98. context.error.Ln;
  99. context.result := ArgError
  100. END
  101. ELSE
  102. context.error.String("Error: expected file name");
  103. context.error.Ln;
  104. context.result := ArgError
  105. END
  106. END Load;
  107. (** Program resource destination [options] ~ *)
  108. PROCEDURE Program * (context : Commands.Context);
  109. VAR
  110. resource, dest: ARRAY 256 OF CHAR;
  111. mem: BlCommands.MemoryDest;
  112. zfpga: BlCommands.ZynqFpgaDest;
  113. file: BlCommands.FileDest;
  114. i: LONGINT;
  115. BEGIN
  116. IF context.arg.GetString(resource) THEN
  117. IF context.arg.GetString(dest) THEN
  118. IF dest = "ZynqFpga" THEN
  119. IF session.Program(resource, zfpga) THEN
  120. context.out.String("Programming FPGA done");
  121. context.out.Ln
  122. ELSE
  123. context.error.String(session.ack);
  124. context.error.Ln;
  125. context.result := ExecError
  126. END
  127. ELSIF dest = "memory" THEN
  128. IF context.arg.GetInteger(mem.address, TRUE) THEN
  129. WHILE context.arg.GetInteger(i, TRUE) DO INCL(mem.cpus, i) END;
  130. IF session.Program(resource, mem) THEN
  131. context.out.String("Programming ARM done");
  132. context.out.Ln
  133. ELSE
  134. context.error.String(session.ack);
  135. context.error.Ln;
  136. context.result := ExecError
  137. END
  138. ELSE
  139. context.error.String("Error: expected load address");
  140. context.error.Ln;
  141. context.result := ArgError
  142. END
  143. ELSIF dest = "file" THEN
  144. IF context.arg.GetString(file.name) THEN
  145. IF session.Program(resource, file) THEN
  146. context.out.String("Programming file done");
  147. context.out.Ln
  148. ELSE
  149. context.error.String(session.ack);
  150. context.error.Ln;
  151. context.result := ExecError
  152. END
  153. ELSE
  154. context.error.String("Error: expected file name");
  155. context.error.Ln;
  156. context.result := ArgError
  157. END
  158. ELSE
  159. context.error.String("Error: unknown destination '");
  160. context.error.String(dest);
  161. context.error.String("'.");
  162. context.error.Ln;
  163. context.result := ArgError
  164. END
  165. ELSE
  166. context.error.String("Error: expected destination");
  167. context.error.Ln;
  168. context.result := ArgError
  169. END
  170. ELSE
  171. context.error.String("Error: expected resource name");
  172. context.error.Ln;
  173. context.result := ArgError
  174. END
  175. END Program;
  176. (** Check resource algorithm *)
  177. PROCEDURE Check * (context : Commands.Context);
  178. VAR
  179. buffer: ARRAY 1024 OF CHAR;
  180. reference, resource: ARRAY 256 OF CHAR;
  181. algorithm, hashName: ARRAY 32 OF CHAR;
  182. hash: CryptoHashes.Hash;
  183. file: Files.File;
  184. reader: Files.Reader;
  185. r: Resource;
  186. len: LONGINT;
  187. BEGIN
  188. IF context.arg.GetString(resource) THEN
  189. IF context.arg.GetString(algorithm) THEN
  190. (* Get hash object *)
  191. hashName := "Crypto";
  192. Strings.Append(hashName, algorithm);
  193. hash := CryptoHashes.NewHash(hashName);
  194. IF hash = NIL THEN
  195. context.error.String("Error: unknown hash algorithm: ");
  196. context.error.String(algorithm);
  197. context.error.String(' (module ');
  198. context.error.String(hashName);
  199. context.error.String(' not found)');
  200. context.error.Ln;
  201. context.result := ArgError;
  202. RETURN
  203. END;
  204. (* Get & read file *)
  205. r := resources;
  206. WHILE (r # NIL) & (r.resource # resource) DO r := r.next END;
  207. IF r = NIL THEN
  208. context.error.String("Error: could not find the resource: ");
  209. context.error.String(resource);
  210. context.error.Ln;
  211. context.result := ArgError;
  212. RETURN
  213. END;
  214. file := Files.Old(r.file);
  215. IF file = NIL THEN
  216. context.error.String("Error: could not open file ");
  217. context.error.String(r.file);
  218. context.error.Ln;
  219. context.result := ArgError;
  220. RETURN
  221. END;
  222. Files.OpenReader(reader, file, 0);
  223. IF reader = NIL THEN
  224. context.error.String("Error: could not read file ");
  225. context.error.String(r.file);
  226. context.error.Ln;
  227. context.result := ArgError;
  228. RETURN
  229. END;
  230. hash.Initialize;
  231. WHILE reader.res = Streams.Ok DO
  232. reader.Bytes(buffer, 0, LEN(buffer), len);
  233. hash.Update(buffer, 0, len)
  234. END;
  235. hash.GetHash(buffer, 0);
  236. CryptoUtils.Bin2Hex(buffer, 0, reference, 0, hash.size);
  237. (* Send command *)
  238. IF session.Check(resource, algorithm, reference) THEN
  239. context.out.String("Hash check succeeded");
  240. context.out.Ln
  241. ELSE
  242. context.error.String(session.ack);
  243. context.error.Ln;
  244. context.result := ExecError
  245. END
  246. ELSE
  247. context.error.String("Error: expected algorithm name");
  248. context.error.Ln;
  249. context.result := ArgError
  250. END
  251. ELSE
  252. context.error.String("Error: expected resource name");
  253. context.error.Ln;
  254. context.result := ArgError
  255. END
  256. END Check;
  257. PROCEDURE Save * (context: Commands.Context);
  258. VAR
  259. resource: ARRAY 256 OF CHAR;
  260. BEGIN
  261. IF ~context.arg.GetString(resource) THEN
  262. context.error.String("Error: expected resource name");
  263. context.error.Ln;
  264. context.result := ArgError;
  265. RETURN
  266. END;
  267. IF session.Save(resource) THEN
  268. context.out.String("Resource saved");
  269. context.out.Ln;
  270. ELSE
  271. context.error.String(session.ack);
  272. context.error.Ln;
  273. context.result := ExecError
  274. END;
  275. END Save;
  276. PROCEDURE Start * (context : Commands.Context);
  277. BEGIN
  278. IF session.Start() THEN
  279. context.out.String("Application started");
  280. context.out.Ln
  281. ELSE
  282. context.error.String(session.ack);
  283. context.error.Ln;
  284. context.result := ExecError
  285. END
  286. END Start;
  287. PROCEDURE Mount * (context: Commands.Context);
  288. VAR
  289. prefix, disk: ARRAY 128 OF CHAR;
  290. partition: LONGINT;
  291. BEGIN
  292. IF ~context.arg.GetString(prefix) THEN
  293. context.error.String("Error: expected prefix");
  294. context.error.Ln;
  295. context.result := ExecError;
  296. RETURN
  297. END;
  298. IF ~context.arg.GetString(disk) THEN
  299. context.error.String("Error: expected disk name");
  300. context.error.Ln;
  301. context.result := ExecError;
  302. RETURN
  303. END;
  304. IF ~context.arg.GetInteger(partition, FALSE) THEN
  305. context.error.String("Error: expected partition id");
  306. context.error.Ln;
  307. context.result := ExecError;
  308. RETURN
  309. END;
  310. IF session.Mount(prefix, disk, partition) THEN
  311. context.out.String(disk);
  312. context.out.Char('#');
  313. context.out.Int(partition, 0);
  314. context.out.String(" mounted as ");
  315. context.out.String(prefix);
  316. context.out.Ln
  317. ELSE
  318. context.error.String(session.ack);
  319. context.error.Ln;
  320. context.result := ExecError
  321. END
  322. END Mount;
  323. (** SetSource protocol [options] ~ *)
  324. PROCEDURE SetSource * (context : Commands.Context);
  325. VAR
  326. protocol: ARRAY 32 OF CHAR;
  327. tftp: BlCommands.TftpSource;
  328. BEGIN
  329. IF session = NIL THEN
  330. context.error.String("Error: no session started yet. Please call BlTools.SelectBoard first");
  331. context.error.Ln;
  332. RETURN
  333. END;
  334. IF context.arg.GetString(protocol) THEN
  335. IF protocol = "TFTP" THEN
  336. IF context.arg.GetString(tftp.host) THEN
  337. IF session.SetSource(tftp) THEN
  338. TFTPServer.Start;
  339. context.out.String("Data source set");
  340. context.out.Ln
  341. ELSE
  342. context.error.String(session.ack);
  343. context.error.Ln;
  344. context.result := ExecError
  345. END
  346. ELSE
  347. context.error.String("Error: expected hostname");
  348. context.error.Ln;
  349. context.result := ArgError
  350. END
  351. ELSE
  352. context.error.String("Error: unknown protocol '");
  353. context.error.String(protocol);
  354. context.error.String("'.");
  355. context.error.Ln;
  356. context.result := ArgError
  357. END
  358. ELSE
  359. context.error.String("Error: expected protocol name");
  360. context.error.Ln;
  361. context.result := ArgError
  362. END
  363. END SetSource;
  364. (* SetInput (UDP|UART|file) ~ *)
  365. PROCEDURE SetInput*(context : Commands.Context);
  366. VAR
  367. input: ARRAY 256 OF CHAR;
  368. BEGIN
  369. IF context.arg.GetString(input) THEN
  370. IF session.SetInput(input) THEN
  371. context.out.String("Change input done");
  372. context.out.Ln
  373. ELSE
  374. context.out.String(session.ack);
  375. context.out.Ln;
  376. context.result := ExecError
  377. END
  378. ELSE
  379. context.out.String("Error: expected input");
  380. context.out.Ln;
  381. context.result := ArgError
  382. END
  383. END SetInput;
  384. PROCEDURE Timeout*(context: Commands.Context);
  385. VAR
  386. time: LONGINT;
  387. BEGIN
  388. IF context.arg.GetInteger(time, FALSE) THEN
  389. IF session.SetTimeout(time) THEN
  390. context.out.String("Timeout set");
  391. context.out.Ln
  392. ELSE
  393. context.out.String(session.ack);
  394. context.out.Ln;
  395. context.result := ExecError
  396. END
  397. ELSE
  398. context.out.String("Error: Expected timeout value");
  399. context.out.Ln
  400. END
  401. END Timeout;
  402. PROCEDURE Reset * (context: Commands.Context);
  403. BEGIN
  404. IF session.Reset() THEN
  405. context.out.String("Bootloader reset");
  406. context.out.Ln
  407. ELSE
  408. context.error.String(session.ack);
  409. context.error.Ln;
  410. context.result := ExecError
  411. END
  412. END Reset;
  413. PROCEDURE Command * (context: Commands.Context);
  414. VAR
  415. cmd: ARRAY 1024 OF CHAR;
  416. len: LONGINT;
  417. BEGIN
  418. context.arg.Bytes(cmd, 0, context.arg.Available(), len);
  419. IF session.ExecuteCommand(cmd) THEN
  420. context.out.String("Command ");
  421. context.out.String(cmd);
  422. context.out.String(" successful");
  423. context.out.Ln
  424. ELSE
  425. context.out.String(session.ack);
  426. context.out.Ln;
  427. context.result := ExecError
  428. END
  429. END Command;
  430. PROCEDURE Deploy * (context : Commands.Context);
  431. BEGIN
  432. END Deploy;
  433. END BlTools.
  434. TFTPServer.Start
  435. SystemTools.DoCommands
  436. BlTools.StartSession 10.3.34.8 ~
  437. BlTools.SetSource TFTP 10.3.34.145 ~
  438. BlTools.Load TestFifo.bin bs ~
  439. BlTools.Check bs MD5 ~
  440. BlTools.Program bs ZynqFpga ~
  441. BlTools.Load A2.Bin a2 ~
  442. BlTools.Check a2 MD5 ~
  443. BlTools.Program a2 memory 100000H 0 1 ~
  444. BlTools.Program a3 ZynqFpga ~
  445. BlTools.Start ~
  446. BlTools.StopSession ~
  447. ~
  448. SystemTools.DoCommands
  449. BlTools.StartSession 10.3.34.8 ~
  450. BlTools.SetSource TFTP 10.3.34.145 ~
  451. BlTools.Load A2.Bin a2 ~
  452. BlTools.Check a2 MD5 ~
  453. BlTools.Program a2 memory 100000H 0 1 ~
  454. BlTools.Start ~
  455. BlTools.StopSession ~
  456. ~
  457. BlTools.SetInput UART ~
  458. SystemTools.DoCommands
  459. BlTools.StartSession 10.3.34.8 ~
  460. BlTools.SetSource TFTP 10.3.34.145 ~
  461. BlTools.Timeout 1 ~
  462. BlTools.StopSession ~
  463. ~