main.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. package main
  2. import (
  3. "encoding/binary"
  4. "encoding/hex"
  5. "fmt"
  6. "hash/crc32"
  7. "io"
  8. "io/ioutil"
  9. "os"
  10. "path/filepath"
  11. "github.com/akamensky/argparse"
  12. )
  13. func swab16(x uint16) uint16 {
  14. return (x&0x00ff)<<8 | (x&0xff00)>>8
  15. }
  16. func swab32(x uint32) uint32 {
  17. return (x&0x000000ff)<<24 | (x&0x0000ff00)<<8 | (x&0x00ff0000)>>8 | (x&0xff000000)>>24
  18. }
  19. func sumArr(arr []uint8) uint32 {
  20. sum := uint32(0)
  21. for _, val := range arr {
  22. sum += uint32(val)
  23. }
  24. return sum
  25. }
  26. func calChecknum(_type string, datas []byte) uint32 {
  27. if _type == "sum32" {
  28. return sumArr(datas)
  29. } else if _type == "crc32" {
  30. return crc32.ChecksumIEEE(datas)
  31. } else {
  32. print("unKown type: " + _type)
  33. return 0
  34. }
  35. }
  36. func getFileSize(filename string) (int64, error) {
  37. fileinfo, err := os.Stat(filename)
  38. if err != nil {
  39. return 0, err
  40. }
  41. size := fileinfo.Size()
  42. return size, nil
  43. }
  44. func ReadBinFile(_name string, _type string, _en string, _block int, _addcheck int, _addpos int) {
  45. FileName := filepath.Base(_name)
  46. // FileType := filepath.Ext(_name)
  47. InputFilePath := _name
  48. OutputFilePath := FileName + "." + _type
  49. inputFile, err := os.Open(InputFilePath)
  50. if err != nil {
  51. panic(err)
  52. }
  53. defer inputFile.Close()
  54. // 计算总帧数
  55. fileInfo, err := inputFile.Stat()
  56. if err != nil {
  57. panic(err)
  58. }
  59. fileSize := fileInfo.Size()
  60. totalFrames := uint16((fileSize + int64(_block) - 1) / int64(_block))
  61. outputFile, err := os.OpenFile(OutputFilePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
  62. if err != nil {
  63. panic(err)
  64. }
  65. defer outputFile.Close()
  66. var Endian binary.ByteOrder
  67. switch _en {
  68. case "big":
  69. Endian = binary.BigEndian
  70. case "little":
  71. Endian = binary.LittleEndian
  72. default:
  73. fmt.Println("错误: 未知的大小端类型", _en)
  74. return
  75. }
  76. curFrame := 0
  77. if _block > 0 {
  78. buffer := make([]byte, _block)
  79. for {
  80. n, err := inputFile.Read(buffer)
  81. if n > 0 {
  82. // 计算分片的校验和
  83. check := calChecknum(_type, buffer[:n])
  84. // 写入分片内容+分片校验和
  85. binary.Write(outputFile, Endian, buffer[:n])
  86. if _addpos == 1 {
  87. // 追加偏移量
  88. binary.Write(outputFile, Endian, uint16(curFrame))
  89. binary.Write(outputFile, Endian, uint16(totalFrames))
  90. }
  91. // 追加校验码
  92. binary.Write(outputFile, Endian, check)
  93. curFrame ++
  94. }
  95. if err != nil {
  96. if err == io.EOF {
  97. break // 文件读取完毕
  98. }
  99. panic(err)
  100. }
  101. }
  102. } else {
  103. data, err := ioutil.ReadAll(inputFile)
  104. if err != nil {
  105. panic(err)
  106. }
  107. // 写入全部内容
  108. binary.Write(outputFile, Endian, data)
  109. }
  110. // 读取文件内容到字节切片
  111. inputFile, err = os.Open(InputFilePath)
  112. if err != nil {
  113. panic(err)
  114. }
  115. defer inputFile.Close()
  116. data, err := ioutil.ReadAll(inputFile)
  117. if err != nil {
  118. panic(err)
  119. }
  120. check := calChecknum(_type, data[:])
  121. if _addcheck == 1 {
  122. // 追加校验码
  123. binary.Write(outputFile, Endian, check)
  124. }
  125. // 大小端转换
  126. var networkBytes [4]byte
  127. if _en == "big" {
  128. binary.BigEndian.PutUint32(networkBytes[:], check)
  129. } else {
  130. binary.LittleEndian.PutUint32(networkBytes[:], check)
  131. }
  132. check_hex := hex.EncodeToString(networkBytes[:])
  133. // 打印输出内容
  134. size, err := getFileSize(InputFilePath)
  135. fmt.Println(InputFilePath, fmt.Sprintf("%d", size), _type, check_hex)
  136. // 关闭文件
  137. err = outputFile.Close()
  138. if err != nil {
  139. fmt.Println(err)
  140. }
  141. // 重命名文件
  142. out_name1 := FileName + "." + _type + "[" + check_hex + "]"
  143. err = os.Rename(OutputFilePath, out_name1)
  144. if err != nil {
  145. fmt.Println("重命名文件出错:", err)
  146. return
  147. }
  148. }
  149. func main() {
  150. parser := argparse.NewParser("goChecknum", "这是一个用于固件校验码工具, 制作升级文件")
  151. _name := parser.String("n", "name", &argparse.Options{Required: true, Help: "bin文件名, 譬如 test.bin", Default: "test.bin"})
  152. _type := parser.String("t", "type", &argparse.Options{Required: false, Help: "校验方式: sum32,crc32", Default: "sum32"})
  153. _en := parser.String("e", "en", &argparse.Options{Required: false, Help: "校验码大小端: little,big", Default: "little"})
  154. _section := parser.Int("s", "section", &argparse.Options{Required: false, Help: "分块大小: 0,1024,2048", Default: 0})
  155. _addcheck := parser.Int("c", "addcheck", &argparse.Options{Required: false, Help: "文件结尾追加校验码", Default: 1})
  156. _addpos := parser.Int("p", "addpos", &argparse.Options{Required: false, Help: "文件结尾追加偏移", Default: 1})
  157. err := parser.Parse(os.Args)
  158. if err != nil {
  159. fmt.Print(parser.Usage(err)) // 帮助 -h or --help
  160. return
  161. }
  162. ReadBinFile(*_name, *_type, *_en, *_section, *_addcheck, *_addpos)
  163. }