diff --git a/server/src/Controllers.cs b/server/src/Controllers.cs
index 80365ed..968ab0a 100644
--- a/server/src/Controllers.cs
+++ b/server/src/Controllers.cs
@@ -1,6 +1,6 @@
-using System.Buffers.Binary;
using System.Net;
using Common;
+using DotNext;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
@@ -143,6 +143,8 @@ public class JtagController : ControllerBase
{
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
+ private const string BITSTREAM_PATH = "bitstream/Jtag";
+
///
/// 页面
///
@@ -244,7 +246,7 @@ public class JtagController : ControllerBase
// 生成安全的文件名(避免路径遍历攻击)
var fileName = Path.GetRandomFileName();
- var uploadsFolder = Path.Combine(Environment.CurrentDirectory, $"bitstream/{address}");
+ var uploadsFolder = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}");
// 如果存在文件,则删除原文件再上传
if (Directory.Exists(uploadsFolder))
@@ -276,7 +278,7 @@ public class JtagController : ControllerBase
public async ValueTask DownloadBitstream(string address, int port)
{
// 检查文件
- var fileDir = Path.Combine(Environment.CurrentDirectory, $"bitstream/{address}");
+ var fileDir = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}");
if (!Directory.Exists(fileDir))
return TypedResults.BadRequest("Empty bitstream, Please upload it first");
@@ -306,10 +308,6 @@ public class JtagController : ControllerBase
if (!retBuffer.IsSuccessful)
return TypedResults.InternalServerError(retBuffer.Error);
revBuffer = retBuffer.Value;
- // for (int i = 0; i < buffer.Length; i++)
- // {
- // revBuffer[i] = Common.Number.ReverseBits(revBuffer[i]);
- // }
await memoryStream.WriteAsync(revBuffer, 0, bytesRead);
totalBytesRead += bytesRead;
@@ -357,22 +355,36 @@ public class RemoteUpdater : ControllerBase
{
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
+ private const string BITSTREAM_PATH = "bitstream/RemoteUpdate";
+
///
/// 上传远程更新比特流文件
///
/// 设备地址
- /// 比特流文件
+ /// 黄金比特流文件
+ /// 比特流文件1
+ /// 比特流文件2
+ /// 比特流文件3
+ /// 上传结果
[HttpPost("UploadBitstream")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
- public async ValueTask UploadBitstream(string address, IFormFile file)
+ public async ValueTask UploadBitstreams(
+ string address,
+ IFormFile? goldenBitream,
+ IFormFile? bitstream1,
+ IFormFile? bitstream2,
+ IFormFile? bitstream3)
{
- if (file == null || file.Length == 0)
+ if ((goldenBitream is null || goldenBitream.Length == 0) &&
+ (bitstream1 is null || bitstream1.Length == 0) &&
+ (bitstream2 is null || bitstream2.Length == 0) &&
+ (bitstream3 is null || bitstream3.Length == 0))
return TypedResults.BadRequest("未选择文件");
// 生成安全的文件名(避免路径遍历攻击)
var fileName = Path.GetRandomFileName();
- var uploadsFolder = Path.Combine(Environment.CurrentDirectory, $"bitstream/RemoteUpdate/{address}");
+ var uploadsFolder = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}");
// 如果存在文件,则删除原文件再上传
if (Directory.Exists(uploadsFolder))
@@ -381,19 +393,79 @@ public class RemoteUpdater : ControllerBase
}
Directory.CreateDirectory(uploadsFolder);
- var filePath = Path.Combine(uploadsFolder, fileName);
-
- using (var stream = new FileStream(filePath, FileMode.Create))
+ for (int bitstreamNum = 0; bitstreamNum < 4; bitstreamNum++)
{
- await file.CopyToAsync(stream);
+ IFormFile file;
+ if (bitstreamNum == 0 && goldenBitream is not null)
+ file = goldenBitream;
+ else if (bitstreamNum == 1 && bitstream1 is not null)
+ file = bitstream1;
+ else if (bitstreamNum == 2 && bitstream2 is not null)
+ file = bitstream2;
+ else if (bitstreamNum == 3 && bitstream3 is not null)
+ file = bitstream3;
+ else continue;
+
+ var fileFolder = Path.Combine(uploadsFolder, bitstreamNum.ToString());
+ Directory.CreateDirectory(fileFolder);
+
+ var filePath = Path.Combine(fileFolder, fileName);
+
+ using (var stream = new FileStream(filePath, FileMode.Create))
+ {
+ await file.CopyToAsync(stream);
+ }
}
logger.Info($"Device {address} Upload Bitstream Successfully");
return TypedResults.Ok("Bitstream Upload Successfully");
}
+ private async ValueTask> ProcessBitstream(string filePath)
+ {
+ using (var fileStream = System.IO.File.Open(filePath, System.IO.FileMode.Open))
+ {
+ if (fileStream is null || fileStream.Length <= 0)
+ return new(new ArgumentException("Wrong bitstream path"));
+
+ // 定义缓冲区大小: 32KB
+ byte[] buffer = new byte[32 * 1024];
+ byte[] revBuffer = new byte[32 * 1024];
+ long totalBytesRead = 0;
+
+ // 使用异步流读取文件
+ using (var memoryStream = new MemoryStream())
+ {
+ int bytesRead;
+ while ((bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
+ {
+ // 反转 32bits
+ var retBuffer = Common.Number.ReverseBytes(buffer, 4);
+ if (!retBuffer.IsSuccessful)
+ return new(retBuffer.Error);
+ revBuffer = retBuffer.Value;
+
+ await memoryStream.WriteAsync(revBuffer, 0, bytesRead);
+ totalBytesRead += bytesRead;
+ }
+
+ // 将所有数据转换为字节数组(注意:如果文件非常大,可能不适合完全加载到内存)
+ var restStreamLen = memoryStream.Length % (4 * 1024);
+ if (restStreamLen != 0)
+ {
+ var appendLen = ((int)(4 * 1024 - restStreamLen));
+ var bytesAppend = new byte[appendLen];
+ Array.Fill(bytesAppend, 0xFF);
+ await memoryStream.WriteAsync(bytesAppend, 0, appendLen);
+ }
+
+ return new(memoryStream.ToArray());
+ }
+ }
+ }
+
///
- /// 远程更新比特流文件
+ /// 远程更新单个比特流文件
///
/// 设备地址
/// 设备端口
@@ -405,7 +477,7 @@ public class RemoteUpdater : ControllerBase
public async ValueTask UpdateBitstream(string address, int port, int bitstreamNum)
{
// 检查文件
- var fileDir = Path.Combine(Environment.CurrentDirectory, $"bitstream/RemoteUpdate/{address}");
+ var fileDir = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}/{bitstreamNum}");
if (!Directory.Exists(fileDir))
return TypedResults.BadRequest("Empty bitstream, Please upload it first");
@@ -414,63 +486,22 @@ public class RemoteUpdater : ControllerBase
// 读取文件
var filePath = Directory.GetFiles(fileDir)[0];
- using (var fileStream = System.IO.File.Open(filePath, System.IO.FileMode.Open))
+ var fileBytes = await ProcessBitstream(filePath);
+ if (!fileBytes.IsSuccessful) return TypedResults.InternalServerError(fileBytes.Error);
+
+ // 下载比特流
+ var remoteUpdater = new RemoteUpdate.RemoteUpdateClient(address, port);
+ var ret = await remoteUpdater.UpdateBitstream(bitstreamNum, fileBytes.Value);
+
+ if (ret.IsSuccessful)
{
- if (fileStream is null || fileStream.Length <= 0)
- return TypedResults.BadRequest("Wrong bitstream, Please upload it again");
-
- // 定义缓冲区大小: 32KB
- byte[] buffer = new byte[32 * 1024];
- byte[] revBuffer = new byte[32 * 1024];
- long totalBytesRead = 0;
-
- // 使用异步流读取文件
- using (var memoryStream = new MemoryStream())
- {
- int bytesRead;
- while ((bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
- {
- // 反转 32bits
- var retBuffer = Common.Number.ReverseBytes(buffer, 4);
- if (!retBuffer.IsSuccessful)
- return TypedResults.InternalServerError(retBuffer.Error);
- revBuffer = retBuffer.Value;
- // for (int i = 0; i < buffer.Length; i++)
- // {
- // revBuffer[i] = Common.Number.ReverseBits(revBuffer[i]);
- // }
-
- await memoryStream.WriteAsync(revBuffer, 0, bytesRead);
- totalBytesRead += bytesRead;
- }
-
- // 将所有数据转换为字节数组(注意:如果文件非常大,可能不适合完全加载到内存)
- var restStreamLen = memoryStream.Length % (4 * 1024);
- if (restStreamLen != 0)
- {
- var appendLen = ((int)(4 * 1024 - restStreamLen));
- var bytesAppend = new byte[appendLen];
- Array.Fill(bytesAppend, 0xFF);
- await memoryStream.WriteAsync(bytesAppend, 0, appendLen);
- }
- var fileBytes = memoryStream.ToArray();
-
- // 下载比特流
- var remoteUpdater = new RemoteUpdate.RemoteUpdateClient(address, port);
- var ret = await remoteUpdater.UpdateBitstream(bitstreamNum, fileBytes);
-
- if (ret.IsSuccessful)
- {
- logger.Info($"Device {address} Update bitstream successfully");
- return TypedResults.Ok(ret.Value);
- }
- else
- {
- logger.Error(ret.Error);
- return TypedResults.InternalServerError(ret.Error);
- }
- }
-
+ logger.Info($"Device {address} Update bitstream successfully");
+ return TypedResults.Ok(ret.Value);
+ }
+ else
+ {
+ logger.Error(ret.Error);
+ return TypedResults.InternalServerError(ret.Error);
}
}
@@ -479,6 +510,94 @@ public class RemoteUpdater : ControllerBase
return TypedResults.InternalServerError(error);
}
}
+
+
+ ///
+ /// 下载多个比特流文件
+ ///
+ /// 设备地址
+ /// 设备端口
+ /// 比特流编号
+ /// 总共上传比特流的数量
+ [HttpPost("DownloadMultiBitstreams")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status400BadRequest)]
+ [ProducesResponseType(StatusCodes.Status500InternalServerError)]
+ public async ValueTask DownloadMultiBitstreams(string address, int port, int? bitstreamNum)
+ {
+ // 检查文件
+ var bitstreamsFolder = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}");
+ if (!Directory.Exists(bitstreamsFolder))
+ return TypedResults.BadRequest("Empty bitstream, Please upload it first");
+
+ try
+ {
+ var bitstreams = new List() { null, null, null, null };
+ int cnt = 0; // 上传比特流数量
+ for (int i = 0; i < 4; i++)
+ {
+ var bitstreamDir = Path.Combine(bitstreamsFolder, i.ToString());
+ if (!Directory.Exists(bitstreamDir))
+ continue;
+ cnt++;
+
+ // 读取文件
+ var filePath = Directory.GetFiles(bitstreamDir)[0];
+ var fileBytes = await ProcessBitstream(filePath);
+ if (!fileBytes.IsSuccessful) return TypedResults.InternalServerError(fileBytes.Error);
+ bitstreams[i] = fileBytes.Value;
+ }
+
+ // 下载比特流
+ var remoteUpdater = new RemoteUpdate.RemoteUpdateClient(address, port);
+ {
+ var ret = await remoteUpdater.UploadBitstreams(bitstreams[0], bitstreams[1], bitstreams[2], bitstreams[3]);
+ if (!ret.IsSuccessful) return TypedResults.InternalServerError(ret.Error);
+ if (!ret.Value) return TypedResults.InternalServerError("Upload MultiBitstreams failed");
+ }
+
+ if (bitstreamNum is not null)
+ {
+ var ret = await remoteUpdater.HotResetBitstream(bitstreamNum ?? 0);
+ if (!ret.IsSuccessful) return TypedResults.InternalServerError(ret.Error);
+ if (!ret.Value) return TypedResults.InternalServerError("Hot reset failed");
+ }
+ return TypedResults.Ok(cnt);
+ }
+ catch (Exception error)
+ {
+ return TypedResults.InternalServerError(error);
+ }
+ }
+
+
+ ///
+ /// 热复位比特流文件
+ ///
+ /// 设备地址
+ /// 设备端口
+ /// 比特流编号
+ /// 操作结果
+ [HttpPost("HotResetBitstream")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status400BadRequest)]
+ [ProducesResponseType(StatusCodes.Status500InternalServerError)]
+ public async ValueTask HotResetBitstream(string address, int port, int bitstreamNum)
+ {
+ var remoteUpdater = new RemoteUpdate.RemoteUpdateClient(address, port);
+ var ret = await remoteUpdater.HotResetBitstream(bitstreamNum);
+
+ if (ret.IsSuccessful)
+ {
+ logger.Info($"Device {address}即可 Update bitstream successfully");
+ return TypedResults.Ok(ret.Value);
+ }
+ else
+ {
+ logger.Error(ret.Error);
+ return TypedResults.InternalServerError(ret.Error);
+ }
+ }
}
diff --git a/server/src/RemoteUpdate.cs b/server/src/RemoteUpdate.cs
index 330f33c..b6db774 100644
--- a/server/src/RemoteUpdate.cs
+++ b/server/src/RemoteUpdate.cs
@@ -1,4 +1,3 @@
-using System.Buffers.Binary;
using System.Net;
using DotNext;
namespace RemoteUpdate;
@@ -187,10 +186,6 @@ public class RemoteUpdateClient
var bytesData = new byte[FLASH_SECTOR_LENGTH];
Array.Fill(bytesData, 0xFF);
- // bytesData[FLASH_SECTOR_LENGTH - 4] = 0x80; // 0b10000000
- // bytesData[FLASH_SECTOR_LENGTH - 3] = 0xCC; // 0b11001100
- // bytesData[FLASH_SECTOR_LENGTH - 2] = 0xB4; // 0b10110100
- // bytesData[FLASH_SECTOR_LENGTH - 1] = 0x29; // 0b00101001
bytesData[FLASH_SECTOR_LENGTH - 1] = 0x01;
bytesData[FLASH_SECTOR_LENGTH - 2] = 0x33;
bytesData[FLASH_SECTOR_LENGTH - 3] = 0x2D;
@@ -238,7 +233,6 @@ public class RemoteUpdateClient
// Init data
var bytesData = new byte[FLASH_SECTOR_LENGTH];
for (int i = 3; i < FLASH_SECTOR_LENGTH; i += 4)
- // bytesData[i] = Common.Number.ReverseBits((byte)0xA0);
bytesData[i] = (byte)0xA0;
{
@@ -273,54 +267,6 @@ public class RemoteUpdateClient
var bytesSrc = new byte[] { 0x0F, 0x00, 0x00, 0x00 };
Buffer.BlockCopy(bytesSrc, 0, bytesData, 0x48, 4);
}
- // {
- // var bytesSrc = new byte[] { 0xAB, 0x00, 0x00, 0x01 };
- // for (int i = 0; i < 4; i++)
- // bytesSrc[i] = Common.Number.ReverseBits(bytesSrc[i]);
- // Buffer.BlockCopy(bytesSrc, 0, bytesData, 0x04, 4);
- // }
- // {
- // var bytesSrc = new byte[] { 0x00, 0x00, 0x00, 0x0B };
- // for (int i = 0; i < 4; i++)
- // bytesSrc[i] = Common.Number.ReverseBits(bytesSrc[i]);
- // Buffer.BlockCopy(bytesSrc, 0, bytesData, 0x08, 4);
- // }
- // {
- // var bytesSrc = new byte[] { 0xAB, 0xC0, 0x00, 0x01 };
- // for (int i = 0; i < 4; i++)
- // bytesSrc[i] = Common.Number.ReverseBits(bytesSrc[i]);
- // Buffer.BlockCopy(bytesSrc, 0, bytesData, 0x34, 4);
- // }
- // {
- // var bytesSrc = new byte[] { 0x00, 0x00, 0x00, 0x00 };
- // for (int i = 0; i < 4; i++)
- // bytesSrc[i] = Common.Number.ReverseBits(bytesSrc[i]);
- // Buffer.BlockCopy(bytesSrc, 0, bytesData, 0x38, 4);
- // }
- // {
- // var bytesSrc = new byte[] { 0xAC, 0x00, 0x00, 0x01 };
- // for (int i = 0; i < 4; i++)
- // bytesSrc[i] = Common.Number.ReverseBits(bytesSrc[i]);
- // Buffer.BlockCopy(bytesSrc, 0, bytesData, 0x3C, 4);
- // }
- // {
- // var bytesSrc = Common.Number.NumberToBytes(FlashAddr.Bitstream[bitstreamNum], 4).Value;
- // for (int i = 0; i < 4; i++)
- // bytesSrc[i] = Common.Number.ReverseBits(bytesSrc[i]);
- // Buffer.BlockCopy(bytesSrc, 0, bytesData, 0x40, 4);
- // }
- // {
- // var bytesSrc = new byte[] { 0xA8, 0x80, 0x00, 0x01 };
- // for (int i = 0; i < 4; i++)
- // bytesSrc[i] = Common.Number.ReverseBits(bytesSrc[i]);
- // Buffer.BlockCopy(bytesSrc, 0, bytesData, 0x44, 4);
- // }
- // {
- // var bytesSrc = new byte[] { 0x00, 0x00, 0x00, 0x0F };
- // for (int i = 0; i < 4; i++)
- // bytesSrc[i] = Common.Number.ReverseBits(bytesSrc[i]);
- // Buffer.BlockCopy(bytesSrc, 0, bytesData, 0x48, 4);
- // }
var ret = await WriteFlash(FlashAddr.Jump[bitstreamNum], 1, bytesData);
if (!ret.IsSuccessful) return new(ret.Error);
@@ -402,8 +348,8 @@ public class RemoteUpdateClient
var remoteCRC = Common.Number.BytesToUInt32(bytes);
if (!remoteCRC.IsSuccessful) return new(remoteCRC.Error);
- logger.Debug($"Expected CRC: \t 0x{Convert.ToString(checkSum, 16)}");
- logger.Debug($"Received CRC: \t 0x{Convert.ToString(remoteCRC.Value, 16)}");
+ logger.Debug($"Bitstream {bitstreamNum} Expected CRC: \t 0x{Convert.ToString(checkSum, 16)}");
+ logger.Debug($"Bitstream {bitstreamNum} Received CRC: \t 0x{Convert.ToString(remoteCRC.Value, 16)}");
return remoteCRC.Value == checkSum;
}
@@ -414,7 +360,7 @@ public class RemoteUpdateClient
///
/// [TODO:parameter]
/// [TODO:return]
- private async ValueTask> HotRest(int bitstreamNum)
+ private async ValueTask> HotReset(int bitstreamNum)
{
// Assert
if (bitstreamNum < 0 || bitstreamNum > 3)
@@ -428,6 +374,81 @@ public class RemoteUpdateClient
return ret.Value;
}
+ ///
+ /// [TODO:description]
+ ///
+ /// [TODO:parameter]
+ /// [TODO:return]
+ public async ValueTask> HotResetBitstream(int bitstreamNum)
+ {
+ await MsgBus.UDPServer.ClearUDPData(this.address);
+ logger.Trace("Clear udp data finished");
+
+ {
+ var ret = await InitRemoteUpdate(bitstreamNum);
+ if (!ret.IsSuccessful) return new(ret.Error);
+ if (!ret.Value) return new(new Exception("Init remote update failed"));
+ }
+
+ {
+ var ret = await HotReset(bitstreamNum);
+ if (!ret.IsSuccessful) return new(ret.Error);
+ return ret.Value;
+ }
+ }
+
+ ///
+ /// [TODO:description]
+ ///
+ /// [TODO:parameter]
+ /// [TODO:parameter]
+ /// [TODO:parameter]
+ /// [TODO:parameter]
+ /// [TODO:return]
+ public async ValueTask> UploadBitstreams(
+ byte[]? goldenBitream,
+ byte[]? bitstream1,
+ byte[]? bitstream2,
+ byte[]? bitstream3)
+ {
+ await MsgBus.UDPServer.ClearUDPData(this.address);
+ logger.Trace("Clear udp data finished");
+
+ for (int bitstreamNum = 0; bitstreamNum < 4; bitstreamNum++)
+ {
+ byte[] bytesData;
+ if (bitstreamNum == 0 && goldenBitream is not null)
+ bytesData = goldenBitream;
+ else if (bitstreamNum == 1 && bitstream1 is not null)
+ bytesData = bitstream1;
+ else if (bitstreamNum == 2 && bitstream2 is not null)
+ bytesData = bitstream2;
+ else if (bitstreamNum == 3 && bitstream3 is not null)
+ bytesData = bitstream3;
+ else continue;
+
+ var bitstreamBlockNum = bytesData.Length / (4 * 1024);
+
+ {
+ var ret = await WriteFlash(FlashAddr.Bitstream[bitstreamNum], bitstreamBlockNum, bytesData);
+ if (!ret.IsSuccessful) return new(ret.Error);
+ if (!ret.Value) return new(new Exception("Write bitstream failed"));
+ }
+
+ {
+ var crc = Honoo.IO.Hashing.Crc.Create(Honoo.IO.Hashing.CrcName.CRC32_MPEG_2);
+ var checkSum = crc.ComputeFinal(bytesData);
+ var ret = await CheckBitstreamCRC(bitstreamNum, bitstreamBlockNum, checkSum.ToUInt32());
+ if (!ret.IsSuccessful) return new(ret.Error);
+ if (!ret.Value) logger.Warn($"Bitstream {bitstreamNum} CRC32 not correct!");
+ else logger.Info($"Bitstream {bitstreamNum} CRC32 calibration passed");
+ }
+
+ }
+
+ return true;
+ }
+
///
/// [TODO:description]
///
@@ -466,7 +487,7 @@ public class RemoteUpdateClient
}
{
- var ret = await HotRest(bitstreamNum);
+ var ret = await HotReset(bitstreamNum);
if (!ret.IsSuccessful) return new(ret.Error);
return ret.Value;
}
@@ -475,33 +496,40 @@ public class RemoteUpdateClient
///
/// [TODO:description]
///
- /// [TODO:parameter]
+ /// [TODO:parameter]
+ /// [TODO:parameter]
+ /// [TODO:parameter]
+ /// [TODO:parameter]
+ /// [TODO:parameter]
/// [TODO:return]
- public async ValueTask> HotResetBitstream(int bitstreamNum)
- {
- await MsgBus.UDPServer.ClearUDPData(this.address);
- logger.Trace("Clear udp data finished");
-
- {
- var ret = await InitRemoteUpdate(bitstreamNum);
- if (!ret.IsSuccessful) return new(ret.Error);
- if (!ret.Value) return new(new Exception("Init remote update failed"));
- }
-
- {
- var ret = await HotRest(bitstreamNum);
- if (!ret.IsSuccessful) return new(ret.Error);
- return ret.Value;
- }
- }
-
- public async ValueTask> UploadBitstreams(
+ public async ValueTask> UpdateBitstreams(
int enableBitstreamNum,
byte[]? goldenBitream,
byte[]? bitstream1,
byte[]? bitstream2,
byte[]? bitstream3)
{
- return true;
+ // Assert
+ if (goldenBitream is null && bitstream1 is null && bitstream2 is null && bitstream3 is null)
+ return new(new ArgumentException(
+ $"At least one bitstream should not be empty"));
+ if ((enableBitstreamNum == 0 && goldenBitream is null) ||
+ (enableBitstreamNum == 1 && bitstream1 is null) ||
+ (enableBitstreamNum == 2 && bitstream2 is null) ||
+ (enableBitstreamNum == 3 && bitstream3 is null))
+ return new(new ArgumentException($"Bitstream {enableBitstreamNum} shouldn't be empty"));
+
+ {
+ var ret = await UploadBitstreams(goldenBitream, bitstream1, bitstream2, bitstream3);
+ if (!ret.IsSuccessful) return new(ret.Error);
+ if (!ret.Value) return false;
+ }
+
+ {
+ var ret = await HotResetBitstream(enableBitstreamNum);
+ if (!ret.IsSuccessful) return new(ret.Error);
+ return ret.Value;
+ }
}
+
}