blob: 2bdb1077d6c1e7f85cd60e7bedf060b5aaaa00d5 [file] [log] [blame]
// Copyright 2023 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_FIRMWARE_GIGABOOT_CPP_INPUT_H_
#define SRC_FIRMWARE_GIGABOOT_CPP_INPUT_H_
#include <lib/zx/time.h>
#include <optional>
#include <string_view>
#include <efi/boot-services.h>
#include <efi/protocol/serial-io.h>
#include <efi/protocol/simple-text-output.h>
#include <efi/types.h>
#include <fbl/vector.h>
#include "utils.h"
namespace gigaboot {
// Wrapper class around console and serial input operations.
// Restores configurable attributes, e.g. serial poll frequency, cursor position,
// on destruction.
class InputReceiver {
public:
explicit InputReceiver(efi_system_table* sys) : sys_(sys) {}
// Given a collection of valid characters, a timeout, and an optional prompt string,
// return the first valid key pressed before the timeout expired,
// or std::nullopt if no valid key was pressed before the end of the timeout.
//
// If the prompt string is not empty, it is printed once every second with a countdown
// of the remaining timeout in seconds.
std::optional<char> GetKeyPrompt(std::string_view valid_keys, zx::duration timeout,
std::string_view prompt = "");
// Get the next key pressed within the timeout period, or an error.
fit::result<efi_status, char> GetKey(zx::duration timeout);
efi_system_table* system_table() const { return sys_; }
private:
// Wrapper class for a serial input device.
// Restores configurable attributes, e.g. serial poll frequency, on destruction.
class Serial {
public:
~Serial();
// Set the serial poll frequency.
// Note: SetPoll returns fit::ok() if there is no underlying serial device.
fit::result<efi_status> SetPoll(zx::duration timeout);
// Return the next character or an error.
// Does not block; returns an error if there is no input within the timeout period.
fit::result<efi_status, char> GetChar();
explicit operator bool() const { return serial_.get(); }
private:
friend class InputReceiver;
Serial();
serial_io_mode mode_;
EfiProtocolPtr<efi_serial_io_protocol> serial_;
};
friend class InputReceiverTest;
Serial& serial() { return serial_; }
efi_system_table* sys_;
Serial serial_;
};
} // namespace gigaboot
#endif // SRC_FIRMWARE_GIGABOOT_CPP_INPUT_H_