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.

linux_smbios.c 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. * Copyright (C) 2013 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 <errno.h>
  21. #include <linux_api.h>
  22. #include <ipxe/linux.h>
  23. #include <ipxe/smbios.h>
  24. /** SMBIOS filename */
  25. static const char smbios_filename[] = "/dev/mem";
  26. /** SMBIOS entry point scan region start address */
  27. #define SMBIOS_ENTRY_START 0xf0000
  28. /** SMBIOS entry point scan region length */
  29. #define SMBIOS_ENTRY_LEN 0x10000
  30. /** SMBIOS mapping alignment */
  31. #define SMBIOS_ALIGN 0x1000
  32. /**
  33. * Find SMBIOS
  34. *
  35. * @v smbios SMBIOS entry point descriptor structure to fill in
  36. * @ret rc Return status code
  37. */
  38. static int linux_find_smbios ( struct smbios *smbios ) {
  39. struct smbios_entry entry;
  40. void *entry_mem;
  41. void *smbios_mem;
  42. size_t smbios_offset;
  43. size_t smbios_indent;
  44. size_t smbios_len;
  45. int fd;
  46. int rc;
  47. /* Open SMBIOS file */
  48. fd = linux_open ( smbios_filename, O_RDONLY );
  49. if ( fd < 0 ) {
  50. rc = -ELINUX ( linux_errno );
  51. DBGC ( smbios, "SMBIOS could not open %s: %s\n",
  52. smbios_filename, linux_strerror ( linux_errno ) );
  53. goto err_open;
  54. }
  55. /* Map the region potentially containing the SMBIOS entry point */
  56. entry_mem = linux_mmap ( NULL, SMBIOS_ENTRY_LEN, PROT_READ, MAP_SHARED,
  57. fd, SMBIOS_ENTRY_START );
  58. if ( entry_mem == MAP_FAILED ) {
  59. rc = -ELINUX ( linux_errno );
  60. DBGC ( smbios, "SMBIOS could not mmap %s (%#x+%#x): %s\n",
  61. smbios_filename, SMBIOS_ENTRY_START, SMBIOS_ENTRY_LEN,
  62. linux_strerror ( linux_errno ) );
  63. goto err_mmap_entry;
  64. }
  65. /* Scan for the SMBIOS entry point */
  66. if ( ( rc = find_smbios_entry ( virt_to_user ( entry_mem ),
  67. SMBIOS_ENTRY_LEN, &entry ) ) != 0 )
  68. goto err_find_entry;
  69. /* Map the region containing the SMBIOS structures */
  70. smbios_indent = ( entry.smbios_address & ( SMBIOS_ALIGN - 1 ) );
  71. smbios_offset = ( entry.smbios_address - smbios_indent );
  72. smbios_len = ( entry.smbios_len + smbios_indent );
  73. smbios_mem = linux_mmap ( NULL, smbios_len, PROT_READ, MAP_SHARED,
  74. fd, smbios_offset );
  75. if ( smbios_mem == MAP_FAILED ) {
  76. rc = -ELINUX ( linux_errno );
  77. DBGC ( smbios, "SMBIOS could not mmap %s (%#zx+%#zx): %s\n",
  78. smbios_filename, smbios_offset, smbios_len,
  79. linux_strerror ( linux_errno ) );
  80. goto err_mmap_smbios;
  81. }
  82. /* Fill in entry point descriptor structure */
  83. smbios->address = virt_to_user ( smbios_mem + smbios_indent );
  84. smbios->len = entry.smbios_len;
  85. smbios->count = entry.smbios_count;
  86. smbios->version = SMBIOS_VERSION ( entry.major, entry.minor );
  87. /* Unmap the entry point region (no longer required) */
  88. linux_munmap ( entry_mem, SMBIOS_ENTRY_LEN );
  89. return 0;
  90. linux_munmap ( smbios_mem, smbios_len );
  91. err_mmap_smbios:
  92. err_find_entry:
  93. linux_munmap ( entry_mem, SMBIOS_ENTRY_LEN );
  94. err_mmap_entry:
  95. linux_close ( fd );
  96. err_open:
  97. return rc;
  98. }
  99. PROVIDE_SMBIOS ( linux, find_smbios, linux_find_smbios );