summaryrefslogtreecommitdiffstats
path: root/assets
diff options
context:
space:
mode:
Diffstat (limited to 'assets')
-rw-r--r--assets/js/rootLantiq.js141
-rw-r--r--assets/js/xymini.js147
2 files changed, 280 insertions, 8 deletions
diff --git a/assets/js/rootLantiq.js b/assets/js/rootLantiq.js
index ff0f478..570133c 100644
--- a/assets/js/rootLantiq.js
+++ b/assets/js/rootLantiq.js
@@ -1,20 +1,28 @@
-async function waitUbootStop(writer, reader, sfpModel, outputMsgCallback) {
- const interval = setInterval(function() {
- writer.write(String.fromCharCode(3));
- }, 10);
+const LOAD_ADDR = "80800000"
+const IMAGE0_ADDR = "C0000 740000";
+const IMAGE1_ADDR = "800000 800000";
+async function detectUboot(reader) {
while (true) {
const { value, done } = await reader.read();
if (value.startsWith('U-Boot')) {
- outputMsgCallback(`Root in progress: Trigger characters received. DO NOT TOUCH THE ${sfpModel} UNTIL THE PROCEDURE IS COMPLETED!`);
- await delay(5000);
- clearInterval(interval);
- break;
+ return;
}
}
}
+async function waitUbootStop(writer, reader, sfpModel, outputMsgCallback) {
+ const interval = setInterval(function() {
+ writer.write(String.fromCharCode(3));
+ }, 10);
+
+ await detectUboot(reader);
+ outputMsgCallback(`Root in progress: Trigger characters received. DO NOT TOUCH THE ${sfpModel} UNTIL THE PROCEDURE IS COMPLETED!`);
+ await delay(5000);
+ clearInterval(interval);
+}
+
async function checkUbootUnlocked(reader) {
while (true) {
try {
@@ -131,3 +139,120 @@ async function unlockHuaweiShell(port, outputMsgCallback, outputErrorCallback, b
return false;
}
}
+
+async function changeBaudrate(port, newBaudrate, currBaudrate, outputErrorCallback) {
+ let reader,writer, readableStreamClosed, writerStreamClosed;
+
+ try {
+ ({ reader, writer, readableStreamClosed, writerStreamClosed } = await openPortLineBreak(port, currBaudrate));
+ await writer.write(`setenv baudrate ${newBaudrate}\n`);
+ await delay(1000);
+ await closePortLineBreak(port, reader, writer, readableStreamClosed, writerStreamClosed);
+ ({ reader, writer, readableStreamClosed, writerStreamClosed } = await openPortLineBreak(port, newBaudrate));
+
+ const interval = setInterval(function() {
+ writer.write(String.fromCharCode(13));
+ }, 10);
+
+ while (true) {
+ const { value, done } = await reader.read();
+
+ if (value.startsWith('FALCON')) {
+ clearInterval(interval);
+ break;
+ }
+ }
+
+ await closePortLineBreak(port, reader, writer, readableStreamClosed, writerStreamClosed);
+ return true;
+ } catch (err) {
+ outputErrorCallback(`Error: ${err.message}`);
+ await closePortLineBreak(port, reader, writer, readableStreamClosed, writerStreamClosed);
+ return false;
+ }
+}
+
+async function sendImageMtd(port, data, baudRate, outputErrorCallback, progressCallback) {
+ let reader,writer, readableStreamClosed, writerStreamClosed;
+
+ try {
+ ({ reader, writer, readableStreamClosed, writerStreamClosed } = await openPortLineBreak(port, baudRate));
+ await writer.write(`loady 0x${LOAD_ADDR}\n`);
+ await delay(1000);
+ await closePortLineBreak(port, reader, writer, readableStreamClosed, writerStreamClosed); /* XYMini needs reopen the port */
+ } catch (err) {
+ outputErrorCallback(`Error: ${err.message}`);
+ await closePortLineBreak(port, reader, writer, readableStreamClosed, writerStreamClosed);
+ return false;
+ }
+
+ try {
+ await port.open({ baudRate: baudRate });
+ reader = port.readable.getReader();
+ writer = port.writable.getWriter();
+
+ await sendXYMini(reader, writer, data, baudRate,
+ (byteTransfered) => {
+ progressCallback(byteTransfered);
+ }
+ );
+ await reader.cancel();
+ await writer.close();
+ await port.close();
+ return true;
+ } catch (err) {
+ await reader.cancel();
+ await writer.close();
+ await port.close();
+ outputErrorCallback(`Error: ${err.message}`);
+ return false;
+ }
+}
+
+async function waitEndImageLoad(port, baudRate, outputErrorCallback) {
+ let reader, writer, readableStreamClosed, writerStreamClosed;
+
+ try {
+ ({ reader, writer, readableStreamClosed, writerStreamClosed } = await openPortLineBreak(port, baudRate));
+
+ while (true) {
+ const { value, done } = await reader.read();
+
+ if (value.includes('Total Size')) {
+ break;
+ }
+ }
+
+ await(1000);
+ await closePortLineBreak(port, reader, writer, readableStreamClosed, writerStreamClosed);
+ return true;
+ } catch (err) {
+ outputErrorCallback(`Error: ${err.message}`);
+ await closePortLineBreak(port, reader, writer, readableStreamClosed, writerStreamClosed);
+ return false;
+ }
+}
+
+async function flashImageMtd(port, image, baudRate, outputErrorCallback) {
+ let reader, writer, readableStreamClosed, writerStreamClosed;
+
+ try {
+ ({ reader, writer, readableStreamClosed, writerStreamClosed } = await openPortLineBreak(port, baudRate));
+ if (image == "image0") {
+ await writer.write(`sf probe 0 && sf erase ${IMAGE0_ADDR} && sf write ${LOAD_ADDR} ${IMAGE0_ADDR} && setenv committed_image 0 && setenv image0_is_valid 1 && saveenv && reset\n`);
+ } else {
+ await writer.write(`sf probe 0 && sf erase ${IMAGE1_ADDR} && sf write ${LOAD_ADDR} ${IMAGE1_ADDR} && setenv committed_image 1 && setenv image1_is_valid 1 && saveenv && reset\n`);
+ }
+
+ await delay(1000);
+
+ /* Wait to avoid the user from disconnecting the SFP while the image is being flashed */
+ await detectUboot(reader);
+ await closePortLineBreak(port, reader, writer, readableStreamClosed, writerStreamClosed);
+ return true;
+ } catch (err) {
+ outputErrorCallback(`Error: ${err.message}`);
+ await closePortLineBreak(port, reader, writer, readableStreamClosed, writerStreamClosed);
+ return false;
+ }
+}
diff --git a/assets/js/xymini.js b/assets/js/xymini.js
new file mode 100644
index 0000000..a1fd1ca
--- /dev/null
+++ b/assets/js/xymini.js
@@ -0,0 +1,147 @@
+/* XYMini Sender - Minimal implementation of file transfer through serial
+ * Copyright (C) Ernesto Castellotti <mail@ernestocastellotti.it>
+ * SPDX-License-Identifier: MPL-2.0-no-copyleft-exception
+ *
+ * Warning: This does not comply with XMODEM and YMODEM standards
+*/
+
+const STX = 0x02;
+const ACK = 0x06;
+const NAK = 0x15;
+const EOF = 0x04;
+const XYMINI_1K_MAGIC = 0x43;
+const PAYLOAD_LEN = 1024;
+const BLOCK_LEN = PAYLOAD_LEN + 5;
+const CRC_POLY = 0x1021;
+
+function uint16 (n) {
+ return n & 0xFFFF;
+}
+
+function updateCrc(crcIn, incr) {
+ const xor = uint16(crcIn >> 15);
+ let result = uint16(crcIn << 1);
+
+ if (incr) {
+ result = uint16(result + 1);
+ }
+
+ if (xor) {
+ result = uint16(result ^= CRC_POLY);
+ }
+
+ return result;
+}
+
+function crc16(data) {
+ let crc;
+
+ for (let i = 0; i < data.length; i++) {
+ for (let j = 0x80; j; j >>= 1) {
+ crc = updateCrc(crc, data[i] & j);
+ }
+ }
+
+ for (let n = 0; n < 16; n++) {
+ crc = updateCrc(crc, 0);
+ }
+
+ return crc;
+}
+
+async function detectXYMini(reader) {
+ const textDecoder = new TextDecoder();
+
+ while (true) {
+ const { value, done } = await reader.read();
+
+ if (value[0] == XYMINI_1K_MAGIC) {
+ console.log("XYMini: detected");
+ break;
+ }
+ }
+}
+
+function generateXYMiniBlock(blockId, payload) {
+ let buf = new Uint8Array(BLOCK_LEN);
+ let i = 0;
+
+ buf[i++] = STX;
+ buf[i++] = blockId;
+ buf[i++] = 0xFF - blockId;
+
+ if (payload.length > PAYLOAD_LEN) {
+ throw new Error("Payload too large to be transmitted in one block");
+ }
+
+ for (let j = 0; j < payload.length; j++) {
+ buf[i++] = payload[j];
+ }
+
+ while (i < BLOCK_LEN - 2) {
+ buf[i++] = 0xFF;
+ }
+
+ let crcBuf = buf.slice(3, PAYLOAD_LEN + 3)
+ let crc = crc16(crcBuf);
+
+ buf[i++] = (crc >> 8) & 0xFF;
+ buf[i++] = crc & 0xFF;
+
+ return buf;
+}
+
+async function sendXYMini(portReader, portWriter, data, baudRate = 115200, progressCallback) {
+ let blockId = 1;
+ let size = data.length;
+ let i = 0;
+ let nakN = 0;
+ let wrongCharN = 0;
+
+ await detectXYMini(portReader);
+
+ while(true) {
+ const payloadSize = Math.min(PAYLOAD_LEN, size);
+
+ if (size) {
+ const payload = data.slice(i, payloadSize + i);
+
+ const block = generateXYMiniBlock(blockId, payload);
+ await portWriter.write(block);
+ } else {
+ portWriter.write(new Uint8Array([EOF]));
+ }
+
+ const { value, done } = await portReader.read();
+
+ if (value[0] == ACK) {
+ if (!size) {
+ console.log("XYMini: End of transmission");
+
+ return;
+ }
+
+ blockId++;
+ size -= payloadSize;
+ i += payloadSize;
+ nakN = 0;
+ wrongCharN = 0;
+ progressCallback(data.length - size);
+ } else if (value[0] == NAK) {
+ if (nakN >= 10) {
+ throw new Error("Received 10 NAK, receiver is rejecting file transmission");
+ }
+
+ console.log("XYMini: NAK");
+ nakN++;
+ } else {
+ if (wrongCharN >= 30) {
+ throw new Error("Received 30 wrong characters, the receiver is rejecting the transmission or the connection is too noisy");
+ }
+
+ console.log("XYMini: wrong character");
+ console.log(value);
+ wrongCharN++;
+ }
+ }
+}