You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

efi_io.c 5.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /*
  2. * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301, USA.
  18. */
  19. FILE_LICENCE ( GPL2_OR_LATER );
  20. #include <assert.h>
  21. #include <ipxe/io.h>
  22. #include <ipxe/efi/efi.h>
  23. #include <ipxe/efi/Protocol/CpuIo.h>
  24. #include <ipxe/efi/efi_io.h>
  25. /** @file
  26. *
  27. * iPXE I/O API for EFI
  28. *
  29. */
  30. /** CPU I/O protocol */
  31. static EFI_CPU_IO_PROTOCOL *cpu_io;
  32. EFI_REQUIRE_PROTOCOL ( EFI_CPU_IO_PROTOCOL, &cpu_io );
  33. /** Maximum address that can be used for port I/O */
  34. #define MAX_PORT_ADDRESS 0xffff
  35. /**
  36. * Determine whether or not address is a port I/O address
  37. *
  38. * @v io_addr I/O address
  39. * @v is_port I/O address is a port I/O address
  40. */
  41. #define IS_PORT_ADDRESS(io_addr) \
  42. ( ( ( intptr_t ) (io_addr) ) <= MAX_PORT_ADDRESS )
  43. /**
  44. * Determine EFI CPU I/O width code
  45. *
  46. * @v size Size of value
  47. * @ret width EFI width code
  48. *
  49. * Someone at Intel clearly gets paid by the number of lines of code
  50. * they write. No-one should ever be able to make I/O this
  51. * convoluted. The EFI_CPU_IO_PROTOCOL_WIDTH enum is my favourite
  52. * idiocy.
  53. */
  54. static EFI_CPU_IO_PROTOCOL_WIDTH efi_width ( size_t size ) {
  55. switch ( size ) {
  56. case 1 : return EfiCpuIoWidthFifoUint8;
  57. case 2 : return EfiCpuIoWidthFifoUint16;
  58. case 4 : return EfiCpuIoWidthFifoUint32;
  59. case 8 : return EfiCpuIoWidthFifoUint64;
  60. default :
  61. assert ( 0 );
  62. /* I wonder what this will actually do... */
  63. return EfiCpuIoWidthMaximum;
  64. }
  65. }
  66. /**
  67. * Read from device
  68. *
  69. * @v io_addr I/O address
  70. * @v size Size of value
  71. * @ret data Value read
  72. */
  73. unsigned long long efi_ioread ( volatile void *io_addr, size_t size ) {
  74. EFI_CPU_IO_PROTOCOL_IO_MEM read;
  75. unsigned long long data = 0;
  76. EFI_STATUS efirc;
  77. read = ( IS_PORT_ADDRESS ( io_addr ) ?
  78. cpu_io->Io.Read : cpu_io->Mem.Read );
  79. if ( ( efirc = read ( cpu_io, efi_width ( size ),
  80. ( intptr_t ) io_addr, 1,
  81. ( void * ) &data ) ) != 0 ) {
  82. DBG ( "EFI I/O read at %p failed: %s\n",
  83. io_addr, efi_strerror ( efirc ) );
  84. return -1ULL;
  85. }
  86. return data;
  87. }
  88. /**
  89. * Write to device
  90. *
  91. * @v data Value to write
  92. * @v io_addr I/O address
  93. * @v size Size of value
  94. */
  95. void efi_iowrite ( unsigned long long data, volatile void *io_addr,
  96. size_t size ) {
  97. EFI_CPU_IO_PROTOCOL_IO_MEM write;
  98. EFI_STATUS efirc;
  99. write = ( IS_PORT_ADDRESS ( io_addr ) ?
  100. cpu_io->Io.Write : cpu_io->Mem.Write );
  101. if ( ( efirc = write ( cpu_io, efi_width ( size ),
  102. ( intptr_t ) io_addr, 1,
  103. ( void * ) &data ) ) != 0 ) {
  104. DBG ( "EFI I/O write at %p failed: %s\n",
  105. io_addr, efi_strerror ( efirc ) );
  106. }
  107. }
  108. /**
  109. * String read from device
  110. *
  111. * @v io_addr I/O address
  112. * @v data Data buffer
  113. * @v size Size of values
  114. * @v count Number of values to read
  115. */
  116. void efi_ioreads ( volatile void *io_addr, void *data,
  117. size_t size, unsigned int count ) {
  118. EFI_CPU_IO_PROTOCOL_IO_MEM read;
  119. EFI_STATUS efirc;
  120. read = ( IS_PORT_ADDRESS ( io_addr ) ?
  121. cpu_io->Io.Read : cpu_io->Mem.Read );
  122. if ( ( efirc = read ( cpu_io, efi_width ( size ),
  123. ( intptr_t ) io_addr, count,
  124. ( void * ) data ) ) != 0 ) {
  125. DBG ( "EFI I/O string read at %p failed: %s\n",
  126. io_addr, efi_strerror ( efirc ) );
  127. }
  128. }
  129. /**
  130. * String write to device
  131. *
  132. * @v io_addr I/O address
  133. * @v data Data buffer
  134. * @v size Size of values
  135. * @v count Number of values to write
  136. */
  137. void efi_iowrites ( volatile void *io_addr, const void *data,
  138. size_t size, unsigned int count ) {
  139. EFI_CPU_IO_PROTOCOL_IO_MEM write;
  140. EFI_STATUS efirc;
  141. write = ( IS_PORT_ADDRESS ( io_addr ) ?
  142. cpu_io->Io.Write : cpu_io->Mem.Write );
  143. if ( ( efirc = write ( cpu_io, efi_width ( size ),
  144. ( intptr_t ) io_addr, count,
  145. ( void * ) data ) ) != 0 ) {
  146. DBG ( "EFI I/O write at %p failed: %s\n",
  147. io_addr, efi_strerror ( efirc ) );
  148. }
  149. }
  150. /**
  151. * Wait for I/O-mapped operation to complete
  152. *
  153. */
  154. static void efi_iodelay ( void ) {
  155. /* Write to non-existent port. Probably x86-only. */
  156. outb ( 0, 0x80 );
  157. }
  158. /**
  159. * Get memory map
  160. *
  161. * Can't be done on EFI so return an empty map
  162. *
  163. * @v memmap Memory map to fill in
  164. */
  165. static void efi_get_memmap ( struct memory_map *memmap ) {
  166. memmap->count = 0;
  167. }
  168. PROVIDE_IOAPI_INLINE ( efi, phys_to_bus );
  169. PROVIDE_IOAPI_INLINE ( efi, bus_to_phys );
  170. PROVIDE_IOAPI_INLINE ( efi, ioremap );
  171. PROVIDE_IOAPI_INLINE ( efi, iounmap );
  172. PROVIDE_IOAPI_INLINE ( efi, io_to_bus );
  173. PROVIDE_IOAPI_INLINE ( efi, readb );
  174. PROVIDE_IOAPI_INLINE ( efi, readw );
  175. PROVIDE_IOAPI_INLINE ( efi, readl );
  176. PROVIDE_IOAPI_INLINE ( efi, readq );
  177. PROVIDE_IOAPI_INLINE ( efi, writeb );
  178. PROVIDE_IOAPI_INLINE ( efi, writew );
  179. PROVIDE_IOAPI_INLINE ( efi, writel );
  180. PROVIDE_IOAPI_INLINE ( efi, writeq );
  181. PROVIDE_IOAPI_INLINE ( efi, inb );
  182. PROVIDE_IOAPI_INLINE ( efi, inw );
  183. PROVIDE_IOAPI_INLINE ( efi, inl );
  184. PROVIDE_IOAPI_INLINE ( efi, outb );
  185. PROVIDE_IOAPI_INLINE ( efi, outw );
  186. PROVIDE_IOAPI_INLINE ( efi, outl );
  187. PROVIDE_IOAPI_INLINE ( efi, insb );
  188. PROVIDE_IOAPI_INLINE ( efi, insw );
  189. PROVIDE_IOAPI_INLINE ( efi, insl );
  190. PROVIDE_IOAPI_INLINE ( efi, outsb );
  191. PROVIDE_IOAPI_INLINE ( efi, outsw );
  192. PROVIDE_IOAPI_INLINE ( efi, outsl );
  193. PROVIDE_IOAPI ( efi, iodelay, efi_iodelay );
  194. PROVIDE_IOAPI_INLINE ( efi, mb );
  195. PROVIDE_IOAPI ( efi, get_memmap, efi_get_memmap );