Nexoniarz is the sole author and SchOS was never published under Apache-2.0, so this is a straight relicence. LICENSE is the FSF GPLv2 text, every first-party SPDX header moves to GPL-2.0-or-later, and NOTICE, README.md, docs/licensing.md and the site say so. projects/schfs-linux follows the rest of the tree. The GPL gives copyleft: a fork has to ship its source. It also lifts the old "Linux drivers, never" rule, since GPL-2.0-only code combines with GPL-2.0-or-later. "Or later" leaves room for GPLv3, but one binary still has to pick one version, so docs/licensing.md now keeps Apache-2.0 and GPLv3 code out of the kernel to keep Linux code possible there. BSD 4-clause code goes from "avoid" to "no", because the advertising clause is GPL-incompatible. LDLS still ships no .ko. That boundary is now project policy rather than a legal requirement, and ldls.md, devices.md and licensing.md section 6 say so. refmod declares license=GPL, and ldls-check passes (27 checks). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
139 lines
4.9 KiB
C
139 lines
4.9 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
//
|
|
// Reading BTF: struct layouts and function prototypes, from the kernel that
|
|
// the driver was built for.
|
|
//
|
|
// docs/architecture/ldls.md, rule 3½ -- the thing that makes rule 3 comfortable.
|
|
//
|
|
// The shim has to agree with a compiled driver about where `pci_driver.probe`
|
|
// sits, and a compiled driver is not negotiable about it. Writing those
|
|
// offsets into our source would mean a field-for-field match with Linux's
|
|
// headers, which *looks* like transcription however it was arrived at.
|
|
//
|
|
// It does not have to be in our source. A kernel built with
|
|
// CONFIG_DEBUG_INFO_BTF publishes `/sys/kernel/btf/vmlinux`: every struct
|
|
// layout and every function prototype, as generated binary type data
|
|
// describing the kernel that is installed. LDLS reads it at load time, on the
|
|
// user's machine, from the user's own kernel.
|
|
//
|
|
// Two things follow. The offsets are never ours to have copied, and they are
|
|
// right for the kernel actually present rather than one we pinned by guessing
|
|
// -- which is most of what rule 4 was worried about.
|
|
//
|
|
// The format is described in Documentation/bpf/btf.rst, which is a published
|
|
// specification; implementing it from that is the case ../docs/licensing.md §5
|
|
// covers. Freestanding, like the rest of ldls/.
|
|
|
|
// --- the format -------------------------------------------------------------
|
|
|
|
#define BTF_MAGIC 0xeB9F
|
|
|
|
struct btf_header {
|
|
unsigned short magic;
|
|
unsigned char version;
|
|
unsigned char flags;
|
|
unsigned int hdr_len;
|
|
// Both offsets are from the end of the header, not from the start of it.
|
|
unsigned int type_off;
|
|
unsigned int type_len;
|
|
unsigned int str_off;
|
|
unsigned int str_len;
|
|
};
|
|
|
|
struct btf_type {
|
|
unsigned int name_off;
|
|
// vlen in bits 0-15, kind in bits 24-28, kind_flag in bit 31.
|
|
unsigned int info;
|
|
union {
|
|
unsigned int size; // STRUCT, UNION, ENUM, INT, DATASEC, FLOAT
|
|
unsigned int type; // PTR, TYPEDEF, CONST, FUNC, VAR, ...
|
|
} u;
|
|
};
|
|
|
|
struct btf_member {
|
|
unsigned int name_off;
|
|
unsigned int type;
|
|
// With kind_flag set this is a bitfield: size in bits 24-31, bit offset in
|
|
// bits 0-23. Without it, a plain bit offset.
|
|
unsigned int offset;
|
|
};
|
|
|
|
struct btf_param {
|
|
unsigned int name_off;
|
|
unsigned int type;
|
|
};
|
|
|
|
#define BTF_KIND_INT 1
|
|
#define BTF_KIND_PTR 2
|
|
#define BTF_KIND_ARRAY 3
|
|
#define BTF_KIND_STRUCT 4
|
|
#define BTF_KIND_UNION 5
|
|
#define BTF_KIND_ENUM 6
|
|
#define BTF_KIND_FWD 7
|
|
#define BTF_KIND_TYPEDEF 8
|
|
#define BTF_KIND_VOLATILE 9
|
|
#define BTF_KIND_CONST 10
|
|
#define BTF_KIND_RESTRICT 11
|
|
#define BTF_KIND_FUNC 12
|
|
#define BTF_KIND_FUNC_PROTO 13
|
|
#define BTF_KIND_VAR 14
|
|
#define BTF_KIND_DATASEC 15
|
|
#define BTF_KIND_FLOAT 16
|
|
#define BTF_KIND_DECL_TAG 17
|
|
#define BTF_KIND_TYPE_TAG 18
|
|
#define BTF_KIND_ENUM64 19
|
|
|
|
#define BTF_INFO_KIND(i) (((i) >> 24) & 0x1f)
|
|
#define BTF_INFO_VLEN(i) ((i) & 0xffff)
|
|
#define BTF_INFO_KFLAG(i) (((i) >> 31) & 1)
|
|
|
|
// --- the reader ---------------------------------------------------------------
|
|
|
|
#define BTF_MAXTYPES 262144 // type ids we will index; vmlinux is ~150k
|
|
|
|
struct btf {
|
|
const unsigned char *img;
|
|
unsigned long long len;
|
|
const struct btf_header *h;
|
|
const unsigned char *types; // start of the type section
|
|
unsigned int types_len;
|
|
const char *str;
|
|
unsigned int str_len;
|
|
|
|
// Type id -> byte offset into the type section. Id 0 is void and has no
|
|
// entry, so this is 1-based and index 0 is unused.
|
|
unsigned int *off; // the caller's, ntypes + 1 entries
|
|
unsigned int ntypes;
|
|
|
|
char err[128];
|
|
};
|
|
|
|
// How many type ids this BTF holds, so the caller can size the index. -1 if
|
|
// the image is not BTF at all.
|
|
long btf_count(const void *image, unsigned long long len);
|
|
|
|
// Index it. `off` must have btf_count()+1 entries.
|
|
int btf_open(struct btf *b, const void *image, unsigned long long len,
|
|
unsigned int *off, unsigned int noff);
|
|
|
|
// The type id of a named type of a given kind, or 0.
|
|
int btf_find(struct btf *b, const char *name, int kind);
|
|
|
|
// Byte offset and size of a named member of a struct or union.
|
|
//
|
|
// Returns 0 on success. Bitfields are refused rather than rounded: a driver
|
|
// that reads one needs the bit position, and a byte offset would be a
|
|
// plausible-looking wrong answer.
|
|
int btf_member_off(struct btf *b, int struct_id, const char *member,
|
|
unsigned int *off_bytes, unsigned int *size_bytes);
|
|
|
|
// The value of a named enumerator, searched across every enum in the file.
|
|
// Constants a driver depends on are not all struct offsets -- see btf.c.
|
|
int btf_enum_value(struct btf *b, const char *name, long long *val);
|
|
|
|
// Size in bytes of a type, following typedefs and qualifiers. 0 if unknown.
|
|
unsigned int btf_type_size(struct btf *b, int id);
|
|
|
|
const char *btf_name_of(struct btf *b, int id);
|
|
int btf_kind_of(struct btf *b, int id);
|
|
const char *btf_err(const struct btf *b);
|