1#!/usr/bin/env python3
2#/*
3# * FreeRTOS Kernel <DEVELOPMENT BRANCH>
4# * Copyright (C) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5# *
6# * SPDX-License-Identifier: MIT
7# *
8# * Permission is hereby granted, free of charge, to any person obtaining a copy of
9# * this software and associated documentation files (the "Software"), to deal in
10# * the Software without restriction, including without limitation the rights to
11# * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
12# * the Software, and to permit persons to whom the Software is furnished to do so,
13# * subject to the following conditions:
14# *
15# * The above copyright notice and this permission notice shall be included in all
16# * copies or substantial portions of the Software.
17# *
18# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19# * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
20# * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
21# * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22# * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23# * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24# *
25# * https://www.FreeRTOS.org
26# * https://github.com/FreeRTOS
27# *
28# */
29
30import os
31import re
32from common.header_checker import HeaderChecker
33
34#--------------------------------------------------------------------------------------------------
35#                                            CONFIG
36#--------------------------------------------------------------------------------------------------
37KERNEL_IGNORED_FILES = [
38    'FreeRTOS-openocd.c',
39    'Makefile',
40    '.DS_Store',
41    'cspell.config.yaml',
42    '.clang-format'
43]
44
45KERNEL_IGNORED_EXTENSIONS = [
46    '.yml',
47    '.css',
48    '.idx',
49    '.md',
50    '.url',
51    '.sty',
52    '.0-rc2',
53    '.s82',
54    '.js',
55    '.out',
56    '.pack',
57    '.2',
58    '.1-kernel-only',
59    '.0-kernel-only',
60    '.0-rc1',
61    '.readme',
62    '.tex',
63    '.png',
64    '.bat',
65    '.sh',
66    '.txt',
67    '.cmake',
68    '.config'
69]
70
71KERNEL_ASM_EXTENSIONS = [
72    '.s',
73    '.S',
74    '.src',
75    '.inc',
76    '.s26',
77    '.s43',
78    '.s79',
79    '.s85',
80    '.s87',
81    '.s90',
82    '.asm',
83    '.h'
84]
85
86KERNEL_PY_EXTENSIONS = [
87    '.py'
88]
89
90KERNEL_IGNORED_PATTERNS = [
91    r'.*\.git.*',
92    r'.*portable/IAR/AtmelSAM7S64/.*AT91SAM7.*',
93    r'.*portable/GCC/ARM7_AT91SAM7S/.*',
94    r'.*portable/MPLAB/PIC18F/stdio.h',
95    r'.*portable/ThirdParty/xClang/XCOREAI/*',
96    r'.*IAR/ARM_C*',
97    r'.*IAR/78K0R/*',
98    r'.*CCS/MSP430X/*',
99    r'.*portable/template/*',
100    r'.*template_configuration/*'
101]
102
103KERNEL_THIRD_PARTY_PATTERNS = [
104    r'.*portable/ThirdParty/GCC/Posix/port*',
105    r'.*portable/ThirdParty/*',
106    r'.*portable/IAR/AVR32_UC3/.*',
107    r'.*portable/GCC/AVR32_UC3/.*',
108]
109
110KERNEL_ARM_COLLAB_FILES_PATTERNS = [
111    r'.*portable/ARMv8M/*',
112    r'.*portable/.*/ARM_CM23*',
113    r'.*portable/.*/ARM_CM33*',
114    r'.*portable/.*/ARM_CM35*',
115    r'.*portable/.*/ARM_CM55*',
116    r'.*portable/.*/ARM_CM85*',
117]
118
119KERNEL_HEADER = [
120    '/*\n',
121    ' * FreeRTOS Kernel <DEVELOPMENT BRANCH>\n',
122    ' * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n',
123    ' *\n',
124    ' * SPDX-License-Identifier: MIT\n',
125    ' *\n',
126    ' * Permission is hereby granted, free of charge, to any person obtaining a copy of\n',
127    ' * this software and associated documentation files (the "Software"), to deal in\n',
128    ' * the Software without restriction, including without limitation the rights to\n',
129    ' * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\n',
130    ' * the Software, and to permit persons to whom the Software is furnished to do so,\n',
131    ' * subject to the following conditions:\n',
132    ' *\n',
133    ' * The above copyright notice and this permission notice shall be included in all\n',
134    ' * copies or substantial portions of the Software.\n',
135    ' *\n',
136    ' * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n',
137    ' * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\n',
138    ' * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n',
139    ' * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\n',
140    ' * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n',
141    ' * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n',
142    ' *\n',
143    ' * https://www.FreeRTOS.org\n',
144    ' * https://github.com/FreeRTOS\n',
145    ' *\n',
146    ' */\n',
147]
148
149
150FREERTOS_COPYRIGHT_REGEX = r"^(;|#)?( *(\/\*|\*|#|\/\/))? Copyright \(C\) 20\d\d Amazon.com, Inc. or its affiliates. All Rights Reserved\.( \*\/)?$"
151
152FREERTOS_ARM_COLLAB_COPYRIGHT_REGEX = r"(^(;|#)?( *(\/\*|\*|#|\/\/))? Copyright \(C\) 20\d\d Amazon.com, Inc. or its affiliates. All Rights Reserved\.( \*\/)?$)|" + \
153                                      r"(^(;|#)?( *(\/\*|\*|#|\/\/))? Copyright 20\d\d Arm Limited and/or its affiliates( \*\/)?$)|" + \
154                                      r"(^(;|#)?( *(\/\*|\*|#|\/\/))? <open-source-office@arm.com>( \*\/)?$)"
155
156
157class KernelHeaderChecker(HeaderChecker):
158    def __init__(
159        self,
160        header,
161        padding=1000,
162        ignored_files=None,
163        ignored_ext=None,
164        ignored_patterns=None,
165        py_ext=None,
166        asm_ext=None,
167        third_party_patterns=None,
168        copyright_regex = None
169    ):
170        super().__init__(header, padding, ignored_files, ignored_ext, ignored_patterns,
171                         py_ext, asm_ext, third_party_patterns, copyright_regex)
172
173        self.armCollabRegex = re.compile(FREERTOS_ARM_COLLAB_COPYRIGHT_REGEX)
174
175        self.armCollabFilesPatternList = []
176        for pattern in KERNEL_ARM_COLLAB_FILES_PATTERNS:
177            self.armCollabFilesPatternList.append(re.compile(pattern))
178
179    def isArmCollabFile(self, path):
180        for pattern in self.armCollabFilesPatternList:
181            if pattern.match(path):
182                return True
183        return False
184
185    def checkArmCollabFile(self, path):
186        isValid = False
187        file_ext = os.path.splitext(path)[-1]
188
189        with open(path, encoding="utf-8", errors="ignore") as file:
190            chunk = file.read(len("".join(self.header)) + self.padding)
191            lines = [("%s\n" % line) for line in chunk.strip().splitlines()][
192                : len(self.header) + 2
193            ]
194            if (len(lines) > 0) and (lines[0].find("#!") == 0):
195                lines.remove(lines[0])
196
197        # Split lines in sections.
198        headers = dict()
199        headers["text"] = []
200        headers["copyright"] = []
201        headers["spdx"] = []
202        for line in lines:
203            if self.armCollabRegex.match(line):
204                headers["copyright"].append(line)
205            elif "SPDX-License-Identifier:" in line:
206                headers["spdx"].append(line)
207            else:
208                headers["text"].append(line)
209
210        text_equal = self.isValidHeaderSection(file_ext, "text", headers["text"])
211        spdx_equal = self.isValidHeaderSection(file_ext, "spdx", headers["spdx"])
212
213        if text_equal and spdx_equal and len(headers["copyright"]) == 3:
214            isValid = True
215
216        return isValid
217
218    def customCheck(self, path):
219        isValid = False
220        if self.isArmCollabFile(path):
221            isValid = self.checkArmCollabFile(path)
222        return isValid
223
224
225def main():
226    parser = HeaderChecker.configArgParser()
227    args   = parser.parse_args()
228
229    # Configure the checks then run
230    checker = KernelHeaderChecker(KERNEL_HEADER,
231                                  copyright_regex=FREERTOS_COPYRIGHT_REGEX,
232                                  ignored_files=KERNEL_IGNORED_FILES,
233                                  ignored_ext=KERNEL_IGNORED_EXTENSIONS,
234                                  ignored_patterns=KERNEL_IGNORED_PATTERNS,
235                                  third_party_patterns=KERNEL_THIRD_PARTY_PATTERNS,
236                                  py_ext=KERNEL_PY_EXTENSIONS,
237                                  asm_ext=KERNEL_ASM_EXTENSIONS)
238    checker.ignoreFile(os.path.split(__file__)[-1])
239
240    rc = checker.processArgs(args)
241    if rc:
242        checker.showHelp(__file__)
243
244    return rc
245
246if __name__ == '__main__':
247    exit(main())
248