/*
* $Id$
*
* Copyright (C) 2003-2015 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.driver.video.vesa;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.ByteBuffer;
import javax.naming.NameNotFoundException;
import org.jnode.naming.InitialNaming;
import org.jnode.system.resource.MemoryResource;
import org.jnode.system.resource.ResourceManager;
import org.jnode.system.resource.ResourceNotFreeException;
import org.jnode.system.resource.ResourceOwner;
import org.jnode.system.resource.SimpleResourceOwner;
import org.jnode.util.NumberUtils;
import org.jnode.vm.Unsafe;
import org.jnode.vm.scheduler.VmProcessor;
import org.vmmagic.unboxed.Address;
import org.vmmagic.unboxed.ObjectReference;
/**
*
* @author Fabien DUMINY (fduminy at jnode.org)
*
*/
public class VESACommand {
private static ResourceManager manager;
private static ResourceOwner owner = new SimpleResourceOwner("VESACommand");
private static void print(String message) {
// Unsafe.debug(message);
}
private static void println(String message) {
print(message + "\n");
}
private static void printError(String message) {
println(message);
}
public static void main(String[] args) throws NameNotFoundException, ResourceNotFreeException {
println("VESA detected : " + detect());
}
public static ByteBuffer getBiosMemory() throws NameNotFoundException, ResourceNotFreeException {
// steps 1 & 2 : allocate new buffer and copy the bios image to it
manager = InitialNaming.lookup(ResourceManager.NAME);
Address start = Address.fromInt(0xC0000);
// int size = 0x8000; // 32 Kb
int size = 0x10000; // 64 Kb
int mode = ResourceManager.MEMMODE_NORMAL;
MemoryResource resource = manager.claimMemoryResource(owner, start, size, mode);
ByteBuffer buffer = null;
try {
buffer = ByteBuffer.allocate(size);
for (int i = 0; i < size; i++) {
buffer.put(resource.getByte(i));
}
buffer.rewind();
} finally {
resource.release();
}
return buffer;
}
public static PMInfoBlock detect() throws NameNotFoundException, ResourceNotFreeException {
ByteBuffer biosMemory = getBiosMemory();
// step 3 : scan to the bios image to find signature and check the
// validity of the checksum
final int signatureLength = 4;
PMInfoBlock pmInfoBlock = null;
for (int offset = 0; offset < biosMemory.limit() - (signatureLength - 1); offset++) {
int pos = biosMemory.position() + 1;
boolean p = (biosMemory.get() == (byte) 'P');
boolean m = (biosMemory.get() == (byte) 'M');
boolean i = (biosMemory.get() == (byte) 'I');
boolean d = (biosMemory.get() == (byte) 'D');
/*
* byte b0 = biosMemory.get(); boolean p = (b0 == (byte)'P') || (b0 ==
* (byte)'D'); byte b = biosMemory.get(); boolean m = (b ==
* (byte)'M') || (b == (byte)'I'); b = biosMemory.get(); boolean i =
* (b == (byte)'I') || (b == (byte)'M'); b = biosMemory.get();
* boolean d = (b == (byte)'D') || (b == (byte)'P');
*/
if (p) {
// println("offset="+NumberUtils.hex(offset)+" value="+b+"
// p="+p+" m="+m+" i="+i+" d="+d);
// println("offset="+NumberUtils.hex(offset)+" p="+p+" m="+m+"
// i="+i+" d="+d);
}
if (p && m && i && d) {
println("signature detected at offset " + NumberUtils.hex(offset));
byte checksum = (byte) (((byte) 'P') + ((byte) 'M') + ((byte) 'I') + ((byte) 'D'));
// int size = 7 * 4 + 2 * 1;
int size = 7 * 2 + 2 * 1;
for (int offs = 0; offs < size; offs++) {
checksum += (byte) biosMemory.get();
println("at offset " + NumberUtils.hex(offs) + " checksum=" + checksum);
}
if (checksum == 0) {
println("found correct checksum");
biosMemory.position(pos + 3).limit();
pmInfoBlock = new PMInfoBlock(biosMemory);
break;
} else {
printError("bad checksum");
}
}
biosMemory.position(pos);
}
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
VmProcessor.current().dumpStatistics(out);
System.out.println("after dumpStatistics");
if (pmInfoBlock != null) {
System.out.println("step4");
// step 4
byte[] biosDataSel = new byte[0x600]; // should be filled with
// zeros by the VM
println("step4.1");
short selector = getSelector(biosDataSel);
println("step4.2");
pmInfoBlock.setBiosDataSel(selector);
println("step5");
// step 5
int size = 0x7FFF; // 32 Kb
int mode = ResourceManager.MEMMODE_NORMAL;
int address = 0xA0000;
@SuppressWarnings("unused")
MemoryResource resource =
manager.claimMemoryResource(owner, Address.fromInt(address), size, mode);
println("....");
println("....");
println("before call to vbe function");
int codePtr = pmInfoBlock.getEntryPoint();
println("codePtr=" + NumberUtils.hex(codePtr));
// FIXME ... if the javadoc for 'Unsafe.callVbeFunction' is credible, this is a
// bad thing to do.
int result =
Unsafe.callVbeFunction(Address.fromInt(codePtr), 0, Address.fromInt(address));
println("codePtr=" + result);
}
return pmInfoBlock;
}
public static short getSelector(Address address) {
println("getSelector point 1");
long addr = address.toLong();
println("getSelector point 2");
short result = (short) ((addr & 0xFFFFFFFF00000000L) >> 32);
println("getSelector point 3");
return result;
}
private static short getSelector(Object obj) {
println("getSelector point A");
if (obj == null)
return -1;
println("getSelector point B");
ObjectReference objRef = ObjectReference.fromObject(obj);
println("getSelector point C");
return (objRef == null) ? null : getSelector(objRef.toAddress());
}
}