1# SPDX-License-Identifier: Apache-2.0
2#
3# Copyright (c) 2024 Realtek Semiconductor Corporation, SIBG-SD7
4# Author: Dylan Hsieh <dylan.hsieh@realtek.com>
5
6"""
7The RTS5912 specific image header shows the bootROM how to
8load the image from flash to internal SRAM, this script obtains
9the header to original BIN and output a new BIN file.
10"""
11
12import argparse
13import os
14import struct
15
16IMAGE_MAGIC = 0x524C544B  # ASCII 'RLTK'
17IMAGE_HDR_SIZE = 32
18RAM_LOAD = 0x0000020
19FREQ_50M = 0
20FREQ_25M = 1
21FREQ_12P5M = 2
22FREQ_6P25M = 3
23NORMAL_read = "0x03"
24DUAL_read = "0x3B"
25QUAD_read = "0x6B"
26
27
28def parse_args():
29    """
30    Parsing the arguments
31    """
32    parser = argparse.ArgumentParser(allow_abbrev=False)
33
34    parser.add_argument(
35        "-L",
36        "--load-addr",
37        type=int,
38        dest="load_addr",
39        help="Load address for image when it should run from RAM.",
40    )
41
42    parser.add_argument(
43        "-I",
44        "--input",
45        type=str,
46        dest="original_bin",
47        default="zephyr.bin",
48        help="Input bin file path",
49    )
50
51    parser.add_argument(
52        "-O",
53        "--output",
54        type=str,
55        dest="signed_bin",
56        default="zephyr.rts5912.bin",
57        help="Output bin file path",
58    )
59
60    parser.add_argument(
61        "-F",
62        "--spi-freq",
63        type=int,
64        dest="spi_freq",
65        choices=[FREQ_50M, FREQ_25M, FREQ_12P5M, FREQ_6P25M],
66        default=FREQ_6P25M,
67        help="Specify the frequency of SPI I/F.",
68    )
69
70    parser.add_argument(
71        "-R",
72        "--spi-rdcmd",
73        type=str,
74        dest="spi_rdcmd",
75        choices=[NORMAL_read, DUAL_read, QUAD_read],
76        default=NORMAL_read,
77        help="Specify the command for flash read.",
78    )
79
80    parser.add_argument("-V", "--verbose", action="count", default=0, help="Verbose Output")
81
82    ret_args = parser.parse_args()
83    return ret_args
84
85
86def img_gen(load_addr, spi_freq, spi_rdcmd, original_bin, signed_bin):
87    """
88    To obtain the RTS5912 image header and output a new BIN file
89    """
90    img_size = os.path.getsize(original_bin)
91    payload = bytearray(0)
92    img_size = os.path.getsize(original_bin)
93
94    fmt = (
95        "<"
96        +
97        # type ImageHdr struct {
98        "I"  # Magic    uint32
99        + "I"  # LoadAddr uint32
100        + "H"  # HdrSz    uint16
101        + "H"  # reserved uint16
102        + "I"  # ImgSz    uint32
103        + "I"  # Flags    uint32
104        + "I"  # reserved uint32
105        + "I"  # reserved uint32
106        + "B"  # SpiFmt   uint8
107        + "B"  # SpiRdCmd uint8
108        + "H"  # reserved uint16
109    )  # }
110
111    header = struct.pack(
112        fmt,
113        IMAGE_MAGIC,
114        load_addr,
115        IMAGE_HDR_SIZE,
116        0,
117        img_size,
118        RAM_LOAD,
119        0,
120        0,
121        0 + (int(spi_freq) << 2),
122        int(spi_rdcmd, 0),
123        0,
124    )
125
126    payload[: len(header)] = header
127
128    with open(signed_bin, "wb") as signed:
129        signed.write(payload)
130        signed.flush()
131        signed.close()
132
133    with open(signed_bin, "ab") as signed, open(original_bin, "rb") as original:
134        signed.write(original.read())
135        signed.flush()
136        signed.close()
137        original.close()
138
139
140def main():
141    """
142    Image generateor tool entry point
143    """
144    args = parse_args()
145    if args.verbose:
146        print(f"  Input = {args.original_bin}")
147        print(f"  Output = {args.signed_bin}")
148        print(f"  Load Address = {hex(args.load_addr)}")
149        print(f"  SPI Frequency = {args.spi_freq}")
150        print(f"  SPI Read Command = {args.spi_rdcmd}")
151    img_gen(
152        args.load_addr,
153        args.spi_freq,
154        args.spi_rdcmd,
155        args.original_bin,
156        args.signed_bin,
157    )
158
159
160if __name__ == "__main__":
161    main()
162