Dmitriy Matrenichev fa3b933705
chore: replace fmt.Errorf with errors.New where possible
This time use `eg` from `x/tools` repo tool to do this.

Signed-off-by: Dmitriy Matrenichev <dmitry.matrenichev@siderolabs.com>
2024-02-14 17:39:30 +03:00

70 lines
1.5 KiB
Go

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package uki
import (
"bytes"
"encoding/binary"
"errors"
"os"
"strings"
)
// DiscoverKernelVersion reads kernel version from the kernel image.
//
// This only works for x86 kernel images.
//
// Based on https://www.kernel.org/doc/html/v5.6/x86/boot.html.
func DiscoverKernelVersion(kernelPath string) (string, error) {
f, err := os.Open(kernelPath)
if err != nil {
return "", err
}
defer f.Close() //nolint:errcheck
header := make([]byte, 1024)
_, err = f.Read(header)
if err != nil {
return "", err
}
// check header magic
if string(header[0x202:0x206]) != "HdrS" {
return "", errors.New("invalid kernel image")
}
setupSects := header[0x1f1]
versionOffset := binary.LittleEndian.Uint16(header[0x20e:0x210])
if versionOffset == 0 {
return "", errors.New("no kernel version")
}
if versionOffset > uint16(setupSects)*0x200 {
return "", errors.New("invalid kernel version offset")
}
versionOffset += 0x200
version := make([]byte, 256)
_, err = f.ReadAt(version, int64(versionOffset))
if err != nil {
return "", err
}
idx := bytes.IndexByte(version, 0)
if idx == -1 {
return "", errors.New("invalid kernel version")
}
versionString := string(version[:idx])
versionString, _, _ = strings.Cut(versionString, " ")
return versionString, nil
}