1 asm(".code16gcc"); 2 #include <stddef.h> 3 #include "bios.h" 4 #include "segment.h" 5 #include "ioport.h" 6 #include "processor-flags.h" 7 #include "e820.h" 8 set_fs(uint16_t seg)9static inline void set_fs(uint16_t seg) 10 { 11 asm volatile("movw %0,%%fs" : : "rm" (seg)); 12 } 13 rdfs8(unsigned long addr)14static inline uint8_t rdfs8(unsigned long addr) 15 { 16 uint8_t v; 17 18 asm volatile("addr32 movb %%fs:%1,%0" : "=q" (v) : "m" (*(uint8_t *)addr)); 19 20 return v; 21 } 22 rdfs32(unsigned long addr)23static inline uint32_t rdfs32(unsigned long addr) 24 { 25 uint32_t v; 26 27 asm volatile("addr32 movl %%fs:%1,%0" : "=r" (v) : "m" (*(uint32_t *)addr)); 28 29 return v; 30 } 31 rdcs16(void * p)32static inline uint16_t rdcs16(void *p) 33 { 34 uint32_t addr = ((uintptr_t) p) & 65535; 35 uint16_t v; 36 37 asm volatile("addr32 movw %%cs:%1,%0" : "=r" (v) : "m" (*(uint32_t *)addr)); 38 39 return v; 40 } 41 42 uint16_t e820_seg; 43 e820_query_map(struct biosregs * regs)44bioscall void e820_query_map(struct biosregs *regs) 45 { 46 uint32_t map_size; 47 uint32_t ndx; 48 49 set_fs(rdcs16(&e820_seg)); 50 51 ndx = regs->ebx; 52 53 map_size = rdfs32(offsetof(struct e820map, nr_map)); 54 55 if (ndx < map_size) { 56 uint32_t start; 57 unsigned int i; 58 uint8_t *p; 59 60 start = offsetof(struct e820map, map[ndx]); 61 62 p = (void *) regs->edi; 63 64 for (i = 0; i < sizeof(struct e820entry); i++) 65 *p++ = rdfs8(start + i); 66 } 67 68 regs->eax = SMAP; 69 regs->ecx = sizeof(struct e820entry); 70 regs->ebx = ++ndx; 71 72 if (ndx >= map_size) 73 regs->ebx = 0; /* end of map */ 74 } 75 int15_handler(struct biosregs * regs)76bioscall void int15_handler(struct biosregs *regs) 77 { 78 switch (regs->eax) { 79 case 0xe820: 80 e820_query_map(regs); 81 break; 82 default: 83 /* Set CF to indicate failure. */ 84 regs->eflags |= X86_EFLAGS_CF; 85 break; 86 } 87 } 88 /* 89 * It's probably much more useful to make this print to the serial 90 * line rather than print to a non-displayed VGA memory 91 */ int10_putchar(struct biosregs * args)92static inline void int10_putchar(struct biosregs *args) 93 { 94 uint8_t al = args->eax & 0xFF; 95 96 outb(0x3f8, al); 97 } 98 99 #define VBE_STATUS_OK 0x004F 100 #define VBE_STATUS_FAIL 0x014F 101 int10_vesa(struct biosregs * args)102static void int10_vesa(struct biosregs *args) 103 { 104 args->eax = VBE_STATUS_FAIL; 105 } 106 int10_handler(struct biosregs * args)107bioscall void int10_handler(struct biosregs *args) 108 { 109 uint8_t ah; 110 111 ah = (args->eax & 0xff00) >> 8; 112 113 switch (ah) { 114 case 0x0e: 115 int10_putchar(args); 116 break; 117 case 0x4f: 118 int10_vesa(args); 119 break; 120 } 121 122 } 123