Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to access the fan? #1350

Open
bingmatv opened this issue Oct 6, 2024 · 21 comments
Open

How to access the fan? #1350

bingmatv opened this issue Oct 6, 2024 · 21 comments

Comments

@bingmatv
Copy link

bingmatv commented Oct 6, 2024

Some computers have a fan to prevent the temperature from being too hot, how to access and control the fan speed?

@bjorn3
Copy link
Contributor

bjorn3 commented Oct 6, 2024

The firmware controls the fan speed, not the OS. What the OS can do however is request the frequency of the CPU to change depending on how much cpu usage there is. For this it needs to follow the ACPI specification to request the firmware/cpu to change the frequency.

@bingmatv
Copy link
Author

bingmatv commented Oct 23, 2024

firmware controls the fan speed

Laptops may use Lithium battery, which is unstable; So the user should control the power quantity stored in Lithium battery, some researchers say that power around 50% is good for Lithium battery. But Sodium-ion battery is more stable. Can the OS control the power stored in Lithium battery, .e.g, between 45% and 55%? Sodium-based batteries are more stable so it's not important to control power stored in Sodium-based batteries.

@bjorn3
Copy link
Contributor

bjorn3 commented Oct 23, 2024

Depends on the laptop. There is an embedded controller on the mainboard which controls the charging logic. On some laptops there is an option to set a charging limit through ACPI, but on others there is no way to set a limit at all.

@bingmatv
Copy link
Author

On some laptops there is an option to set a charging limit through ACPI

How to find the memory address (if the ACPI allows) to set charging limit?

@bjorn3
Copy link
Contributor

bjorn3 commented Nov 20, 2024

There is no specific memory address. Instead you have to interpret AML bytecode that is part of the ACPI tables to set the charging limit. This AML bytecode may write to a memory address or it may trigger an interrupt calling into the firmware depending on how the firmware implemented setting the charging limit. The crates in https://github.com/rust-osdev/acpi may be useful for interacting with ACPI. Just be aware that the specification is a mess and basically everyone has to emulate all bugs in the Windows ACPI implementation to be compatible with common firmware implementations. https://github.com/rust-osdev/acpi does not yet do this (even Linux has trouble with getting everything exactly right), so it may not work on your specific system. You may also want to look at https://github.com/acpica/acpica which is the code Linux uses to interface with ACPI. There are no Rust bindings for this yet though afaik.

@bingmatv
Copy link
Author

If the AML contains newlines, should I write \n escape character or directly press Enter key?

@bjorn3
Copy link
Contributor

bjorn3 commented Nov 22, 2024

AML is a binary format. It is not a string, so it doesn't contain newlines.

@bingmatv
Copy link
Author

Brave search engine provides AI to answer questions, I searched

battery charging limit using acpi machine language

The AI said:

Method (_SBF, 1)
{
  // Set battery charging limit to 80%
  Store(0x50, ResourceTemplate())
}

Method (_BST, 0)
{
  // Check battery status
  If (BatteryStatus() == 2) // 2 = charging
  {
    // Stop charging when battery reaches 80%
    If (BatteryLevel() >= 0x50) // 0x50 = 80%
    {
      Store(0, ResourceTemplate())
    }
  }
}

Is it correct?

@bjorn3
Copy link
Contributor

bjorn3 commented Nov 22, 2024

That is the text representation of AML. The actual ACPI tables contain AML in a binary format which is compiled from this text representation.

@bingmatv
Copy link
Author

That is the text representation of AML

Can the parse_table function https://docs.rs/aml/latest/aml/struct.AmlContext.html#method.parse_table parse the text representation to set charging limit?

@bjorn3
Copy link
Contributor

bjorn3 commented Nov 23, 2024

No, the aml crate doesn't have a compiler for the text representation of AML afaik. You shouldn't need to use the text representation of AML at any point. Instead read the binary version directly from the ACPI tables provided by the firmware of your system. Each firmware will provide different AML specific for the machine it runs on.

@bingmatv
Copy link
Author

Each firmware will provide different AML specific

Is there a universal way to set battery limit? How to know the length to read ACPI? It seems bootloader_api::info::BootInfo only provides rsdp_addr meaning the address.

@bjorn3
Copy link
Contributor

bjorn3 commented Nov 25, 2024

rsdp_addr points to the RSDP1, which itself contains the address of the RSDT (ACPI v1) and XSDT (ACPI v2)[^2]. The RSDT/XSDT is the index you can use to find all other ACPI tables. If you use the acpi crate you can use acpi::AcpiTables::from_rsdp to iterate over all ACPI tables.

Footnotes

  1. https://wiki.osdev.org/RSDP

@ChocolateLoverRaj
Copy link

Can the OS control the power stored in Lithium battery, .e.g, between 45% and 55%?

As @bjorn3 said, it depends on the laptop. Check if the OS that the laptop was designed for (such as Windows or Linux) has a way of controlling battery charging.

I know for some ThinkPads you can set a charging limit so it only charges up to a certain %.

On most Chromebooks you can stop charging, set a charging current limit, and for some Chromebooks you can set a % limit.

I think you would have to communicate with the laptop's embedded controller and send commands to it to control charging (and on Chromebooks you can control the fan too). I think this is pretty complicated to do in your own OS and you would have to look at the Linux kernel's code.

@tsatke
Copy link

tsatke commented Nov 27, 2024

you would have to look at the Linux kernel's code.

Not to be a party pooper, but you have to be careful when learning or borrowing from the linux kernel. It's GPL licensed, so your kernel would need a compatible license (or you do your own stuff).

Also mentioned here https://wiki.osdev.org/Linux_Kernel_Primer

@bingmatv
Copy link
Author

bingmatv commented Dec 5, 2024

you can use acpi::AcpiTables::from_rsdp to iterate over all ACPI tables

from_rsdp needs a handler, which needs PhysicalMapping.

@bjorn3
Copy link
Contributor

bjorn3 commented Dec 5, 2024

You are supposed to implement the AcpiHandler yourself calling into the memory management code of your OS to map/unmap the specified physical memory to some arbitrary location in the virtual address space of the kernel.

@bingmatv
Copy link
Author

bingmatv commented Dec 5, 2024

Is BootInfo::kernel_len the length of my kernel? Can I put user data immediately at kernel_addr + kernel_len?

@bjorn3
Copy link
Contributor

bjorn3 commented Dec 5, 2024

Is BootInfo::kernel_len the length of my kernel?

Yes

Can I put user data immediately at kernel_addr + kernel_len?

No, that location may be reserved by the firmware or hardware. You have to iterate through the memory map in boot_info.memory_regions and search for entries whose kind is MemoryRegionKind::Usable. Those entries indicate memory you are free to use in whatever way you want to use them.

@bingmatv
Copy link
Author

bingmatv commented Dec 8, 2024

Why are start and end in MemoryRegion u64 but not usize?

@bjorn3
Copy link
Contributor

bjorn3 commented Dec 8, 2024

Not sure of that is the reason, but the page tables use 64bit entries when PAE is enabled, not pointer size entries. The distinction doesn't matter on x86_64 where PAE is always enabled and usize is always 64bit, but it avoids some casting between u64 and usize. On 32bit x86 the distinction does matter however.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants