bios32.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "io.h"
  7. #define VFLAG(...) if(vflag) print(__VA_ARGS__)
  8. #define UPTR2INT(p) ((uintptr)(p))
  9. static int vflag = 0;
  10. typedef struct BIOS32sdh { /* BIOS32 Service Directory Header */
  11. u8int signature[4]; /* "_32_" */
  12. u8int physaddr[4]; /* physical address of entry point */
  13. u8int revision;
  14. u8int length; /* of header in paragraphs */
  15. u8int checksum; /* */
  16. u8int reserved[5];
  17. } BIOS32sdh;
  18. typedef struct BIOS32si { /* BIOS32 Service Interface */
  19. u8int* base; /* base address of service */
  20. int length; /* length of service */
  21. u32int offset; /* service entry-point from base */
  22. u16int ptr[3]; /* far pointer m16:32 */
  23. } BIOS32si;
  24. static Lock bios32lock;
  25. static u16int bios32ptr[3];
  26. static void* bios32entry;
  27. int
  28. bios32ci(BIOS32si* si, BIOS32ci* ci)
  29. {
  30. int r;
  31. lock(&bios32lock);
  32. r = bios32call(ci, si->ptr);
  33. unlock(&bios32lock);
  34. return r;
  35. }
  36. static void*
  37. rsdchecksum(void* addr, int length)
  38. {
  39. u8int *p, sum;
  40. sum = 0;
  41. for(p = addr; length-- > 0; p++)
  42. sum += *p;
  43. if(sum == 0)
  44. return addr;
  45. return nil;
  46. }
  47. static void*
  48. rsdscan(u8int* addr, int len, char* signature)
  49. {
  50. int sl;
  51. u8int *e, *p;
  52. e = addr+len;
  53. sl = strlen(signature);
  54. for(p = addr; p+sl < e; p += 16){
  55. if(memcmp(p, signature, sl))
  56. continue;
  57. return p;
  58. }
  59. return nil;
  60. }
  61. static int
  62. bios32locate(void)
  63. {
  64. uintptr ptr;
  65. BIOS32sdh *sdh;
  66. VFLAG("bios32link\n");
  67. if((sdh = rsdscan(BIOSSEG(0xE000), 0x20000, "_32_")) == nil)
  68. return -1;
  69. if(rsdchecksum(sdh, sizeof(BIOS32sdh)) == nil)
  70. return -1;
  71. VFLAG("sdh @ %#p, entry %#ux\n", sdh, L32GET(sdh->physaddr));
  72. bios32entry = vmap(L32GET(sdh->physaddr), 4096+1);
  73. VFLAG("entry @ %#p\n", bios32entry);
  74. ptr = UPTR2INT(bios32entry);
  75. bios32ptr[0] = ptr & 0xffff;
  76. bios32ptr[1] = (ptr>>16) & 0xffff;
  77. bios32ptr[2] = KESEL;
  78. VFLAG("bios32link: ptr %ux %ux %ux\n",
  79. bios32ptr[0], bios32ptr[1], bios32ptr[2]);
  80. return 0;
  81. }
  82. void
  83. BIOS32close(BIOS32si* si)
  84. {
  85. vunmap(si->base, si->length);
  86. free(si);
  87. }
  88. BIOS32si*
  89. bios32open(char* id)
  90. {
  91. uint ptr;
  92. BIOS32ci ci;
  93. BIOS32si *si;
  94. lock(&bios32lock);
  95. if(bios32ptr[2] == 0 && bios32locate() < 0){
  96. unlock(&bios32lock);
  97. return nil;
  98. }
  99. VFLAG("bios32si: %s\n", id);
  100. memset(&ci, 0, sizeof(BIOS32ci));
  101. ci.eax = (id[3]<<24|(id[2]<<16)|(id[1]<<8)|id[0]);
  102. bios32call(&ci, bios32ptr);
  103. unlock(&bios32lock);
  104. VFLAG("bios32si: eax %ux\n", ci.eax);
  105. if(ci.eax & 0xff)
  106. return nil;
  107. VFLAG("bios32si: base %#ux length %#ux offset %#ux\n",
  108. ci.ebx, ci.ecx, ci.edx);
  109. if((si = malloc(sizeof(BIOS32si))) == nil)
  110. return nil;
  111. if((si->base = vmap(ci.ebx, ci.ecx)) == nil){
  112. free(si);
  113. return nil;
  114. }
  115. si->length = ci.ecx;
  116. ptr = UPTR2INT(si->base)+ci.edx;
  117. si->ptr[0] = ptr & 0xffff;
  118. si->ptr[1] = (ptr>>16) & 0xffff;
  119. si->ptr[2] = KESEL;
  120. VFLAG("bios32si: eax entry %ux\n", ptr);
  121. return si;
  122. }