feature: add more web api for remote update
This commit is contained in:
		@@ -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";
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 页面
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@@ -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<IResult> 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";
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 上传远程更新比特流文件
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="address"> 设备地址 </param>
 | 
			
		||||
    /// <param name="file">比特流文件</param>
 | 
			
		||||
    /// <param name="goldenBitream">黄金比特流文件</param>
 | 
			
		||||
    /// <param name="bitstream1">比特流文件1</param>
 | 
			
		||||
    /// <param name="bitstream2">比特流文件2</param>
 | 
			
		||||
    /// <param name="bitstream3">比特流文件3</param>
 | 
			
		||||
    /// <returns>上传结果</returns>
 | 
			
		||||
    [HttpPost("UploadBitstream")]
 | 
			
		||||
    [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
 | 
			
		||||
    public async ValueTask<IResult> UploadBitstream(string address, IFormFile file)
 | 
			
		||||
    public async ValueTask<IResult> 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<Result<byte[]>> 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<byte>(bytesAppend, 0xFF);
 | 
			
		||||
                    await memoryStream.WriteAsync(bytesAppend, 0, appendLen);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return new(memoryStream.ToArray());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 远程更新比特流文件
 | 
			
		||||
    /// 远程更新单个比特流文件
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="address"> 设备地址 </param>
 | 
			
		||||
    /// <param name="port"> 设备端口 </param>
 | 
			
		||||
@@ -405,7 +477,7 @@ public class RemoteUpdater : ControllerBase
 | 
			
		||||
    public async ValueTask<IResult> 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<byte>(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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 下载多个比特流文件
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="address">设备地址</param>
 | 
			
		||||
    /// <param name="port">设备端口</param>
 | 
			
		||||
    /// <param name="bitstreamNum">比特流编号</param>
 | 
			
		||||
    /// <returns>总共上传比特流的数量</returns>
 | 
			
		||||
    [HttpPost("DownloadMultiBitstreams")]
 | 
			
		||||
    [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
 | 
			
		||||
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
 | 
			
		||||
    public async ValueTask<IResult> 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<byte[]?>() { 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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 热复位比特流文件
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="address">设备地址</param>
 | 
			
		||||
    /// <param name="port">设备端口</param>
 | 
			
		||||
    /// <param name="bitstreamNum">比特流编号</param>
 | 
			
		||||
    /// <returns>操作结果</returns>
 | 
			
		||||
    [HttpPost("HotResetBitstream")]
 | 
			
		||||
    [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
 | 
			
		||||
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
 | 
			
		||||
    public async ValueTask<IResult> 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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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<byte>(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
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="bitstreamNum">[TODO:parameter]</param>
 | 
			
		||||
    /// <returns>[TODO:return]</returns>
 | 
			
		||||
    private async ValueTask<Result<bool>> HotRest(int bitstreamNum)
 | 
			
		||||
    private async ValueTask<Result<bool>> HotReset(int bitstreamNum)
 | 
			
		||||
    {
 | 
			
		||||
        // Assert
 | 
			
		||||
        if (bitstreamNum < 0 || bitstreamNum > 3)
 | 
			
		||||
@@ -428,6 +374,81 @@ public class RemoteUpdateClient
 | 
			
		||||
        return ret.Value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// [TODO:description]
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="bitstreamNum">[TODO:parameter]</param>
 | 
			
		||||
    /// <returns>[TODO:return]</returns>
 | 
			
		||||
    public async ValueTask<Result<bool>> 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;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// [TODO:description]
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="goldenBitream">[TODO:parameter]</param>
 | 
			
		||||
    /// <param name="bitstream1">[TODO:parameter]</param>
 | 
			
		||||
    /// <param name="bitstream2">[TODO:parameter]</param>
 | 
			
		||||
    /// <param name="bitstream3">[TODO:parameter]</param>
 | 
			
		||||
    /// <returns>[TODO:return]</returns>
 | 
			
		||||
    public async ValueTask<Result<bool>> 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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// [TODO:description]
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@@ -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
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// [TODO:description]
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="bitstreamNum">[TODO:parameter]</param>
 | 
			
		||||
    /// <param name="enableBitstreamNum">[TODO:parameter]</param>
 | 
			
		||||
    /// <param name="goldenBitream">[TODO:parameter]</param>
 | 
			
		||||
    /// <param name="bitstream1">[TODO:parameter]</param>
 | 
			
		||||
    /// <param name="bitstream2">[TODO:parameter]</param>
 | 
			
		||||
    /// <param name="bitstream3">[TODO:parameter]</param>
 | 
			
		||||
    /// <returns>[TODO:return]</returns>
 | 
			
		||||
    public async ValueTask<Result<bool>> 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<Result<bool>> UploadBitstreams(
 | 
			
		||||
    public async ValueTask<Result<bool>> 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;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user