mirror of
https://github.com/systemd/systemd
synced 2026-03-30 19:54:51 +02:00
Compare commits
11 Commits
81218ac1e1
...
0a51337df1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a51337df1 | ||
|
|
0bb6699edc | ||
|
|
6b292fa17b | ||
|
|
a6d4e83b8a | ||
|
|
dc46792831 | ||
|
|
6870cf0729 | ||
|
|
6b652c03a4 | ||
|
|
200b1d997d | ||
|
|
ea7ded75f3 | ||
|
|
9eb3e30a76 | ||
|
|
87bd39508b |
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Main License
|
## Main License
|
||||||
|
|
||||||
The systemd project uses single-line references to Unique Licese Identifiers as
|
The systemd project uses single-line references to Unique License Identifiers as
|
||||||
defined by the Linux Foundation's SPDX project (https://spdx.org/). The line in
|
defined by the Linux Foundation's SPDX project (https://spdx.org/). The line in
|
||||||
each individual source file identifies the license applicable to that file.
|
each individual source file identifies the license applicable to that file.
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ The following exceptions apply:
|
|||||||
- src/basic/siphash24.h
|
- src/basic/siphash24.h
|
||||||
- src/systemctl/systemd-sysv-install.SKELETON
|
- src/systemctl/systemd-sysv-install.SKELETON
|
||||||
- tools/check-includes.pl
|
- tools/check-includes.pl
|
||||||
- all examples, code and scripts, under man/ except where otherwise noted
|
- all examples under man/
|
||||||
* the following sources are under **Public Domain** (LicenseRef-murmurhash2-public-domain):
|
* the following sources are under **Public Domain** (LicenseRef-murmurhash2-public-domain):
|
||||||
- src/basic/MurmurHash2.c
|
- src/basic/MurmurHash2.c
|
||||||
- src/basic/MurmurHash2.h
|
- src/basic/MurmurHash2.h
|
||||||
|
|||||||
@ -44,3 +44,49 @@ See [reporting of security vulnerabilities](SECURITY.md).
|
|||||||
We'd like to apologize in advance if we are not able to process and reply to your issue or PR right-away. We have a lot of work to do, but we are trying our best!
|
We'd like to apologize in advance if we are not able to process and reply to your issue or PR right-away. We have a lot of work to do, but we are trying our best!
|
||||||
|
|
||||||
Thank you very much for your contributions!
|
Thank you very much for your contributions!
|
||||||
|
|
||||||
|
# Backward Compatibility And External Dependencies
|
||||||
|
|
||||||
|
We strive to keep backward compatibility where possible and reasonable. The following are general guidelines, not hard
|
||||||
|
rules, and case-by-case exceptions might be applied at the discretion of the maintainers. The current set of build time
|
||||||
|
and runtime dependencies are documented in the [README](../README).
|
||||||
|
|
||||||
|
## New features
|
||||||
|
|
||||||
|
It is fine for new features/functionality/tools/daemons to require bleeding edge external dependencies, provided there
|
||||||
|
are runtime and build time graceful fallbacks (e.g.: daemon will not be built, runtime functionality will be skipped with
|
||||||
|
clear log message).
|
||||||
|
In case a new feature is added to both `systemd` and one of its dependencies, we expect the corresponding feature code to
|
||||||
|
be merged upstream in the dependency before accepting our side of the implementation.
|
||||||
|
Making use of new kernel syscalls can be achieved through compat wrappers in our tree (see: `src/basic/missing_syscall_def.h`),
|
||||||
|
and does not need to wait for glibc support.
|
||||||
|
|
||||||
|
## External Build/Runtime Dependencies
|
||||||
|
|
||||||
|
It is often tempting to bump external dependencies minimum versions to cut cruft, and in general it's an essential part
|
||||||
|
of the maintenance process. But as a generic rule, existing dependencies should not be bumped without very strong
|
||||||
|
reasons. When possible, we try to keep compatibility with the most recent LTS releases of each mainstream distribution
|
||||||
|
for optional components, and with all currently maintained (i.e.: not EOL) LTS releases for core components. When in
|
||||||
|
doubt, ask before committing time to work on contributions if it's not clear that cutting support would be obviously
|
||||||
|
acceptable.
|
||||||
|
|
||||||
|
## Kernel Requirements
|
||||||
|
|
||||||
|
Same principles as with other dependencies should be applied. It is fine to require newer kernel versions for additional
|
||||||
|
functionality or optional features, but very strong reasons should be required for breaking compatibility for existing
|
||||||
|
functionality, especially for core components. It is not uncommon, for example, for embedded systems to be stuck on older
|
||||||
|
kernel versions due to hardware requirements, so do not assume everybody is running with latest and greatest at all times.
|
||||||
|
In general, [currently maintained LTS branches](https://www.kernel.org/category/releases.html) should keep being supported
|
||||||
|
for existing functionality, especially for core components.
|
||||||
|
|
||||||
|
## `libsystemd.so`
|
||||||
|
|
||||||
|
`libsystemd.so` is a shared public library, so breaking ABI/API compatibility creates a lot of work for its users, and should
|
||||||
|
always be avoided apart from the most extreme circumstances. For example, always add a new interface instead of modifying
|
||||||
|
the signature of an existing function. It is fine to mark an interface as deprecated to gently nudge users toward a newer one,
|
||||||
|
but in general support for the old one should be maintained whenever possible.
|
||||||
|
Symbol versioning and the compiler's deprecated attribute should be used when managing the lifetime of a public interface.
|
||||||
|
|
||||||
|
## `libudev.so`
|
||||||
|
|
||||||
|
`libudev.so` is a shared public library, and is still maintained, but should not gain new symbols at this point.
|
||||||
|
|||||||
@ -49,12 +49,6 @@ typedef void (*free_func_t)(void *p);
|
|||||||
|
|
||||||
#define malloc0(n) (calloc(1, (n) ?: 1))
|
#define malloc0(n) (calloc(1, (n) ?: 1))
|
||||||
|
|
||||||
#define mfree(memory) \
|
|
||||||
({ \
|
|
||||||
free(memory); \
|
|
||||||
(typeof(memory)) NULL; \
|
|
||||||
})
|
|
||||||
|
|
||||||
#define free_and_replace(a, b) \
|
#define free_and_replace(a, b) \
|
||||||
({ \
|
({ \
|
||||||
typeof(a)* _a = &(a); \
|
typeof(a)* _a = &(a); \
|
||||||
|
|||||||
@ -1,109 +1,186 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generic Linux boot protocol using the EFI/PE entry point of the kernel. Passes
|
||||||
|
* initrd with the LINUX_INITRD_MEDIA_GUID DevicePath and cmdline with
|
||||||
|
* EFI LoadedImageProtocol.
|
||||||
|
*
|
||||||
|
* This method works for Linux 5.8 and newer on ARM/Aarch64, x86/x68_64 and RISC-V.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <efi.h>
|
#include <efi.h>
|
||||||
#include <efilib.h>
|
#include <efilib.h>
|
||||||
|
|
||||||
#include "linux.h"
|
|
||||||
#include "initrd.h"
|
#include "initrd.h"
|
||||||
|
#include "linux.h"
|
||||||
|
#include "pe.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#ifdef __i386__
|
static EFI_LOADED_IMAGE * loaded_image_free(EFI_LOADED_IMAGE *img) {
|
||||||
#define __regparm0__ __attribute__((regparm(0)))
|
if (!img)
|
||||||
#else
|
return NULL;
|
||||||
#define __regparm0__
|
mfree(img->LoadOptions);
|
||||||
#endif
|
return mfree(img);
|
||||||
|
}
|
||||||
|
|
||||||
typedef VOID(*handover_f)(VOID *image, EFI_SYSTEM_TABLE *table, struct boot_params *params) __regparm0__;
|
static EFI_STATUS loaded_image_register(
|
||||||
|
const CHAR8 *cmdline, UINTN cmdline_len,
|
||||||
|
const VOID *linux_buffer, UINTN linux_length,
|
||||||
|
EFI_HANDLE *ret_image) {
|
||||||
|
|
||||||
static VOID linux_efi_handover(EFI_HANDLE image, struct boot_params *params) {
|
EFI_LOADED_IMAGE *loaded_image = NULL;
|
||||||
handover_f handover;
|
EFI_STATUS err;
|
||||||
UINTN start = (UINTN)params->hdr.code32_start;
|
|
||||||
|
|
||||||
assert(params);
|
assert(cmdline || cmdline_len > 0);
|
||||||
|
assert(linux_buffer && linux_length > 0);
|
||||||
|
assert(ret_image);
|
||||||
|
|
||||||
#ifdef __x86_64__
|
/* create and install new LoadedImage Protocol */
|
||||||
asm volatile ("cli");
|
loaded_image = AllocatePool(sizeof(EFI_LOADED_IMAGE));
|
||||||
start += 512;
|
if (!loaded_image)
|
||||||
#endif
|
return EFI_OUT_OF_RESOURCES;
|
||||||
handover = (handover_f)(start + params->hdr.handover_offset);
|
|
||||||
handover(image, ST, params);
|
/* provide the image base address and size */
|
||||||
|
*loaded_image = (EFI_LOADED_IMAGE) {
|
||||||
|
.ImageBase = (VOID *) linux_buffer,
|
||||||
|
.ImageSize = linux_length
|
||||||
|
};
|
||||||
|
|
||||||
|
/* if a cmdline is set convert it to UTF16 */
|
||||||
|
if (cmdline) {
|
||||||
|
loaded_image->LoadOptions = stra_to_str(cmdline);
|
||||||
|
if (!loaded_image->LoadOptions) {
|
||||||
|
loaded_image = loaded_image_free(loaded_image);
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
loaded_image->LoadOptionsSize = StrSize(loaded_image->LoadOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* install a new LoadedImage protocol. ret_handle is a new image handle */
|
||||||
|
err = uefi_call_wrapper(BS->InstallMultipleProtocolInterfaces, 4,
|
||||||
|
ret_image,
|
||||||
|
&LoadedImageProtocol, loaded_image,
|
||||||
|
NULL);
|
||||||
|
if (EFI_ERROR(err))
|
||||||
|
loaded_image = loaded_image_free(loaded_image);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static EFI_STATUS loaded_image_unregister(EFI_HANDLE loaded_image_handle) {
|
||||||
|
EFI_LOADED_IMAGE_PROTOCOL *loaded_image;
|
||||||
|
EFI_STATUS err;
|
||||||
|
|
||||||
|
if (!loaded_image_handle)
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
|
||||||
|
/* get the LoadedImage protocol that we allocated earlier */
|
||||||
|
err = uefi_call_wrapper(
|
||||||
|
BS->OpenProtocol, 6,
|
||||||
|
loaded_image_handle, &LoadedImageProtocol, (VOID **) &loaded_image,
|
||||||
|
NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
||||||
|
if (EFI_ERROR(err))
|
||||||
|
return err;
|
||||||
|
|
||||||
|
/* close the handle */
|
||||||
|
(void) uefi_call_wrapper(
|
||||||
|
BS->CloseProtocol, 4,
|
||||||
|
loaded_image_handle, &LoadedImageProtocol, NULL, NULL);
|
||||||
|
err = uefi_call_wrapper(BS->UninstallMultipleProtocolInterfaces, 4,
|
||||||
|
loaded_image_handle,
|
||||||
|
&LoadedImageProtocol, loaded_image,
|
||||||
|
NULL);
|
||||||
|
if (EFI_ERROR(err))
|
||||||
|
return err;
|
||||||
|
loaded_image_handle = NULL;
|
||||||
|
loaded_image = loaded_image_free(loaded_image);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void cleanup_initrd(EFI_HANDLE *initrd_handle) {
|
||||||
|
(void) initrd_unregister(*initrd_handle);
|
||||||
|
*initrd_handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void cleanup_loaded_image(EFI_HANDLE *loaded_image_handle) {
|
||||||
|
(void) loaded_image_unregister(*loaded_image_handle);
|
||||||
|
*loaded_image_handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* struct to call cleanup_pages */
|
||||||
|
struct pages {
|
||||||
|
EFI_PHYSICAL_ADDRESS addr;
|
||||||
|
UINTN num;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void cleanup_pages(struct pages *p) {
|
||||||
|
if (p->addr == 0)
|
||||||
|
return;
|
||||||
|
(void) uefi_call_wrapper(BS->FreePages, 2, p->addr, p->num);
|
||||||
}
|
}
|
||||||
|
|
||||||
EFI_STATUS linux_exec(
|
EFI_STATUS linux_exec(
|
||||||
EFI_HANDLE image,
|
EFI_HANDLE image,
|
||||||
const CHAR8 *cmdline, UINTN cmdline_len,
|
const CHAR8 *cmdline, UINTN cmdline_len,
|
||||||
const VOID *linux_buffer,
|
const VOID *linux_buffer, UINTN linux_length,
|
||||||
const VOID *initrd_buffer, UINTN initrd_length) {
|
const VOID *initrd_buffer, UINTN initrd_length) {
|
||||||
|
|
||||||
const struct boot_params *image_params;
|
_cleanup_(cleanup_initrd) EFI_HANDLE initrd_handle = NULL;
|
||||||
struct boot_params *boot_params;
|
_cleanup_(cleanup_loaded_image) EFI_HANDLE loaded_image_handle = NULL;
|
||||||
EFI_HANDLE initrd_handle = NULL;
|
UINT32 kernel_alignment, kernel_size_of_image, kernel_entry_address;
|
||||||
EFI_PHYSICAL_ADDRESS addr;
|
EFI_IMAGE_ENTRY_POINT kernel_entry;
|
||||||
UINT8 setup_sectors;
|
_cleanup_(cleanup_pages) struct pages kernel = {};
|
||||||
|
VOID *new_buffer;
|
||||||
EFI_STATUS err;
|
EFI_STATUS err;
|
||||||
|
|
||||||
assert(image);
|
assert(image);
|
||||||
assert(cmdline || cmdline_len == 0);
|
assert(cmdline || cmdline_len == 0);
|
||||||
assert(linux_buffer);
|
assert(linux_buffer && linux_length > 0);
|
||||||
assert(initrd_buffer || initrd_length == 0);
|
assert(initrd_buffer || initrd_length == 0);
|
||||||
|
|
||||||
image_params = (const struct boot_params *) linux_buffer;
|
/* get the necessary fields from the PE header */
|
||||||
|
err = pe_alignment_info(linux_buffer, &kernel_entry_address, &kernel_size_of_image, &kernel_alignment);
|
||||||
|
if (EFI_ERROR(err))
|
||||||
|
return err;
|
||||||
|
/* sanity check */
|
||||||
|
assert(kernel_size_of_image >= linux_length);
|
||||||
|
|
||||||
if (image_params->hdr.boot_flag != 0xAA55 ||
|
/* Linux kernel complains if it's not loaded at a properly aligned memory address. The correct alignment
|
||||||
image_params->hdr.header != SETUP_MAGIC ||
|
is provided by Linux as the SegmentAlignment in the PeOptionalHeader. Additionally the kernel needs to
|
||||||
image_params->hdr.version < 0x20b ||
|
be in a memory segment thats SizeOfImage (again from PeOptionalHeader) large, so that the Kernel has
|
||||||
!image_params->hdr.relocatable_kernel)
|
space for its BSS section. SizeOfImage is always larger than linux_length, which is only the size of
|
||||||
return EFI_LOAD_ERROR;
|
Code, (static) Data and Headers.
|
||||||
|
|
||||||
addr = UINT32_MAX; /* Below the 32bit boundary */
|
Interrestingly only ARM/Aarch64 and RISC-V kernel stubs check these assertions and can even boot (with warnings)
|
||||||
|
if they are not met. x86 and x86_64 kernel stubs don't do checks and fail if the BSS section is too small.
|
||||||
|
*/
|
||||||
|
/* allocate SizeOfImage + SectionAlignment because the new_buffer can move up to Alignment-1 bytes */
|
||||||
|
kernel.num = EFI_SIZE_TO_PAGES(ALIGN_TO(kernel_size_of_image, kernel_alignment) + kernel_alignment);
|
||||||
err = uefi_call_wrapper(
|
err = uefi_call_wrapper(
|
||||||
BS->AllocatePages, 4,
|
BS->AllocatePages, 4,
|
||||||
AllocateMaxAddress,
|
AllocateAnyPages, EfiLoaderData,
|
||||||
EfiLoaderData,
|
kernel.num, &kernel.addr);
|
||||||
EFI_SIZE_TO_PAGES(0x4000),
|
if (EFI_ERROR(err))
|
||||||
&addr);
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
new_buffer = PHYSICAL_ADDRESS_TO_POINTER(ALIGN_TO(kernel.addr, kernel_alignment));
|
||||||
|
CopyMem(new_buffer, linux_buffer, linux_length);
|
||||||
|
/* zero out rest of memory (probably not needed, but BSS section should be 0) */
|
||||||
|
SetMem((UINT8 *)new_buffer + linux_length, kernel_size_of_image - linux_length, 0);
|
||||||
|
|
||||||
|
/* get the entry point inside the relocated kernel */
|
||||||
|
kernel_entry = (EFI_IMAGE_ENTRY_POINT) ((const UINT8 *)new_buffer + kernel_entry_address);
|
||||||
|
|
||||||
|
/* register a LoadedImage Protocol in order to pass on the commandline */
|
||||||
|
err = loaded_image_register(cmdline, cmdline_len, new_buffer, linux_length, &loaded_image_handle);
|
||||||
if (EFI_ERROR(err))
|
if (EFI_ERROR(err))
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
boot_params = (struct boot_params *) PHYSICAL_ADDRESS_TO_POINTER(addr);
|
/* register a LINUX_INITRD_MEDIA DevicePath to serve the initrd */
|
||||||
ZeroMem(boot_params, 0x4000);
|
|
||||||
boot_params->hdr = image_params->hdr;
|
|
||||||
boot_params->hdr.type_of_loader = 0xff;
|
|
||||||
setup_sectors = image_params->hdr.setup_sects > 0 ? image_params->hdr.setup_sects : 4;
|
|
||||||
boot_params->hdr.code32_start = (UINT32) POINTER_TO_PHYSICAL_ADDRESS(linux_buffer) + (setup_sectors + 1) * 512;
|
|
||||||
|
|
||||||
if (cmdline) {
|
|
||||||
addr = 0xA0000;
|
|
||||||
|
|
||||||
err = uefi_call_wrapper(
|
|
||||||
BS->AllocatePages, 4,
|
|
||||||
AllocateMaxAddress,
|
|
||||||
EfiLoaderData,
|
|
||||||
EFI_SIZE_TO_PAGES(cmdline_len + 1),
|
|
||||||
&addr);
|
|
||||||
if (EFI_ERROR(err))
|
|
||||||
return err;
|
|
||||||
|
|
||||||
CopyMem(PHYSICAL_ADDRESS_TO_POINTER(addr), cmdline, cmdline_len);
|
|
||||||
((CHAR8 *) PHYSICAL_ADDRESS_TO_POINTER(addr))[cmdline_len] = 0;
|
|
||||||
boot_params->hdr.cmd_line_ptr = (UINT32) addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Providing the initrd via LINUX_INITRD_MEDIA_GUID is only supported by Linux 5.8+ (5.7+ on ARM64).
|
|
||||||
Until supported kernels become more established, we continue to set ramdisk in the handover struct.
|
|
||||||
This value is overridden by kernels that support LINUX_INITRD_MEDIA_GUID.
|
|
||||||
If you need to know which protocol was used by the kernel, pass "efi=debug" to the kernel,
|
|
||||||
this will print a line when InitrdMediaGuid was successfully used to load the initrd.
|
|
||||||
*/
|
|
||||||
boot_params->hdr.ramdisk_image = (UINT32) POINTER_TO_PHYSICAL_ADDRESS(initrd_buffer);
|
|
||||||
boot_params->hdr.ramdisk_size = (UINT32) initrd_length;
|
|
||||||
|
|
||||||
/* register LINUX_INITRD_MEDIA_GUID */
|
|
||||||
err = initrd_register(initrd_buffer, initrd_length, &initrd_handle);
|
err = initrd_register(initrd_buffer, initrd_length, &initrd_handle);
|
||||||
if (EFI_ERROR(err))
|
if (EFI_ERROR(err))
|
||||||
return err;
|
return err;
|
||||||
linux_efi_handover(image, boot_params);
|
|
||||||
(void) initrd_unregister(initrd_handle);
|
/* call the kernel */
|
||||||
initrd_handle = NULL;
|
return uefi_call_wrapper(kernel_entry, 2, loaded_image_handle, ST);
|
||||||
return EFI_LOAD_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,90 +2,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <efi.h>
|
#include <efi.h>
|
||||||
#include "macro-fundamental.h"
|
|
||||||
|
|
||||||
#define SETUP_MAGIC 0x53726448 /* "HdrS" */
|
|
||||||
|
|
||||||
struct setup_header {
|
|
||||||
UINT8 setup_sects;
|
|
||||||
UINT16 root_flags;
|
|
||||||
UINT32 syssize;
|
|
||||||
UINT16 ram_size;
|
|
||||||
UINT16 vid_mode;
|
|
||||||
UINT16 root_dev;
|
|
||||||
UINT16 boot_flag;
|
|
||||||
UINT16 jump;
|
|
||||||
UINT32 header;
|
|
||||||
UINT16 version;
|
|
||||||
UINT32 realmode_swtch;
|
|
||||||
UINT16 start_sys_seg;
|
|
||||||
UINT16 kernel_version;
|
|
||||||
UINT8 type_of_loader;
|
|
||||||
UINT8 loadflags;
|
|
||||||
UINT16 setup_move_size;
|
|
||||||
UINT32 code32_start;
|
|
||||||
UINT32 ramdisk_image;
|
|
||||||
UINT32 ramdisk_size;
|
|
||||||
UINT32 bootsect_kludge;
|
|
||||||
UINT16 heap_end_ptr;
|
|
||||||
UINT8 ext_loader_ver;
|
|
||||||
UINT8 ext_loader_type;
|
|
||||||
UINT32 cmd_line_ptr;
|
|
||||||
UINT32 initrd_addr_max;
|
|
||||||
UINT32 kernel_alignment;
|
|
||||||
UINT8 relocatable_kernel;
|
|
||||||
UINT8 min_alignment;
|
|
||||||
UINT16 xloadflags;
|
|
||||||
UINT32 cmdline_size;
|
|
||||||
UINT32 hardware_subarch;
|
|
||||||
UINT64 hardware_subarch_data;
|
|
||||||
UINT32 payload_offset;
|
|
||||||
UINT32 payload_length;
|
|
||||||
UINT64 setup_data;
|
|
||||||
UINT64 pref_address;
|
|
||||||
UINT32 init_size;
|
|
||||||
UINT32 handover_offset;
|
|
||||||
} _packed_;
|
|
||||||
|
|
||||||
/* adapted from linux' bootparam.h */
|
|
||||||
struct boot_params {
|
|
||||||
UINT8 screen_info[64]; // was: struct screen_info
|
|
||||||
UINT8 apm_bios_info[20]; // was: struct apm_bios_info
|
|
||||||
UINT8 _pad2[4];
|
|
||||||
UINT64 tboot_addr;
|
|
||||||
UINT8 ist_info[16]; // was: struct ist_info
|
|
||||||
UINT8 _pad3[16];
|
|
||||||
UINT8 hd0_info[16];
|
|
||||||
UINT8 hd1_info[16];
|
|
||||||
UINT8 sys_desc_table[16]; // was: struct sys_desc_table
|
|
||||||
UINT8 olpc_ofw_header[16]; // was: struct olpc_ofw_header
|
|
||||||
UINT32 ext_ramdisk_image;
|
|
||||||
UINT32 ext_ramdisk_size;
|
|
||||||
UINT32 ext_cmd_line_ptr;
|
|
||||||
UINT8 _pad4[116];
|
|
||||||
UINT8 edid_info[128]; // was: struct edid_info
|
|
||||||
UINT8 efi_info[32]; // was: struct efi_info
|
|
||||||
UINT32 alt_mem_k;
|
|
||||||
UINT32 scratch;
|
|
||||||
UINT8 e820_entries;
|
|
||||||
UINT8 eddbuf_entries;
|
|
||||||
UINT8 edd_mbr_sig_buf_entries;
|
|
||||||
UINT8 kbd_status;
|
|
||||||
UINT8 secure_boot;
|
|
||||||
UINT8 _pad5[2];
|
|
||||||
UINT8 sentinel;
|
|
||||||
UINT8 _pad6[1];
|
|
||||||
struct setup_header hdr;
|
|
||||||
UINT8 _pad7[0x290-0x1f1-sizeof(struct setup_header)];
|
|
||||||
UINT32 edd_mbr_sig_buffer[16]; // was: edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]
|
|
||||||
UINT8 e820_table[20*128]; // was: struct boot_e820_entry e820_table[E820_MAX_ENTRIES_ZEROPAGE]
|
|
||||||
UINT8 _pad8[48];
|
|
||||||
UINT8 eddbuf[6*82]; // was: struct edd_info eddbuf[EDDMAXNR]
|
|
||||||
UINT8 _pad9[276];
|
|
||||||
} _packed_;
|
|
||||||
|
|
||||||
EFI_STATUS linux_exec(
|
EFI_STATUS linux_exec(
|
||||||
EFI_HANDLE image,
|
EFI_HANDLE image,
|
||||||
const CHAR8 *cmdline, UINTN cmdline_len,
|
const CHAR8 *cmdline, UINTN cmdline_len,
|
||||||
const VOID *linux_buffer,
|
const VOID *linux_buffer, UINTN linux_length,
|
||||||
const VOID *initrd_buffer, UINTN initrd_length);
|
const VOID *initrd_buffer, UINTN initrd_length);
|
||||||
|
|||||||
200
src/boot/efi/linux_x86.c
Normal file
200
src/boot/efi/linux_x86.c
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* x86 specific code to for EFI handover boot protocol
|
||||||
|
* Linux kernels version 5.8 and newer support providing the initrd by
|
||||||
|
* LINUX_INITRD_MEDIA_GUID DevicePath. In order to support older kernels too,
|
||||||
|
* this x86 specific linux_exec function passes the initrd by setting the
|
||||||
|
* corresponding fields in the setup_header struct.
|
||||||
|
*
|
||||||
|
* see https://www.kernel.org/doc/html/latest/x86/boot.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <efi.h>
|
||||||
|
#include <efilib.h>
|
||||||
|
|
||||||
|
#include "initrd.h"
|
||||||
|
#include "linux.h"
|
||||||
|
#include "macro-fundamental.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#define SETUP_MAGIC 0x53726448 /* "HdrS" */
|
||||||
|
|
||||||
|
struct setup_header {
|
||||||
|
UINT8 setup_sects;
|
||||||
|
UINT16 root_flags;
|
||||||
|
UINT32 syssize;
|
||||||
|
UINT16 ram_size;
|
||||||
|
UINT16 vid_mode;
|
||||||
|
UINT16 root_dev;
|
||||||
|
UINT16 boot_flag;
|
||||||
|
UINT16 jump;
|
||||||
|
UINT32 header;
|
||||||
|
UINT16 version;
|
||||||
|
UINT32 realmode_swtch;
|
||||||
|
UINT16 start_sys_seg;
|
||||||
|
UINT16 kernel_version;
|
||||||
|
UINT8 type_of_loader;
|
||||||
|
UINT8 loadflags;
|
||||||
|
UINT16 setup_move_size;
|
||||||
|
UINT32 code32_start;
|
||||||
|
UINT32 ramdisk_image;
|
||||||
|
UINT32 ramdisk_size;
|
||||||
|
UINT32 bootsect_kludge;
|
||||||
|
UINT16 heap_end_ptr;
|
||||||
|
UINT8 ext_loader_ver;
|
||||||
|
UINT8 ext_loader_type;
|
||||||
|
UINT32 cmd_line_ptr;
|
||||||
|
UINT32 initrd_addr_max;
|
||||||
|
UINT32 kernel_alignment;
|
||||||
|
UINT8 relocatable_kernel;
|
||||||
|
UINT8 min_alignment;
|
||||||
|
UINT16 xloadflags;
|
||||||
|
UINT32 cmdline_size;
|
||||||
|
UINT32 hardware_subarch;
|
||||||
|
UINT64 hardware_subarch_data;
|
||||||
|
UINT32 payload_offset;
|
||||||
|
UINT32 payload_length;
|
||||||
|
UINT64 setup_data;
|
||||||
|
UINT64 pref_address;
|
||||||
|
UINT32 init_size;
|
||||||
|
UINT32 handover_offset;
|
||||||
|
} _packed_;
|
||||||
|
|
||||||
|
/* adapted from linux' bootparam.h */
|
||||||
|
struct boot_params {
|
||||||
|
UINT8 screen_info[64]; // was: struct screen_info
|
||||||
|
UINT8 apm_bios_info[20]; // was: struct apm_bios_info
|
||||||
|
UINT8 _pad2[4];
|
||||||
|
UINT64 tboot_addr;
|
||||||
|
UINT8 ist_info[16]; // was: struct ist_info
|
||||||
|
UINT8 _pad3[16];
|
||||||
|
UINT8 hd0_info[16];
|
||||||
|
UINT8 hd1_info[16];
|
||||||
|
UINT8 sys_desc_table[16]; // was: struct sys_desc_table
|
||||||
|
UINT8 olpc_ofw_header[16]; // was: struct olpc_ofw_header
|
||||||
|
UINT32 ext_ramdisk_image;
|
||||||
|
UINT32 ext_ramdisk_size;
|
||||||
|
UINT32 ext_cmd_line_ptr;
|
||||||
|
UINT8 _pad4[116];
|
||||||
|
UINT8 edid_info[128]; // was: struct edid_info
|
||||||
|
UINT8 efi_info[32]; // was: struct efi_info
|
||||||
|
UINT32 alt_mem_k;
|
||||||
|
UINT32 scratch;
|
||||||
|
UINT8 e820_entries;
|
||||||
|
UINT8 eddbuf_entries;
|
||||||
|
UINT8 edd_mbr_sig_buf_entries;
|
||||||
|
UINT8 kbd_status;
|
||||||
|
UINT8 secure_boot;
|
||||||
|
UINT8 _pad5[2];
|
||||||
|
UINT8 sentinel;
|
||||||
|
UINT8 _pad6[1];
|
||||||
|
struct setup_header hdr;
|
||||||
|
UINT8 _pad7[0x290-0x1f1-sizeof(struct setup_header)];
|
||||||
|
UINT32 edd_mbr_sig_buffer[16]; // was: edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]
|
||||||
|
UINT8 e820_table[20*128]; // was: struct boot_e820_entry e820_table[E820_MAX_ENTRIES_ZEROPAGE]
|
||||||
|
UINT8 _pad8[48];
|
||||||
|
UINT8 eddbuf[6*82]; // was: struct edd_info eddbuf[EDDMAXNR]
|
||||||
|
UINT8 _pad9[276];
|
||||||
|
} _packed_;
|
||||||
|
|
||||||
|
#ifdef __i386__
|
||||||
|
#define __regparm0__ __attribute__((regparm(0)))
|
||||||
|
#else
|
||||||
|
#define __regparm0__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef VOID(*handover_f)(VOID *image, EFI_SYSTEM_TABLE *table, struct boot_params *params) __regparm0__;
|
||||||
|
|
||||||
|
static VOID linux_efi_handover(EFI_HANDLE image, struct boot_params *params) {
|
||||||
|
handover_f handover;
|
||||||
|
UINTN start = (UINTN)params->hdr.code32_start;
|
||||||
|
|
||||||
|
assert(params);
|
||||||
|
|
||||||
|
#ifdef __x86_64__
|
||||||
|
asm volatile ("cli");
|
||||||
|
start += 512;
|
||||||
|
#endif
|
||||||
|
handover = (handover_f)(start + params->hdr.handover_offset);
|
||||||
|
handover(image, ST, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS linux_exec(
|
||||||
|
EFI_HANDLE image,
|
||||||
|
const CHAR8 *cmdline, UINTN cmdline_len,
|
||||||
|
const VOID *linux_buffer, UINTN linux_length,
|
||||||
|
const VOID *initrd_buffer, UINTN initrd_length) {
|
||||||
|
|
||||||
|
const struct boot_params *image_params;
|
||||||
|
struct boot_params *boot_params;
|
||||||
|
EFI_HANDLE initrd_handle = NULL;
|
||||||
|
EFI_PHYSICAL_ADDRESS addr;
|
||||||
|
UINT8 setup_sectors;
|
||||||
|
EFI_STATUS err;
|
||||||
|
|
||||||
|
assert(image);
|
||||||
|
assert(cmdline || cmdline_len == 0);
|
||||||
|
assert(linux_buffer);
|
||||||
|
assert(initrd_buffer || initrd_length == 0);
|
||||||
|
|
||||||
|
image_params = (const struct boot_params *) linux_buffer;
|
||||||
|
|
||||||
|
if (image_params->hdr.boot_flag != 0xAA55 ||
|
||||||
|
image_params->hdr.header != SETUP_MAGIC ||
|
||||||
|
image_params->hdr.version < 0x20b ||
|
||||||
|
!image_params->hdr.relocatable_kernel)
|
||||||
|
return EFI_LOAD_ERROR;
|
||||||
|
|
||||||
|
addr = UINT32_MAX; /* Below the 32bit boundary */
|
||||||
|
err = uefi_call_wrapper(
|
||||||
|
BS->AllocatePages, 4,
|
||||||
|
AllocateMaxAddress,
|
||||||
|
EfiLoaderData,
|
||||||
|
EFI_SIZE_TO_PAGES(0x4000),
|
||||||
|
&addr);
|
||||||
|
if (EFI_ERROR(err))
|
||||||
|
return err;
|
||||||
|
|
||||||
|
boot_params = (struct boot_params *) PHYSICAL_ADDRESS_TO_POINTER(addr);
|
||||||
|
ZeroMem(boot_params, 0x4000);
|
||||||
|
boot_params->hdr = image_params->hdr;
|
||||||
|
boot_params->hdr.type_of_loader = 0xff;
|
||||||
|
setup_sectors = image_params->hdr.setup_sects > 0 ? image_params->hdr.setup_sects : 4;
|
||||||
|
boot_params->hdr.code32_start = (UINT32) POINTER_TO_PHYSICAL_ADDRESS(linux_buffer) + (setup_sectors + 1) * 512;
|
||||||
|
|
||||||
|
if (cmdline) {
|
||||||
|
addr = 0xA0000;
|
||||||
|
|
||||||
|
err = uefi_call_wrapper(
|
||||||
|
BS->AllocatePages, 4,
|
||||||
|
AllocateMaxAddress,
|
||||||
|
EfiLoaderData,
|
||||||
|
EFI_SIZE_TO_PAGES(cmdline_len + 1),
|
||||||
|
&addr);
|
||||||
|
if (EFI_ERROR(err))
|
||||||
|
return err;
|
||||||
|
|
||||||
|
CopyMem(PHYSICAL_ADDRESS_TO_POINTER(addr), cmdline, cmdline_len);
|
||||||
|
((CHAR8 *) PHYSICAL_ADDRESS_TO_POINTER(addr))[cmdline_len] = 0;
|
||||||
|
boot_params->hdr.cmd_line_ptr = (UINT32) addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Providing the initrd via LINUX_INITRD_MEDIA_GUID is only supported by Linux 5.8+ (5.7+ on ARM64).
|
||||||
|
Until supported kernels become more established, we continue to set ramdisk in the handover struct.
|
||||||
|
This value is overridden by kernels that support LINUX_INITRD_MEDIA_GUID.
|
||||||
|
If you need to know which protocol was used by the kernel, pass "efi=debug" to the kernel,
|
||||||
|
this will print a line when InitrdMediaGuid was successfully used to load the initrd.
|
||||||
|
*/
|
||||||
|
boot_params->hdr.ramdisk_image = (UINT32) POINTER_TO_PHYSICAL_ADDRESS(initrd_buffer);
|
||||||
|
boot_params->hdr.ramdisk_size = (UINT32) initrd_length;
|
||||||
|
|
||||||
|
/* register LINUX_INITRD_MEDIA_GUID */
|
||||||
|
err = initrd_register(initrd_buffer, initrd_length, &initrd_handle);
|
||||||
|
if (EFI_ERROR(err))
|
||||||
|
return err;
|
||||||
|
linux_efi_handover(image, boot_params);
|
||||||
|
(void) initrd_unregister(initrd_handle);
|
||||||
|
initrd_handle = NULL;
|
||||||
|
return EFI_LOAD_ERROR;
|
||||||
|
}
|
||||||
@ -39,7 +39,6 @@ systemd_boot_sources = '''
|
|||||||
'''.split()
|
'''.split()
|
||||||
|
|
||||||
stub_sources = '''
|
stub_sources = '''
|
||||||
linux.c
|
|
||||||
initrd.c
|
initrd.c
|
||||||
splash.c
|
splash.c
|
||||||
stub.c
|
stub.c
|
||||||
@ -209,6 +208,11 @@ if have_gnu_efi
|
|||||||
'-include', efi_config_h,
|
'-include', efi_config_h,
|
||||||
'-include', version_h,
|
'-include', version_h,
|
||||||
]
|
]
|
||||||
|
if ['ia32', 'x86_64'].contains(efi_arch)
|
||||||
|
stub_sources += 'linux_x86.c'
|
||||||
|
else
|
||||||
|
stub_sources += 'linux.c'
|
||||||
|
endif
|
||||||
if efi_arch == 'x86_64'
|
if efi_arch == 'x86_64'
|
||||||
compile_args += ['-mno-red-zone',
|
compile_args += ['-mno-red-zone',
|
||||||
'-mno-sse',
|
'-mno-sse',
|
||||||
|
|||||||
@ -56,10 +56,46 @@ struct CoffFileHeader {
|
|||||||
UINT16 Characteristics;
|
UINT16 Characteristics;
|
||||||
} _packed_;
|
} _packed_;
|
||||||
|
|
||||||
|
#define OPTHDR32_MAGIC 0x10B /* PE32 OptionalHeader */
|
||||||
|
#define OPTHDR64_MAGIC 0x20B /* PE32+ OptionalHeader */
|
||||||
|
|
||||||
|
struct PeOptionalHeader {
|
||||||
|
UINT16 Magic;
|
||||||
|
UINT8 LinkerMajor;
|
||||||
|
UINT8 LinkerMinor;
|
||||||
|
UINT32 SizeOfCode;
|
||||||
|
UINT32 SizeOfInitializedData;
|
||||||
|
UINT32 SizeOfUninitializeData;
|
||||||
|
UINT32 AddressOfEntryPoint;
|
||||||
|
UINT32 BaseOfCode;
|
||||||
|
union {
|
||||||
|
struct { /* PE32 */
|
||||||
|
UINT32 BaseOfData;
|
||||||
|
UINT32 ImageBase32;
|
||||||
|
};
|
||||||
|
UINT64 ImageBase64; /* PE32+ */
|
||||||
|
};
|
||||||
|
UINT32 SectionAlignment;
|
||||||
|
UINT32 FileAlignment;
|
||||||
|
UINT16 MajorOperatingSystemVersion;
|
||||||
|
UINT16 MinorOperatingSystemVersion;
|
||||||
|
UINT16 MajorImageVersion;
|
||||||
|
UINT16 MinorImageVersion;
|
||||||
|
UINT16 MajorSubsystemVersion;
|
||||||
|
UINT16 MinorSubsystemVersion;
|
||||||
|
UINT32 Win32VersionValue;
|
||||||
|
UINT32 SizeOfImage;
|
||||||
|
UINT32 SizeOfHeaders;
|
||||||
|
UINT32 CheckSum;
|
||||||
|
UINT16 Subsystem;
|
||||||
|
UINT16 DllCharacteristics;
|
||||||
|
/* fields with different sizes for 32/64 omitted */
|
||||||
|
} _packed_;
|
||||||
|
|
||||||
struct PeFileHeader {
|
struct PeFileHeader {
|
||||||
UINT8 Magic[4];
|
UINT8 Magic[4];
|
||||||
struct CoffFileHeader FileHeader;
|
struct CoffFileHeader FileHeader;
|
||||||
/* OptionalHeader omitted */
|
struct PeOptionalHeader OptionalHeader;
|
||||||
} _packed_;
|
} _packed_;
|
||||||
|
|
||||||
struct PeSectionHeader {
|
struct PeSectionHeader {
|
||||||
@ -91,7 +127,7 @@ static inline BOOLEAN verify_pe(const struct PeFileHeader *pe) {
|
|||||||
static inline UINTN section_table_offset(const struct DosFileHeader *dos, const struct PeFileHeader *pe) {
|
static inline UINTN section_table_offset(const struct DosFileHeader *dos, const struct PeFileHeader *pe) {
|
||||||
assert(dos);
|
assert(dos);
|
||||||
assert(pe);
|
assert(pe);
|
||||||
return dos->ExeHeader + sizeof(struct PeFileHeader) + pe->FileHeader.SizeOfOptionalHeader;
|
return dos->ExeHeader + OFFSETOF(struct PeFileHeader, OptionalHeader) + pe->FileHeader.SizeOfOptionalHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID locate_sections(
|
static VOID locate_sections(
|
||||||
@ -122,6 +158,41 @@ static VOID locate_sections(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EFI_STATUS pe_alignment_info(
|
||||||
|
const VOID *base,
|
||||||
|
UINT32 *ret_entry_point_address,
|
||||||
|
UINT32 *ret_size_of_image,
|
||||||
|
UINT32 *ret_section_alignment) {
|
||||||
|
|
||||||
|
const struct DosFileHeader *dos;
|
||||||
|
const struct PeFileHeader *pe;
|
||||||
|
|
||||||
|
assert(base);
|
||||||
|
assert(ret_entry_point_address);
|
||||||
|
assert(ret_size_of_image);
|
||||||
|
assert(ret_section_alignment);
|
||||||
|
|
||||||
|
dos = (const struct DosFileHeader *) base;
|
||||||
|
if (!verify_dos(dos))
|
||||||
|
return EFI_LOAD_ERROR;
|
||||||
|
|
||||||
|
pe = (const struct PeFileHeader*) ((const UINT8 *)base + dos->ExeHeader);
|
||||||
|
if (!verify_pe(pe))
|
||||||
|
return EFI_LOAD_ERROR;
|
||||||
|
|
||||||
|
*ret_entry_point_address = pe->OptionalHeader.AddressOfEntryPoint;
|
||||||
|
|
||||||
|
if (pe->OptionalHeader.Magic == OPTHDR32_MAGIC) {
|
||||||
|
*ret_size_of_image = pe->OptionalHeader.SizeOfImage;
|
||||||
|
*ret_section_alignment = pe->OptionalHeader.SectionAlignment;
|
||||||
|
} else if (pe->OptionalHeader.Magic == OPTHDR64_MAGIC) {
|
||||||
|
*ret_size_of_image = pe->OptionalHeader.SizeOfImage;
|
||||||
|
*ret_section_alignment = pe->OptionalHeader.SectionAlignment;
|
||||||
|
} else
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
EFI_STATUS pe_memory_locate_sections(
|
EFI_STATUS pe_memory_locate_sections(
|
||||||
const CHAR8 *base,
|
const CHAR8 *base,
|
||||||
const CHAR8 **sections,
|
const CHAR8 **sections,
|
||||||
|
|||||||
@ -15,3 +15,9 @@ EFI_STATUS pe_file_locate_sections(
|
|||||||
const CHAR8 **sections,
|
const CHAR8 **sections,
|
||||||
UINTN *offsets,
|
UINTN *offsets,
|
||||||
UINTN *sizes);
|
UINTN *sizes);
|
||||||
|
|
||||||
|
EFI_STATUS pe_alignment_info(
|
||||||
|
const VOID *base,
|
||||||
|
UINT32 *ret_entry_point_address,
|
||||||
|
UINT32 *ret_size_of_image,
|
||||||
|
UINT32 *ret_section_alignment);
|
||||||
|
|||||||
@ -152,7 +152,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
|||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
UINTN cmdline_len = 0, initrd_size, credential_initrd_size = 0, sysext_initrd_size = 0;
|
UINTN cmdline_len = 0, linux_size, initrd_size, credential_initrd_size = 0, sysext_initrd_size = 0;
|
||||||
_cleanup_freepool_ VOID *credential_initrd = NULL, *sysext_initrd = NULL;
|
_cleanup_freepool_ VOID *credential_initrd = NULL, *sysext_initrd = NULL;
|
||||||
EFI_PHYSICAL_ADDRESS linux_base, initrd_base;
|
EFI_PHYSICAL_ADDRESS linux_base, initrd_base;
|
||||||
EFI_LOADED_IMAGE *loaded_image;
|
EFI_LOADED_IMAGE *loaded_image;
|
||||||
@ -222,6 +222,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
|||||||
&sysext_initrd,
|
&sysext_initrd,
|
||||||
&sysext_initrd_size);
|
&sysext_initrd_size);
|
||||||
|
|
||||||
|
linux_size = szs[SECTION_LINUX];
|
||||||
linux_base = POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[SECTION_LINUX];
|
linux_base = POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[SECTION_LINUX];
|
||||||
|
|
||||||
initrd_size = szs[SECTION_INITRD];
|
initrd_size = szs[SECTION_INITRD];
|
||||||
@ -250,7 +251,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = linux_exec(image, cmdline, cmdline_len,
|
err = linux_exec(image, cmdline, cmdline_len,
|
||||||
PHYSICAL_ADDRESS_TO_POINTER(linux_base),
|
PHYSICAL_ADDRESS_TO_POINTER(linux_base), linux_size,
|
||||||
PHYSICAL_ADDRESS_TO_POINTER(initrd_base), initrd_size);
|
PHYSICAL_ADDRESS_TO_POINTER(initrd_base), initrd_size);
|
||||||
graphics_mode(FALSE);
|
graphics_mode(FALSE);
|
||||||
return log_error_status_stall(err, L"Execution of embedded linux image failed: %r", err);
|
return log_error_status_stall(err, L"Execution of embedded linux image failed: %r", err);
|
||||||
|
|||||||
@ -61,6 +61,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define memcpy(a, b, c) CopyMem((a), (b), (c))
|
#define memcpy(a, b, c) CopyMem((a), (b), (c))
|
||||||
|
#define free(a) FreePool(a)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(static_assert)
|
#if defined(static_assert)
|
||||||
@ -266,3 +267,9 @@
|
|||||||
* @x: a string literal.
|
* @x: a string literal.
|
||||||
*/
|
*/
|
||||||
#define STRLEN(x) (sizeof(""x"") - sizeof(typeof(x[0])))
|
#define STRLEN(x) (sizeof(""x"") - sizeof(typeof(x[0])))
|
||||||
|
|
||||||
|
#define mfree(memory) \
|
||||||
|
({ \
|
||||||
|
free(memory); \
|
||||||
|
(typeof(memory)) NULL; \
|
||||||
|
})
|
||||||
|
|||||||
@ -178,7 +178,7 @@ int device_monitor_new_full(sd_device_monitor **ret, MonitorNetlinkGroup group,
|
|||||||
|
|
||||||
netns = ioctl(m->sock, SIOCGSKNS);
|
netns = ioctl(m->sock, SIOCGSKNS);
|
||||||
if (netns < 0)
|
if (netns < 0)
|
||||||
log_debug_errno(errno, "sd-device-monitor: Unable to get network namespace of udev netlink socket, unable to determine if we are in host netns: %m");
|
log_debug_errno(errno, "sd-device-monitor: Unable to get network namespace of udev netlink socket, unable to determine if we are in host netns, ignoring: %m");
|
||||||
else {
|
else {
|
||||||
struct stat a, b;
|
struct stat a, b;
|
||||||
|
|
||||||
@ -191,9 +191,9 @@ int device_monitor_new_full(sd_device_monitor **ret, MonitorNetlinkGroup group,
|
|||||||
if (ERRNO_IS_PRIVILEGE(errno))
|
if (ERRNO_IS_PRIVILEGE(errno))
|
||||||
/* If we can't access PID1's netns info due to permissions, it's fine, this is a
|
/* If we can't access PID1's netns info due to permissions, it's fine, this is a
|
||||||
* safety check only after all. */
|
* safety check only after all. */
|
||||||
log_debug_errno(errno, "sd-device-monitor: No permission to stat PID1's netns, unable to determine if we are in host netns: %m");
|
log_debug_errno(errno, "sd-device-monitor: No permission to stat PID1's netns, unable to determine if we are in host netns, ignoring: %m");
|
||||||
else
|
else
|
||||||
log_debug_errno(errno, "sd-device-monitor: Failed to stat PID1's netns: %m");
|
log_debug_errno(errno, "sd-device-monitor: Failed to stat PID1's netns, ignoring: %m");
|
||||||
|
|
||||||
} else if (a.st_dev != b.st_dev || a.st_ino != b.st_ino)
|
} else if (a.st_dev != b.st_dev || a.st_ino != b.st_ino)
|
||||||
log_debug("sd-device-monitor: Netlink socket we listen on is not from host netns, we won't see device events.");
|
log_debug("sd-device-monitor: Netlink socket we listen on is not from host netns, we won't see device events.");
|
||||||
|
|||||||
@ -28,7 +28,7 @@ teardown() {
|
|||||||
run_test() {
|
run_test() {
|
||||||
since="$(date +%T)"
|
since="$(date +%T)"
|
||||||
|
|
||||||
udevadm trigger -w --action add /dev/null
|
SYSTEMD_LOG_LEVEL=debug udevadm trigger --verbose --settle --action add /dev/null
|
||||||
|
|
||||||
for _ in {1..20}; do
|
for _ in {1..20}; do
|
||||||
if coredumpctl --since "$since" --no-legend --no-pager | grep /bin/udevadm ; then
|
if coredumpctl --since "$since" --no-legend --no-pager | grep /bin/udevadm ; then
|
||||||
|
|||||||
@ -15,7 +15,7 @@ ACTION=="change", SUBSYSTEM=="mem", KERNEL=="null", TAG+="changed"
|
|||||||
EOF
|
EOF
|
||||||
|
|
||||||
udevadm control --reload
|
udevadm control --reload
|
||||||
udevadm trigger --settle --action add /dev/null
|
SYSTEMD_LOG_LEVEL=debug udevadm trigger --verbose --settle --action add /dev/null
|
||||||
|
|
||||||
test -f /run/udev/tags/added/c1:3
|
test -f /run/udev/tags/added/c1:3
|
||||||
test ! -f /run/udev/tags/changed/c1:3
|
test ! -f /run/udev/tags/changed/c1:3
|
||||||
@ -24,7 +24,7 @@ udevadm info /dev/null | grep -q 'E: CURRENT_TAGS=.*:added:.*'
|
|||||||
udevadm info /dev/null | grep -q 'E: TAGS=.*:changed:.*' && { echo 'unexpected TAGS='; exit 1; }
|
udevadm info /dev/null | grep -q 'E: TAGS=.*:changed:.*' && { echo 'unexpected TAGS='; exit 1; }
|
||||||
udevadm info /dev/null | grep -q 'E: CURRENT_TAGS=.*:changed:.*' && { echo 'unexpected CURRENT_TAGS='; exit 1; }
|
udevadm info /dev/null | grep -q 'E: CURRENT_TAGS=.*:changed:.*' && { echo 'unexpected CURRENT_TAGS='; exit 1; }
|
||||||
|
|
||||||
udevadm trigger --settle --action change /dev/null
|
SYSTEMD_LOG_LEVEL=debug udevadm trigger --verbose --settle --action change /dev/null
|
||||||
|
|
||||||
test -f /run/udev/tags/added/c1:3
|
test -f /run/udev/tags/added/c1:3
|
||||||
test -f /run/udev/tags/changed/c1:3
|
test -f /run/udev/tags/changed/c1:3
|
||||||
@ -33,7 +33,7 @@ udevadm info /dev/null | grep -q 'E: CURRENT_TAGS=.*:added:.*' && { echo 'unexpe
|
|||||||
udevadm info /dev/null | grep -q 'E: TAGS=.*:changed:.*'
|
udevadm info /dev/null | grep -q 'E: TAGS=.*:changed:.*'
|
||||||
udevadm info /dev/null | grep -q 'E: CURRENT_TAGS=.*:changed:.*'
|
udevadm info /dev/null | grep -q 'E: CURRENT_TAGS=.*:changed:.*'
|
||||||
|
|
||||||
udevadm trigger --settle --action add /dev/null
|
SYSTEMD_LOG_LEVEL=debug udevadm trigger --verbose --settle --action add /dev/null
|
||||||
|
|
||||||
test -f /run/udev/tags/added/c1:3
|
test -f /run/udev/tags/added/c1:3
|
||||||
test -f /run/udev/tags/changed/c1:3
|
test -f /run/udev/tags/changed/c1:3
|
||||||
|
|||||||
@ -10,7 +10,7 @@ ACTION=="add", SUBSYSTEM=="mem", KERNEL=="null", IMPORT{program}="/bin/echo -e H
|
|||||||
EOF
|
EOF
|
||||||
|
|
||||||
udevadm control --reload
|
udevadm control --reload
|
||||||
udevadm trigger --settle --action add /dev/null
|
SYSTEMD_LOG_LEVEL=debug udevadm trigger --verbose --settle --action add /dev/null
|
||||||
|
|
||||||
test -f /run/udev/data/c1:3
|
test -f /run/udev/data/c1:3
|
||||||
udevadm info /dev/null | grep -q 'E: HOGE=aa\\x20\\x20\\x20bb'
|
udevadm info /dev/null | grep -q 'E: HOGE=aa\\x20\\x20\\x20bb'
|
||||||
|
|||||||
@ -38,7 +38,7 @@ ProtectSystem=strict
|
|||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartKillSignal=SIGUSR2
|
RestartKillSignal=SIGUSR2
|
||||||
RestartSec=0
|
RestartSec=0
|
||||||
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6 AF_PACKET AF_ALG
|
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6 AF_PACKET
|
||||||
RestrictNamespaces=yes
|
RestrictNamespaces=yes
|
||||||
RestrictRealtime=yes
|
RestrictRealtime=yes
|
||||||
RestrictSUIDSGID=yes
|
RestrictSUIDSGID=yes
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user