]> git.proxmox.com Git - mirror_edk2.git/blobdiff - StdLib/LibC/Uefi/Devices/Console/daConsole.c
Add Socket Libraries.
[mirror_edk2.git] / StdLib / LibC / Uefi / Devices / Console / daConsole.c
index c5799590813c22cb3d5b9158cacb0500bcec90ea..5dfc18acb49b9366c476f45ad9e8ce15f550cd59 100644 (file)
@@ -45,6 +45,12 @@ static const int stdioFlags[NUM_SPECIAL] = {
 static DeviceNode    *ConNode[NUM_SPECIAL];\r
 static ConInstance   *ConInstanceList;\r
 \r
+static wchar_t       *ConReadBuf;\r
+\r
+/* Flags settable by Ioctl */\r
+static BOOLEAN        TtyCooked;\r
+static BOOLEAN        TtyEcho;\r
+\r
 ssize_t\r
 WideTtyCvt( CHAR16 *dest, const char *buf, size_t n)\r
 {\r
@@ -127,74 +133,6 @@ da_ConSeek(
   }\r
 }\r
 \r
-static\r
-ssize_t\r
-EFIAPI\r
-da_ConRead(\r
-  IN OUT  struct __filedes   *filp,\r
-  IN OUT  off_t              *offset,         // Console ignores this\r
-  IN      size_t              BufferSize,\r
-     OUT  VOID               *Buffer\r
-)\r
-{\r
-  EFI_SIMPLE_TEXT_INPUT_PROTOCOL   *Proto;\r
-  ConInstance                      *Stream;\r
-  CHAR16                           *OutPtr;\r
-  EFI_INPUT_KEY                     Key;\r
-  UINTN                             NumChar;\r
-  UINTN                             Edex;\r
-  EFI_STATUS                        Status = RETURN_SUCCESS;\r
-  UINTN                             i;\r
-\r
-  Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);\r
-  // Quick check to see if Stream looks reasonable\r
-  if(Stream->Cookie != CON_COOKIE) {    // Cookie == 'IoAb'\r
-    EFIerrno = RETURN_INVALID_PARAMETER;\r
-    return -1;    // Looks like a bad This pointer\r
-  }\r
-  if(Stream->InstanceNum != STDIN_FILENO) {\r
-    // Read only valid for stdin\r
-    EFIerrno = RETURN_UNSUPPORTED;\r
-    return -1;\r
-  }\r
-  // It looks like things are OK for trying to read\r
-  // We will accumulate *BufferSize characters or until we encounter\r
-  // an "activation" character.  Currently any control character.\r
-  Proto = (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)Stream->Dev;\r
-  OutPtr = Buffer;\r
-  NumChar = (BufferSize - 1) / sizeof(CHAR16);\r
-  i = 0;\r
-  do {\r
-    if((Stream->UnGetKey.UnicodeChar == CHAR_NULL) && (Stream->UnGetKey.ScanCode == SCAN_NULL)) {\r
-      Status = gBS->WaitForEvent( 1, &Proto->WaitForKey, &Edex);\r
-      if(Status != RETURN_SUCCESS) {\r
-        break;\r
-      }\r
-      Status = Proto->ReadKeyStroke(Proto, &Key);\r
-      if(Status != RETURN_SUCCESS) {\r
-        break;\r
-      }\r
-    }\r
-    else {\r
-      Key.ScanCode          = Stream->UnGetKey.ScanCode;\r
-      Key.UnicodeChar       = Stream->UnGetKey.UnicodeChar;\r
-      Stream->UnGetKey.ScanCode     = SCAN_NULL;\r
-      Stream->UnGetKey.UnicodeChar  = CHAR_NULL;\r
-    }\r
-    if(Key.ScanCode == SCAN_NULL) {\r
-      *OutPtr++ = Key.UnicodeChar;\r
-      ++i;\r
-    }\r
-    if(iswcntrl(Key.UnicodeChar)) {    // If a control character, or a scan code\r
-      break;\r
-    }\r
-  } while(i < NumChar);\r
-\r
-  *OutPtr = L'\0';    // Terminate the input buffer\r
-  EFIerrno = Status;\r
-  return (ssize_t)(i * sizeof(CHAR16));  // Will be 0 if we didn't get a key\r
-}\r
-\r
 /* Write a NULL terminated WCS to the EFI console.\r
 \r
   @param[in,out]  BufferSize  Number of bytes in Buffer.  Set to zero if\r
@@ -265,6 +203,109 @@ da_ConWrite(
   return BufferSize;\r
 }\r
 \r
+/** Read characters from the console input device.\r
+\r
+    @param[in,out]  filp          Pointer to file descriptor for this file.\r
+    @param[in,out]  offset        Ignored.\r
+    @param[in]      BufferSize    Buffer size, in bytes.\r
+    @param[out]     Buffer        Buffer in which to place the read characters.\r
+\r
+    @return     Number of bytes actually placed into Buffer.\r
+\r
+    @todo       Handle encodings other than ASCII-7 and UEFI.\r
+**/\r
+static\r
+ssize_t\r
+EFIAPI\r
+da_ConRead(\r
+  IN OUT  struct __filedes   *filp,\r
+  IN OUT  off_t              *offset,         // Console ignores this\r
+  IN      size_t              BufferSize,\r
+     OUT  VOID               *Buffer\r
+)\r
+{\r
+  EFI_SIMPLE_TEXT_INPUT_PROTOCOL   *Proto;\r
+  ConInstance                      *Stream;\r
+  wchar_t                          *OutPtr;\r
+  EFI_INPUT_KEY                     Key;\r
+  UINTN                             NumChar;\r
+  UINTN                             Edex;\r
+  EFI_STATUS                        Status = RETURN_SUCCESS;\r
+  UINTN                             i;\r
+  char                              EchoBuff[MB_CUR_MAX + 1];\r
+  int                               NumEcho;\r
+\r
+  Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);\r
+  // Quick check to see if Stream looks reasonable\r
+  if(Stream->Cookie != CON_COOKIE) {    // Cookie == 'IoAb'\r
+    EFIerrno = RETURN_INVALID_PARAMETER;\r
+    return -1;    // Looks like a bad This pointer\r
+  }\r
+  if(Stream->InstanceNum != STDIN_FILENO) {\r
+    // Read only valid for stdin\r
+    EFIerrno = RETURN_UNSUPPORTED;\r
+    return -1;\r
+  }\r
+  // It looks like things are OK for trying to read\r
+  // We will accumulate *BufferSize characters or until we encounter\r
+  // an "activation" character.  Currently any control character.\r
+  Proto = (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)Stream->Dev;\r
+  OutPtr = ConReadBuf;\r
+  NumChar = (BufferSize > MAX_INPUT)? MAX_INPUT : BufferSize;\r
+  i = 0;\r
+  do {\r
+    if((Stream->UnGetKey.UnicodeChar == CHAR_NULL) && (Stream->UnGetKey.ScanCode == SCAN_NULL)) {\r
+      Status = gBS->WaitForEvent( 1, &Proto->WaitForKey, &Edex);\r
+      if(Status != RETURN_SUCCESS) {\r
+        break;\r
+      }\r
+      Status = Proto->ReadKeyStroke(Proto, &Key);\r
+      if(Status != RETURN_SUCCESS) {\r
+        break;\r
+      }\r
+    }\r
+    else {\r
+      Key.ScanCode          = Stream->UnGetKey.ScanCode;\r
+      Key.UnicodeChar       = Stream->UnGetKey.UnicodeChar;\r
+      Stream->UnGetKey.ScanCode     = SCAN_NULL;\r
+      Stream->UnGetKey.UnicodeChar  = CHAR_NULL;\r
+    }\r
+    if(Key.ScanCode == SCAN_NULL) {\r
+      NumEcho = 0;\r
+      if(TtyCooked && (Key.UnicodeChar == CHAR_CARRIAGE_RETURN)) {\r
+        *OutPtr++ = CHAR_LINEFEED;\r
+        NumEcho = wctomb(EchoBuff, CHAR_LINEFEED);\r
+      }\r
+      else {\r
+        *OutPtr++ = Key.UnicodeChar;\r
+        NumEcho = wctomb(EchoBuff, Key.UnicodeChar);\r
+      }\r
+      ++i;\r
+      EchoBuff[NumEcho] = 0;  /* Terminate the Echo buffer */\r
+      if(TtyEcho) {\r
+        /* Echo the character just input */\r
+        da_ConWrite(&gMD->fdarray[STDOUT_FILENO], NULL, 2, EchoBuff);\r
+      }\r
+    }\r
+    if(iswcntrl(Key.UnicodeChar)) {    // If a control character, or a scan code\r
+      break;\r
+    }\r
+  } while(i < NumChar);\r
+\r
+  *OutPtr = L'\0';    // Terminate the input buffer\r
+\r
+  /*  Convert the input buffer and place in Buffer.\r
+      If the fully converted input buffer won't fit, write what will and\r
+      leave the rest in ConReadBuf with ConReadLeft indicating how many\r
+      unconverted characters remain in ConReadBuf.\r
+  */\r
+  NumEcho = (int)wcstombs(Buffer, ConReadBuf, BufferSize);   /* Re-use NumEcho to hold number of bytes in Buffer */\r
+  /* More work needs to be done before locales other than C can be supported. */\r
+\r
+  EFIerrno = Status;\r
+  return (ssize_t)NumEcho;  // Will be 0 if we didn't get a key\r
+}\r
+\r
 /** Console-specific helper function for the fstat() function.\r
 \r
     st_size       Set to number of characters read for stdin and number written for stdout and stderr.\r
@@ -347,27 +388,28 @@ da_ConIoctl(
 int\r
 EFIAPI\r
 da_ConOpen(\r
+  DeviceNode         *DevNode,\r
   struct __filedes   *filp,\r
-  void               *DevInstance,\r
+  int                 DevInstance,    // Not used for console devices\r
   wchar_t            *Path,           // Not used for console devices\r
-  wchar_t            *Flags           // Not used for console devices\r
+  wchar_t            *MPath           // Not used for console devices\r
   )\r
 {\r
   ConInstance                      *Stream;\r
 \r
   if((filp == NULL)           ||\r
-     (DevInstance  == NULL))\r
+     (DevNode  == NULL))\r
   {\r
     EFIerrno = RETURN_INVALID_PARAMETER;\r
     return -1;\r
   }\r
-  Stream = (ConInstance *)DevInstance;\r
+  Stream = (ConInstance *)DevNode->InstanceList;\r
   // Quick check to see if Stream looks reasonable\r
   if(Stream->Cookie != CON_COOKIE) {    // Cookie == 'IoAb'\r
     EFIerrno = RETURN_INVALID_PARAMETER;\r
     return -1;    // Looks like a bad This pointer\r
   }\r
-  gMD->StdIo[Stream->InstanceNum] = (ConInstance *)DevInstance;\r
+  gMD->StdIo[Stream->InstanceNum] = Stream;\r
   filp->f_iflags |= (S_IFREG | _S_IFCHR | _S_ICONSOLE);\r
   filp->f_offset = 0;\r
   filp->f_ops = &Stream->Abstraction;\r
@@ -448,7 +490,8 @@ __Cons_construct(
   int             i;\r
 \r
   ConInstanceList = (ConInstance *)AllocateZeroPool(NUM_SPECIAL * sizeof(ConInstance));\r
-  if(ConInstanceList == NULL) {\r
+  ConReadBuf      = (wchar_t *)AllocateZeroPool((MAX_INPUT + 1) * sizeof(wchar_t));\r
+  if((ConInstanceList == NULL) || (ConReadBuf == NULL))  {\r
     return RETURN_OUT_OF_RESOURCES;\r
   }\r
 \r
@@ -507,6 +550,10 @@ __Cons_construct(
     }\r
     Stream->Parent = ConNode[i];\r
   }\r
+  /* Initialize Ioctl flags until Ioctl is really implemented. */\r
+  TtyCooked = TRUE;\r
+  TtyEcho   = TRUE;\r
+\r
   return  Status;\r
 }\r
 \r
@@ -527,6 +574,9 @@ __Cons_deconstruct(
   if(ConInstanceList != NULL) {\r
     FreePool(ConInstanceList);\r
   }\r
+  if(ConReadBuf != NULL) {\r
+    FreePool(ConReadBuf);\r
+  }\r
 \r
   return RETURN_SUCCESS;\r
 }\r