blob: 7928586e9bbb6c86f6afd391517bad3ec0bb7c9a [file] [log] [blame]
// Copyright (C) 2025 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package filesystem
import (
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
)
type bootloaderInfo struct {
bootloaderImg android.Path
}
var bootloaderInfoProvider = blueprint.NewProvider[bootloaderInfo]()
type prebuiltBootloader struct {
android.ModuleBase
properties PrebuiltBootloaderProperties
vbmetaPartitions vbmetaPartitionInfos
}
type PrebuiltBootloaderProperties struct {
Src *string `android:"path"`
// List of OTA updatable partitions of bootloader.img.
// These will be unpacked from bootloader.img and added to the list
// of partitions to be updated.
Ab_ota_partitions []string
// Tool for unpacking bootloader.img
Unpack_tool *string `android:"path"`
}
// TODO(soong-team): This module should be registered with the name
// `prebuilt_bootloader`. If not, update the property error in
// [androidDevice.checkRadioVersion]. Remove this TODO once the module type is
// registered.
func PrebuiltBootloaderFactory() android.Module {
module := &prebuiltBootloader{}
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
module.AddProperties(&module.properties)
return module
}
func (p *prebuiltBootloader) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if p.properties.Src == nil {
ctx.PropertyErrorf("src", "Source cannot be empty")
}
bootloader := android.PathForModuleSrc(ctx, proptools.String(p.properties.Src))
bootloaderFiles := append(android.Paths{}, bootloader)
bootloaderFiles = append(bootloaderFiles, p.partitionFilesBootloader(ctx)...)
ctx.SetOutputFiles(bootloaderFiles, "")
android.SetProvider(ctx, vbmetaPartitionsProvider, p.vbmetaPartitions)
android.SetProvider(ctx, bootloaderInfoProvider, bootloaderInfo{
bootloaderImg: bootloader,
})
}
// Unpack a partition from a bootloader.img and add them to
// the list of partitions to be updated.
func (p *prebuiltBootloader) partitionFilesBootloader(ctx android.ModuleContext) android.Paths {
bootloader := android.PathForModuleSrc(ctx, proptools.String(p.properties.Src))
if len(p.properties.Ab_ota_partitions) == 0 {
return nil
}
var files android.Paths
unpackedDir := android.PathForModuleOut(ctx, "unpack_bootloader")
builder := android.NewRuleBuilder(pctx, ctx).Sbox(
unpackedDir,
android.PathForModuleOut(ctx, "unpack_bootloader.textproto"),
)
for _, partition := range p.properties.Ab_ota_partitions {
unpackedImg := unpackedDir.Join(ctx, partition+".img")
cmd := builder.Command()
cmd.Input(android.PathForModuleSrc(ctx, proptools.String(p.properties.Unpack_tool))).
Flag(" unpack ").
Flag("-o ").
Textf("%s ", cmd.PathForOutput(unpackedDir)).
Input(bootloader).
Text(" " + partition).
ImplicitOutput(unpackedImg)
files = append(files, unpackedImg)
// avb signed
signed := p.avbAddHash(ctx, builder, partition, unpackedImg)
files = append(files, signed)
p.vbmetaPartitions = append(p.vbmetaPartitions, vbmetaPartitionInfo{
Name: partition,
Output: signed,
AbOtaBootloaderPartition: true,
})
}
builder.Build("unpack_bootloader", "unpack_bootloader")
return files
}
func (p *prebuiltBootloader) avbAddHash(ctx android.ModuleContext, builder *android.RuleBuilder, partitionName string, unpackedPartition android.OutputPath) android.Path {
output := unpackedPartition.InSameDir(ctx, partitionName+"_vbfooted.img")
builder.Command().Text("cp").Input(unpackedPartition).Output(output)
cmd := builder.Command()
cmd.BuiltTool("avbtool").
Text("add_hash_footer").
FlagWithOutput("--image ", output).
FlagWithArg("--partition_name ", partitionName).
Textf(`--salt $(sha256sum "%s" "%s" | cut -d " " -f 1 | tr -d '\n')`, cmd.PathForInput(ctx.Config().BuildNumberFile(ctx)), cmd.PathForInput(ctx.Config().BuildDateFile(ctx))).
OrderOnly(ctx.Config().BuildNumberFile(ctx)).OrderOnly(ctx.Config().BuildDateFile(ctx))
vbmetaPaddingSize := 64*1024 + 4096
cmd.Textf("--partition_size $(( %d + (( $(stat -c %%s %s) - 1) / 4096 + 1) * 4096 ))", vbmetaPaddingSize, cmd.PathForOutput(unpackedPartition))
return output
}