Source code for pyplugins.hyper.uboot

"""
U-Boot Plugin
=============

This module implements a plugin for the Penguin hypervisor environment that simulates U-Boot environment variable
management. It provides handlers for U-Boot hypercalls such as ``fw_setenv``, ``fw_getenv``, and ``fw_printenv``, allowing
the guest to set, get, and print U-Boot environment variables. All changes are logged to a file for auditing.

Usage
-----

The plugin is loaded by the Penguin framework and responds to U-Boot-related hypercalls.

Example Log Output
------------------

::

    bootcmd=run boot_flash
    baudrate=115200
    ethaddr

Arguments
---------

- ``outdir``: Output directory for the U-Boot log file.
- ``conf``: Configuration dictionary, may contain ``uboot_env`` for initial environment.
- ``verbose``: If set, enables debug logging.

Classes
-------

- UBoot: Main plugin class for handling U-Boot environment variable operations.

"""

import os
from penguin import Plugin, plugins

UBOOT_LOG = "uboot.log"


[docs] class UBoot(Plugin): """ UBoot is a plugin that simulates U-Boot environment variable management. **Arguments:** - `outdir` (str): Output directory for the U-Boot log file. - `conf` (dict): Configuration dictionary, may contain `uboot_env` for initial environment. - `verbose` (bool): Enables debug logging if True. """ def __init__(self) -> None: """ Initialize the UBoot plugin. - Sets up the output directory and log file. - Loads the initial U-Boot environment from configuration. - Subscribes to U-Boot hypercalls. **Returns:** None """ self.outdir = self.get_arg("outdir") open(os.path.join(self.outdir, UBOOT_LOG), "w").close() self.uboot_log = set() if self.get_arg_bool("verbose"): self.logger.setLevel("DEBUG") # U-Boot self.uboot_env = self.get_arg("conf").get("uboot_env", dict())
[docs] @plugins.SendHypercall.subscribe("fw_setenv") def cmd_fw_setenv(self, var: str, val: str) -> tuple[int, str]: """ Set a U-Boot environment variable and log the change. **Parameters:** - `var` (str): The environment variable name. - `val` (str): The value to set. **Returns:** - `(int, str)`: Tuple containing status code (0 for success) and an empty string. """ if var not in self.uboot_log: self.uboot_log.add(var) with open(os.path.join(self.outdir, UBOOT_LOG), "a") as f: f.write(f"{var}={val}\n") self.uboot_env[var] = val self.logger.debug(f"fw_setenv {var}={val}") return 0, ""
[docs] @plugins.SendHypercall.subscribe("fw_getenv") def cmd_fw_getenv(self, var: str) -> tuple[int, str]: """ Get the value of a U-Boot environment variable. **Parameters:** - `var` (str): The environment variable name. **Returns:** - `(int, str)`: Tuple containing status code (0 for success, 1 if not found) and the value or empty string. """ try: return 0, self.uboot_env[var] except KeyError: if var not in self.uboot_log: self.uboot_log.add(var) with open(os.path.join(self.outdir, UBOOT_LOG), "a") as f: f.write(var + "\n") self.logger.debug(f"fw_getenv {var}") return 1, ""
[docs] @plugins.SendHypercall.subscribe("fw_printenv") def cmd_fw_printenv(self, arg: str) -> None: """ Print the U-Boot environment variables. **Parameters:** - `arg` (str): Argument for printenv (unused). **Raises:** NotImplementedError **Returns:** None """ raise NotImplementedError("fw_printenv shim unimplemented")