blob: 2554c3363ae5e060437ecb02b125f9bc3a084add [file] [log] [blame]
Lorenz Brunc7b036b2023-06-01 12:23:57 +02001package kmod
2
3import (
4 "fmt"
5 "log"
6
7 kmodpb "source.monogon.dev/metropolis/pkg/kmod/spec"
8)
9
10// MakeMetaFromModuleInfo is a more flexible alternative to MakeMeta. It only
11// relies on ModuleInfo structures, additional processing can be done outside of
12// this function. It does however require that for dynamically-loaded modules
13// the "path" key is set to the path of the .ko file relative to the module
14// root.
15func MakeMetaFromModuleInfo(modinfos []ModuleInfo) (*kmodpb.Meta, error) {
16 modIndices := make(map[string]uint32)
17 modInfoMap := make(map[string]ModuleInfo)
18 var meta kmodpb.Meta
19 meta.ModuleDeviceMatches = &kmodpb.RadixNode{
20 Type: kmodpb.RadixNode_ROOT,
21 }
22 var i uint32
23 for _, m := range modinfos {
24 meta.Modules = append(meta.Modules, &kmodpb.Module{
25 Name: m.Name(),
26 Path: m.Get("path"),
27 })
28 for _, p := range m.Aliases() {
29 if m.Get("path") == "" {
30 // Ignore built-in modaliases as they do not need to be loaded.
31 continue
32 }
33 if err := AddPattern(meta.ModuleDeviceMatches, p, i); err != nil {
34 return nil, fmt.Errorf("failed adding device match %q: %w", p, err)
35 }
36 }
37 modIndices[m.Name()] = i
38 modInfoMap[m.Name()] = m
39 i++
40 }
41 for _, m := range meta.Modules {
42 for _, dep := range modInfoMap[m.Name].GetDependencies() {
43 if _, ok := modIndices[dep]; !ok {
44 log.Printf("Unknown dependency %q for module %q", modInfoMap[m.Name].GetDependencies(), m.Name)
45 }
46 m.Depends = append(m.Depends, modIndices[dep])
47 }
48 }
49 return &meta, nil
50}