Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix configuration for arm64 and fix kConfigValidate #177

Merged
merged 4 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions cmd/lvh/kernels/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ import (
"github.com/spf13/cobra"
)

func configureCommand() *cobra.Command {
var arch string
const (
archFlag = "arch"
archHelp = "target architecture to configure the kernel, e.g. 'amd64' or 'arm64' (default to native architecture)"
)

func configureCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "configure <kernel>",
Short: "configure kernel",
Expand All @@ -26,20 +29,20 @@ func configureCommand() *cobra.Command {
}

kname := args[0]
if err := kd.ConfigureKernel(context.Background(), log, kname, arch); err != nil {
if err := kd.ConfigureKernel(context.Background(), log, kname, cmd.Flag(archFlag).Value.String()); err != nil {
log.Fatal(err)
}

},
}

cmd.Flags().StringVar(&arch, "arch", "", "target architecture to configure the kernel, e.g. 'amd64' or 'arm64' (default to native architecture)")
cmd.Flags().String(archFlag, "", archHelp)

return cmd
}

func rawConfigureCommand() *cobra.Command {
return &cobra.Command{
cmd := &cobra.Command{
Use: "raw_configure <kernel_dir> [<kernel_name>]",
Short: "configure a kernel prepared by means other than lvh",
Args: cobra.RangeArgs(1, 2),
Expand All @@ -55,10 +58,14 @@ func rawConfigureCommand() *cobra.Command {
if len(args) > 1 {
kname = args[1]
}
if err := kd.RawConfigure(context.Background(), log, kdir, kname); err != nil {
if err := kd.RawConfigure(context.Background(), log, kdir, kname, cmd.Flag(archFlag).Value.String()); err != nil {
log.Fatal(err)
}

},
}

cmd.Flags().String(archFlag, "", archHelp)

return cmd
}
66 changes: 45 additions & 21 deletions pkg/kernels/dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,30 +54,41 @@ func (kd *KernelsDir) ConfigureKernel(ctx context.Context, log *logrus.Logger, k
return kd.configureKernel(ctx, log, kc, targetArch)
}

func (kd *KernelsDir) RawConfigure(ctx context.Context, log *logrus.Logger, kernDir, kernName string) error {
func (kd *KernelsDir) RawConfigure(ctx context.Context, log *logrus.Logger, kernDir, kernName string, targetArch string) error {
kc := kd.KernelConfig(kernName)
return kd.rawConfigureKernel(ctx, log, kc, kernDir)
return kd.rawConfigureKernel(ctx, log, kc, targetArch, kernDir)
}

func kcfonfigValidate(opts []ConfigOption) error {
func kConfigValidate(opts []ConfigOption) error {

var ret error
// we want to check that:
// - what is supposed to be enabled, is enabled
// - what is supposed to be disabled, is not enabled
// - what is supposed to be configured as module, is configured as a module

type configState string

const (
enabledState configState = "y"
disabledState configState = "n"
moduleState configState = "m"
)

type OptMapVal struct {
enabled bool
state configState
checked bool
}

optMap := make(map[string]OptMapVal)
for _, opt := range opts {
switch opt[0] {
case "--enable":
optMap[opt[1]] = OptMapVal{enabled: true}
optMap[opt[1]] = OptMapVal{state: enabledState}
case "--disable":
optMap[opt[1]] = OptMapVal{enabled: false}
optMap[opt[1]] = OptMapVal{state: disabledState}
case "--module":
optMap[opt[1]] = OptMapVal{state: moduleState}
default:
return fmt.Errorf("Unknown option: %s", opt[0])
}
Expand All @@ -90,18 +101,20 @@ func kcfonfigValidate(opts []ConfigOption) error {
}
defer kcfg.Close()

enabledRe := regexp.MustCompile(`([a-zA-Z0-9_]+)=y`)
enabledOrModuleRe := regexp.MustCompile(`([a-zA-Z0-9_]+)=(y|m)`)
disabledRe := regexp.MustCompile(`# ([a-zA-Z0-9_]+) is not set`)
s := bufio.NewScanner(kcfg)
for s.Scan() {
txt := s.Text()
var opt string
optEnabled := false
if match := enabledRe.FindStringSubmatch(txt); len(match) > 0 {
var optState configState
if match := enabledOrModuleRe.FindStringSubmatch(txt); len(match) > 2 {
opt = match[1]
optEnabled = true
} else if match := disabledRe.FindStringSubmatch(txt); len(match) > 0 {
// the regex can only match 'y' or 'm' so this should be correct
optState = configState(match[2])
} else if match := disabledRe.FindStringSubmatch(txt); len(match) > 1 {
opt = match[1]
optState = disabledState
} else {
continue
}
Expand All @@ -114,10 +127,10 @@ func kcfonfigValidate(opts []ConfigOption) error {
mapVal.checked = true
optMap[opt] = mapVal

if mapVal.enabled != optEnabled {
if mapVal.state != optState {
ret = errors.Join(ret,
fmt.Errorf("value %s misconfigured: expected: %t but seems to be %t based on '%s'",
opt, mapVal.enabled, optEnabled, txt))
fmt.Errorf("value %s misconfigured: expected: %q but seems to be %q based on %q",
opt, mapVal.state, optState, txt))
}

}
Expand All @@ -127,9 +140,12 @@ func kcfonfigValidate(opts []ConfigOption) error {
}

for i, v := range optMap {
if v.enabled && !v.checked {
if v.state == enabledState && !v.checked {
ret = errors.Join(ret, fmt.Errorf("value %s enabled but not found", i))
}
if v.state == moduleState && !v.checked {
ret = errors.Join(ret, fmt.Errorf("value %s configured as module but not found", i))
}
}

return ret
Expand All @@ -149,7 +165,7 @@ func runAndLogMake(

func (kd *KernelsDir) rawConfigureKernel(
ctx context.Context, log *logrus.Logger,
kc *KernelConf, srcDir string,
kc *KernelConf, srcDir string, targetArch string,
makePrepareArgs ...string,
) error {
oldPath, err := os.Getwd()
Expand Down Expand Up @@ -178,27 +194,35 @@ func (kd *KernelsDir) rawConfigureKernel(
}

if false {
if err := kcfonfigValidate(configOptions[:i+1]); err != nil {
if err := kConfigValidate(configOptions[:i+1]); err != nil {
return fmt.Errorf("failed to validate config after applying %v: %w", opts, err)
}
}

}

if false {
if err := kcfonfigValidate(configOptions); err != nil {
if err := kConfigValidate(configOptions); err != nil {
return fmt.Errorf("failed to validate config after scripts: %w", err)
}
}

crossCompilationArgs, err := arch.CrossCompileMakeArgs(targetArch)
if err != nil {
return fmt.Errorf("failed to retrieve cross compilation args: %w", err)
}

olddefconfigMakeArgs := []string{"olddefconfig"}
olddefconfigMakeArgs = append(olddefconfigMakeArgs, crossCompilationArgs...)

// run make olddefconfig to clean up the config file, and ensure that everything is in order
if err := runAndLogMake(ctx, log, kc, "olddefconfig"); err != nil {
if err := runAndLogMake(ctx, log, kc, olddefconfigMakeArgs...); err != nil {
return err
}

// NB: some configuration options are only available in certain
// kernels. We have no way of dealing with this currently.
if err := kcfonfigValidate(configOptions); err != nil {
if err := kConfigValidate(configOptions); err != nil {
log.Warnf("discrepancies in generated config: %s", err)
}

Expand All @@ -216,7 +240,7 @@ func (kd *KernelsDir) configureKernel(ctx context.Context, log *logrus.Logger, k
configureMakeArgs := []string{"defconfig", "prepare"}
configureMakeArgs = append(configureMakeArgs, crossCompilationArgs...)

return kd.rawConfigureKernel(ctx, log, kc, srcDir, configureMakeArgs...)
return kd.rawConfigureKernel(ctx, log, kc, srcDir, targetArch, configureMakeArgs...)

}

Expand Down
Loading