bios32.c 3.0 KB

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