mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 14:37:46 +00:00
Kernel/SysFS: Stop cluttering the codebase with pieces of SysFS parts
Instead, start to put everything in one place to resemble the directory structure of the SysFS when actually using it.
This commit is contained in:
parent
cba4750921
commit
290eb53cb5
22 changed files with 26 additions and 26 deletions
187
Kernel/FileSystem/SysFS/Subsystems/Firmware/BIOS.cpp
Normal file
187
Kernel/FileSystem/SysFS/Subsystems/Firmware/BIOS.cpp
Normal file
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/StringView.h>
|
||||
#include <Kernel/FileSystem/OpenFileDescription.h>
|
||||
#include <Kernel/FileSystem/SysFS/Subsystems/Firmware/BIOS.h>
|
||||
#include <Kernel/KBufferBuilder.h>
|
||||
#include <Kernel/Memory/MemoryManager.h>
|
||||
#include <Kernel/Memory/TypedMapping.h>
|
||||
#include <Kernel/Sections.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
#define SMBIOS_BASE_SEARCH_ADDR 0xf0000
|
||||
#define SMBIOS_END_SEARCH_ADDR 0xfffff
|
||||
#define SMBIOS_SEARCH_AREA_SIZE (SMBIOS_END_SEARCH_ADDR - SMBIOS_BASE_SEARCH_ADDR)
|
||||
|
||||
UNMAP_AFTER_INIT NonnullRefPtr<DMIEntryPointExposedBlob> DMIEntryPointExposedBlob::must_create(PhysicalAddress dmi_entry_point, size_t blob_size)
|
||||
{
|
||||
return adopt_ref(*new (nothrow) DMIEntryPointExposedBlob(dmi_entry_point, blob_size));
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT BIOSSysFSComponent::BIOSSysFSComponent()
|
||||
{
|
||||
}
|
||||
|
||||
ErrorOr<size_t> BIOSSysFSComponent::read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, OpenFileDescription*) const
|
||||
{
|
||||
auto blob = TRY(try_to_generate_buffer());
|
||||
|
||||
if ((size_t)offset >= blob->size())
|
||||
return 0;
|
||||
|
||||
ssize_t nread = min(static_cast<off_t>(blob->size() - offset), static_cast<off_t>(count));
|
||||
TRY(buffer.write(blob->data() + offset, nread));
|
||||
return nread;
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT DMIEntryPointExposedBlob::DMIEntryPointExposedBlob(PhysicalAddress dmi_entry_point, size_t blob_size)
|
||||
: BIOSSysFSComponent()
|
||||
, m_dmi_entry_point(dmi_entry_point)
|
||||
, m_dmi_entry_point_length(blob_size)
|
||||
{
|
||||
}
|
||||
|
||||
ErrorOr<NonnullOwnPtr<KBuffer>> DMIEntryPointExposedBlob::try_to_generate_buffer() const
|
||||
{
|
||||
auto dmi_blob = TRY(Memory::map_typed<u8>((m_dmi_entry_point), m_dmi_entry_point_length));
|
||||
return KBuffer::try_create_with_bytes(Span<u8> { dmi_blob.ptr(), m_dmi_entry_point_length });
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT NonnullRefPtr<SMBIOSExposedTable> SMBIOSExposedTable::must_create(PhysicalAddress smbios_structure_table, size_t smbios_structure_table_length)
|
||||
{
|
||||
return adopt_ref(*new (nothrow) SMBIOSExposedTable(smbios_structure_table, smbios_structure_table_length));
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT SMBIOSExposedTable::SMBIOSExposedTable(PhysicalAddress smbios_structure_table, size_t smbios_structure_table_length)
|
||||
: BIOSSysFSComponent()
|
||||
, m_smbios_structure_table(smbios_structure_table)
|
||||
, m_smbios_structure_table_length(smbios_structure_table_length)
|
||||
{
|
||||
}
|
||||
|
||||
ErrorOr<NonnullOwnPtr<KBuffer>> SMBIOSExposedTable::try_to_generate_buffer() const
|
||||
{
|
||||
auto dmi_blob = TRY(Memory::map_typed<u8>((m_smbios_structure_table), m_smbios_structure_table_length));
|
||||
return KBuffer::try_create_with_bytes(Span<u8> { dmi_blob.ptr(), m_smbios_structure_table_length });
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT void BIOSSysFSDirectory::set_dmi_64_bit_entry_initialization_values()
|
||||
{
|
||||
dbgln("BIOSSysFSDirectory: SMBIOS 64bit Entry point @ {}", m_dmi_entry_point);
|
||||
auto smbios_entry = Memory::map_typed<SMBIOS::EntryPoint64bit>(m_dmi_entry_point, SMBIOS_SEARCH_AREA_SIZE).release_value_but_fixme_should_propagate_errors();
|
||||
m_smbios_structure_table = PhysicalAddress(smbios_entry.ptr()->table_ptr);
|
||||
m_dmi_entry_point_length = smbios_entry.ptr()->length;
|
||||
m_smbios_structure_table_length = smbios_entry.ptr()->table_maximum_size;
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT void BIOSSysFSDirectory::set_dmi_32_bit_entry_initialization_values()
|
||||
{
|
||||
dbgln("BIOSSysFSDirectory: SMBIOS 32bit Entry point @ {}", m_dmi_entry_point);
|
||||
auto smbios_entry = Memory::map_typed<SMBIOS::EntryPoint32bit>(m_dmi_entry_point, SMBIOS_SEARCH_AREA_SIZE).release_value_but_fixme_should_propagate_errors();
|
||||
m_smbios_structure_table = PhysicalAddress(smbios_entry.ptr()->legacy_structure.smbios_table_ptr);
|
||||
m_dmi_entry_point_length = smbios_entry.ptr()->length;
|
||||
m_smbios_structure_table_length = smbios_entry.ptr()->legacy_structure.smbios_table_length;
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT NonnullRefPtr<BIOSSysFSDirectory> BIOSSysFSDirectory::must_create(FirmwareSysFSDirectory& firmware_directory)
|
||||
{
|
||||
auto bios_directory = MUST(adopt_nonnull_ref_or_enomem(new (nothrow) BIOSSysFSDirectory(firmware_directory)));
|
||||
bios_directory->create_components();
|
||||
return bios_directory;
|
||||
}
|
||||
|
||||
void BIOSSysFSDirectory::create_components()
|
||||
{
|
||||
if (m_dmi_entry_point.is_null() || m_smbios_structure_table.is_null())
|
||||
return;
|
||||
if (m_dmi_entry_point_length == 0) {
|
||||
dbgln("BIOSSysFSDirectory: invalid dmi entry length");
|
||||
return;
|
||||
}
|
||||
if (m_smbios_structure_table_length == 0) {
|
||||
dbgln("BIOSSysFSDirectory: invalid smbios structure table length");
|
||||
return;
|
||||
}
|
||||
m_components.append(DMIEntryPointExposedBlob::must_create(m_dmi_entry_point, m_dmi_entry_point_length));
|
||||
m_components.append(SMBIOSExposedTable::must_create(m_smbios_structure_table, m_smbios_structure_table_length));
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT void BIOSSysFSDirectory::initialize_dmi_exposer()
|
||||
{
|
||||
VERIFY(!(m_dmi_entry_point.is_null()));
|
||||
if (m_using_64bit_dmi_entry_point) {
|
||||
set_dmi_64_bit_entry_initialization_values();
|
||||
} else {
|
||||
set_dmi_32_bit_entry_initialization_values();
|
||||
}
|
||||
dbgln("BIOSSysFSDirectory: Data table @ {}", m_smbios_structure_table);
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT BIOSSysFSDirectory::BIOSSysFSDirectory(FirmwareSysFSDirectory& firmware_directory)
|
||||
: SysFSDirectory(firmware_directory)
|
||||
{
|
||||
auto entry_32bit = find_dmi_entry32bit_point();
|
||||
if (entry_32bit.has_value()) {
|
||||
m_dmi_entry_point = entry_32bit.value();
|
||||
}
|
||||
|
||||
auto entry_64bit = find_dmi_entry64bit_point();
|
||||
if (entry_64bit.has_value()) {
|
||||
m_dmi_entry_point = entry_64bit.value();
|
||||
m_using_64bit_dmi_entry_point = true;
|
||||
}
|
||||
if (m_dmi_entry_point.is_null())
|
||||
return;
|
||||
initialize_dmi_exposer();
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT Optional<PhysicalAddress> BIOSSysFSDirectory::find_dmi_entry64bit_point()
|
||||
{
|
||||
auto bios_or_error = map_bios();
|
||||
if (bios_or_error.is_error())
|
||||
return {};
|
||||
return bios_or_error.value().find_chunk_starting_with("_SM3_", 16);
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT Optional<PhysicalAddress> BIOSSysFSDirectory::find_dmi_entry32bit_point()
|
||||
{
|
||||
auto bios_or_error = map_bios();
|
||||
if (bios_or_error.is_error())
|
||||
return {};
|
||||
return bios_or_error.value().find_chunk_starting_with("_SM_", 16);
|
||||
}
|
||||
|
||||
ErrorOr<Memory::MappedROM> map_bios()
|
||||
{
|
||||
Memory::MappedROM mapping;
|
||||
mapping.size = 128 * KiB;
|
||||
mapping.paddr = PhysicalAddress(0xe0000);
|
||||
auto region_size = TRY(Memory::page_round_up(mapping.size));
|
||||
mapping.region = TRY(MM.allocate_kernel_region(mapping.paddr, region_size, {}, Memory::Region::Access::Read));
|
||||
return mapping;
|
||||
}
|
||||
|
||||
ErrorOr<Memory::MappedROM> map_ebda()
|
||||
{
|
||||
auto ebda_segment_ptr = TRY(Memory::map_typed<u16>(PhysicalAddress(0x40e)));
|
||||
PhysicalAddress ebda_paddr(PhysicalAddress(*ebda_segment_ptr).get() << 4);
|
||||
// The EBDA size is stored in the first byte of the EBDA in 1K units
|
||||
size_t ebda_size = *TRY(Memory::map_typed<u8>(ebda_paddr));
|
||||
ebda_size *= 1024;
|
||||
|
||||
Memory::MappedROM mapping;
|
||||
auto region_size = TRY(Memory::page_round_up(ebda_size));
|
||||
mapping.region = TRY(MM.allocate_kernel_region(ebda_paddr.page_base(), region_size, {}, Memory::Region::Access::Read));
|
||||
mapping.offset = ebda_paddr.offset_in_page();
|
||||
mapping.size = ebda_size;
|
||||
mapping.paddr = ebda_paddr;
|
||||
return mapping;
|
||||
}
|
||||
|
||||
}
|
126
Kernel/FileSystem/SysFS/Subsystems/Firmware/BIOS.h
Normal file
126
Kernel/FileSystem/SysFS/Subsystems/Firmware/BIOS.h
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/RefPtr.h>
|
||||
#include <AK/Types.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <Kernel/FileSystem/SysFS.h>
|
||||
#include <Kernel/FileSystem/SysFS/Subsystems/Firmware/Directory.h>
|
||||
#include <Kernel/KBuffer.h>
|
||||
#include <Kernel/Memory/MappedROM.h>
|
||||
#include <Kernel/Memory/Region.h>
|
||||
#include <Kernel/PhysicalAddress.h>
|
||||
#include <Kernel/VirtualAddress.h>
|
||||
|
||||
namespace Kernel::SMBIOS {
|
||||
|
||||
struct [[gnu::packed]] LegacyEntryPoint32bit {
|
||||
char legacy_sig[5];
|
||||
u8 checksum2;
|
||||
u16 smbios_table_length;
|
||||
u32 smbios_table_ptr;
|
||||
u16 smbios_tables_count;
|
||||
u8 smbios_bcd_revision;
|
||||
};
|
||||
|
||||
struct [[gnu::packed]] EntryPoint32bit {
|
||||
char sig[4];
|
||||
u8 checksum;
|
||||
u8 length;
|
||||
u8 major_version;
|
||||
u8 minor_version;
|
||||
u16 maximum_structure_size;
|
||||
u8 implementation_revision;
|
||||
char formatted_area[5];
|
||||
LegacyEntryPoint32bit legacy_structure;
|
||||
};
|
||||
|
||||
struct [[gnu::packed]] EntryPoint64bit {
|
||||
char sig[5];
|
||||
u8 checksum;
|
||||
u8 length;
|
||||
u8 major_version;
|
||||
u8 minor_version;
|
||||
u8 document_revision;
|
||||
u8 revision;
|
||||
u8 reserved;
|
||||
u32 table_maximum_size;
|
||||
u64 table_ptr;
|
||||
};
|
||||
}
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
ErrorOr<Memory::MappedROM> map_bios();
|
||||
ErrorOr<Memory::MappedROM> map_ebda();
|
||||
|
||||
class BIOSSysFSComponent : public SysFSComponent {
|
||||
public:
|
||||
virtual ErrorOr<size_t> read_bytes(off_t, size_t, UserOrKernelBuffer&, OpenFileDescription*) const override;
|
||||
|
||||
protected:
|
||||
virtual ErrorOr<NonnullOwnPtr<KBuffer>> try_to_generate_buffer() const = 0;
|
||||
BIOSSysFSComponent();
|
||||
};
|
||||
|
||||
class DMIEntryPointExposedBlob final : public BIOSSysFSComponent {
|
||||
public:
|
||||
virtual StringView name() const override { return "smbios_entry_point"sv; }
|
||||
static NonnullRefPtr<DMIEntryPointExposedBlob> must_create(PhysicalAddress dmi_entry_point, size_t blob_size);
|
||||
|
||||
private:
|
||||
DMIEntryPointExposedBlob(PhysicalAddress dmi_entry_point, size_t blob_size);
|
||||
virtual ErrorOr<NonnullOwnPtr<KBuffer>> try_to_generate_buffer() const override;
|
||||
|
||||
virtual size_t size() const override { return m_dmi_entry_point_length; }
|
||||
|
||||
PhysicalAddress m_dmi_entry_point;
|
||||
size_t const m_dmi_entry_point_length { 0 };
|
||||
};
|
||||
|
||||
class SMBIOSExposedTable final : public BIOSSysFSComponent {
|
||||
public:
|
||||
virtual StringView name() const override { return "DMI"sv; }
|
||||
static NonnullRefPtr<SMBIOSExposedTable> must_create(PhysicalAddress, size_t blob_size);
|
||||
|
||||
private:
|
||||
SMBIOSExposedTable(PhysicalAddress dmi_entry_point, size_t blob_size);
|
||||
virtual ErrorOr<NonnullOwnPtr<KBuffer>> try_to_generate_buffer() const override;
|
||||
|
||||
virtual size_t size() const override { return m_smbios_structure_table_length; }
|
||||
|
||||
PhysicalAddress m_smbios_structure_table;
|
||||
size_t const m_smbios_structure_table_length { 0 };
|
||||
};
|
||||
|
||||
class BIOSSysFSDirectory : public SysFSDirectory {
|
||||
public:
|
||||
virtual StringView name() const override { return "bios"sv; }
|
||||
static NonnullRefPtr<BIOSSysFSDirectory> must_create(FirmwareSysFSDirectory&);
|
||||
|
||||
void create_components();
|
||||
|
||||
private:
|
||||
explicit BIOSSysFSDirectory(FirmwareSysFSDirectory&);
|
||||
|
||||
void set_dmi_64_bit_entry_initialization_values();
|
||||
void set_dmi_32_bit_entry_initialization_values();
|
||||
void initialize_dmi_exposer();
|
||||
|
||||
Optional<PhysicalAddress> find_dmi_entry64bit_point();
|
||||
Optional<PhysicalAddress> find_dmi_entry32bit_point();
|
||||
|
||||
PhysicalAddress m_dmi_entry_point;
|
||||
PhysicalAddress m_smbios_structure_table;
|
||||
bool m_using_64bit_dmi_entry_point { false };
|
||||
size_t m_smbios_structure_table_length { 0 };
|
||||
size_t m_dmi_entry_point_length { 0 };
|
||||
};
|
||||
|
||||
}
|
35
Kernel/FileSystem/SysFS/Subsystems/Firmware/Directory.cpp
Normal file
35
Kernel/FileSystem/SysFS/Subsystems/Firmware/Directory.cpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/FileSystem/SysFS/Subsystems/Firmware/BIOS.h>
|
||||
#include <Kernel/FileSystem/SysFS/Subsystems/Firmware/Directory.h>
|
||||
#include <Kernel/FileSystem/SysFS/Subsystems/Firmware/PowerStateSwitch.h>
|
||||
#include <Kernel/Firmware/ACPI/Parser.h>
|
||||
#include <Kernel/Sections.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
UNMAP_AFTER_INIT void FirmwareSysFSDirectory::initialize()
|
||||
{
|
||||
auto firmware_directory = adopt_ref_if_nonnull(new (nothrow) FirmwareSysFSDirectory()).release_nonnull();
|
||||
SysFSComponentRegistry::the().register_new_component(firmware_directory);
|
||||
firmware_directory->create_components();
|
||||
}
|
||||
|
||||
void FirmwareSysFSDirectory::create_components()
|
||||
{
|
||||
m_components.append(BIOSSysFSDirectory::must_create(*this));
|
||||
if (ACPI::is_enabled())
|
||||
m_components.append(ACPI::ACPISysFSDirectory::must_create(*this));
|
||||
m_components.append(PowerStateSwitchNode::must_create(*this));
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT FirmwareSysFSDirectory::FirmwareSysFSDirectory()
|
||||
: SysFSDirectory(SysFSComponentRegistry::the().root_directory())
|
||||
{
|
||||
}
|
||||
|
||||
}
|
25
Kernel/FileSystem/SysFS/Subsystems/Firmware/Directory.h
Normal file
25
Kernel/FileSystem/SysFS/Subsystems/Firmware/Directory.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Types.h>
|
||||
#include <Kernel/FileSystem/SysFS.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class FirmwareSysFSDirectory : public SysFSDirectory {
|
||||
public:
|
||||
virtual StringView name() const override { return "firmware"sv; }
|
||||
static void initialize();
|
||||
|
||||
void create_components();
|
||||
|
||||
private:
|
||||
FirmwareSysFSDirectory();
|
||||
};
|
||||
|
||||
}
|
108
Kernel/FileSystem/SysFS/Subsystems/Firmware/PowerStateSwitch.cpp
Normal file
108
Kernel/FileSystem/SysFS/Subsystems/Firmware/PowerStateSwitch.cpp
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/Arch/x86/IO.h>
|
||||
#include <Kernel/FileSystem/FileSystem.h>
|
||||
#include <Kernel/FileSystem/SysFS/Subsystems/Firmware/PowerStateSwitch.h>
|
||||
#include <Kernel/Firmware/ACPI/Parser.h>
|
||||
#include <Kernel/Process.h>
|
||||
#include <Kernel/Sections.h>
|
||||
#include <Kernel/TTY/ConsoleManagement.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
mode_t PowerStateSwitchNode::permissions() const
|
||||
{
|
||||
return S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP;
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT NonnullRefPtr<PowerStateSwitchNode> PowerStateSwitchNode::must_create(FirmwareSysFSDirectory& firmware_directory)
|
||||
{
|
||||
return adopt_ref_if_nonnull(new (nothrow) PowerStateSwitchNode(firmware_directory)).release_nonnull();
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT PowerStateSwitchNode::PowerStateSwitchNode(FirmwareSysFSDirectory&)
|
||||
: SysFSComponent()
|
||||
{
|
||||
}
|
||||
|
||||
ErrorOr<void> PowerStateSwitchNode::truncate(u64 size)
|
||||
{
|
||||
// Note: This node doesn't store any useful data anyway, so we can safely
|
||||
// truncate this to zero (essentially ignoring the request without failing).
|
||||
if (size != 0)
|
||||
return EPERM;
|
||||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<size_t> PowerStateSwitchNode::write_bytes(off_t offset, size_t count, UserOrKernelBuffer const& data, OpenFileDescription*)
|
||||
{
|
||||
if (Checked<off_t>::addition_would_overflow(offset, count))
|
||||
return EOVERFLOW;
|
||||
if (offset > 0)
|
||||
return EINVAL;
|
||||
if (count > 1)
|
||||
return EINVAL;
|
||||
|
||||
char buf[1];
|
||||
TRY(data.read(buf, 1));
|
||||
switch (buf[0]) {
|
||||
case '0':
|
||||
return EINVAL;
|
||||
case '1':
|
||||
reboot();
|
||||
VERIFY_NOT_REACHED();
|
||||
case '2':
|
||||
poweroff();
|
||||
VERIFY_NOT_REACHED();
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
void PowerStateSwitchNode::reboot()
|
||||
{
|
||||
MutexLocker locker(Process::current().big_lock());
|
||||
|
||||
dbgln("acquiring FS locks...");
|
||||
FileSystem::lock_all();
|
||||
dbgln("syncing mounted filesystems...");
|
||||
FileSystem::sync();
|
||||
dbgln("attempting reboot via ACPI");
|
||||
if (ACPI::is_enabled())
|
||||
ACPI::Parser::the()->try_acpi_reboot();
|
||||
dbgln("attempting reboot via KB Controller...");
|
||||
IO::out8(0x64, 0xFE);
|
||||
dbgln("reboot attempts failed, applications will stop responding.");
|
||||
dmesgln("Reboot can't be completed. It's safe to turn off the computer!");
|
||||
Processor::halt();
|
||||
}
|
||||
|
||||
void PowerStateSwitchNode::poweroff()
|
||||
{
|
||||
MutexLocker locker(Process::current().big_lock());
|
||||
|
||||
ConsoleManagement::the().switch_to_debug();
|
||||
|
||||
dbgln("acquiring FS locks...");
|
||||
FileSystem::lock_all();
|
||||
dbgln("syncing mounted filesystems...");
|
||||
FileSystem::sync();
|
||||
dbgln("attempting system shutdown...");
|
||||
// QEMU Shutdown
|
||||
IO::out16(0x604, 0x2000);
|
||||
// If we're here, the shutdown failed. Try VirtualBox shutdown.
|
||||
IO::out16(0x4004, 0x3400);
|
||||
// VirtualBox shutdown failed. Try Bochs/Old QEMU shutdown.
|
||||
IO::out16(0xb004, 0x2000);
|
||||
dbgln("shutdown attempts failed, applications will stop responding.");
|
||||
dmesgln("Shutdown can't be completed. It's safe to turn off the computer!");
|
||||
Processor::halt();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/RefPtr.h>
|
||||
#include <AK/Types.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <Kernel/FileSystem/SysFS.h>
|
||||
#include <Kernel/FileSystem/SysFS/Subsystems/Firmware/Directory.h>
|
||||
#include <Kernel/KBuffer.h>
|
||||
#include <Kernel/Memory/MappedROM.h>
|
||||
#include <Kernel/Memory/Region.h>
|
||||
#include <Kernel/PhysicalAddress.h>
|
||||
#include <Kernel/VirtualAddress.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class PowerStateSwitchNode final : public SysFSComponent {
|
||||
public:
|
||||
virtual StringView name() const override { return "power_state"sv; }
|
||||
static NonnullRefPtr<PowerStateSwitchNode> must_create(FirmwareSysFSDirectory&);
|
||||
virtual mode_t permissions() const override;
|
||||
virtual ErrorOr<size_t> write_bytes(off_t, size_t, UserOrKernelBuffer const&, OpenFileDescription*) override;
|
||||
virtual ErrorOr<void> truncate(u64) override;
|
||||
virtual ErrorOr<void> set_mtime(time_t) override { return {}; }
|
||||
|
||||
private:
|
||||
PowerStateSwitchNode(FirmwareSysFSDirectory&);
|
||||
|
||||
void reboot();
|
||||
void poweroff();
|
||||
};
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue