OSDev.org https://forum.osdev.org/ |
|
qemu differences between -fda and -hda(and a smal VGA issue) https://forum.osdev.org/viewtopic.php?f=1&t=33419 |
Page 1 of 1 |
Author: | FATTOMCAT [ Sun Jan 06, 2019 9:51 am ] |
Post subject: | qemu differences between -fda and -hda(and a smal VGA issue) |
Im quiet newt in kernels and bootloaders. I recently wrote a basic bootloader and a kernel that should change colors in the VGA palette. The kernel doesnt make any problems runs perfectly but It does not change the colors as expectet. Since I was not able to find a mistake I tried to run the bootloader+kernel from a bootstick on my machine. I got a blackscreen and a blinking cursor. So I decided to use a gui tool for writing the bootstick ("usb-creator-gtk"), I used it to write my img file to the stick and then tested it using qemu as the program asked me to do. The bootloader was not able to load the kernel. (qemu-system-x86_64 -hda /dev/sdc) But if I use qemu-system-x86_64 -fda /dev/sdc the kernel gets loaded and works (except the VGA palette). How I load the kernel code : Code: load_kernel_dx_drive_sectors: xor ax, ax;set zero mov es, ax;ser es zero mov bx, 0x9000 ;(es:bx) push dx ;backup input data (dl=BOOT_DRIVE, dh=SECTORS) mov ah, 0x02 ;13h : read from disk mov al, dh ; read dh sectors mov ch, 0x00 ; cylinder 0 mov dh, 0x00 ; head 0 mov cl, 0x02 ; start reading from the 2nd cylinder (skip boot sector) int 13h ; EXECUTE Then it jumps to .error and the screen gets "purple" Code: jc .error; error (carryflag not set) --> red screen pop dx cmp dh, al ; al = sectors read --> if not as expected then : ERROR jne .error2 push 0x0d; push 320*200 call clearScreen_char_n add esp, 4 ret .error: push 0x0d; push 320*200 call clearScreen_char_n add esp, 4 ret .error2: push 0x0f; push 320*200 call clearScreen_char_n add esp, 4 ret The Way I compile: Code: nasm boot.asm -f bin -o boot.bin nasm -f elf32 kernel.asm -o kasm.o gcc -w -g -m32 -c -ffreestanding -o kernel.o kernel.c -lgcc ld -melf_i386 -Tlinker.ld -nostdlib --nmagic -o kernel.elf kernel.o kasm.o objcopy -O binary kernel.elf kernel.bin dd if=/dev/zero of=disk.img bs=512 count=2880 dd if=boot.bin of=disk.img bs=512 conv=notrunc dd if=kernel.bin of=disk.img bs=512 seek=1 conv=notrunc My linker script : Code: OUTPUT_FORMAT(elf32-i386) ENTRY(main) SECTIONS { . = 0x9000; .text : { *(.text) } .data : { *(.data) } .bss : { *(.bss) *(COMMON) } } I think It does not matter but to be sure, how I change the palette: Code: void writeVGA_DAC_color(char index, char r, char g, char b){ write_port(0x3C6, 0b11111111); write_port(0x3C8, index); write_port(0x3C9, r); write_port(0x3C9, g); write_port(0x3C9, b); } I hope someone can explain that behaviour to me/tell me what I do wrong. Thanks in advance. |
Author: | ~ [ Sun Jan 06, 2019 11:08 am ] |
Post subject: | Re: qemu differences between -fda and -hda(and a smal VGA is |
From Tutorial 2 of Denthor of Asphixia (TUT2.TXT): http://planet-source-code.com/vb/script ... 1&lngWId=3 0x3C8 is the palette color index write port. 0x3C9 is the 3-byte RGB register for the current color index. Code: Procedure WritePalette(ColorNum: Byte; R,G,B: Byte);
{ It writes the values of Red, Green and Blue for a given color } Begin Port[$3C8] := ColorNum; Port[$3C9] := R; Port[$3C9] := G; Port[$3C9] := B; End; |
Author: | MichaelPetch [ Sun Jan 06, 2019 12:46 pm ] |
Post subject: | Re: qemu differences between -fda and -hda(and a smal VGA is |
Regarding the issue of booting from a USB stick (and not the palette). I assume you it gave you a blank screen and cursor on real hardware? If so, were you booting your USB using FDD (Floppy Disk Emulation). This is likely a setting in the BIOS. If it is FDD then the reason it may not have worked is because of not having a BIOS Parameter Block(BPB). You might want to see my Stackoverflow Answer to see if this might have been part of the problem. If you didn't properly initialize your segments to what you need (rather on relying on values set by the BIOS before transferring to your bootloader) that could cause problems as well. Unfortunately it is hard to tell because you only show snippets of code, and not everything. |
Author: | FATTOMCAT [ Sun Jan 06, 2019 1:11 pm ] |
Post subject: | Re: qemu differences between -fda and -hda(and a smal VGA is |
I found out what was wrong with my code. I used x00 as bootdrive which apears to only work for floppys (-fda), I changed to 0x80 for harddrives (-hda) and the bootstick booted perfectly (on real hardware too). The only thing that remains is the palette which Im currently working on. |
Author: | MichaelPetch [ Sun Jan 06, 2019 2:14 pm ] |
Post subject: | Re: qemu differences between -fda and -hda(and a smal VGA is |
You don't need to hard code the boot drive. When the BIOS transfers control to your bootloader it will set DL to the drive that was booted on. If you just use the value passed by the BIOS in DL then you can avoid hard coding a value like 0x00, 0x80, 0x81 etc. |
Author: | FATTOMCAT [ Sun Jan 06, 2019 2:18 pm ] |
Post subject: | Re: qemu differences between -fda and -hda(and a smal VGA is |
Ok, I'll give it a try. Thanks I have tried it it works with qemu but not on my computer (just a black screen with blinking cursor). One more edit : It works now whit the "automatic" dl. I didn't have a BPB. |
Author: | FATTOMCAT [ Sun Jan 06, 2019 3:34 pm ] |
Post subject: | Re: qemu differences between -fda and -hda(and a smal VGA is |
To the Palette: I followed the steps in the tutorial posted by "~" as closely as possible but my color does not change. The stuff i produced : Code: extern void write_port(unsigned char port, unsigned char value); void fill(int color){ volatile unsigned char * video_ptr = (volatile unsigned char *) VIDEO_PTR; int counter =0; while(counter < 320*200){ video_ptr[counter] = color; counter ++; } } void writeVGA_DAC_color(unsigned char index, unsigned char r, unsigned char g, unsigned char b){ write_port((unsigned char)0x3C6, 0b11111111); //init DAC mask write_port((unsigned char)0x3C8, index); write_port((unsigned char)0x3C9, r); write_port((unsigned char)0x3C9, g); write_port((unsigned char)0x3C9, b); } void drawHorizontalLine(int x, int y, int length, unsigned char color){ volatile unsigned char * video_ptr = (volatile unsigned char *) VIDEO_PTR; int pos = 320*y + x; int counter = 0; while(counter < length){ video_ptr[pos] = color; pos ++; counter ++; } } void drawVerticalLine(int x, int y, int length, unsigned char color){ volatile unsigned char * video_ptr = (volatile unsigned char *) VIDEO_PTR; int pos = 320*y + x; int counter = 0; while(counter < length){ video_ptr[pos] = color; pos += 320; counter ++; } } asm : Code: write_port: mov edx, [esp + 4] ; push argument 1 to edx mov al, [esp + 4 + 4] ; push argument 2 to al (lower output) out dx, al ; write al to port dx ret The main function : Code: void main(){
//unsigned char * result; //volatile unsigned char * video_ptr = (volatile unsigned char *) VIDEO_PTR; fill(0xf7); drawVerticalLine(30, 100, 50, 0x09); drawHorizontalLine(30, 100, 200, 0x09); writeVGA_DAC_color(0x09, 0b11111111, 0, 0);//doesn't work drawVerticalLine(30, 100, 50, 0x09); drawHorizontalLine(30, 100, 200, 0x09); return; } |
Author: | ~ [ Sun Jan 06, 2019 6:07 pm ] |
Post subject: | Re: qemu differences between -fda and -hda(and a smal VGA is |
Try to remove this line. This is the PEL Mask Register. It's supposed to be already initialized by the BIOS. You need to study carefully the video mode you intend to use (whether has planes or not, memory organization, start video address, whether it uses a pallete): Code: write_port((unsigned char)0x3C6, 0b11111111); //init DAC mask If it doesn't work, try to produce functions identical to the ones from Denthor's TUT2.TXT in addition to yours. Run it at least under DOSBox, extract the functions and try them. If not, something else happens with your video mode. They should work. The link I posted seems to have them in C, assembly and Pascal. |
Author: | ~ [ Mon Jan 07, 2019 8:41 am ] | ||
Post subject: | qemu differences between -fda and -hda(and a smal VGA issue) | ||
Try the attached EXE/C demo file for a cleaner way to handle the standard 256-color VGA palette. Code: #include <stdio.h>
#include <dos.h> #include <stdlib.h> /* Functions: --------------------------------------------- void VGA_ModifyPalette256Color( unsigned char Color0_255, unsigned char *RGB ); Modifies a single color in the VGA's 256-color palette, a color index from 0 to 255. The function needs a char array with 3 elements to hold the RGB value. --------------------------------------------- void VGA_BIOS_enter_mode13h(void) Enter the VGA/MCGA BIOS graphics mode 13h 320x200x256-color. --------------------------------------------- void VGA_BIOS_enter_mode03h(void) Enter the MCGA BIOS text mode 03h 80x25x16-color. --------------------------------------------- void VGA_palette256_test_320x200_pixel_screen() Tests the BIOS mode 13h mode by increasing in 1 each pixel value for the 64000 visible bytes (320*200) starting at physical address 0xA0000. --------------------------------------------- unsigned char CMOS_read(unsigned char idx) Reads a value from the CMOS memory. The index can be between 0 to 255. Find a CMOS map to know what data is located at each CMOS position, for example at http://www.bioscentral.com/misc/cmosmap.htm --------------------------------------------- void VGA_test_random_palette256() Tries to generate a random palette to demonstrate changing random colors from it. --------------------------------------------- */ /* Implementation Write a byte value to port 0x3C8 to set the 256-color palette index that we want to write. Then write port 0x3C9 3 consecutive times with 1 byte to set the RGB values. Each palette value only uses 6 effective bits (values 0 to 63). The combination of RGB for the VGA results in a 18-bit color that adjusts the screen from darkness to full white for each color in the 256-color palette. Port 0x3C8 -- PEL Addres Write Mode Register Port 0x3C9 -- PEL Data Register */ void VGA_ModifyPalette256Color( unsigned char Color0_255, unsigned char *RGB ) { outportb(0x3C8,Color0_255&0xFF); //Write byte: Index color 0-255 outportb(0x3C9,RGB[0]&63); //Write byte: Red outportb(0x3C9,RGB[1]&63); //Write byte: Green outportb(0x3C9,RGB[2]&63); //Write byte: Blue } /* Implementation mov ax,0x0013 int 10h Call BIOS INT 10h service 00h to set VGA/MCGA graphics mode 13h (320x200x256-color). */ void VGA_BIOS_enter_mode13h(void) { _AX = 0x0013; geninterrupt(0x10); } /* Implementation mov ax,0x0003 int 10h Call BIOS INT 10h service 00h to set VGA/MCGA text mode 03h (80x25x16-color). */ void VGA_BIOS_enter_mode03h(void) { _AX = 0x0003; geninterrupt(0x10); } //A single palette triplet: /// unsigned char _RGB[3]; //A generic pointer to the start //of memory for a given VGA mode: /// unsigned char *vga; /* Implementation Point, with a C pointer, to physical address 0xA0000. Now inside a loop (while 0) we will traverse index values 0 to 64000 for the 320*200 screen. Write the the test byte (char) pixel color at address (vga_start+while0_index). Increase the test pixel color in 1. Increase the while 0 index in 1. Here ends the while 0 loop. */ void VGA_palette256_test_320x200_pixel_screen() { //This index x needs to be unsigned int or //unsigned long, wideword, or uwide_t //for compatibility with 16-bit compilers: /// unsigned int x=0; char test_pixel_color=0; //Write the whole screen increasing the //pixel color: /// while(x<64000) //while 0 START { *(vga+x)=test_pixel_color; //Write pixel test_pixel_color++; //Increase pixel color index in 1 (0-255) x++; //Increase 320x200 screen position } //while 0 END } /* Implementation Pass an 8-bit index value in a byte argument to specify which CMOS memory position we want to read. Write the byte index value to port 0x70. Read the byte value at that index address from the CMOS from port 0x71. Return the contents of the CMOS byte at that position as an unsigned char. */ unsigned char CMOS_read(unsigned char idx) { unsigned char toRet=0; outportb(0x70,idx); toRet=inportb(0x71); return toRet; } /* Implementation Work only with unsigned integers since we want to have at least a range of 0 to 65535 even with 16-bit compilers. Create a random value from the values that change constantly in the CMOS by constantly adding the values for RTC seconds, RTC minutes, RTC hours, RTC day of week, RTC data day, RTC date month, RTC date year (CMOS positions 0, 2, 4, 6, 7, 8, 9). Read those values through a random-generating function and add them all, and also add them directly, also adding the previous value in the CMOS "random" value with += for the full expression. Also generate a random pixel start unsigned integer by adding the value of a random-generating function and the CMOS random value. The while 0 loop index must start randomly between 0 and 127 for added randomness. Now, inside a loop (while 0), we will generate the RGB triplet values as randomly as possible, and then we will modify each palette index from a random start to 255. The R, G and B components will use the exact same CMOS_rand expression, but we will duplicate it so that each component, each time, can be as random as possible, specially because the random functions from Turbo C (at least 1.01) aren't truly random. They seem to produce the same random value always once the program is compiled, so we must use the dynamic values from the CMOS and long delaying for more randomness based on the Real Time Clock (RTC). For each component, RGB[0], RGB[1] and RGB[2], think up on any expressions that result in highly random values. After setting each of them, call delay() or equivalent with a value between 10 and 30 milliseconds for making the CMOS randomness have more effect. Now write the color by calling our function to modify the effective color of a single color index of the 256-color VGA palette. For calling it, employ the same randomizing expression for CMOS_rand, duplicating it again, and limiting it to 0-255 by ANDing with 0xFF to write random palette positions instead of modifying it sequentially. Increase the while 0 index, which goes from a random start to 255. Here ends the while 0 loop. */ void VGA_test_random_palette256() { unsigned int x; unsigned int rand_pixel_start; unsigned int CMOS_rand; CMOS_rand+=CMOS_read(0)+CMOS_read(2)+CMOS_read(4)+CMOS_read(6)+CMOS_read(7)+CMOS_read(8)+CMOS_read(9)+random(CMOS_read(0))+random(CMOS_read(2))+random(CMOS_read(4))+random(CMOS_read(6))+random(CMOS_read(7))+random(CMOS_read(8))+random(CMOS_read(9)); rand_pixel_start=rand()+CMOS_rand; x=(CMOS_rand)&0x7F; while(x<256) //while 0 START { //R CMOS_rand+=CMOS_read(0)+CMOS_read(2)+CMOS_read(4)+CMOS_read(6)+CMOS_read(7)+CMOS_read(8)+CMOS_read(9)+random(CMOS_read(0))+random(CMOS_read(2))+random(CMOS_read(4))+random(CMOS_read(6))+random(CMOS_read(7))+random(CMOS_read(8))+random(CMOS_read(9)); _RGB[0]=CMOS_rand+rand_pixel_start&63; delay(10); //G CMOS_rand+=CMOS_read(0)+CMOS_read(2)+CMOS_read(4)+CMOS_read(6)+CMOS_read(7)+CMOS_read(8)+CMOS_read(9)+random(CMOS_read(0))+random(CMOS_read(2))+random(CMOS_read(4))+random(CMOS_read(6))+random(CMOS_read(7))+random(CMOS_read(8))+random(CMOS_read(9)); _RGB[1]=CMOS_rand+rand()&63; delay(20); //B CMOS_rand+=CMOS_read(0)+CMOS_read(2)+CMOS_read(4)+CMOS_read(6)+CMOS_read(7)+CMOS_read(8)+CMOS_read(9)+random(CMOS_read(0))+random(CMOS_read(2))+random(CMOS_read(4))+random(CMOS_read(6))+random(CMOS_read(7))+random(CMOS_read(8))+random(CMOS_read(9)); _RGB[2]=CMOS_rand+(rand_pixel_start>>1)&63; delay(30); //Write color triplet in the VGA CMOS_rand+=CMOS_read(0)+CMOS_read(2)+CMOS_read(4)+CMOS_read(6)+CMOS_read(7)+CMOS_read(8)+CMOS_read(9)+random(CMOS_read(0))+random(CMOS_read(2))+random(CMOS_read(4))+random(CMOS_read(6))+random(CMOS_read(7))+random(CMOS_read(8))+random(CMOS_read(9)); VGA_ModifyPalette256Color((unsigned char)(x+CMOS_rand)&0xFF,_RGB); x++; } //while 0 END } /* Implementation Set a VGA start pointer to physical address 0xA0000 to address bytes or chars. Enter mode 13h with the BIOS. Print a message telling the user to press ENTER to watch a sequential screen write demo for 320x200x256-color graphics mode. After pressing ENTER, show the user another message asking to press ENTER again to watch a demostration of changing the VGA 256-color palette randomly. Show the demo and wait for the user to press ENTER. When the user presses ENTER, return to 80x25 text mode 03h with the BIOS. Show a message saying that the demo has ended and wait for the user to press ENTER one last time to exit the program. */ int main(void) { //Point to the base of memory for //graphics mode 13h, located at //flat address 0xA0000: /// vga = MK_FP(0xA000, 0); //Enter graphics mode 13h 320x200x256-color VGA/MCGA //and display a message with the DOS C library //from Turbo C: /// VGA_BIOS_enter_mode13h(); printf("Press ENTER to test the default palette\n"); getchar(); VGA_palette256_test_320x200_pixel_screen(); getchar(); //Change the palette randomly //and test again the result: /// printf("Press ENTER to test a random palette\n"); getchar(); VGA_test_random_palette256(); VGA_palette256_test_320x200_pixel_screen(); getchar(); //Return to text mode 03h 80x25x16-color //MCGA and display a message with the //DOS C library from Turbo C: /// VGA_BIOS_enter_mode03h(); printf("Ended\n"); getchar(); return 0; } //Se ve como si aumentaran en 1 cada pixel //en una paleta de 256 colores con suficiente //diferencia entre cada color de la paleta. //The graphic of the code looks like it increases //by 1 each pixel value in a 256-color palette //with enough difference between each palette //color. //El fuego se ve como... (al analizar el algoritmo //para ver cómo se va formando); un efecto de haz de luz //afilado pero desenfocado (como el de Expert Software) se ve como...
|
Author: | Combuster [ Mon Jan 07, 2019 9:57 am ] |
Post subject: | Re: qemu differences between -fda and -hda(and a smal VGA is |
Code: writeVGA_DAC_color(0x09, 0b11111111, 0, 0);//doesn't work The DAC has 3x 6-bit registers. That's an 8-bit value.
|
Page 1 of 1 | All times are UTC - 6 hours |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |