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

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