2019-01-07 17:25:22 +01:00
|
|
|
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
|
|
|
*
|
2019-01-07 18:40:12 +01:00
|
|
|
* Copyright 2014-2017, Teo Mrnjavac <teo@kde.org>
|
|
|
|
* Copyright 2017-2018, Adriaan de Groot <groot@kde.org>
|
2019-01-07 17:25:22 +01:00
|
|
|
* Copyright 2018, Collabora Ltd
|
|
|
|
*
|
|
|
|
* Calamares is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* Calamares 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 General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2019-02-22 12:58:55 +01:00
|
|
|
#include "GlobalStorage.h"
|
|
|
|
#include "JobQueue.h"
|
|
|
|
|
2019-01-07 17:25:22 +01:00
|
|
|
#include "core/PartitionLayout.h"
|
|
|
|
|
2019-01-07 17:26:37 +01:00
|
|
|
#include "core/KPMHelpers.h"
|
|
|
|
#include "core/PartitionActions.h"
|
|
|
|
#include "core/PartitionInfo.h"
|
2019-02-22 18:42:16 +01:00
|
|
|
#include "core/PartUtils.h"
|
2019-01-07 17:26:37 +01:00
|
|
|
|
|
|
|
#include <kpmcore/core/device.h>
|
|
|
|
#include <kpmcore/core/partition.h>
|
2019-01-07 17:25:22 +01:00
|
|
|
#include <kpmcore/fs/filesystem.h>
|
|
|
|
|
2019-02-22 18:42:16 +01:00
|
|
|
static FileSystem::Type
|
2019-02-22 12:58:55 +01:00
|
|
|
getDefaultFileSystemType()
|
|
|
|
{
|
|
|
|
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
|
2019-02-22 18:42:16 +01:00
|
|
|
FileSystem::Type defaultFS = FileSystem::Ext4;
|
2019-02-22 12:58:55 +01:00
|
|
|
|
2019-02-22 18:42:16 +01:00
|
|
|
if ( gs->contains( "defaultFileSystemType" ) )
|
|
|
|
{
|
|
|
|
PartUtils::findFS( gs->value( "defaultFileSystemType" ).toString(), &defaultFS);
|
|
|
|
if ( defaultFS == FileSystem::Unknown )
|
|
|
|
defaultFS = FileSystem::Ext4;
|
|
|
|
}
|
2019-02-22 12:58:55 +01:00
|
|
|
|
2019-02-22 18:42:16 +01:00
|
|
|
return defaultFS;
|
2019-02-22 12:58:55 +01:00
|
|
|
}
|
|
|
|
|
2019-01-07 17:25:22 +01:00
|
|
|
PartitionLayout::PartitionLayout()
|
|
|
|
{
|
2019-02-22 13:08:59 +01:00
|
|
|
m_defaultFsType = getDefaultFileSystemType();
|
2019-01-07 17:25:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
PartitionLayout::PartitionLayout( PartitionLayout::PartitionEntry entry )
|
|
|
|
{
|
2019-02-22 13:08:59 +01:00
|
|
|
m_defaultFsType = getDefaultFileSystemType();
|
|
|
|
m_partLayout.append( entry );
|
2019-01-07 17:25:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
PartitionLayout::PartitionLayout( const PartitionLayout& layout )
|
2019-02-22 13:08:59 +01:00
|
|
|
: m_partLayout( layout.m_partLayout )
|
|
|
|
, m_defaultFsType( layout.m_defaultFsType )
|
2019-01-07 17:25:22 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
PartitionLayout::~PartitionLayout()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PartitionLayout::addEntry( PartitionLayout::PartitionEntry entry )
|
|
|
|
{
|
2019-02-22 13:08:59 +01:00
|
|
|
m_partLayout.append( entry );
|
2019-01-07 17:25:22 +01:00
|
|
|
}
|
|
|
|
|
2019-02-11 23:37:14 +01:00
|
|
|
PartitionLayout::PartitionEntry::PartitionEntry(const QString& size, const QString& min)
|
|
|
|
{
|
2019-02-28 13:18:02 +01:00
|
|
|
partSize = PartUtils::parseSizeString( size , &partSizeUnit );
|
2019-02-11 23:37:14 +01:00
|
|
|
if ( !min.isEmpty() )
|
2019-02-28 13:18:02 +01:00
|
|
|
partMinSize = PartUtils::parseSizeString( min , &partMinSizeUnit );
|
2019-02-11 23:37:14 +01:00
|
|
|
}
|
|
|
|
|
2019-01-07 17:25:22 +01:00
|
|
|
void
|
2019-02-11 23:27:45 +01:00
|
|
|
PartitionLayout::addEntry( const QString& mountPoint, const QString& size, const QString& min )
|
2019-01-07 17:25:22 +01:00
|
|
|
{
|
2019-02-11 23:37:14 +01:00
|
|
|
PartitionLayout::PartitionEntry entry( size, min );
|
2019-01-07 17:25:22 +01:00
|
|
|
|
|
|
|
entry.partMountPoint = mountPoint;
|
2019-02-22 13:08:59 +01:00
|
|
|
entry.partFileSystem = m_defaultFsType;
|
2019-01-07 17:25:22 +01:00
|
|
|
|
2019-02-22 13:08:59 +01:00
|
|
|
m_partLayout.append( entry );
|
2019-01-07 17:25:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-02-11 23:27:45 +01:00
|
|
|
PartitionLayout::addEntry( const QString& label, const QString& mountPoint, const QString& fs, const QString& size, const QString& min )
|
2019-01-07 17:25:22 +01:00
|
|
|
{
|
2019-02-11 23:37:14 +01:00
|
|
|
PartitionLayout::PartitionEntry entry( size, min );
|
2019-01-07 17:25:22 +01:00
|
|
|
|
|
|
|
entry.partLabel = label;
|
|
|
|
entry.partMountPoint = mountPoint;
|
2019-02-22 18:42:16 +01:00
|
|
|
PartUtils::findFS( fs, &entry.partFileSystem );
|
2019-02-22 12:58:55 +01:00
|
|
|
if ( entry.partFileSystem == FileSystem::Unknown )
|
2019-02-22 13:08:59 +01:00
|
|
|
entry.partFileSystem = m_defaultFsType;
|
2019-01-07 17:25:22 +01:00
|
|
|
|
2019-02-22 13:08:59 +01:00
|
|
|
m_partLayout.append( entry );
|
2019-01-07 17:25:22 +01:00
|
|
|
}
|
2019-01-07 17:26:37 +01:00
|
|
|
|
|
|
|
static qint64
|
|
|
|
sizeToSectors( double size, PartitionLayout::SizeUnit unit, qint64 totalSize, qint64 logicalSize )
|
|
|
|
{
|
|
|
|
qint64 sectors;
|
|
|
|
double tmp;
|
|
|
|
|
|
|
|
if ( unit == PartitionLayout::SizeUnit::Percent )
|
|
|
|
{
|
|
|
|
tmp = static_cast<double>( totalSize ) * size / 100;
|
|
|
|
sectors = static_cast<qint64>( tmp );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tmp = size;
|
|
|
|
if ( unit >= PartitionLayout::SizeUnit::KiB )
|
|
|
|
tmp *= 1024;
|
|
|
|
if ( unit >= PartitionLayout::SizeUnit::MiB )
|
|
|
|
tmp *= 1024;
|
|
|
|
if ( unit >= PartitionLayout::SizeUnit::GiB )
|
|
|
|
tmp *= 1024;
|
|
|
|
|
|
|
|
sectors = PartitionActions::bytesToSectors( static_cast<unsigned long long>( tmp ),
|
|
|
|
logicalSize
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return sectors;
|
|
|
|
}
|
|
|
|
|
|
|
|
QList< Partition* >
|
|
|
|
PartitionLayout::execute( Device *dev, qint64 firstSector,
|
2019-01-07 17:27:12 +01:00
|
|
|
qint64 lastSector, QString luksPassphrase,
|
|
|
|
PartitionNode* parent,
|
|
|
|
const PartitionRole& role )
|
2019-01-07 17:26:37 +01:00
|
|
|
{
|
|
|
|
QList< Partition* > partList;
|
|
|
|
qint64 size, minSize, end;
|
2019-01-08 14:05:38 +01:00
|
|
|
qint64 totalSize = lastSector - firstSector + 1;
|
2019-01-07 17:26:37 +01:00
|
|
|
qint64 availableSize = totalSize;
|
|
|
|
|
|
|
|
// TODO: Refine partition sizes to make sure there is room for every partition
|
|
|
|
// Use a default (200-500M ?) minimum size for partition without minSize
|
|
|
|
|
2019-02-22 13:08:59 +01:00
|
|
|
foreach( const PartitionLayout::PartitionEntry& part, m_partLayout )
|
2019-01-07 17:26:37 +01:00
|
|
|
{
|
|
|
|
Partition *currentPartition = nullptr;
|
|
|
|
|
|
|
|
// Calculate partition size
|
|
|
|
size = sizeToSectors( part.partSize, part.partSizeUnit, totalSize, dev->logicalSize() );
|
|
|
|
minSize = sizeToSectors( part.partMinSize, part.partMinSizeUnit, totalSize, dev->logicalSize() );
|
|
|
|
if ( size < minSize )
|
|
|
|
size = minSize;
|
|
|
|
if ( size > availableSize )
|
|
|
|
size = availableSize;
|
2019-01-08 14:05:38 +01:00
|
|
|
end = firstSector + size - 1;
|
2019-01-07 17:26:37 +01:00
|
|
|
|
|
|
|
if ( luksPassphrase.isEmpty() )
|
|
|
|
{
|
|
|
|
currentPartition = KPMHelpers::createNewPartition(
|
2019-01-07 17:27:12 +01:00
|
|
|
parent,
|
2019-01-07 17:26:37 +01:00
|
|
|
*dev,
|
2019-01-07 17:27:12 +01:00
|
|
|
role,
|
2019-02-22 18:42:16 +01:00
|
|
|
part.partFileSystem,
|
2019-01-07 17:26:37 +01:00
|
|
|
firstSector,
|
|
|
|
end,
|
|
|
|
PartitionTable::FlagNone
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
currentPartition = KPMHelpers::createNewEncryptedPartition(
|
2019-01-07 17:27:12 +01:00
|
|
|
parent,
|
2019-01-07 17:26:37 +01:00
|
|
|
*dev,
|
2019-01-07 17:27:12 +01:00
|
|
|
role,
|
2019-02-22 18:42:16 +01:00
|
|
|
part.partFileSystem,
|
2019-01-07 17:26:37 +01:00
|
|
|
firstSector,
|
|
|
|
end,
|
|
|
|
luksPassphrase,
|
|
|
|
PartitionTable::FlagNone
|
|
|
|
);
|
|
|
|
}
|
|
|
|
PartitionInfo::setFormat( currentPartition, true );
|
|
|
|
PartitionInfo::setMountPoint( currentPartition, part.partMountPoint );
|
|
|
|
if ( !part.partLabel.isEmpty() )
|
|
|
|
currentPartition->fileSystem().setLabel( part.partLabel );
|
|
|
|
// Some buggy (legacy) BIOSes test if the bootflag of at least one partition is set.
|
|
|
|
// Otherwise they ignore the device in boot-order, so add it here.
|
|
|
|
partList.append( currentPartition );
|
|
|
|
firstSector = end + 1;
|
|
|
|
availableSize -= size;
|
|
|
|
}
|
|
|
|
|
|
|
|
return partList;
|
|
|
|
}
|