Merge branch 'master' into sam460ex

This commit is contained in:
François Revol 2012-09-10 11:14:31 +02:00
commit 95540b8a19
19 changed files with 851 additions and 608 deletions

View File

@ -7,7 +7,7 @@ HAIKU_BOOT_PLATFORM = raspberrypi_arm ;
# Various hardcoded addresses
#
HAIKU_BOARD_LOADER_BASE = 0x32000000 ;
HAIKU_BOARD_LOADER_BASE = 0x0 ;
#
# Flash image

View File

@ -1,4 +1,5 @@
Setting up the Haiku boot partition
-------------------------------------
partition 1 -- FAT32, bootable flag, type 'c'
partition 2 -- BeFS, Haiku filesystem, type 'eb'
@ -7,7 +8,7 @@ The boot partition must contain the following files to boot Haiku:
* bootcode.bin : 2nd stage bootloader, starts with SDRAM disabled
* loader.bin : 3rd stage bootloader, starts with SDRAM enabled
* start.elf: The GPU binary firmware image, provided by the foundation.
* kernel.img: Haiku Loader (haiku_loader)
* haiku_loader: Haiku Loader
* config.txt: A configuration file read by the GPU.
Optional files:
@ -20,4 +21,13 @@ Additional GPU firmware images, rename over start.elf to use them:
- this is the default
* arm224_start.elf : 224M ARM, 32M GPU split
- (use this for Linux only with no 3D or video processing.
Its enough for the 1080p framebuffer, but not much else)
Enough for the 1080p framebuffer, but not much else)
Building
-------------------------------------
jam -q -sHAIKU_BOOT_BOARD=raspberry_pi -sHAIKU_BOOT_PLATFORM=raspberrypi_arm haiku_loader
config.txt options
-------------------------------------
kernel=haiku_loader
disable_commandline_tags=1

View File

@ -60,10 +60,6 @@ load_symbols true
#acpi false
# ACPI support, enabled by default
#acpi_avoid_full_init true
# Avoids running _INI and _STA methods and final object initialization,
# which may be used to for debugging ACPI issues, false by default
#disable_ioapic true
# Disables IO-APIC support, enabled by default

View File

@ -1,5 +1,5 @@
/*
* Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2004-2012, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
@ -12,6 +12,7 @@
#include <OS.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -27,6 +28,58 @@ int32 get_rounded_cpu_speed(void);
#endif
#if __INTEL__
/*! Tries to parse an Intel CPU ID string to match our usual naming scheme.
Note, this function is not thread safe, and must only be called once
at a time.
*/
static const char*
parse_intel(const char* name)
{
static char buffer[49];
// ignore initial spaces
int index = 0;
for (; name[index] != '\0'; index++) {
if (name[index] != ' ')
break;
}
// ignore vendor
for (; name[index] != '\0'; index++) {
if (name[index] == ' ') {
index++;
break;
}
}
// parse model
int outIndex = 0;
for (; name[index] != '\0'; index++) {
if (!strncmp(&name[index], "(R)", 3)) {
outIndex += strlcpy(&buffer[outIndex], "®",
sizeof(buffer) - outIndex);
index += 2;
} else if (!strncmp(&name[index], "(TM)", 4)) {
outIndex += strlcpy(&buffer[outIndex], "",
sizeof(buffer) - outIndex);
index += 3;
} else if (!strncmp(&name[index], " CPU", 4)) {
// Cut out the CPU string
index += 3;
} else if (!strncmp(&name[index], " @", 2)) {
// Cut off the remainder
break;
} else
buffer[outIndex++] = name[index];
}
buffer[outIndex] = '\0';
return buffer;
}
#endif
const char *
get_cpu_vendor_string(enum cpu_types type)
{
@ -61,7 +114,7 @@ get_cpu_vendor_string(enum cpu_types type)
#ifdef __INTEL__
/* Parameter 'name' needs to point to an allocated array of 49 characters. */
/*! Parameter 'name' needs to point to an allocated array of 49 characters. */
void
get_cpuid_model_string(char *name)
{
@ -345,6 +398,11 @@ get_cpu_model_string(system_info *info)
#endif /* __INTEL__ */
default:
if ((info->cpu_type & B_CPU_x86_VENDOR_MASK) == B_CPU_INTEL_x86) {
// Fallback to manual parsing of the model string
get_cpuid_model_string(cpuidName);
return parse_intel(cpuidName);
}
return NULL;
}
}

View File

@ -88,18 +88,14 @@ acpi_std_ops(int32 op,...)
ACPI_STATUS status;
ACPI_OBJECT arg;
ACPI_OBJECT_LIST parameter;
uint32 flags;
void *settings;
bool acpiDisabled = false;
bool acpiAvoidFullInit = false;
AcpiGbl_CopyDsdtLocally = true;
settings = load_driver_settings("kernel");
if (settings != NULL) {
acpiDisabled = !get_driver_boolean_parameter(settings, "acpi",
true, true);
acpiAvoidFullInit = get_driver_boolean_parameter(settings,
"acpi_avoid_full_init", false, false);
unload_driver_settings(settings);
}
@ -186,10 +182,6 @@ acpi_std_ops(int32 op,...)
AcpiEvaluateObject(NULL, "\\_PIC", &parameter, NULL);
flags = acpiAvoidFullInit ?
ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT :
ACPI_FULL_INITIALIZATION;
// FreeBSD seems to pass in the above flags here as
// well but specs don't define ACPI_NO_DEVICE_INIT
// and ACPI_NO_OBJECT_INIT here.
@ -200,7 +192,7 @@ acpi_std_ops(int32 op,...)
goto err;
}
status = AcpiInitializeObjects(flags);
status = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION);
if (ACPI_FAILURE(status)) {
ERROR("AcpiInitializeObjects failed (%s)\n",
AcpiFormatException(status));

View File

@ -1640,6 +1640,7 @@ status_t
init_ipv6()
{
mutex_init(&sRawSocketsLock, "raw sockets");
mutex_init(&sFragmentLock, "IPv4 Fragments");
mutex_init(&sMulticastGroupsLock, "IPv6 multicast groups");
mutex_init(&sReceivingProtocolLock, "IPv6 receiving protocols");
@ -1685,6 +1686,7 @@ err2:
err1:
mutex_destroy(&sReceivingProtocolLock);
mutex_destroy(&sMulticastGroupsLock);
mutex_destroy(&sFragmentLock);
mutex_destroy(&sRawSocketsLock);
TRACE("init_ipv6: error %s", strerror(status));
return status;
@ -1709,6 +1711,7 @@ uninit_ipv6()
mutex_unlock(&sReceivingProtocolLock);
mutex_destroy(&sMulticastGroupsLock);
mutex_destroy(&sFragmentLock);
mutex_destroy(&sRawSocketsLock);
mutex_destroy(&sReceivingProtocolLock);

View File

@ -999,7 +999,6 @@ AboutView::_CreateCreditsView()
"Ithamar R. Adema\n"
"Bruno G. Albuquerque\n"
"Stephan Aßmus\n"
"Salvatore Benedetto\n"
"Stefano Ceccherini\n"
"Rudolf Cornelissen\n"
"Alexandre Deckner\n"
@ -1010,25 +1009,19 @@ AboutView::_CreateCreditsView()
"René Gollent\n"
"Bryce Groff\n"
"Colin Günther\n"
"Karsten Heimrich\n"
"Fredrik Holmqvist\n"
"Philippe Houdoin\n"
"Maurice Kalinowski\n"
"Euan Kirkhope\n"
"Ryan Leavengood\n"
"Michael Lotz\n"
"Brecht Machiels\n"
"Matt Madia\n"
"Scott McCreary\n"
"David McPaul\n"
"Wim van der Meer\n"
"Fredrik Modéen\n"
"Marcus Overhagen\n"
"Michael Pfeiffer\n"
"François Revol\n"
"Philippe Saint-Pierre\n"
"John Scipione\n"
"Andrej Spielmann\n"
"Jonas Sundström\n"
"Oliver Tappe\n"
"Gerasim Troeglazov\n"
@ -1046,13 +1039,19 @@ AboutView::_CreateCreditsView()
fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey);
fCreditsView->Insert(
"Andrew Bachmann\n"
"Salvatore Benedetto\n"
"Tyler Dauwalder\n"
"Daniel Furrer\n"
"Andre Alves Garzia\n"
"Karsten Heimrich\n"
"Erik Jaesler\n"
"Maurice Kalinowski\n"
"Euan Kirkhope\n"
"Marcin Konicki\n"
"Waldemar Kornewald\n"
"Thomas Kurschel\n"
"Brecht Machiels\n"
"Wim van der Meer\n"
"Frans Van Nispen\n"
"Adi Oanca\n"
"Michael Phipps\n"
@ -1060,6 +1059,7 @@ AboutView::_CreateCreditsView()
"David Reid\n"
"Hugo Santos\n"
"Alexander G. M. Smith\n"
"Andrej Spielmann\n"
"Bryan Varner\n"
"Nathan Whitehorn\n"
"Michael Wilber\n"
@ -1096,8 +1096,10 @@ AboutView::_CreateCreditsView()
"Michael Davidson\n"
"David Dengg\n"
"John Drinkwater\n"
"Yongcong Du\n"
"Cian Duffy\n"
"Vincent Duvert\n"
"Pawel Dziepak\n"
"Mikael Eiman\n"
"Fredrik Ekdahl\n"
"Joshua R. Elsasser\n"
@ -1112,7 +1114,9 @@ AboutView::_CreateCreditsView()
"Deyan Genovski\n"
"Pete Goodeve\n"
"Lucian Adrian Grijincu\n"
"Jessica Hamilton\n"
"Sean Healy\n"
"Andreas Henriksson\n"
"Matthijs Hollemans\n"
"Mathew Hounsell\n"
"Morgan Howe\n"
@ -1163,20 +1167,22 @@ AboutView::_CreateCreditsView()
"Jeremy Rand\n"
"Hartmut Reh\n"
"Daniel Reinhold\n"
"Sergei Reznikov\n"
"Chris Roberts\n"
"Samuel Rodríguez Pérez\n"
"Thomas Roell\n"
"Rafael Romo\n"
"Ralf Schülke\n"
"Reznikov Sergei\n"
"Zousar Shaker\n"
"Caitlin Shaw\n"
"Alex Smith\n"
"Geoffry Song\n"
"Daniel Switkin\n"
"Atsushi Takamatsu\n"
"James Urquhart\n"
"Jason Vandermark\n"
"Sandor Vroemisse\n"
"Jürgen Wall\n"
"Denis Washington\n"
"Ulrich Wimboeck\n"
"Johannes Wischert\n"
@ -1188,7 +1194,7 @@ AboutView::_CreateCreditsView()
"Zhao Shuai\n");
fCreditsView->Insert(
B_TRANSLATE("\n" B_UTF8_ELLIPSIS
" and probably some more we forgot to mention (sorry!)"
"and probably some more we forgot to mention (sorry!)"
"\n\n"));
fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuOrange);
@ -1256,11 +1262,12 @@ AboutView::_CreateCreditsView()
fCreditsView->Insert(
B_TRANSLATE("The BeGeistert team\n"));
fCreditsView->Insert(
B_TRANSLATE("Google & their Google Summer of Code program\n"));
B_TRANSLATE("Google and their Google Summer of Code and Google Code In "
"programs\n"));
fCreditsView->Insert(
B_TRANSLATE("The University of Auckland and Christof Lutteroth\n\n"));
fCreditsView->Insert(
B_TRANSLATE("... and the many people making donations!\n\n"));
B_TRANSLATE(B_UTF8_ELLIPSIS "and the many people making donations!\n\n"));
// copyrights for various projects we use

