foo
[bootcensus] / src / kmain.c
1 /*
2 pcboot - bootable PC demo/game kernel
3 Copyright (C) 2018  John Tsiombikas <nuclear@member.fsf.org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY, without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 */
18 #include <stdio.h>
19 #include <string.h>
20 #include <ctype.h>
21 #include "segm.h"
22 #include "intr.h"
23 #include "mem.h"
24 #include "keyb.h"
25 #include "psaux.h"
26 #include "timer.h"
27 #include "contty.h"
28 #include "video.h"
29 #include "vbe.h"
30 #include "audio.h"
31 #include "panic.h"
32
33 static int video_init(void);
34 static int modecmp(const void *a, const void *b);
35
36 static struct video_mode vmode;
37 static void *fbptr;
38
39
40 void pcboot_main(void)
41 {
42         init_segm();
43         init_intr();
44
45         con_init();
46         kb_init();
47         init_psaux();
48
49         init_mem();
50
51         /* initialize the timer */
52         init_timer();
53
54         audio_init();
55
56         enable_intr();
57
58         printf("PCBoot kernel initialized\n");
59
60         if(video_init() == -1) {
61                 panic("Failed to find suitable video mode");
62         }
63
64         for(;;) {
65                 wait_vsync();
66                 memset(fbptr, 0x80, vmode.width * vmode.height * vmode.bpp / 8);
67         }
68 }
69
70 static int video_init(void)
71 {
72         struct vbe_edid edid;
73         struct video_mode vinf, *vmodes;
74         int i, xres, yres, nmodes, mode_idx = -1;
75         const char *vendor;
76
77         if(mode_idx == -1 && (vendor = get_video_vendor()) && strstr(vendor, "SeaBIOS")) {
78                 mode_idx = find_video_mode_idx(800, 600, 0);
79         }
80
81         if(mode_idx == -1 && vbe_get_edid(&edid) == 0 && edid_preferred_resolution(&edid, &xres, &yres) == 0) {
82                 printf("EDID: preferred resolution: %dx%d\n", xres, yres);
83                 mode_idx = find_video_mode_idx(xres, yres, 0);
84         }
85
86         nmodes = video_mode_count();
87         if(!(vmodes = malloc(nmodes * sizeof *vmodes))) {
88                 printf("failed to allocate video modes array (%d modes)\n", nmodes);
89                 return -1;
90         }
91
92         for(i=0; i<nmodes; i++) {
93                 video_mode_info(i, &vinf);
94                 vmodes[i] = vinf;
95         }
96
97         if(mode_idx >= 0) {
98                 if(!(fbptr = set_video_mode(vmodes[mode_idx].mode))) {
99                         printf("failed to set video mode: %x (%dx%d %dbpp)\n", mode_idx,
100                                         vmodes[mode_idx].width, vmodes[mode_idx].height, vmodes[mode_idx].bpp);
101                         mode_idx = -1;
102                 } else {
103                         vmode = vmodes[mode_idx];
104                         printf("video mode: %x (%dx%d %dbpp)\n", vmode.mode, vmode.width,
105                                         vmode.height, vmode.bpp);
106                 }
107         }
108
109         if(mode_idx == -1) {
110                 qsort(vmodes, nmodes, sizeof *vmodes, modecmp);
111
112                 for(i=0; i<nmodes; i++) {
113                         if((fbptr = set_video_mode(vmodes[i].mode))) {
114                                 vmode = vmodes[i];
115                                 printf("video mode: %x (%dx%d %dbpp)\n", vmode.mode, vmode.width,
116                                                 vmode.height, vmode.bpp);
117                                 break;
118                         }
119                 }
120                 if(i >= nmodes) {
121                         printf("failed to find a suitable video mode\n");
122                         return -1;
123                 }
124         }
125         free(vmodes);
126
127         return 0;
128 }
129
130
131
132 static int modecmp(const void *a, const void *b)
133 {
134         const struct video_mode *ma = a;
135         const struct video_mode *mb = b;
136         unsigned long aval = ma->width | (ma->height << 16);
137         unsigned long bval = mb->width | (mb->height << 16);
138
139         if(aval != bval) {
140                 return bval - aval;
141         }
142         return mb->bpp - ma->bpp;
143 }