/* Writes NumberOfBytes data bytes from Buffer to the serial device. The number of bytes actually written to the serial device is returned. If the return value is less than NumberOfBytes, then the write operation failed. If Buffer is NULL, then ASSERT(). If NumberOfBytes is zero, then return 0. */
UINTN EFIAPI SerialPortWrite(IN UINT8 *Buffer, IN UINTN NumberOfBytes)
/* Writes NumberOfBytes data bytes from Buffer to the serial device. The number of bytes actually written to the serial device is returned. If the return value is less than NumberOfBytes, then the write operation failed. If Buffer is NULL, then ASSERT(). If NumberOfBytes is zero, then return 0. */
UINTN EFIAPI SerialPortWrite(IN UINT8 *Buffer, IN UINTN NumberOfBytes)
{
  XENCONS_RING_IDX  Consumer, Producer;
  UINTN             Sent;
  ASSERT (Buffer != NULL);
  if (NumberOfBytes == 0) {
    return 0;
  }
  if (!mXenConsoleInterface) {
    return 0;
  }
  Sent = 0;
  do {
    Consumer = mXenConsoleInterface->out_cons;
    Producer = mXenConsoleInterface->out_prod;
    MemoryFence ();
    while (Sent < NumberOfBytes && ((Producer - Consumer) < sizeof (mXenConsoleInterface->out))) {
      mXenConsoleInterface->out[MASK_XENCONS_IDX (Producer++, mXenConsoleInterface->out)] = Buffer[Sent++];
    }
    MemoryFence ();
    mXenConsoleInterface->out_prod = Producer;
    XenHypercallEventChannelOp (EVTCHNOP_send, &mXenConsoleEventChain);
  } while (Sent < NumberOfBytes);
  return Sent;
}