[gnu-efi]: How to call InitializeGlobalIoDevice funtion when I wanna call CMOS Read/Write?

115 views Asked by At

Below is the code to initializing the IO device, and I wanna to call a function to do CMOS read/write, but I don't know the DevicePath and Protocol? Does anyone know this? thanks a lot;

    /*
    
    Routine Description:
    
        Check to see if DevicePath exists for a given Protocol. Return Error if it
        exists. Return GlobalIoFuncs set match the DevicePath
    
      Arguments:
    
        DevicePath      - to operate on
        Protocol        - to check the DevicePath against
        ErrorStr        - ASCII string to display on error
        GlobalIoFncs    - Returned with DeviceIoProtocol for the DevicePath
    
    Returns:
    
        Pass or Fail based on  wether GlobalIoFncs where found
    
    */
EFI_STATUS 
InitializeGlobalIoDevice (
            IN  EFI_DEVICE_PATH             *DevicePath,
            IN  EFI_GUID                    *Protocol,
            IN  CHAR8                       *ErrorStr EFI_UNUSED,
            OUT EFI_DEVICE_IO_INTERFACE     **GlobalIoFncs
            )
    {
        EFI_STATUS      Status;
        EFI_HANDLE      Handle;
    
        //
        // Check to see if this device path already has Protocol on it.
        //  if so we are loading recursivly and should exit with an error
        //
        Status = uefi_call_wrapper(BS->LocateDevicePath, 3, Protocol, &DevicePath, &Handle);
        if (!EFI_ERROR(Status)) {
            DEBUG ((D_INIT, "Device Already Loaded for %a device\n", ErrorStr));
            return EFI_LOAD_ERROR;
        }
    
        Status = uefi_call_wrapper(BS->LocateDevicePath, 3, &DeviceIoProtocol, &DevicePath, &Handle);
        if (!EFI_ERROR(Status)) {
            Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handle, &DeviceIoProtocol, (VOID*)GlobalIoFncs);
        }
    
        ASSERT (!EFI_ERROR(Status));
        return Status;
    }

Need your help....

1

There are 1 answers

0
KagurazakaKotori On

In UEFI spec, there is no Protocol or Device Path defined for CMOS.

If you'd like to read/write the CMOS RTC, there are GetTime() and SetTime() APIs defined in Runtime Services. They can be directly called from RT in gnu-efi.

If you want to read/write other CMOS registers, simply access I/O port 0x70/0x71 with inb/outb instruction with inline assembly in C. That's also how EDK2 accesses CMOS.

https://github.com/tianocore/edk2/blob/master/OvmfPkg/Library/PlatformInitLib/Cmos.c https://github.com/tianocore/edk2/blob/master/MdePkg/Library/BaseIoLibIntrinsic/IoLib.c