View File

@ -1,6 +1,6 @@
/*
* Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de.
* Copyright (c) 2002, Carlos Hasan, for Haiku.
* Copyright 2004-2012, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2002, Carlos Hasan.
*
* Distributed under the terms of the MIT license.
*/
@ -15,8 +15,8 @@
#include <cpu_type.h>
// ToDo: -disable_cpu_sn option is not yet implemented
// ToDo: most of this file should go into an architecture dependent source file
// TODO: -disable_cpu_sn option is not yet implemented
// TODO: most of this file should go into an architecture dependent source file
#ifdef __INTEL__
struct cache_description {
@ -196,8 +196,8 @@ print_intel_cache_descriptors(enum cpu_types type, cpuid_info *info)
if (cacheDescriptors[i] == 0x40) {
printf("\tNo integrated L%u cache\n",
type >= B_CPU_INTEL_PENTIUM_IV
&& (type & B_CPU_x86_VENDOR_MASK) == B_CPU_INTEL_x86 ?
3 : 2);
&& (type & B_CPU_x86_VENDOR_MASK) == B_CPU_INTEL_x86
? 3 : 2);
} else
printf("\t%s\n", sIntelCacheDescriptions[j].description);
break;
@ -242,7 +242,8 @@ print_level2_cache(uint32 reg, const char *name)
{
uint32 size = (reg >> 16) & 0xffff;
uint32 ways = (reg >> 12) & 0xf;
uint32 linesPerTag = (reg >> 8) & 0xf; // intel does not define this
uint32 linesPerTag = (reg >> 8) & 0xf;
// intel does not define this
uint32 lineSize = reg & 0xff;
printf("\t%s: %lu KB, ", name, size);
@ -295,12 +296,14 @@ print_cache_desc(int32 cpu)
print_level2_cache(info.regs.ecx, "L2 cache");
}
static void
print_intel_cache_desc(int32 cpu)
{
cpuid_info info;
// A second parameters needs to be passed to CPUID which determines the cache level to query
// A second parameters needs to be passed to CPUID which determines the
// cache level to query
get_cpuid(&info, 0x00000004, cpu);
putchar('\n');
@ -459,24 +462,31 @@ print_features(uint32 features)
#ifdef __INTEL__
static void
print_processor_signature(system_info *sys_info, cpuid_info *info, const char *prefix)
print_processor_signature(system_info *sys_info, cpuid_info *info,
const char *prefix)
{
if ((sys_info->cpu_type & B_CPU_x86_VENDOR_MASK) == B_CPU_AMD_x86) {
printf("\t%s%sype %lu, family %lu, model %u, stepping %lu, features 0x%08lx\n",
prefix ? prefix : "", prefix && prefix[0] ? "t" : "T",
printf("\t%s%sype %lu, family %lu, model %lu, stepping %lu, features "
"0x%08lx\n", prefix ? prefix : "", prefix && prefix[0] ? "t" : "T",
info->eax_1.type,
info->eax_1.family + (info->eax_1.family == 0xf ? info->eax_1.extended_family : 0),
info->eax_1.model + (info->eax_1.model == 0xf ? info->eax_1.extended_model << 4 : 0),
info->eax_1.family + (info->eax_1.family == 0xf
? info->eax_1.extended_family : 0),
info->eax_1.model + (info->eax_1.model == 0xf
? info->eax_1.extended_model << 4 : 0),
info->eax_1.stepping,
info->eax_1.features);
} else if ((sys_info->cpu_type & B_CPU_x86_VENDOR_MASK) == B_CPU_INTEL_x86) {
} else if ((sys_info->cpu_type & B_CPU_x86_VENDOR_MASK)
== B_CPU_INTEL_x86) {
// model calculation is different for INTEL
printf("\t%s%sype %lu, family %lu, model %u, stepping %lu, features 0x%08lx\n",
prefix ? prefix : "", prefix && prefix[0] ? "t" : "T",
printf("\t%s%sype %lu, family %lu, model %lu, stepping %lu, features "
"0x%08lx\n", prefix ? prefix : "", prefix && prefix[0] ? "t" : "T",
info->eax_1.type,
info->eax_1.family + (info->eax_1.family == 0xf ? info->eax_1.extended_family : 0),
info->eax_1.model + ((info->eax_1.family == 0xf || info->eax_1.family == 0x6) ? info->eax_1.extended_model << 4 : 0),
info->eax_1.family + (info->eax_1.family == 0xf
? info->eax_1.extended_family : 0),
info->eax_1.model
+ ((info->eax_1.family == 0xf || info->eax_1.family == 0x6)
? info->eax_1.extended_model << 4 : 0),
info->eax_1.stepping,
info->eax_1.features);
}
@ -500,12 +510,10 @@ dump_platform(system_info *info)
static void
dump_cpu(system_info *info, int32 cpu)
{
/* references:
*
* http://grafi.ii.pw.edu.pl/gbm/x86/cpuid.html
* http://www.sandpile.org/ia32/cpuid.htm
* http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/TN13.pdf (Duron erratum)
*/
// References:
// http://grafi.ii.pw.edu.pl/gbm/x86/cpuid.html
// http://www.sandpile.org/ia32/cpuid.htm
// http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/TN13.pdf (Duron erratum)
cpuid_info baseInfo;
if (get_cpuid(&baseInfo, 0, cpu) != B_OK) {
@ -514,15 +522,18 @@ dump_cpu(system_info *info, int32 cpu)
}
int32 maxStandardFunction = baseInfo.eax_0.max_eax;
if (maxStandardFunction >= 500)
maxStandardFunction = 0; /* old Pentium sample chips has cpu signature here */
if (maxStandardFunction >= 500) {
// old Pentium sample chips has cpu signature here
maxStandardFunction = 0;
}
/* Extended cpuid */
// Extended cpuid
cpuid_info cpuInfo;
get_cpuid(&cpuInfo, 0x80000000, cpu);
// extended cpuid is only supported if max_eax is greater than the service id
// Extended cpuid is only supported if max_eax is greater than the
// service id
int32 maxExtendedFunction = 0;
if (cpuInfo.eax_0.max_eax > 0x80000000)
maxExtendedFunction = cpuInfo.eax_0.max_eax & 0xff;
@ -586,7 +597,8 @@ dump_cpu(system_info *info, int32 cpu)
get_cpuid(&cpuInfo, 0x80000007, cpu);
print_amd_power_management_features(cpuInfo.regs.edx);
}
} else if ((info->cpu_type & B_CPU_x86_VENDOR_MASK) == B_CPU_TRANSMETA_x86)
} else if ((info->cpu_type & B_CPU_x86_VENDOR_MASK)
== B_CPU_TRANSMETA_x86)
print_transmeta_features(cpuInfo.regs.edx);
}
@ -595,7 +607,8 @@ dump_cpu(system_info *info, int32 cpu)
if (!strncmp(baseInfo.eax_0.vendor_id, "CyrixInstead", 12)) {
get_cpuid(&cpuInfo, 0x00000002, cpu);
print_intel_cache_descriptors(info->cpu_type, &cpuInfo);
} else if ((info->cpu_type & B_CPU_x86_VENDOR_MASK) == B_CPU_INTEL_x86) {
} else if ((info->cpu_type & B_CPU_x86_VENDOR_MASK)
== B_CPU_INTEL_x86) {
// Intel does not support extended function 5 (but it does 6 hmm)
print_intel_cache_desc(cpu);
} else {
@ -620,7 +633,8 @@ dump_cpu(system_info *info, int32 cpu)
if (flagsInfo.eax_1.features & (1UL << 18)) {
get_cpuid(&cpuInfo, 3, cpu);
printf("Serial number: %04lx-%04lx-%04lx-%04lx-%04lx-%04lx\n",
flagsInfo.eax_1.features >> 16, flagsInfo.eax_1.features & 0xffff,
flagsInfo.eax_1.features >> 16,
flagsInfo.eax_1.features & 0xffff,
cpuInfo.regs.edx >> 16, cpuInfo.regs.edx & 0xffff,
cpuInfo.regs.ecx >> 16, cpuInfo.regs.edx & 0xffff);
}
@ -646,8 +660,8 @@ dump_cpus(system_info *info)
snprintf(modelString, 32, "(Unknown %x)", info->cpu_type);
}
printf("%ld %s%s%s, revision %04lx running at %LdMHz (ID: 0x%08lx 0x%08lx)\n\n",
info->cpu_count,
printf("%ld %s%s%s, revision %04lx running at %LdMHz (ID: 0x%08lx "
"0x%08lx)\n\n", info->cpu_count,
vendor ? vendor : "", vendor ? " " : "", model,
info->cpu_revision,
info->cpu_clock_speed / 1000000,

View File

@ -1,23 +1,25 @@
SubDir HAIKU_TOP src preferences virtualmemory ;
Preference VirtualMemory :
UsePrivateHeaders shared system ;
Preference VirtualMemory :
VirtualMemory.cpp
SettingsWindow.cpp
Settings.cpp
$(DRIVER_SETTINGS)
: be $(TARGET_LIBSTDC++) $(HAIKU_LOCALE_LIBS)
: be libshared.a $(TARGET_LIBSTDC++) $(HAIKU_LOCALE_LIBS)
: VirtualMemory.rdef
;
;
if ! $(TARGET_PLATFORM_HAIKU_COMPATIBLE) {
SEARCH on [ FGristFiles driver_settings.c ] +=
SEARCH on [ FGristFiles driver_settings.c ] +=
[ FDirName $(HAIKU_TOP) src system libroot os ] ;
}
DoCatalogs VirtualMemory :
x-vnd.Haiku-VirtualMemory
:
VirtualMemory.cpp
SettingsWindow.cpp
;
DoCatalogs VirtualMemory :
x-vnd.Haiku-VirtualMemory
:
VirtualMemory.cpp
SettingsWindow.cpp
;

View File

@ -1,192 +1,213 @@
/*
* Copyright 2010-2011, Hamish Morrison, hamish@lavabit.com
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de
* All rights reserved. Distributed under the terms of the MIT License.
*
* Copyright 2010-2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Hamish Morrison, hamish@lavabit.com
* Alexander von Gluck, kallisti5@unixzen.com
*/
#include "Settings.h"
#include <File.h>
#include <Entry.h>
#include <FindDirectory.h>
#include <Path.h>
#include <Volume.h>
#include <VolumeRoster.h>
#include <driver_settings.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <File.h>
#include <FindDirectory.h>
#include <Path.h>
#include <VolumeRoster.h>
static const char* kWindowSettingsFile = "VM_data";
static const char* kVirtualMemorySettings = "virtual_memory";
static const int64 kMegaByte = 1024 * 1024;
#include <driver_settings.h>
static const char* const kWindowSettingsFile = "virtualmemory_preferences";
static const char* const kVirtualMemorySettings = "virtual_memory";
static const off_t kMegaByte = 1024 * 1024;
static const off_t kGigaByte = kMegaByte * 1024;
Settings::Settings()
:
fPositionUpdated(false)
{
_ReadWindowSettings();
_ReadSwapSettings();
fDefaultSettings.enabled = true;
fDefaultSettings.automatic = true;
system_info sysInfo;
get_system_info(&sysInfo);
fDefaultSettings.size = (off_t)sysInfo.max_pages * B_PAGE_SIZE;
if (fDefaultSettings.size <= kGigaByte) {
// Memory under 1GB? double the swap
// This matches the behaviour of the kernel
fDefaultSettings.size *= 2;
}
fDefaultSettings.volume = dev_for_path("/boot");
}
Settings::~Settings()
void
Settings::SetSwapEnabled(bool enabled, bool revertable)
{
_WriteWindowSettings();
_WriteSwapSettings();
fCurrentSettings.enabled = enabled;
if (!revertable)
fInitialSettings.enabled = enabled;
}
void
Settings::SetSwapAutomatic(bool automatic, bool revertable)
{
fCurrentSettings.automatic = automatic;
if (!revertable)
fInitialSettings.automatic = automatic;
}
void
Settings::SetSwapSize(off_t size, bool revertable)
{
fCurrentSettings.size = size;
if (!revertable)
fInitialSettings.size = size;
}
void
Settings::SetSwapVolume(dev_t volume, bool revertable)
{
fCurrentSettings.volume = volume;
if (!revertable)
fInitialSettings.volume = volume;
}
void
Settings::SetWindowPosition(BPoint position)
{
if (position == fWindowPosition)
return;
fWindowPosition = position;
fPositionUpdated = true;
}
void
Settings::SetSwapEnabled(bool enabled)
status_t
Settings::ReadWindowSettings()
{
fSwapEnabled = enabled;
}
void
Settings::SetSwapSize(off_t size)
{
fSwapSize = size;
}
void
Settings::SetSwapVolume(BVolume &volume)
{
if (volume.Device() == SwapVolume().Device()
|| volume.InitCheck() != B_OK)
return;
fSwapVolume.SetTo(volume.Device());
}
void
Settings::RevertSwapChanges()
{
fSwapEnabled = fInitialSwapEnabled;
fSwapSize = fInitialSwapSize;
fSwapVolume.SetTo(fInitialSwapVolume);
}
bool
Settings::IsRevertible()
{
return fSwapEnabled != fInitialSwapEnabled
|| fSwapSize != fInitialSwapSize
|| fSwapVolume.Device() != fInitialSwapVolume;
}
void
Settings::_ReadWindowSettings()
{
bool success = false;
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) {
path.Append(kWindowSettingsFile);
BFile file;
if (file.SetTo(path.Path(), B_READ_ONLY) == B_OK)
if (file.Read(&fWindowPosition, sizeof(BPoint)) == sizeof(BPoint))
success = true;
}
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
return B_ERROR;
if (!success)
fWindowPosition.Set(-1, -1);
path.Append(kWindowSettingsFile);
BFile file;
if (file.SetTo(path.Path(), B_READ_ONLY) != B_OK)
return B_ERROR;
if (file.Read(&fWindowPosition, sizeof(BPoint)) == sizeof(BPoint))
return B_OK;
return B_ERROR;
}
void
Settings::_WriteWindowSettings()
status_t
Settings::WriteWindowSettings()
{
if (!fPositionUpdated)
return;
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) < B_OK)
return;
return B_ERROR;
path.Append(kWindowSettingsFile);
BFile file;
if (file.SetTo(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE) == B_OK)
file.Write(&fWindowPosition, sizeof(BPoint));
if (file.SetTo(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE)
!= B_OK)
return B_ERROR;
file.Write(&fWindowPosition, sizeof(BPoint));
return B_OK;
}
void
Settings::_ReadSwapSettings()
status_t
Settings::ReadSwapSettings()
{
void* settings = load_driver_settings(kVirtualMemorySettings);
if (settings != NULL) {
SetSwapEnabled(get_driver_boolean_parameter(settings, "vm", false, false));
const char* swapSize = get_driver_parameter(settings, "swap_size", NULL, NULL);
SetSwapSize(swapSize ? atoll(swapSize) : 0);
#ifdef SWAP_VOLUME_IMPLEMENTED
// we need to hang onto this one
fBadVolName = strdup(get_driver_parameter(settings, "swap_volume", NULL, NULL));
BVolumeRoster volumeRoster;
BVolume temporaryVolume;
if (fBadVolName != NULL) {
status_t result = volumeRoster.GetNextVolume(&temporaryVolume);
char volumeName[B_FILE_NAME_LENGTH];
while (result != B_BAD_VALUE) {
temporaryVolume.GetName(volumeName);
if (strcmp(volumeName, fBadVolName) == 0
&& temporaryVolume.IsPersistent() && volumeName[0]) {
SetSwapVolume(temporaryVolume);
break;
}
result = volumeRoster.GetNextVolume(&temporaryVolume);
if (settings == NULL)
return kErrorSettingsNotFound;
const char* enabled = get_driver_parameter(settings, "vm", NULL, NULL);
const char* automatic = get_driver_parameter(settings, "swap_auto",
NULL, NULL);
const char* size = get_driver_parameter(settings, "swap_size", NULL, NULL);
const char* volume = get_driver_parameter(settings, "swap_volume_name",
NULL, NULL);
const char* device = get_driver_parameter(settings,
"swap_volume_device", NULL, NULL);
const char* filesystem = get_driver_parameter(settings,
"swap_volume_filesystem", NULL, NULL);
const char* capacity = get_driver_parameter(settings,
"swap_volume_capacity", NULL, NULL);
if (enabled == NULL || automatic == NULL || size == NULL || device == NULL
|| volume == NULL || capacity == NULL || filesystem == NULL)
return kErrorSettingsInvalid;
off_t volCapacity = atoll(capacity);
SetSwapEnabled(get_driver_boolean_parameter(settings,
"vm", true, false));
SetSwapAutomatic(get_driver_boolean_parameter(settings,
"swap_auto", true, false));
SetSwapSize(atoll(size));
unload_driver_settings(settings);
int32 bestScore = -1;
dev_t bestVol = -1;
BVolume vol;
fs_info volStat;
BVolumeRoster roster;
while (roster.GetNextVolume(&vol) == B_OK) {
if (!vol.IsPersistent() || vol.IsReadOnly() || vol.IsRemovable()
|| vol.IsShared())
continue;
if (fs_stat_dev(vol.Device(), &volStat) == 0) {
int32 score = 0;
if (strcmp(volume, volStat.volume_name) == 0)
score += 4;
if (strcmp(device, volStat.device_name) == 0)
score += 3;
if (volCapacity == volStat.total_blocks * volStat.block_size)
score += 2;
if (strcmp(filesystem, volStat.fsh_name) == 0)
score += 1;
if (score >= 4 && score > bestScore) {
bestVol = vol.Device();
bestScore = score;
}
} else
volumeRoster.GetBootVolume(&fSwapVolume);
#endif
unload_driver_settings(settings);
} else
_SetSwapNull();
}
}
#ifndef SWAP_VOLUME_IMPLEMENTED
BVolumeRoster volumeRoster;
volumeRoster.GetBootVolume(&fSwapVolume);
#endif
SetSwapVolume(bestVol);
fInitialSettings = fCurrentSettings;
fInitialSwapEnabled = fSwapEnabled;
fInitialSwapSize = fSwapSize;
fInitialSwapVolume = fSwapVolume.Device();
if (bestVol < 0)
return kErrorVolumeNotFound;
return B_OK;
}
void
Settings::_WriteSwapSettings()
{
if (!IsRevertible())
return;
status_t
Settings::WriteSwapSettings()
{
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
return;
return B_ERROR;
path.Append("kernel/drivers");
path.Append(kVirtualMemorySettings);
@ -194,36 +215,62 @@ Settings::_WriteSwapSettings()
BFile file;
if (file.SetTo(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE)
!= B_OK)
return;
char buffer[256];
#ifdef SWAP_VOLUME_IMPLEMENTED
char volumeName[B_FILE_NAME_LENGTH] = {0};
if (SwapVolume().InitCheck() != B_NO_INIT)
SwapVolume().GetName(volumeName);
else if (fBadVolName)
strcpy(volumeName, fBadVolName);
snprintf(buffer, sizeof(buffer), "vm %s\nswap_size %Ld\nswap_volume %s\n",
SwapEnabled() ? "on" : "off", SwapSize(),
volumeName[0] ? volumeName : NULL);
#else
snprintf(buffer, sizeof(buffer), "vm %s\nswap_size %Ld\n",
fSwapEnabled ? "on" : "off", fSwapSize);
#endif
return B_ERROR;
fs_info info;
if (fs_stat_dev(SwapVolume(), &info) != 0)
return B_ERROR;
char buffer[1024];
snprintf(buffer, sizeof(buffer), "vm %s\nswap_auto %s\nswap_size %lld\n"
"swap_volume_name %s\nswap_volume_device %s\n"
"swap_volume_filesystem %s\nswap_volume_capacity %lld\n",
SwapEnabled() ? "on" : "off", SwapAutomatic() ? "yes" : "no",
SwapSize(), info.volume_name, info.device_name, info.fsh_name,
info.total_blocks * info.block_size);
file.Write(buffer, strlen(buffer));
return B_OK;
}
bool
Settings::IsRevertable()
{
return SwapEnabled() != fInitialSettings.enabled
|| SwapAutomatic() != fInitialSettings.automatic
|| SwapSize() != fInitialSettings.size
|| SwapVolume() != fInitialSettings.volume;
}
void
Settings::_SetSwapNull()
Settings::RevertSwapSettings()
{
SetSwapEnabled(false);
BVolumeRoster volumeRoster;
BVolume temporaryVolume;
volumeRoster.GetBootVolume(&temporaryVolume);
SetSwapVolume(temporaryVolume);
SetSwapSize(0);
SetSwapEnabled(fInitialSettings.enabled);
SetSwapAutomatic(fInitialSettings.automatic);
SetSwapSize(fInitialSettings.size);
SetSwapVolume(fInitialSettings.volume);
}
bool
Settings::IsDefaultable()
{
return SwapEnabled() != fDefaultSettings.enabled
|| SwapAutomatic() != fDefaultSettings.automatic
|| SwapSize() != fDefaultSettings.size
|| SwapVolume() != fDefaultSettings.volume;
}
void
Settings::DefaultSwapSettings(bool revertable)
{
SetSwapEnabled(fDefaultSettings.enabled);
SetSwapAutomatic(fDefaultSettings.automatic);
SetSwapSize(fDefaultSettings.size);
SetSwapVolume(fDefaultSettings.volume);
if (!revertable)
fInitialSettings = fDefaultSettings;
}

View File

@ -1,54 +1,74 @@
/*
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de
* All rights reserved. Distributed under the terms of the MIT License.
*
* Copyright 2010-2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Hamish Morrison, hamish@lavabit.com
* Alexander von Gluck, kallisti5@unixzen.com
*/
#ifndef SETTINGS_H
#define SETTINGS_H
#include <stdio.h>
#include <stdlib.h>
#include <Point.h>
#include <Volume.h>
static const int32 kErrorSettingsNotFound = B_ERRORS_END + 1;
static const int32 kErrorSettingsInvalid = B_ERRORS_END + 2;
static const int32 kErrorVolumeNotFound = B_ERRORS_END + 3;
class Settings {
public :
Settings();
virtual ~Settings();
public:
Settings();
BPoint WindowPosition() const { return fWindowPosition; }
void SetWindowPosition(BPoint position);
bool SwapEnabled() const
{ return fCurrentSettings.enabled; }
bool SwapAutomatic() const
{ return fCurrentSettings.automatic; }
off_t SwapSize() const { return fCurrentSettings.size; }
dev_t SwapVolume() { return fCurrentSettings.volume; }
BPoint WindowPosition() const { return fWindowPosition; }
bool SwapEnabled() const { return fSwapEnabled; }
off_t SwapSize() const { return fSwapSize; }
BVolume& SwapVolume() { return fSwapVolume; }
void SetSwapEnabled(bool enabled);
void SetSwapSize(off_t size);
void SetSwapVolume(BVolume& volume);
void RevertSwapChanges();
bool IsRevertible();
void SetSwapEnabled(bool enabled,
bool revertable = true);
void SetSwapAutomatic(bool automatic,
bool revertable = true);
void SetSwapSize(off_t size, bool revertable = true);
void SetSwapVolume(dev_t volume,
bool revertable = true);
void SetWindowPosition(BPoint position);
private:
void _ReadWindowSettings();
void _WriteWindowSettings();
status_t ReadWindowSettings();
status_t WriteWindowSettings();
status_t ReadSwapSettings();
status_t WriteSwapSettings();
void _ReadSwapSettings();
void _WriteSwapSettings();
bool IsRevertable();
void RevertSwapSettings();
void _SetSwapNull();
bool IsDefaultable();
void DefaultSwapSettings(bool revertable = true);
private:
struct SwapSettings {
bool enabled;
bool automatic;
off_t size;
dev_t volume;
};
BPoint fWindowPosition;
BPoint fWindowPosition;
bool fSwapEnabled;
off_t fSwapSize;
BVolume fSwapVolume;
bool fInitialSwapEnabled;
off_t fInitialSwapSize;
dev_t fInitialSwapVolume;
bool fPositionUpdated;
const char* fBadVolName;
SwapSettings fCurrentSettings;
SwapSettings fInitialSettings;
SwapSettings fDefaultSettings;
};
#endif /* SETTINGS_H */

View File

@ -1,12 +1,17 @@
/*
* Copyright 2010-2011, Hamish Morrison, hamish@lavabit.com
* Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de
* All rights reserved. Distributed under the terms of the MIT License.
*
* Copyright 2010-2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Hamish Morrison, hamish@lavabit.com
* Alexander von Gluck, kallisti5@unixzen.com
*/
#include "SettingsWindow.h"
#include "Settings.h"
#include <Application.h>
#include <Alert.h>
@ -14,22 +19,25 @@
#include <Button.h>
#include <Catalog.h>
#include <CheckBox.h>
#include <GroupLayout.h>
#include <GroupLayoutBuilder.h>
#include <Locale.h>
#include <Directory.h>
#include <FindDirectory.h>
#include <LayoutBuilder.h>
#include <MenuItem.h>
#include <MenuField.h>
#include <NodeMonitor.h>
#include <Path.h>
#include <PopUpMenu.h>
#include <Screen.h>
#include <StringForSize.h>
#include <StringView.h>
#include <String.h>
#include <Slider.h>
#include <PopUpMenu.h>
#include <MenuItem.h>
#include <MenuField.h>
#include <Screen.h>
#include <FindDirectory.h>
#include <Path.h>
#include <system_info.h>
#include <Volume.h>
#include <VolumeRoster.h>
#include <stdio.h>
#include "Settings.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "SettingsWindow"
@ -39,91 +47,72 @@ static const uint32 kMsgDefaults = 'dflt';
static const uint32 kMsgRevert = 'rvrt';
static const uint32 kMsgSliderUpdate = 'slup';
static const uint32 kMsgSwapEnabledUpdate = 'swen';
static const uint32 kMsgSwapAutomaticUpdate = 'swat';
static const uint32 kMsgVolumeSelected = 'vlsl';
static const int64 kMegaByte = 1024 * 1024;
class SizeSlider : public BSlider {
public:
SizeSlider(const char* name, const char* label,
BMessage* message, int32 min, int32 max, uint32 flags);
virtual ~SizeSlider();
virtual const char* UpdateText() const;
private:
mutable BString fText;
};
static const off_t kMegaByte = 1024 * 1024;
static dev_t gBootDev = -1;
SizeSlider::SizeSlider(const char* name, const char* label,
BMessage* message, int32 min, int32 max, uint32 flags)
: BSlider(name, label, message, min, max, B_HORIZONTAL, B_BLOCK_THUMB, flags)
:
BSlider(name, label, message, min, max, B_HORIZONTAL,
B_BLOCK_THUMB, flags)
{
rgb_color color = ui_color(B_CONTROL_HIGHLIGHT_COLOR);
UseFillColor(true, &color);
}
SizeSlider::~SizeSlider()
{
}
const char*
byte_string(int64 size)
{
double value = 1. * size;
static char string[256];
if (value < 1024)
snprintf(string, sizeof(string), B_TRANSLATE("%Ld B"), size);
else {
static const char *units[] = {
B_TRANSLATE_MARK("KB"),
B_TRANSLATE_MARK("MB"),
B_TRANSLATE_MARK("GB"),
NULL
};
int32 i = -1;
do {
value /= 1024.0;
i++;
} while (value >= 1024 && units[i + 1]);
off_t rounded = off_t(value * 100LL);
snprintf(string, sizeof(string), "%g %s", rounded / 100.0,
B_TRANSLATE_NOCOLLECT(units[i]));
}
return string;
}
const char*
SizeSlider::UpdateText() const
{
fText = byte_string(Value() * kMegaByte);
return fText.String();
return string_for_size(Value() * kMegaByte, fText, sizeof(fText));
}
class VolumeMenuItem : public BMenuItem {
public:
VolumeMenuItem(const char* label, BMessage* message, BVolume* volume);
BVolume* Volume() { return fVolume; }
private:
BVolume* fVolume;
};
VolumeMenuItem::VolumeMenuItem(const char* label, BMessage* message,
BVolume* volume)
: BMenuItem(label, message)
VolumeMenuItem::VolumeMenuItem(BVolume volume, BMessage* message)
:
BMenuItem("", message),
fVolume(volume)
{
fVolume = volume;
GenerateLabel();
}
void
VolumeMenuItem::MessageReceived(BMessage* message)
{
if (message->what == B_NODE_MONITOR) {
int32 code;
if (message->FindInt32("opcode", &code) == B_OK)
if (code == B_ENTRY_MOVED)
GenerateLabel();
}
}
void
VolumeMenuItem::GenerateLabel()
{
char name[B_FILE_NAME_LENGTH + 1];
fVolume.GetName(name);
BDirectory dir;
if (fVolume.GetRootDirectory(&dir) == B_OK) {
BEntry entry;
if (dir.GetEntry(&entry) == B_OK) {
BPath path;
if (entry.GetPath(&path) == B_OK) {
BString label;
label << name << " (" << path.Path() << ")";
SetLabel(label);
return;
}
}
}
SetLabel(name);
}
@ -131,81 +120,90 @@ SettingsWindow::SettingsWindow()
:
BWindow(BRect(0, 0, 269, 172), B_TRANSLATE_SYSTEM_NAME("VirtualMemory"),
B_TITLED_WINDOW, B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS
| B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS),
fLocked(false)
| B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS)
{
BView* view = new BGroupView();
gBootDev = dev_for_path("/boot");
BAlignment align(B_ALIGN_LEFT, B_ALIGN_MIDDLE);
if (fSettings.ReadWindowSettings() != B_OK)
CenterOnScreen();
else
MoveTo(fSettings.WindowPosition());
status_t result = fSettings.ReadSwapSettings();
if (result == kErrorSettingsNotFound)
fSettings.DefaultSwapSettings(false);
else if (result == kErrorSettingsInvalid) {
int32 choice = (new BAlert(B_TRANSLATE_SYSTEM_NAME("VirtualMemory"),
B_TRANSLATE("The settings specified in the settings file "
"are invalid. You can load the defaults or quit."),
B_TRANSLATE("Load defaults"), B_TRANSLATE("Quit")))->Go();
if (choice == 1) {
be_app->PostMessage(B_QUIT_REQUESTED);
return;
}
fSettings.DefaultSwapSettings(false);
} else if (result == kErrorVolumeNotFound) {
int32 choice = (new BAlert(B_TRANSLATE_SYSTEM_NAME("VirtualMemory"),
B_TRANSLATE("The volume specified in the settings file "
"could not be found. You can use the boot volume or quit."),
B_TRANSLATE("Use boot volume"), B_TRANSLATE("Quit")))->Go();
if (choice == 1) {
be_app->PostMessage(B_QUIT_REQUESTED);
return;
}
fSettings.SetSwapVolume(gBootDev, false);
}
fSwapEnabledCheckBox = new BCheckBox("enable swap",
B_TRANSLATE("Enable virtual memory"),
new BMessage(kMsgSwapEnabledUpdate));
fSwapEnabledCheckBox->SetExplicitAlignment(align);
BBox* box = new BBox("box", B_FOLLOW_LEFT_RIGHT);
box->SetLabel(fSwapEnabledCheckBox);
fSwapAutomaticCheckBox = new BCheckBox("auto swap",
B_TRANSLATE("Choose swap size automatically"),
new BMessage(kMsgSwapAutomaticUpdate));
fSwapEnabledCheckBox->SetExplicitAlignment(align);
system_info info;
get_system_info(&info);
fSwapUsageBar = new BStatusBar("swap usage");
BString string = B_TRANSLATE("Physical memory: ");
string << byte_string((off_t)info.max_pages * B_PAGE_SIZE);
BStringView* memoryView = new BStringView("physical memory", string.String());
BPopUpMenu* menu = new BPopUpMenu("volume menu");
fVolumeMenuField = new BMenuField("volume menu field",
B_TRANSLATE("Use volume:"), menu);
fVolumeMenuField->SetExplicitAlignment(align);
string = B_TRANSLATE("Current swap file size: ");
string << byte_string(fSettings.SwapSize());
BStringView* swapfileView = new BStringView("current swap size", string.String());
BPopUpMenu* menu = new BPopUpMenu("invalid");
// collect volumes
// TODO: listen to volume changes!
// TODO: accept dropped volumes
BVolumeRoster volumeRoster;
BVolume* volume = new BVolume();
char name[B_FILE_NAME_LENGTH];
while (volumeRoster.GetNextVolume(volume) == B_OK) {
if (!volume->IsPersistent() || volume->GetName(name) != B_OK || !name[0])
BVolumeRoster roster;
BVolume vol;
while (roster.GetNextVolume(&vol) == B_OK) {
if (!vol.IsPersistent() || vol.IsReadOnly() || vol.IsRemovable()
|| vol.IsShared())
continue;
VolumeMenuItem* item = new VolumeMenuItem(name,
new BMessage(kMsgVolumeSelected), volume);
menu->AddItem(item);
volume = new BVolume();
_AddVolumeMenuItem(vol.Device());
}
fVolumeMenuField = new BMenuField("volumes", B_TRANSLATE("Use volume:"), menu);
fSizeSlider = new SizeSlider("size slider",
B_TRANSLATE("Requested swap file size:"), new BMessage(kMsgSliderUpdate),
1, 1, B_WILL_DRAW | B_FRAME_EVENTS);
watch_node(NULL, B_WATCH_MOUNT, this, this);
fSizeSlider = new SizeSlider("size slider",
B_TRANSLATE("Requested swap file size:"),
new BMessage(kMsgSliderUpdate), 0, 0, B_WILL_DRAW | B_FRAME_EVENTS);
fSizeSlider->SetViewColor(255, 0, 255);
fSizeSlider->SetExplicitAlignment(align);
fWarningStringView = new BStringView("", "");
fWarningStringView->SetAlignment(B_ALIGN_CENTER);
fWarningStringView = new BStringView("warning",
B_TRANSLATE("Changes will take effect upon reboot."));
view->SetLayout(new BGroupLayout(B_HORIZONTAL));
view->AddChild(BGroupLayoutBuilder(B_VERTICAL, 10)
.AddGroup(B_HORIZONTAL)
.Add(memoryView)
.AddGlue()
.End()
.AddGroup(B_HORIZONTAL)
.Add(swapfileView)
.AddGlue()
.End()
#ifdef SWAP_VOLUME_IMPLEMENTED
.AddGroup(B_HORIZONTAL)
.Add(fVolumeMenuField)
.AddGlue()
.End()
#else
.AddGlue()
#endif
BBox* box = new BBox("box");
box->SetLabel(fSwapEnabledCheckBox);
box->AddChild(BLayoutBuilder::Group<>(B_VERTICAL, B_USE_DEFAULT_SPACING)
.Add(fSwapUsageBar)
.Add(fSwapAutomaticCheckBox)
.Add(fVolumeMenuField)
.Add(fSizeSlider)
.Add(fWarningStringView)
.SetInsets(10, 10, 10, 10)
);
box->AddChild(view);
.SetInsets(10)
.View());
fDefaultsButton = new BButton("defaults", B_TRANSLATE("Defaults"),
new BMessage(kMsgDefaults));
@ -214,32 +212,28 @@ SettingsWindow::SettingsWindow()
new BMessage(kMsgRevert));
fRevertButton->SetEnabled(false);
SetLayout(new BGroupLayout(B_HORIZONTAL));
AddChild(BGroupLayoutBuilder(B_VERTICAL, 10)
BLayoutBuilder::Group<>(this, B_VERTICAL, B_USE_DEFAULT_SPACING)
.Add(box)
.AddGroup(B_HORIZONTAL, 10)
.Add(fDefaultsButton)
.Add(fRevertButton)
.AddGlue()
.End()
.SetInsets(10, 10, 10, 10)
);
.SetInsets(10);
BScreen screen;
BRect screenFrame = screen.Frame();
if (!screenFrame.Contains(fSettings.WindowPosition()))
CenterOnScreen();
else
MoveTo(fSettings.WindowPosition());
#ifdef SWAP_VOLUME_IMPLEMENTED
// Validate the volume specified in settings file
status_t result = fSettings.SwapVolume().InitCheck();
if (result != B_OK) {
BAlert* alert = new BAlert("VirtualMemory", B_TRANSLATE(
"The swap volume specified in the settings file is invalid.\n"
"You can keep the current setting or switch to the "
BAlert* alert = new BAlert(B_TRANSLATE_SYSTEM_NAME("VirtualMemory"),
B_TRANSLATE("The swap volume specified in the settings file is ",
"invalid.\n You can keep the current setting or switch to the "
"default swap volume."),
B_TRANSLATE("Keep"), B_TRANSLATE("Switch"), NULL,
B_WIDTH_AS_USUAL, B_WARNING_ALERT);
@ -255,11 +249,9 @@ SettingsWindow::SettingsWindow()
#endif
_Update();
}
SettingsWindow::~SettingsWindow()
{
// TODO: We may want to run this at an interval
_UpdateSwapInfo();
}
@ -267,36 +259,53 @@ void
SettingsWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
case B_NODE_MONITOR:
{
int32 opcode;
if (message->FindInt32("opcode", &opcode) != B_OK)
break;
dev_t device;
if (opcode == B_DEVICE_MOUNTED
&& message->FindInt32("new device", &device) == B_OK) {
BVolume vol(device);
if (!vol.IsPersistent() || vol.IsReadOnly()
|| vol.IsRemovable() || vol.IsShared()) {
break;
}
_AddVolumeMenuItem(device);
} else if (opcode == B_DEVICE_UNMOUNTED
&& message->FindInt32("device", &device) == B_OK) {
_RemoveVolumeMenuItem(device);
}
_Update();
break;
}
case kMsgRevert:
fSettings.RevertSwapChanges();
fSettings.RevertSwapSettings();
_Update();
break;
case kMsgDefaults:
_SetSwapDefaults();
fSettings.DefaultSwapSettings();
_Update();
break;
case kMsgSliderUpdate:
fSettings.SetSwapSize((off_t)fSizeSlider->Value() * kMegaByte);
_RecordChoices();
_Update();
break;
case kMsgVolumeSelected:
fSettings.SetSwapVolume(*((VolumeMenuItem*)fVolumeMenuField->Menu()
->FindMarked())->Volume());
_RecordChoices();
_Update();
break;
case kMsgSwapEnabledUpdate:
{
int32 value;
if (message->FindInt32("be:value", &value) != B_OK)
break;
if (value == 0) {
// print out warning, give the user the time to think about it :)
if (fSwapEnabledCheckBox->Value() == 0) {
// print out warning, give the user the
// time to think about it :)
// ToDo: maybe we want to remove this possibility in the GUI
// as Be did, but I thought a proper warning could be helpful
// (for those that want to change that anyway)
BAlert* alert = new BAlert("VirtualMemory",
B_TRANSLATE(
BAlert* alert = new BAlert(
B_TRANSLATE_SYSTEM_NAME("VirtualMemory"), B_TRANSLATE(
"Disabling virtual memory will have unwanted effects on "
"system stability once the memory is used up.\n"
"Virtual memory does not affect system performance "
@ -312,7 +321,13 @@ SettingsWindow::MessageReceived(BMessage* message)
}
}
fSettings.SetSwapEnabled(value != 0);
_RecordChoices();
_Update();
break;
}
case kMsgSwapAutomaticUpdate:
{
_RecordChoices();
_Update();
break;
}
@ -327,142 +342,155 @@ bool
SettingsWindow::QuitRequested()
{
fSettings.SetWindowPosition(Frame().LeftTop());
_RecordChoices();
fSettings.WriteWindowSettings();
fSettings.WriteSwapSettings();
be_app->PostMessage(B_QUIT_REQUESTED);
return true;
}
status_t
SettingsWindow::_AddVolumeMenuItem(dev_t device)
{
if (_FindVolumeMenuItem(device) != NULL)
return B_ERROR;
VolumeMenuItem* item = new VolumeMenuItem(device,
new BMessage(kMsgVolumeSelected));
fs_info info;
if (fs_stat_dev(device, &info) == 0) {
node_ref node;
node.device = info.dev;
node.node = info.root;
AddHandler(item);
watch_node(&node, B_WATCH_NAME, item);
}
fVolumeMenuField->Menu()->AddItem(item);
return B_OK;
}
status_t
SettingsWindow::_RemoveVolumeMenuItem(dev_t device)
{
VolumeMenuItem* item = _FindVolumeMenuItem(device);
if (item != NULL) {
fVolumeMenuField->Menu()->RemoveItem(item);
delete item;
return B_OK;
}
return B_ERROR;
}
VolumeMenuItem*
SettingsWindow::_FindVolumeMenuItem(dev_t device)
{
VolumeMenuItem* item = NULL;
int32 count = fVolumeMenuField->Menu()->CountItems();
for (int i = 0; i < count; i++) {
item = (VolumeMenuItem*)fVolumeMenuField->Menu()->ItemAt(i);
if (item->Volume().Device() == device)
return item;
}
return NULL;
}
void
SettingsWindow::_RecordChoices()
{
fSettings.SetSwapAutomatic(fSwapAutomaticCheckBox->Value());
fSettings.SetSwapEnabled(fSwapEnabledCheckBox->Value());
fSettings.SetSwapSize((off_t)fSizeSlider->Value() * kMegaByte);
fSettings.SetSwapVolume(((VolumeMenuItem*)fVolumeMenuField
->Menu()->FindMarked())->Volume().Device());
}
void
SettingsWindow::_Update()
{
if ((fSwapEnabledCheckBox->Value() != 0) != fSettings.SwapEnabled())
fSwapEnabledCheckBox->SetValue(fSettings.SwapEnabled());
fSwapEnabledCheckBox->SetValue(fSettings.SwapEnabled());
fSwapAutomaticCheckBox->SetValue(fSettings.SwapAutomatic());
#ifdef SWAP_VOLUME_IMPLEMENTED
if (fVolumeMenuField->IsEnabled() != fSettings.SwapEnabled())
fVolumeMenuField->SetEnabled(fSettings.SwapEnabled());
VolumeMenuItem* selectedVolumeItem =
(VolumeMenuItem*)fVolumeMenuField->Menu()->FindMarked();
if (selectedVolumeItem == NULL) {
VolumeMenuItem* currentVolumeItem;
int32 items = fVolumeMenuField->Menu()->CountItems();
for (int32 index = 0; index < items; ++index) {
currentVolumeItem = ((VolumeMenuItem*)fVolumeMenuField->Menu()->ItemAt(index));
if (*(currentVolumeItem->fVolume) == fSettings.SwapVolume()) {
currentVolumeItem->SetMarked(true);
break;
}
VolumeMenuItem* item = _FindVolumeMenuItem(fSettings.SwapVolume());
if (item != NULL) {
fSizeSlider->SetEnabled(true);
item->SetMarked(true);
BEntry swapFile;
if (gBootDev == item->Volume().Device())
swapFile.SetTo("/var/swap");
else {
BDirectory root;
item->Volume().GetRootDirectory(&root);
swapFile.SetTo(&root, "swap");
}
} else if (*selectedVolumeItem->fVolume != fSettings.SwapVolume()) {
VolumeMenuItem* currentVolumeItem;
int32 items = fVolumeMenuField->Menu()->CountItems();
for (int32 index = 0; index < items; ++index) {
currentVolumeItem = ((VolumeMenuItem*)fVolumeMenuField->Menu()->ItemAt(index));
if (*(currentVolumeItem->fVolume) == fSettings.SwapVolume()) {
currentVolumeItem->SetMarked(true);
break;
}
}
}
#endif
fWarningStringView->SetText("");
fLocked = false;
if (fSettings.IsRevertible())
fWarningStringView->SetText(
B_TRANSLATE("Changes will take effect on restart!"));
if (fRevertButton->IsEnabled() != fSettings.IsRevertible())
fRevertButton->SetEnabled(fSettings.IsRevertible());
off_t minSize, maxSize;
if (_GetSwapFileLimits(minSize, maxSize) == B_OK) {
// round to nearest MB -- slider steps in whole MBs
off_t swapFileSize = 0;
swapFile.GetSize(&swapFileSize);
char sizeStr[16];
off_t freeSpace = item->Volume().FreeBytes() + swapFileSize;
off_t safeSpace = freeSpace - (off_t)(0.15 * freeSpace);
(safeSpace >>= 20) <<= 20;
off_t minSize = B_PAGE_SIZE + kMegaByte;
(minSize >>= 20) <<= 20;
(maxSize >>= 20) <<= 20;
BString minLabel, maxLabel;
minLabel << byte_string(minSize);
maxLabel << byte_string(maxSize);
if (minLabel != fSizeSlider->MinLimitLabel()
|| maxLabel != fSizeSlider->MaxLimitLabel()) {
fSizeSlider->SetLimitLabels(minLabel.String(), maxLabel.String());
fSizeSlider->SetLimits(minSize / kMegaByte, maxSize / kMegaByte);
}
} else if (fSettings.SwapEnabled()) {
fWarningStringView->SetText(
B_TRANSLATE("Insufficient space for a swap file."));
fLocked = true;
}
if (fSizeSlider->Value() != fSettings.SwapSize() / kMegaByte)
minLabel << string_for_size(minSize, sizeStr, sizeof(sizeStr));
maxLabel << string_for_size(safeSpace, sizeStr, sizeof(sizeStr));
fSizeSlider->SetLimitLabels(minLabel.String(), maxLabel.String());
fSizeSlider->SetLimits(minSize / kMegaByte, safeSpace / kMegaByte);
fSizeSlider->SetValue(fSettings.SwapSize() / kMegaByte);
if (fSizeSlider->IsEnabled() != fSettings.SwapEnabled() || fLocked)
{
fSizeSlider->SetEnabled(fSettings.SwapEnabled() && !fLocked);
fSettings.SetSwapSize((off_t)fSizeSlider->Value() * kMegaByte);
}
}
} else
fSizeSlider->SetEnabled(false);
bool revertable = fSettings.IsRevertable();
if (revertable)
fWarningStringView->Show();
else
fWarningStringView->Hide();
status_t
SettingsWindow::_GetSwapFileLimits(off_t& minSize, off_t& maxSize)
{
minSize = kMegaByte;
fRevertButton->SetEnabled(revertable);
fDefaultsButton->SetEnabled(fSettings.IsDefaultable());
// maximum size is the free space on the current volume
// (minus some safety offset, depending on the disk size)
off_t freeSpace = fSettings.SwapVolume().FreeBytes();
off_t safetyFreeSpace = fSettings.SwapVolume().Capacity() / 100;
if (safetyFreeSpace > 1024 * kMegaByte)
safetyFreeSpace = 1024 * kMegaByte;
// Automatic Swap depends on swap being enabled
fSwapAutomaticCheckBox->SetEnabled(fSettings.SwapEnabled());
// check if there already is a page file on this disk and
// adjust the free space accordingly
BPath path;
if (find_directory(B_COMMON_VAR_DIRECTORY, &path, false,
&fSettings.SwapVolume()) == B_OK) {
path.Append("swap");
BEntry swap(path.Path());
off_t size;
if (swap.GetSize(&size) == B_OK) {
// If swap file exists, forget about safety space;
// disk may have filled after creation of swap file.
safetyFreeSpace = 0;
freeSpace += size;
}
}
maxSize = freeSpace - safetyFreeSpace;
if (maxSize < minSize) {
maxSize = 0;
minSize = 0;
return B_ERROR;
}
return B_OK;
// Manual swap settings depend on enabled swap
// and automatic swap being disabled
fSizeSlider->SetEnabled(fSettings.SwapEnabled()
&& !fSwapAutomaticCheckBox->Value());
fVolumeMenuField->SetEnabled(fSettings.SwapEnabled()
&& !fSwapAutomaticCheckBox->Value());
}
void
SettingsWindow::_SetSwapDefaults()
SettingsWindow::_UpdateSwapInfo()
{
fSettings.SetSwapEnabled(true);
system_memory_info memInfo = {};
__get_system_info_etc(B_MEMORY_INFO, &memInfo, sizeof(memInfo));
BVolumeRoster volumeRoster;
BVolume temporaryVolume;
volumeRoster.GetBootVolume(&temporaryVolume);
fSettings.SetSwapVolume(temporaryVolume);
off_t currentSwapSize = memInfo.max_swap_space;
off_t currentSwapUsed = (memInfo.max_swap_space - memInfo.free_swap_space);
system_info info;
get_system_info(&info);
off_t defaultSize = (off_t)info.max_pages * B_PAGE_SIZE;
off_t minSize, maxSize;
_GetSwapFileLimits(minSize, maxSize);
if (defaultSize > maxSize / 2)
defaultSize = maxSize / 2;
fSettings.SetSwapSize(defaultSize);
char sizeStr[16];
BString swapSizeStr = string_for_size(currentSwapSize, sizeStr,
sizeof(sizeStr));
BString swapUsedStr = string_for_size(currentSwapUsed, sizeStr,
sizeof(sizeStr));
BString string = swapUsedStr << " / " << swapSizeStr;
fSwapUsageBar->SetMaxValue(currentSwapSize / kMegaByte);
fSwapUsageBar->Update(currentSwapUsed / kMegaByte,
B_TRANSLATE("Current Swap:"), string.String());
}

View File

@ -1,43 +1,88 @@
/*
* Copyright 2005-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2005-2006, Axel Dörfler, axeld@pinc-software.de
* All rights reserved. Distributed under the terms of the MIT License.
*
* Copyright 2010-2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Hamish Morrison, hamish@lavabit.com
* Alexander von Gluck, kallisti5@unixzen.com
*/
#ifndef SETTINGS_WINDOW_H
#define SETTINGS_WINDOW_H
#include <MenuItem.h>
#include <Slider.h>
#include <StatusBar.h>
#include <Volume.h>
#include <Window.h>
#include "Settings.h"
class BStringView;
class BCheckBox;
class BSlider;
class BButton;
class BMenuField;
class SizeSlider : public BSlider {
public:
SizeSlider(const char* name, const char* label,
BMessage* message, int32 min, int32 max,
uint32 flags);
virtual ~SizeSlider() {};
virtual const char* UpdateText() const;
private:
mutable char fText[128];
};
class VolumeMenuItem : public BMenuItem, public BHandler {
public:
VolumeMenuItem(BVolume volume, BMessage* message);
virtual ~VolumeMenuItem() {}
virtual BVolume Volume() { return fVolume; }
virtual void MessageReceived(BMessage* message);
virtual void GenerateLabel();
private:
BVolume fVolume;
};
class SettingsWindow : public BWindow {
public:
SettingsWindow();
virtual ~SettingsWindow();
public:
SettingsWindow();
virtual ~SettingsWindow() {};
virtual bool QuitRequested();
virtual void MessageReceived(BMessage* message);
virtual void MessageReceived(BMessage* message);
virtual bool QuitRequested();
private:
void _Update();
status_t _GetSwapFileLimits(off_t& minSize, off_t& maxSize);
void _SetSwapDefaults();
private:
status_t _AddVolumeMenuItem(dev_t device);
status_t _RemoveVolumeMenuItem(dev_t device);
VolumeMenuItem* _FindVolumeMenuItem(dev_t device);
BCheckBox* fSwapEnabledCheckBox;
BSlider* fSizeSlider;
BButton* fDefaultsButton;
BButton* fRevertButton;
BStringView* fWarningStringView;
BMenuField* fVolumeMenuField;
Settings fSettings;
bool fLocked;
void _RecordChoices();
void _Update();
void _UpdateSwapInfo();
BCheckBox* fSwapEnabledCheckBox;
BCheckBox* fSwapAutomaticCheckBox;
BSlider* fSizeSlider;
BButton* fDefaultsButton;
BButton* fRevertButton;
BStringView* fWarningStringView;
BMenuField* fVolumeMenuField;
BStatusBar* fSwapUsageBar;
Settings fSettings;
};
#endif /* SETTINGS_WINDOW_H */

View File

@ -8,6 +8,7 @@
#include "SettingsWindow.h"
#include <Alert.h>
#include <Catalog.h>
#include <TextView.h>

View File

@ -7,24 +7,15 @@
#include <Application.h>
#include <Catalog.h>
#include <Locale.h>
class VMSettings;
class VirtualMemory : public BApplication {
public:
VirtualMemory();
virtual ~VirtualMemory();
public:
VirtualMemory();
virtual ~VirtualMemory();
virtual void ReadyToRun();
virtual void AboutRequested();
private:
void GetCurrentSettings(bool& enabled, off_t& size);
VMSettings *fSettings;
virtual void ReadyToRun();
virtual void AboutRequested();
};
#endif /* VIRTUAL_MEMORY_H */

View File

@ -25,7 +25,6 @@
#include "mmu.h"
#include "acpi.h"
#include "hpet.h"
#define NO_SMP 0

View File

@ -1,8 +1,14 @@
.section .init
.globl _start
_start:
b jmp_loader
.balign 0x8000, 0
.section .text
/* Start "safe" code area.
* 0x4000 minimum safe area
* defined in boot_loader_raspberrypi_arm.ld
*/
jmp_loader:
/* Start Haiku loader */

View File

@ -1,6 +1,4 @@
/*
* Copyright 2012, Alexander von Gluck IV, kallisti5@unixzen.com.
* Copyright 2011, Hamish Morrison, hamish@lavabit.com.
* Copyright 2008, Zhao Shuai, upczhsh@163.com.
* Copyright 2008-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de.
@ -8,6 +6,13 @@
*
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*
* Copyright 2011-2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Hamish Morrison, hamish@lavabit.com
* Alexander von Gluck IV, kallisti5@unixzen.com
*/
@ -1456,52 +1461,59 @@ swap_init_post_modules()
if (enabled != NULL) {
swapEnabled = get_driver_boolean_parameter(settings, "vm",
false, false);
true, false);
swapAutomatic = get_driver_boolean_parameter(settings, "swap_auto",
true, false);
const char* size = get_driver_parameter(settings, "swap_size",
NULL, NULL);
const char* volume = get_driver_parameter(settings,
"swap_volume_name", NULL, NULL);
const char* device = get_driver_parameter(settings,
"swap_volume_device", NULL, NULL);
const char* filesystem = get_driver_parameter(settings,
"swap_volume_filesystem", NULL, NULL);
const char* capacity = get_driver_parameter(settings,
"swap_volume_capacity", NULL, NULL);
if (swapEnabled && !swapAutomatic) {
const char* size = get_driver_parameter(settings, "swap_size",
NULL, NULL);
const char* volume = get_driver_parameter(settings,
"swap_volume_name", NULL, NULL);
const char* device = get_driver_parameter(settings,
"swap_volume_device", NULL, NULL);
const char* filesystem = get_driver_parameter(settings,
"swap_volume_filesystem", NULL, NULL);
const char* capacity = get_driver_parameter(settings,
"swap_volume_capacity", NULL, NULL);
if (size != NULL && device != NULL && volume != NULL
&& filesystem != NULL && capacity != NULL) {
// User specified a size / volume
swapAutomatic = false;
swapSize = atoll(size);
strncpy(selectedVolume.name, volume,
sizeof(selectedVolume.name));
strncpy(selectedVolume.device, device,
sizeof(selectedVolume.device));
strncpy(selectedVolume.filesystem, filesystem,
sizeof(selectedVolume.filesystem));
selectedVolume.capacity = atoll(capacity);
} else if (size != NULL) {
// Older file format, no location information (assume /var/swap)
swapAutomatic = false;
swapSize = atoll(size);
swapDeviceID = gBootDevice;
if (size != NULL && device != NULL && volume != NULL
&& filesystem != NULL && capacity != NULL) {
// User specified a size / volume that seems valid
swapAutomatic = false;
swapSize = atoll(size);
strncpy(selectedVolume.name, volume,
sizeof(selectedVolume.name));
strncpy(selectedVolume.device, device,
sizeof(selectedVolume.device));
strncpy(selectedVolume.filesystem, filesystem,
sizeof(selectedVolume.filesystem));
selectedVolume.capacity = atoll(capacity);
} else {
// Something isn't right with swap config, go auto
swapAutomatic = true;
dprintf("%s: virtual_memory configuration is invalid, "
"using automatic swap\n", __func__);
}
}
unload_driver_settings(settings);
}
unload_driver_settings(settings);
}
if (swapAutomatic) {
swapEnabled = true;
swapSize = (off_t)vm_page_num_pages() * B_PAGE_SIZE;
if (swapSize <= (1024 * 1024 * 1024)) {
// Memory under 1GB? double the swap
swapSize *= 2;
}
// Automatic swap defaults to the boot device
swapDeviceID = gBootDevice;
}
if (!swapEnabled || swapSize < B_PAGE_SIZE)
if (!swapEnabled || swapSize < B_PAGE_SIZE) {
dprintf("%s: virtual_memory is disabled\n", __func__);
return;
}
if (!swapAutomatic && swapDeviceID < 0) {
// If user-specified swap, and no swap device has been chosen yet...

View File

@ -11,10 +11,22 @@ UND_STACK_SIZE = 0;
SECTIONS
{
/*
* Raspberry Pi boot logic:
* start.elf loads the kernel specified in config.txt
* if a dtb exists, it is loaded at 0x100 and the kernel at 0x8000
* else if disable_commandline_tags true, set kernel load address to 0x0
* else load kernel at 0x8000 and put atags at 0x100
*/
. = BOARD_LOADER_BASE;
/* text/read-only data */
.text : {
/* .init is a stub that jumps to code at .text */
.init : {
*(.init)
}
.text 0x8000 : {
CREATE_OBJECT_SYMBOLS
*(.text .text.* .gnu.linkonce.t.*)
*(.plt)