talm
69 строк · 1.5 Кб
1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5package uki
6
7import (
8"bytes"
9"encoding/binary"
10"errors"
11"os"
12"strings"
13)
14
15// DiscoverKernelVersion reads kernel version from the kernel image.
16//
17// This only works for x86 kernel images.
18//
19// Based on https://www.kernel.org/doc/html/v5.6/x86/boot.html.
20func DiscoverKernelVersion(kernelPath string) (string, error) {
21f, err := os.Open(kernelPath)
22if err != nil {
23return "", err
24}
25
26defer f.Close() //nolint:errcheck
27
28header := make([]byte, 1024)
29
30_, err = f.Read(header)
31if err != nil {
32return "", err
33}
34
35// check header magic
36if string(header[0x202:0x206]) != "HdrS" {
37return "", errors.New("invalid kernel image")
38}
39
40setupSects := header[0x1f1]
41versionOffset := binary.LittleEndian.Uint16(header[0x20e:0x210])
42
43if versionOffset == 0 {
44return "", errors.New("no kernel version")
45}
46
47if versionOffset > uint16(setupSects)*0x200 {
48return "", errors.New("invalid kernel version offset")
49}
50
51versionOffset += 0x200
52
53version := make([]byte, 256)
54
55_, err = f.ReadAt(version, int64(versionOffset))
56if err != nil {
57return "", err
58}
59
60idx := bytes.IndexByte(version, 0)
61if idx == -1 {
62return "", errors.New("invalid kernel version")
63}
64
65versionString := string(version[:idx])
66versionString, _, _ = strings.Cut(versionString, " ")
67
68return versionString, nil
69}
70