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