census logo
[bootcensus] / src / vbe.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <inttypes.h>
4 #include "vbe.h"
5 #include "asmops.h"
6 #include "int86.h"
7 #include "boot.h"
8
9 #define SEG_ADDR(s)     ((uint32_t)(s) << 4)
10
11 #define MODE_LFB        (1 << 14)
12
13 struct vbe_info *vbe_get_info(void)
14 {
15         struct vbe_info *info;
16         struct int86regs regs;
17
18         info = (struct vbe_info*)low_mem_buffer;
19
20         memcpy(info->sig, "VBE2", 4);
21
22         memset(&regs, 0, sizeof regs);
23         regs.es = (uint32_t)info >> 4;
24         regs.eax = 0x4f00;
25         int86(0x10, &regs);
26
27         if((regs.eax & 0xffff) != 0x4f) {
28                 return 0;
29         }
30
31         return info;
32 }
33
34 struct vbe_mode_info *vbe_get_mode_info(int mode)
35 {
36         struct vbe_mode_info *mi;
37         struct int86regs regs;
38
39         mi = (struct vbe_mode_info*)(low_mem_buffer + 512);
40
41         memset(&regs, 0, sizeof regs);
42         regs.es = (uint32_t)mi >> 4;
43         regs.eax = 0x4f01;
44         regs.ecx = mode;
45         int86(0x10, &regs);
46
47         if((regs.eax & 0xffff) != 0x4f) {
48                 return 0;
49         }
50
51         return mi;
52 }
53
54 int vbe_set_mode(int mode)
55 {
56         struct int86regs regs;
57
58         memset(&regs, 0, sizeof regs);
59         regs.eax = 0x4f02;
60         regs.ebx = mode;
61         int86(0x10, &regs);
62
63         if(regs.eax == 0x100) {
64                 return -1;
65         }
66         return 0;
67 }
68
69 void print_mode_info(struct vbe_mode_info *mi)
70 {
71         static unsigned int maskbits[] = {0, 1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff};
72
73         printf("resolution: %dx%d\n", mi->xres, mi->yres);
74         printf("color depth: %d\n", mi->bpp);
75         printf("mode attributes: %x\n", mi->mode_attr);
76         printf("bytes per scanline: %d\n", mi->scanline_bytes);
77         printf("number of planes: %d\n", (int)mi->num_planes);
78         printf("number of banks: %d\n", (int)mi->num_banks);
79         printf("mem model: %d\n", (int)mi->mem_model);
80         printf("red bits: %d (mask: %x)\n", (int)mi->rmask_size, maskbits[mi->rmask_size] << mi->rpos);
81         printf("green bits: %d (mask: %x)\n", (int)mi->gmask_size, maskbits[mi->gmask_size] << mi->gpos);
82         printf("blue bits: %d (mask: %x)\n", (int)mi->bmask_size, maskbits[mi->bmask_size] << mi->bpos);
83         printf("framebuffer address: %x\n", (unsigned int)mi->fb_addr);
84 }
85
86 int vbe_get_edid(struct vbe_edid *edid)
87 {
88         struct int86regs regs;
89
90         memset(&regs, 0, sizeof regs);
91         regs.es = (uint32_t)low_mem_buffer >> 4;
92         regs.eax = 0x4f15;
93         regs.ebx = 1;
94         int86(0x10, &regs);
95
96         if((regs.eax & 0xffff) != 0x4f) {
97                 return -1;
98         }
99         memcpy(edid, low_mem_buffer, sizeof *edid);
100         return 0;
101 }
102
103 int edid_preferred_resolution(struct vbe_edid *edid, int *xres, int *yres)
104 {
105         if(memcmp(edid->magic, VBE_EDID_MAGIC, 8) != 0) {
106                 return -1;
107         }
108
109         *xres = (int)edid->timing[0].hactive_lsb | ((int)(edid->timing[0].hact_hblank_msb & 0xf0) << 4);
110         *yres = (int)edid->timing[0].vactive_lsb | ((int)(edid->timing[0].vact_vblank_msb & 0xf0) << 4);
111         return 0;
112 }
113
114 void print_edid(struct vbe_edid *edid)
115 {
116         char vendor[4];
117         int xres, yres;
118
119         if(memcmp(edid->magic, VBE_EDID_MAGIC, 8) != 0) {
120                 printf("invalid EDID magic\n");
121                 return;
122         }
123
124         vendor[0] = (edid->vendor >> 10) & 0x1f;
125         vendor[1] = (edid->vendor >> 5) & 0x1f;
126         vendor[2] = edid->vendor & 0x1f;
127         vendor[3] = 0;
128         printf("Manufacturer: %s\n", vendor);
129
130         edid_preferred_resolution(edid, &xres, &yres);
131         printf("Preferred resolution: %dx%d\n", xres, yres);
132 }