xref: /aosp_15_r20/external/linux-firmware/copy.bara.sky (revision 2764adbb83be75699e7e173cb61cdbf8f430c544)
1*2764adbbSAndroid Build Coastguard Worker# Copyright (C) 2024 The Android Open Source Project
2*2764adbbSAndroid Build Coastguard Worker#
3*2764adbbSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
4*2764adbbSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
5*2764adbbSAndroid Build Coastguard Worker# You may obtain a copy of the License at
6*2764adbbSAndroid Build Coastguard Worker#
7*2764adbbSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
8*2764adbbSAndroid Build Coastguard Worker#
9*2764adbbSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*2764adbbSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
11*2764adbbSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*2764adbbSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
13*2764adbbSAndroid Build Coastguard Worker# limitations under the License.
14*2764adbbSAndroid Build Coastguard Worker
15*2764adbbSAndroid Build Coastguard Workerupstream_git_repo = 'https://gitlab.com/kernel-firmware/linux-firmware.git'
16*2764adbbSAndroid Build Coastguard Worker
17*2764adbbSAndroid Build Coastguard Worker# ##########################################################
18*2764adbbSAndroid Build Coastguard Worker# Parsing of linux-firmware WHENCE file
19*2764adbbSAndroid Build Coastguard Worker# ##########################################################
20*2764adbbSAndroid Build Coastguard Worker
21*2764adbbSAndroid Build Coastguard Workersection_divider = '--------------------------------------------------------------------------'
22*2764adbbSAndroid Build Coastguard Worker
23*2764adbbSAndroid Build Coastguard Worker# Handle paths that might be quoted or use backslashes to escape spaces.
24*2764adbbSAndroid Build Coastguard Worker#
25*2764adbbSAndroid Build Coastguard Worker# For some reason some of the paths listed in WHENCE seem to be quoted or
26*2764adbbSAndroid Build Coastguard Worker# use '\ ' to escape spaces in the files, even though this doesn't seem like
27*2764adbbSAndroid Build Coastguard Worker# it should be necessary. Handle it. This takes a path `p`. If it's surrounded
28*2764adbbSAndroid Build Coastguard Worker# by quotes it just strips the quotes off. If it isn't quoted but we see
29*2764adbbSAndroid Build Coastguard Worker# '\ ' we'll transform that to just simple spaces.
30*2764adbbSAndroid Build Coastguard Workerdef unquote_path(p):
31*2764adbbSAndroid Build Coastguard Worker    if p.startswith('"') and p.endswith('"'):
32*2764adbbSAndroid Build Coastguard Worker        p = p[1:-1]
33*2764adbbSAndroid Build Coastguard Worker    else:
34*2764adbbSAndroid Build Coastguard Worker        p = p.replace('\\ ', ' ')
35*2764adbbSAndroid Build Coastguard Worker
36*2764adbbSAndroid Build Coastguard Worker    return p
37*2764adbbSAndroid Build Coastguard Worker
38*2764adbbSAndroid Build Coastguard Worker# Parse WHENCE from the upstream repository and return dict w/ info about files.
39*2764adbbSAndroid Build Coastguard Worker#
40*2764adbbSAndroid Build Coastguard Worker# This will read the upstream whence and return a dictionary keyed by files
41*2764adbbSAndroid Build Coastguard Worker# referenced in the upstream WHENCE (anything tagged 'File:', 'RawFile:', or
42*2764adbbSAndroid Build Coastguard Worker# 'Link:'). Values in the dictionary will be another dict that looks like:
43*2764adbbSAndroid Build Coastguard Worker#   {
44*2764adbbSAndroid Build Coastguard Worker#      'driver':  Name of the driver line associated with this file,
45*2764adbbSAndroid Build Coastguard Worker#      'kind':    The kind of file ('File', 'RawFile', or 'Link')
46*2764adbbSAndroid Build Coastguard Worker#      'license': If this key is present it's the text of the license; if this
47*2764adbbSAndroid Build Coastguard Worker#                 key is not present then the license is unknown.
48*2764adbbSAndroid Build Coastguard Worker#      'link':    Only present for 'kind' == 'Link'. This is where the link
49*2764adbbSAndroid Build Coastguard Worker#                 should point to.
50*2764adbbSAndroid Build Coastguard Worker#   }
51*2764adbbSAndroid Build Coastguard Workerdef parse_whence(whence_text):
52*2764adbbSAndroid Build Coastguard Worker    file_info_map = {}
53*2764adbbSAndroid Build Coastguard Worker
54*2764adbbSAndroid Build Coastguard Worker    driver = 'UNKNOWN'
55*2764adbbSAndroid Build Coastguard Worker    unlicensed_files = []
56*2764adbbSAndroid Build Coastguard Worker    license_text = None
57*2764adbbSAndroid Build Coastguard Worker
58*2764adbbSAndroid Build Coastguard Worker    for line in whence_text.splitlines() + [section_divider]:
59*2764adbbSAndroid Build Coastguard Worker        # Take out trailing spaces / carriage returns
60*2764adbbSAndroid Build Coastguard Worker        line = line.rstrip()
61*2764adbbSAndroid Build Coastguard Worker
62*2764adbbSAndroid Build Coastguard Worker        # Look for tags, which are lines that look like:
63*2764adbbSAndroid Build Coastguard Worker        #   tag: other stuff
64*2764adbbSAndroid Build Coastguard Worker        #
65*2764adbbSAndroid Build Coastguard Worker        # Tags always need to start the line and can't have any spaces in
66*2764adbbSAndroid Build Coastguard Worker        # them, which helps ID them as tags.
67*2764adbbSAndroid Build Coastguard Worker        #
68*2764adbbSAndroid Build Coastguard Worker        # Note that normally we require a space after the colon which keeps
69*2764adbbSAndroid Build Coastguard Worker        # us from getting confused when we're parsing license text that
70*2764adbbSAndroid Build Coastguard Worker        # has a URL. We special-case allow lines to end with a colon
71*2764adbbSAndroid Build Coastguard Worker        # since some tags (like "License:") are sometimes multiline tags
72*2764adbbSAndroid Build Coastguard Worker        # and the first line might just be blank.
73*2764adbbSAndroid Build Coastguard Worker        if ': ' in line or line.endswith(':'):
74*2764adbbSAndroid Build Coastguard Worker            tag, _, rest = line.partition(': ')
75*2764adbbSAndroid Build Coastguard Worker            tag = tag.rstrip(':')
76*2764adbbSAndroid Build Coastguard Worker            if ' ' in tag or '\t' in tag:
77*2764adbbSAndroid Build Coastguard Worker                tag = None
78*2764adbbSAndroid Build Coastguard Worker            else:
79*2764adbbSAndroid Build Coastguard Worker                rest = rest.lstrip()
80*2764adbbSAndroid Build Coastguard Worker        else:
81*2764adbbSAndroid Build Coastguard Worker            tag = None
82*2764adbbSAndroid Build Coastguard Worker
83*2764adbbSAndroid Build Coastguard Worker        # Any new tag or a full separator ends a license.
84*2764adbbSAndroid Build Coastguard Worker        if line == section_divider or (tag and license_text):
85*2764adbbSAndroid Build Coastguard Worker            if license_text:
86*2764adbbSAndroid Build Coastguard Worker                for f in unlicensed_files:
87*2764adbbSAndroid Build Coastguard Worker                    # Clear out blank lines at the start and end
88*2764adbbSAndroid Build Coastguard Worker                    for i, text in enumerate(license_text):
89*2764adbbSAndroid Build Coastguard Worker                        if text:
90*2764adbbSAndroid Build Coastguard Worker                            break
91*2764adbbSAndroid Build Coastguard Worker                    for j, text in reversed(list(enumerate(license_text))):
92*2764adbbSAndroid Build Coastguard Worker                        if text:
93*2764adbbSAndroid Build Coastguard Worker                            break
94*2764adbbSAndroid Build Coastguard Worker                    license_text = license_text[i:j+1]
95*2764adbbSAndroid Build Coastguard Worker
96*2764adbbSAndroid Build Coastguard Worker                    file_info_map[f]['license'] = '\n'.join(license_text)
97*2764adbbSAndroid Build Coastguard Worker            unlicensed_files = []
98*2764adbbSAndroid Build Coastguard Worker            license_text = None
99*2764adbbSAndroid Build Coastguard Worker
100*2764adbbSAndroid Build Coastguard Worker            if line == section_divider:
101*2764adbbSAndroid Build Coastguard Worker                driver = 'UNKNOWN'
102*2764adbbSAndroid Build Coastguard Worker
103*2764adbbSAndroid Build Coastguard Worker        if tag == 'Driver':
104*2764adbbSAndroid Build Coastguard Worker            driver = rest
105*2764adbbSAndroid Build Coastguard Worker        elif tag in ['File', 'RawFile', 'Link']:
106*2764adbbSAndroid Build Coastguard Worker            if tag == 'Link':
107*2764adbbSAndroid Build Coastguard Worker                rest, _, link_dest = rest.partition(' -> ')
108*2764adbbSAndroid Build Coastguard Worker                rest = rest.rstrip()
109*2764adbbSAndroid Build Coastguard Worker                link_dest = unquote_path(link_dest.lstrip())
110*2764adbbSAndroid Build Coastguard Worker
111*2764adbbSAndroid Build Coastguard Worker            rest = unquote_path(rest)
112*2764adbbSAndroid Build Coastguard Worker
113*2764adbbSAndroid Build Coastguard Worker            file_info_map[rest] = { 'driver': driver, 'kind': tag }
114*2764adbbSAndroid Build Coastguard Worker            if tag == 'Link':
115*2764adbbSAndroid Build Coastguard Worker                file_info_map[rest]['link'] = link_dest
116*2764adbbSAndroid Build Coastguard Worker
117*2764adbbSAndroid Build Coastguard Worker            unlicensed_files.append(rest)
118*2764adbbSAndroid Build Coastguard Worker        elif tag in ['License', 'Licence']:
119*2764adbbSAndroid Build Coastguard Worker            license_text = [rest]
120*2764adbbSAndroid Build Coastguard Worker        elif license_text:
121*2764adbbSAndroid Build Coastguard Worker            license_text.append(line)
122*2764adbbSAndroid Build Coastguard Worker
123*2764adbbSAndroid Build Coastguard Worker    return file_info_map
124*2764adbbSAndroid Build Coastguard Worker
125*2764adbbSAndroid Build Coastguard Worker# Look at the license and see if it references other files.
126*2764adbbSAndroid Build Coastguard Worker#
127*2764adbbSAndroid Build Coastguard Worker# Many of the licenses in WHENCE refer to other files in the same directory.
128*2764adbbSAndroid Build Coastguard Worker# This will detect those and return a list of indirectly referenced files.
129*2764adbbSAndroid Build Coastguard Workerdef find_indirect_files(license_text):
130*2764adbbSAndroid Build Coastguard Worker    license_files = []
131*2764adbbSAndroid Build Coastguard Worker
132*2764adbbSAndroid Build Coastguard Worker    # Our regex match works better if there are no carriage returns, so
133*2764adbbSAndroid Build Coastguard Worker    # split everything else and join with spaces. All we care about is
134*2764adbbSAndroid Build Coastguard Worker    # detecting indirectly referenced files anyway.
135*2764adbbSAndroid Build Coastguard Worker    license_text_oneline = ' '.join(license_text.splitlines())
136*2764adbbSAndroid Build Coastguard Worker
137*2764adbbSAndroid Build Coastguard Worker    # The only phrasing that appears present right now refer to one or two
138*2764adbbSAndroid Build Coastguard Worker    # other files and looks like:
139*2764adbbSAndroid Build Coastguard Worker    #   See <filename> for details
140*2764adbbSAndroid Build Coastguard Worker    #   See <filename1> and <filename2> for details
141*2764adbbSAndroid Build Coastguard Worker    #
142*2764adbbSAndroid Build Coastguard Worker    # Detect those two. More can be added later.
143*2764adbbSAndroid Build Coastguard Worker    pattern = re2.compile(r'.*[Ss]ee (.*) for details.*')
144*2764adbbSAndroid Build Coastguard Worker    matcher = pattern.matcher(license_text_oneline)
145*2764adbbSAndroid Build Coastguard Worker    if matcher.matches():
146*2764adbbSAndroid Build Coastguard Worker        for i in range(matcher.group_count()):
147*2764adbbSAndroid Build Coastguard Worker            license_files.extend(matcher.group(i + 1).split(' and '))
148*2764adbbSAndroid Build Coastguard Worker
149*2764adbbSAndroid Build Coastguard Worker    return license_files
150*2764adbbSAndroid Build Coastguard Worker
151*2764adbbSAndroid Build Coastguard Worker# ##########################################################
152*2764adbbSAndroid Build Coastguard Worker# Templates for generated files
153*2764adbbSAndroid Build Coastguard Worker# ##########################################################
154*2764adbbSAndroid Build Coastguard Worker
155*2764adbbSAndroid Build Coastguard Worker# NOTES:
156*2764adbbSAndroid Build Coastguard Worker# - Right now license_type is always BY_EXCEPTION_ONLY. If this is
157*2764adbbSAndroid Build Coastguard Worker#   ever not right we can always add a lookup table by license_kind.
158*2764adbbSAndroid Build Coastguard Workermetadata_template = \
159*2764adbbSAndroid Build Coastguard Worker'''name: "linux-firmware-{name}"
160*2764adbbSAndroid Build Coastguard Workerdescription:
161*2764adbbSAndroid Build Coastguard Worker    "Contains an import of upstream linux-firmware for {name}."
162*2764adbbSAndroid Build Coastguard Worker
163*2764adbbSAndroid Build Coastguard Workerthird_party {{
164*2764adbbSAndroid Build Coastguard Worker  homepage: "{upstream_git_repo}"
165*2764adbbSAndroid Build Coastguard Worker  identifier {{
166*2764adbbSAndroid Build Coastguard Worker    type: "Git"
167*2764adbbSAndroid Build Coastguard Worker    value: "{upstream_git_repo}"
168*2764adbbSAndroid Build Coastguard Worker    primary_source: true
169*2764adbbSAndroid Build Coastguard Worker    version: "{version}"
170*2764adbbSAndroid Build Coastguard Worker  }}
171*2764adbbSAndroid Build Coastguard Worker  version: "{version}"
172*2764adbbSAndroid Build Coastguard Worker  last_upgrade_date {{ year: {year} month: {month} day: {day} }}
173*2764adbbSAndroid Build Coastguard Worker  license_type: BY_EXCEPTION_ONLY
174*2764adbbSAndroid Build Coastguard Worker}}
175*2764adbbSAndroid Build Coastguard Worker'''
176*2764adbbSAndroid Build Coastguard Worker
177*2764adbbSAndroid Build Coastguard Worker# Automatically create the METADATA file under the directory `name`.
178*2764adbbSAndroid Build Coastguard Workerdef create_metadata_file(ctx, name):
179*2764adbbSAndroid Build Coastguard Worker    output = metadata_template.format(
180*2764adbbSAndroid Build Coastguard Worker        name = name,
181*2764adbbSAndroid Build Coastguard Worker        year = ctx.now_as_string('yyyy'),
182*2764adbbSAndroid Build Coastguard Worker        month = ctx.now_as_string('M'),
183*2764adbbSAndroid Build Coastguard Worker        day = ctx.now_as_string('d'),
184*2764adbbSAndroid Build Coastguard Worker        version = ctx.fill_template('${GIT_SHA1}'),
185*2764adbbSAndroid Build Coastguard Worker        upstream_git_repo = upstream_git_repo,
186*2764adbbSAndroid Build Coastguard Worker    )
187*2764adbbSAndroid Build Coastguard Worker
188*2764adbbSAndroid Build Coastguard Worker    ctx.write_path(ctx.new_path(name + '/METADATA'), output)
189*2764adbbSAndroid Build Coastguard Worker
190*2764adbbSAndroid Build Coastguard Workerandroid_bp_template = \
191*2764adbbSAndroid Build Coastguard Worker'''// Copyright (C) {year} The Android Open Source Project
192*2764adbbSAndroid Build Coastguard Worker//
193*2764adbbSAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
194*2764adbbSAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
195*2764adbbSAndroid Build Coastguard Worker// You may obtain a copy of the License at
196*2764adbbSAndroid Build Coastguard Worker//
197*2764adbbSAndroid Build Coastguard Worker//      http://www.apache.org/licenses/LICENSE-2.0
198*2764adbbSAndroid Build Coastguard Worker//
199*2764adbbSAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
200*2764adbbSAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
201*2764adbbSAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
202*2764adbbSAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
203*2764adbbSAndroid Build Coastguard Worker// limitations under the License.
204*2764adbbSAndroid Build Coastguard Worker//
205*2764adbbSAndroid Build Coastguard Worker// This file is autogenerated by copybara, please do not edit.
206*2764adbbSAndroid Build Coastguard Worker
207*2764adbbSAndroid Build Coastguard Workerlicense {{
208*2764adbbSAndroid Build Coastguard Worker    name: "linux_firmware_{name}_license",
209*2764adbbSAndroid Build Coastguard Worker    // Private visibility because nothing links against this. The kernel just
210*2764adbbSAndroid Build Coastguard Worker    // asks for it to be loaded from disk by name.
211*2764adbbSAndroid Build Coastguard Worker    visibility: ["//visibility:private"],
212*2764adbbSAndroid Build Coastguard Worker    license_kinds: [{license_kinds}],
213*2764adbbSAndroid Build Coastguard Worker    license_text: [{license_files}],
214*2764adbbSAndroid Build Coastguard Worker}}
215*2764adbbSAndroid Build Coastguard Worker
216*2764adbbSAndroid Build Coastguard Workerprebuilt_firmware {{
217*2764adbbSAndroid Build Coastguard Worker    name: "linux_firmware_{name}",
218*2764adbbSAndroid Build Coastguard Worker    licenses: ["linux_firmware_{name}_license"],
219*2764adbbSAndroid Build Coastguard Worker    srcs: [{fw_files}],
220*2764adbbSAndroid Build Coastguard Worker    dsts: [{fw_files}],
221*2764adbbSAndroid Build Coastguard Worker    vendor: true,
222*2764adbbSAndroid Build Coastguard Worker}}
223*2764adbbSAndroid Build Coastguard Worker'''
224*2764adbbSAndroid Build Coastguard Worker
225*2764adbbSAndroid Build Coastguard Worker# Format the an array of strings to go into Android.bp
226*2764adbbSAndroid Build Coastguard Workerdef format_android_bp_string_arr(a):
227*2764adbbSAndroid Build Coastguard Worker    if len(a) == 1:
228*2764adbbSAndroid Build Coastguard Worker        return '"%s"' % a[0]
229*2764adbbSAndroid Build Coastguard Worker
230*2764adbbSAndroid Build Coastguard Worker    indent_per = '    '
231*2764adbbSAndroid Build Coastguard Worker    indent = indent_per * 2
232*2764adbbSAndroid Build Coastguard Worker    return '\n' + indent + \
233*2764adbbSAndroid Build Coastguard Worker           (',\n' + indent).join(['"%s"' % s for s in a]) + \
234*2764adbbSAndroid Build Coastguard Worker           ',\n' + indent_per
235*2764adbbSAndroid Build Coastguard Worker
236*2764adbbSAndroid Build Coastguard Worker# Automatically create the Android.bp file under the directory `name`.
237*2764adbbSAndroid Build Coastguard Workerdef create_android_bp_file(ctx, name, license_kind, fw_files):
238*2764adbbSAndroid Build Coastguard Worker    output = android_bp_template.format(
239*2764adbbSAndroid Build Coastguard Worker        name = name,
240*2764adbbSAndroid Build Coastguard Worker        license_kinds = format_android_bp_string_arr([license_kind]),
241*2764adbbSAndroid Build Coastguard Worker        license_files = format_android_bp_string_arr(['LICENSE']),
242*2764adbbSAndroid Build Coastguard Worker        fw_files = format_android_bp_string_arr(fw_files),
243*2764adbbSAndroid Build Coastguard Worker        year = ctx.now_as_string('yyyy'),
244*2764adbbSAndroid Build Coastguard Worker    )
245*2764adbbSAndroid Build Coastguard Worker    ctx.write_path(ctx.new_path(name + '/Android.bp'), output)
246*2764adbbSAndroid Build Coastguard Worker
247*2764adbbSAndroid Build Coastguard Worker# Create the LICENSE file containing all relevant license text.
248*2764adbbSAndroid Build Coastguard Workerdef create_license_file(ctx, name, license_text, license_files, fw_files):
249*2764adbbSAndroid Build Coastguard Worker    license_header_strs = []
250*2764adbbSAndroid Build Coastguard Worker    license_header_strs.append("For the files:")
251*2764adbbSAndroid Build Coastguard Worker    for f in fw_files:
252*2764adbbSAndroid Build Coastguard Worker        license_header_strs.append("- %s" % f)
253*2764adbbSAndroid Build Coastguard Worker    license_header_strs.append("\nThe license is as follows:\n")
254*2764adbbSAndroid Build Coastguard Worker    license_header_strs.append(license_text)
255*2764adbbSAndroid Build Coastguard Worker
256*2764adbbSAndroid Build Coastguard Worker    # Even though the indrectly referenced files are copied to the directory
257*2764adbbSAndroid Build Coastguard Worker    # too, policy says to copy them into the main LICENSE file for easy
258*2764adbbSAndroid Build Coastguard Worker    # reference.
259*2764adbbSAndroid Build Coastguard Worker    license_strs = ['\n'.join(license_header_strs)]
260*2764adbbSAndroid Build Coastguard Worker    for f in license_files:
261*2764adbbSAndroid Build Coastguard Worker        license_strs.append("The text of %s is:\n\n%s" %
262*2764adbbSAndroid Build Coastguard Worker                            (f, ctx.read_path(ctx.new_path(name + '/' + f))))
263*2764adbbSAndroid Build Coastguard Worker
264*2764adbbSAndroid Build Coastguard Worker    ctx.write_path(ctx.new_path(name + '/LICENSE'),
265*2764adbbSAndroid Build Coastguard Worker                   '\n\n---\n\n'.join(license_strs))
266*2764adbbSAndroid Build Coastguard Worker
267*2764adbbSAndroid Build Coastguard Workercommit_message_template = \
268*2764adbbSAndroid Build Coastguard Worker'''IMPORT: {name}
269*2764adbbSAndroid Build Coastguard Worker
270*2764adbbSAndroid Build Coastguard WorkerImport firmware "{name}" using copybara.
271*2764adbbSAndroid Build Coastguard Worker
272*2764adbbSAndroid Build Coastguard WorkerThird-Party Import of: {upstream_git_repo}
273*2764adbbSAndroid Build Coastguard WorkerRequest Document: go/android3p
274*2764adbbSAndroid Build Coastguard WorkerFor CL Reviewers: go/android3p#reviewing-a-cl
275*2764adbbSAndroid Build Coastguard WorkerFor Build Team: go/ab-third-party-imports
276*2764adbbSAndroid Build Coastguard WorkerSecurity Questionnaire: REPLACE WITH bug filed by go/android3p process
277*2764adbbSAndroid Build Coastguard WorkerBug: REPLACE WITH motivation bug
278*2764adbbSAndroid Build Coastguard WorkerBug: REPLACE WITH bug filed by go/android3p process
279*2764adbbSAndroid Build Coastguard WorkerTest: None
280*2764adbbSAndroid Build Coastguard Worker'''
281*2764adbbSAndroid Build Coastguard Worker
282*2764adbbSAndroid Build Coastguard Worker# Automatically set the commit message.
283*2764adbbSAndroid Build Coastguard Workerdef set_commit_message(ctx, name):
284*2764adbbSAndroid Build Coastguard Worker    output = commit_message_template.format(
285*2764adbbSAndroid Build Coastguard Worker        name = name,
286*2764adbbSAndroid Build Coastguard Worker        upstream_git_repo = upstream_git_repo,
287*2764adbbSAndroid Build Coastguard Worker    )
288*2764adbbSAndroid Build Coastguard Worker    ctx.set_message(output)
289*2764adbbSAndroid Build Coastguard Worker
290*2764adbbSAndroid Build Coastguard Worker# ##########################################################
291*2764adbbSAndroid Build Coastguard Worker# Main transformation
292*2764adbbSAndroid Build Coastguard Worker# ##########################################################
293*2764adbbSAndroid Build Coastguard Worker
294*2764adbbSAndroid Build Coastguard Workerdef _firmware_import_transform(ctx):
295*2764adbbSAndroid Build Coastguard Worker    name = ctx.params['name']
296*2764adbbSAndroid Build Coastguard Worker    license_kind = ctx.params['license_kind']
297*2764adbbSAndroid Build Coastguard Worker    expected_license_files = ctx.params['license_files']
298*2764adbbSAndroid Build Coastguard Worker    fw_files = ctx.params['fw_files']
299*2764adbbSAndroid Build Coastguard Worker
300*2764adbbSAndroid Build Coastguard Worker    # We will read the WHENCE to validate that the license upstream lists for
301*2764adbbSAndroid Build Coastguard Worker    # the fw_files matches the license we think we have.
302*2764adbbSAndroid Build Coastguard Worker    whence_text = ctx.read_path(ctx.new_path('WHENCE'))
303*2764adbbSAndroid Build Coastguard Worker    file_info_map = parse_whence(whence_text)
304*2764adbbSAndroid Build Coastguard Worker
305*2764adbbSAndroid Build Coastguard Worker    # To be a valid import then every fw_file we're importing must have the
306*2764adbbSAndroid Build Coastguard Worker    # same license. Validate that.
307*2764adbbSAndroid Build Coastguard Worker    license_text = file_info_map[fw_files[0]].get('license', '')
308*2764adbbSAndroid Build Coastguard Worker    if not license_text:
309*2764adbbSAndroid Build Coastguard Worker        ctx.console.error('Missing license for "%s"' % fw_files[0])
310*2764adbbSAndroid Build Coastguard Worker
311*2764adbbSAndroid Build Coastguard Worker    bad_licenses = [f for f in fw_files
312*2764adbbSAndroid Build Coastguard Worker                    if file_info_map[f].get('license', '') != license_text]
313*2764adbbSAndroid Build Coastguard Worker    if bad_licenses:
314*2764adbbSAndroid Build Coastguard Worker        ctx.console.error(
315*2764adbbSAndroid Build Coastguard Worker            ('All files in a module must have a matching license. ' +
316*2764adbbSAndroid Build Coastguard Worker             'The license(s) for "%s" don\'t match the license for "%s".') %
317*2764adbbSAndroid Build Coastguard Worker            (', '.join(bad_licenses), fw_files[0])
318*2764adbbSAndroid Build Coastguard Worker        )
319*2764adbbSAndroid Build Coastguard Worker
320*2764adbbSAndroid Build Coastguard Worker    for f in expected_license_files:
321*2764adbbSAndroid Build Coastguard Worker        ctx.run(core.move(f, name + '/' + f))
322*2764adbbSAndroid Build Coastguard Worker
323*2764adbbSAndroid Build Coastguard Worker    for f in fw_files:
324*2764adbbSAndroid Build Coastguard Worker        if file_info_map[f]['kind'] == 'Link':
325*2764adbbSAndroid Build Coastguard Worker            dirname = (name + '/' + f).rsplit('/', 1)[0]
326*2764adbbSAndroid Build Coastguard Worker            ctx.create_symlink(ctx.new_path(name + '/' + f),
327*2764adbbSAndroid Build Coastguard Worker                               ctx.new_path(dirname + '/' + file_info_map[f]['link']))
328*2764adbbSAndroid Build Coastguard Worker        else:
329*2764adbbSAndroid Build Coastguard Worker            ctx.run(core.move(f, name + '/' + f))
330*2764adbbSAndroid Build Coastguard Worker
331*2764adbbSAndroid Build Coastguard Worker    # Look for indirectly referenced license files since we'll need those too.
332*2764adbbSAndroid Build Coastguard Worker    license_files = find_indirect_files(license_text)
333*2764adbbSAndroid Build Coastguard Worker
334*2764adbbSAndroid Build Coastguard Worker    # copybara required us to specify all the origin files. To make this work
335*2764adbbSAndroid Build Coastguard Worker    # firmware_import_workflow() requires the callers to provide the list of
336*2764adbbSAndroid Build Coastguard Worker    # indirectly referenced license files. Those should match what we detected.
337*2764adbbSAndroid Build Coastguard Worker    if tuple(sorted(license_files)) != tuple(sorted(expected_license_files)):
338*2764adbbSAndroid Build Coastguard Worker        ctx.console.error(
339*2764adbbSAndroid Build Coastguard Worker            ('Upstream WHENCE specified that licenses were %r but we expected %r.') %
340*2764adbbSAndroid Build Coastguard Worker            (license_files, expected_license_files)
341*2764adbbSAndroid Build Coastguard Worker        )
342*2764adbbSAndroid Build Coastguard Worker
343*2764adbbSAndroid Build Coastguard Worker    create_license_file(ctx, name, license_text, license_files, fw_files)
344*2764adbbSAndroid Build Coastguard Worker    create_metadata_file(ctx, name)
345*2764adbbSAndroid Build Coastguard Worker    create_android_bp_file(ctx, name, license_kind, fw_files)
346*2764adbbSAndroid Build Coastguard Worker    set_commit_message(ctx, name)
347*2764adbbSAndroid Build Coastguard Worker
348*2764adbbSAndroid Build Coastguard Worker    # We don't actually want 'WHENCE' in the destination but we need to read it
349*2764adbbSAndroid Build Coastguard Worker    # so we need to list it in the input files. We can't core.remove() since
350*2764adbbSAndroid Build Coastguard Worker    # that yells at us. Just replace it with some placeholder text.
351*2764adbbSAndroid Build Coastguard Worker    ctx.write_path(ctx.new_path('WHENCE'),
352*2764adbbSAndroid Build Coastguard Worker                   'Upstream WHENCE is parsed to confirm licenses; not copied here.\n')
353*2764adbbSAndroid Build Coastguard Worker
354*2764adbbSAndroid Build Coastguard Worker# Create a workflow for the given files.
355*2764adbbSAndroid Build Coastguard Workerdef firmware_import_workflow(name, license_kind, license_files, fw_files):
356*2764adbbSAndroid Build Coastguard Worker    return core.workflow(
357*2764adbbSAndroid Build Coastguard Worker        name = name,
358*2764adbbSAndroid Build Coastguard Worker        authoring = authoring.overwrite('linux-firmware importer <[email protected]>'),
359*2764adbbSAndroid Build Coastguard Worker
360*2764adbbSAndroid Build Coastguard Worker        origin = git.origin(
361*2764adbbSAndroid Build Coastguard Worker            url = upstream_git_repo,
362*2764adbbSAndroid Build Coastguard Worker            ref = 'main',
363*2764adbbSAndroid Build Coastguard Worker        ),
364*2764adbbSAndroid Build Coastguard Worker
365*2764adbbSAndroid Build Coastguard Worker        # The below is just a placeholder and will be overridden by command
366*2764adbbSAndroid Build Coastguard Worker        # line arguments passed by `run_copybara.sh`. The script is used
367*2764adbbSAndroid Build Coastguard Worker        # because our copybara flow is different than others. Our flow is:
368*2764adbbSAndroid Build Coastguard Worker        # 1. Add the new firmware import to copy.bara.sky and create a
369*2764adbbSAndroid Build Coastguard Worker        #    'ANDROID:' CL for this.
370*2764adbbSAndroid Build Coastguard Worker        # 2. Run copybara locally which creates an 'IMPORT:' CL. Validate
371*2764adbbSAndroid Build Coastguard Worker        #    that it looks OK.
372*2764adbbSAndroid Build Coastguard Worker        # 3. Upload both CLs in a chain and get review.
373*2764adbbSAndroid Build Coastguard Worker        destination = git.destination(
374*2764adbbSAndroid Build Coastguard Worker            url = 'please-use-run_copybara.sh',
375*2764adbbSAndroid Build Coastguard Worker            push = 'please-use-run_copybara.sh',
376*2764adbbSAndroid Build Coastguard Worker        ),
377*2764adbbSAndroid Build Coastguard Worker
378*2764adbbSAndroid Build Coastguard Worker        origin_files = glob(
379*2764adbbSAndroid Build Coastguard Worker            include = license_files + fw_files + ['WHENCE'],
380*2764adbbSAndroid Build Coastguard Worker        ),
381*2764adbbSAndroid Build Coastguard Worker        destination_files = glob(
382*2764adbbSAndroid Build Coastguard Worker            include = [name + '/**'] + ['WHENCE'],
383*2764adbbSAndroid Build Coastguard Worker        ),
384*2764adbbSAndroid Build Coastguard Worker        mode = 'SQUASH',
385*2764adbbSAndroid Build Coastguard Worker        transformations = [
386*2764adbbSAndroid Build Coastguard Worker            core.dynamic_transform(
387*2764adbbSAndroid Build Coastguard Worker                impl = _firmware_import_transform,
388*2764adbbSAndroid Build Coastguard Worker                params = {
389*2764adbbSAndroid Build Coastguard Worker                    'name': name,
390*2764adbbSAndroid Build Coastguard Worker                    'license_kind': license_kind,
391*2764adbbSAndroid Build Coastguard Worker                    'license_files': license_files,
392*2764adbbSAndroid Build Coastguard Worker                    'fw_files': fw_files,
393*2764adbbSAndroid Build Coastguard Worker                },
394*2764adbbSAndroid Build Coastguard Worker            ),
395*2764adbbSAndroid Build Coastguard Worker        ]
396*2764adbbSAndroid Build Coastguard Worker    )
397*2764adbbSAndroid Build Coastguard Worker
398*2764adbbSAndroid Build Coastguard Worker# ##########################################################
399*2764adbbSAndroid Build Coastguard Worker# Firmware that we manage, sorted alphabetically
400*2764adbbSAndroid Build Coastguard Worker# ##########################################################
401*2764adbbSAndroid Build Coastguard Worker
402*2764adbbSAndroid Build Coastguard Worker# Realtek r8152 (and related) USB Ethernet adapters
403*2764adbbSAndroid Build Coastguard Workerfirmware_import_workflow(
404*2764adbbSAndroid Build Coastguard Worker    name = 'r8152',
405*2764adbbSAndroid Build Coastguard Worker    license_kind = 'BSD-Binary-Only',
406*2764adbbSAndroid Build Coastguard Worker    license_files = [
407*2764adbbSAndroid Build Coastguard Worker        'LICENCE.rtlwifi_firmware.txt',
408*2764adbbSAndroid Build Coastguard Worker    ],
409*2764adbbSAndroid Build Coastguard Worker    fw_files = [
410*2764adbbSAndroid Build Coastguard Worker        'rtl_nic/rtl8153a-2.fw',
411*2764adbbSAndroid Build Coastguard Worker        'rtl_nic/rtl8153a-3.fw',
412*2764adbbSAndroid Build Coastguard Worker        'rtl_nic/rtl8153a-4.fw',
413*2764adbbSAndroid Build Coastguard Worker        'rtl_nic/rtl8153b-2.fw',
414*2764adbbSAndroid Build Coastguard Worker        'rtl_nic/rtl8153c-1.fw',
415*2764adbbSAndroid Build Coastguard Worker        'rtl_nic/rtl8156a-2.fw',
416*2764adbbSAndroid Build Coastguard Worker        'rtl_nic/rtl8156b-2.fw',
417*2764adbbSAndroid Build Coastguard Worker    ],
418*2764adbbSAndroid Build Coastguard Worker)
419*2764adbbSAndroid Build Coastguard Worker
420*2764adbbSAndroid Build Coastguard Worker# Ralink RT2800 (and related) USB wireless MACs
421*2764adbbSAndroid Build Coastguard Workerfirmware_import_workflow(
422*2764adbbSAndroid Build Coastguard Worker    name = 'rt2800usb',
423*2764adbbSAndroid Build Coastguard Worker    license_kind = 'BSD-Binary-Only',
424*2764adbbSAndroid Build Coastguard Worker    license_files = [
425*2764adbbSAndroid Build Coastguard Worker        'LICENCE.ralink-firmware.txt',
426*2764adbbSAndroid Build Coastguard Worker    ],
427*2764adbbSAndroid Build Coastguard Worker    fw_files = [
428*2764adbbSAndroid Build Coastguard Worker        'rt2870.bin',
429*2764adbbSAndroid Build Coastguard Worker    ],
430*2764adbbSAndroid Build Coastguard Worker)
431