/*
* $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.fs.fat;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import org.jnode.driver.block.BlockDeviceAPI;
import org.jnode.driver.block.Geometry;
import org.jnode.util.FileUtils;
import org.jnode.util.LittleEndian;
/**
* @author epr
*/
public class GrubFatFormatter {
private byte[] stage1;
private byte[] stage2;
private int bootSectorOffset;
private String configFile;
private int installPartition = 0xFFFFFFFF;
private FatFormatter formatter;
/**
* @param bps
* @param spc
* @param geom
* @param fatSize
*/
public GrubFatFormatter(int bps, int spc, Geometry geom, FatType fatSize, int bootSectorOffset,
String stage1ResourceName, String stage2ResourceName) {
GrubBootSector bs =
(GrubBootSector) createBootSector(stage1ResourceName, stage2ResourceName);
bs.setOemName("JNode1.0");
formatter =
FatFormatter.HDFormatter(bps, (int) geom.getTotalSectors(), geom.getSectors(), geom
.getHeads(), fatSize, 0, calculateReservedSectors(512), bs);
this.bootSectorOffset = bootSectorOffset;
}
private int calculateReservedSectors(int bps) {
return stage2.length / bps + 1 + 1;
}
/**
* Constructor for GrubFatFormatter.
*
* @param bootSectorOffset
* @param stage1ResourceName
* @param stage2ResourceName
*/
public GrubFatFormatter(int bootSectorOffset, String stage1ResourceName,
String stage2ResourceName) {
GrubBootSector bs =
(GrubBootSector) createBootSector(stage1ResourceName, stage2ResourceName);
bs.setOemName("JNode1.0");
formatter = FatFormatter.fat144FloppyFormatter(calculateReservedSectors(512), bs);
this.bootSectorOffset = bootSectorOffset;
}
/**
* Create the actual bootsector.
*/
private BootSector createBootSector(String stage1Name, String stage2Name) {
if (stage1Name == null) {
stage1Name = "stage1";
}
if (stage2Name == null) {
stage2Name = "stage2";
}
try {
getStage1(stage1Name);
getStage2(stage2Name);
return new GrubBootSector(stage1);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
public byte[] getStage1(String stage1ResourceName) throws IOException {
if (stage1 == null) {
InputStream is = getClass().getClassLoader().getResourceAsStream(stage1ResourceName);
byte[] buf = new byte[512];
FileUtils.copy(is, buf);
is.close();
stage1 = buf;
}
return stage1;
}
public byte[] getStage2(String stage2ResourceName) throws IOException {
if (stage2 == null) {
URL stage2URL = getClass().getClassLoader().getResource(stage2ResourceName);
URLConnection conn = stage2URL.openConnection();
byte[] buf = new byte[conn.getContentLength()];
InputStream is = conn.getInputStream();
FileUtils.copy(is, buf);
is.close();
stage2 = buf;
}
return stage2;
}
/**
* @see org.jnode.fs.fat.FatFormatter#format(BlockDeviceAPI)
*/
public void format(BlockDeviceAPI api) throws IOException {
formatter.format(api);
GrubBootSector bs = (GrubBootSector) formatter.getBootSector();
/* Fixup the blocklist end the end of the first sector of stage2 */
LittleEndian.setInt32(stage2, 512 - 8, bootSectorOffset + 2);
/* Fixup the install partition */
LittleEndian.setInt32(stage2, 512 + 0x08, installPartition);
/* Fixup the config file */
if (configFile != null) {
int ofs = 512 + 0x12;
while (stage2[ofs] != 0) {
ofs++;
}
ofs++; /* Skip '\0' */
for (int i = 0; i < configFile.length(); i++) {
stage2[ofs++] = (byte) configFile.charAt(i);
}
stage2[ofs] = 0;
}
/* Write stage2 */
api.write(bs.getBytesPerSector(), ByteBuffer.wrap(stage2));
}
/**
* @return String
*/
public String getConfigFile() {
return configFile;
}
/**
* Sets the configFile.
*
* @param configFile
* The configFile to set
*/
public void setConfigFile(String configFile) {
this.configFile = configFile;
}
/**
* @return int
*/
public int getInstallPartition() {
return installPartition;
}
public BootSector getBootSector() {
return formatter.getBootSector();
}
/**
* Sets the installPartition.
*
* @param installPartition
* The installPartition to set
*/
public void setInstallPartition(int installPartition) {
this.installPartition = installPartition;
}
}