diff --git a/includes/common.inc b/includes/common.inc
index 262e1c5..f5e8b60 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -226,12 +226,34 @@ function drupal_get_profile() {
     $profile = $install_state['parameters']['profile'];
   }
   else {
-    $profile = variable_get('install_profile', 'standard');
+    $profile = variable_get('install_profile', NULL);
+    if (empty($profile)) {
+      $profiles = drupal_get_profiles();
+      $profile = array_shift($profiles);
+    }
   }
 
   return $profile;
 }
 
+/**
+ * Returns an array of the installation profile hierarchy.
+ *
+ * @return $profiles
+ *   An array of installation profiles.
+ */
+function drupal_get_profiles() {
+  global $install_state;
+
+  if (!empty($install_state['profiles'])) {
+    $profiles = $install_state['profiles'];
+  }
+  else {
+    $profiles = variable_get('install_profiles', array('standard'));
+  }
+
+  return $profiles;
+}
 
 /**
  * Sets the breadcrumb trail for the current page.
@@ -5348,7 +5370,6 @@ function drupal_system_listing($mask, $directory, $key = 'name', $min_depth = 1)
   // that /modules is pristine for core; users should avoid changing anything
   // there in favor of sites/all or sites/<domain> directories.
   $profiles = array();
-  $profile = drupal_get_profile();
   // For SimpleTest to be able to test modules packaged together with a
   // distribution we need to include the profile of the parent site (in which
   // test runs are triggered).
@@ -5360,7 +5381,7 @@ function drupal_system_listing($mask, $directory, $key = 'name', $min_depth = 1)
   }
   // In case both profile directories contain the same extension, the actual
   // profile always has precedence.
-  $profiles[] = $profile;
+  $profiles += array_reverse(drupal_get_profiles());
   foreach ($profiles as $profile) {
     if (file_exists("profiles/$profile/$directory")) {
       $searchdir[] = "profiles/$profile/$directory";
diff --git a/includes/install.core.inc b/includes/install.core.inc
index 7a694e9..7bcbb12 100644
--- a/includes/install.core.inc
+++ b/includes/install.core.inc
@@ -162,8 +162,10 @@ function install_state_defaults() {
     // An array of information about the chosen installation profile. This will
     // be filled in based on the profile's .info file.
     'profile_info' => array(),
-    // An array of available installation profiles.
+    // An array of the profile hiearchy.
     'profiles' => array(),
+    // An array of available installation profiles.
+    'profiles_available' => array(),
     // An array of server variables that will be substituted into the global
     // $_SERVER array via drupal_override_server_variables(). Used by
     // non-interactive installations only.
@@ -526,14 +528,14 @@ function install_tasks($install_state) {
   $tasks = array(
     'install_select_profile' => array(
       'display_name' => st('Choose profile'),
-      'display' => count($install_state['profiles']) != 1,
+      'display' => count($install_state['profiles_available']) != 1,
       'run' => INSTALL_TASK_RUN_IF_REACHED,
     ),
-    'install_select_locale' => array(
-      'display_name' => st('Choose language'),
+    'install_load_profile' => array(
       'run' => INSTALL_TASK_RUN_IF_REACHED,
     ),
-    'install_load_profile' => array(
+    'install_select_locale' => array(
+      'display_name' => st('Choose language'),
       'run' => INSTALL_TASK_RUN_IF_REACHED,
     ),
     'install_verify_requirements' => array(
@@ -550,7 +552,7 @@ function install_tasks($install_state) {
       'run' => INSTALL_TASK_RUN_IF_REACHED,
     ),
     'install_profile_modules' => array(
-      'display_name' => count($install_state['profiles']) == 1 ? st('Install site') : st('Install profile'),
+      'display_name' => count($install_state['profiles_available']) == 1 ? st('Install site') : st('Install profile'),
       'type' => 'batch',
     ),
     'install_import_locales' => array(
@@ -565,19 +567,21 @@ function install_tasks($install_state) {
     ),
   );
 
-  // Now add any tasks defined by the installation profile.
-  if (!empty($install_state['parameters']['profile'])) {
-    // Load the profile install file, because it is not always loaded when
-    // hook_install_tasks() is invoked (e.g. batch processing).
-    $profile_install_file = DRUPAL_ROOT . '/profiles/' . $install_state['parameters']['profile'] . '/' . $install_state['parameters']['profile'] . '.install';
-    if (file_exists($profile_install_file)) {
-      include_once $profile_install_file;
-    }
-    $function = $install_state['parameters']['profile'] . '_install_tasks';
-    if (function_exists($function)) {
-      $result = $function($install_state);
-      if (is_array($result)) {
-        $tasks += $result;
+  // Now add any tasks defined by the installation profiles.
+  if (!empty($install_state['profiles'])) {
+    $profiles = array_reverse($install_state['profiles']);
+    foreach ($profiles as $profile) {
+      $profile_install_file = DRUPAL_ROOT . '/profiles/' . $profile . '/' . $profile . '.install';
+      if (file_exists($profile_install_file)) {
+        include_once $profile_install_file;
+      }
+
+      $function = $profile . '_install_tasks';
+      if (function_exists($function)) {
+        $result = $function($install_state);
+        if (is_array($result)) {
+          $tasks += $result;
+        }
       }
     }
   }
@@ -595,14 +599,17 @@ function install_tasks($install_state) {
     ),
   );
 
-  // Allow the installation profile to modify the full list of tasks.
-  if (!empty($install_state['parameters']['profile'])) {
-    $profile_file = DRUPAL_ROOT . '/profiles/' . $install_state['parameters']['profile'] . '/' . $install_state['parameters']['profile'] . '.profile';
-    if (file_exists($profile_file)) {
-      include_once $profile_file;
-      $function = $install_state['parameters']['profile'] . '_install_tasks_alter';
-      if (function_exists($function)) {
-        $function($tasks, $install_state);
+  // Allow for the installation profiles to modify the full list of tasks.
+  if (!empty($install_state['profiles'])) {
+    $profiles = array_reverse($install_state['profiles']);
+    foreach ($profiles as $profile) {
+      $profile_file = DRUPAL_ROOT . '/profiles/' . $profile . '/' . $profile . '.profile';
+      if (file_exists($profile_file)) {
+        include_once $profile_file;
+        $function = $profile . '_install_tasks_alter';
+        if (function_exists($function)) {
+          $function($tasks, $install_state);
+        }
       }
     }
   }
@@ -772,11 +779,26 @@ function install_system_module(&$install_state) {
 
   // Save the list of other modules to install for the upcoming tasks.
   // variable_set() can be used now that system.module is installed.
-  $modules = $install_state['profile_info']['dependencies'];
+  $modules = array();
+  $profiles = array($install_state['parameters']['profile']);
+  $profile_info = $install_state['profile_info'];
+  do {
+    $modules = array_merge($modules, $profile_info['dependencies']);
+    if (!empty($profile_info['base profile']) && isset($profile_info[$profile_info['base profile']])) {
+      $profiles[] = $profile_info['base profile'];
+      $profile_info = $profile_info[$profile_info['base profile']];
+    }
+    else {
+      $profile_info = NULL;
+    }
+  }
+  while ($profile_info);
 
   // The installation profile is also a module, which needs to be installed
   // after all the dependencies have been installed.
-  $modules[] = drupal_get_profile();
+  foreach ($profiles as $profile) {
+    $modules[] = $profile;
+  }
 
   variable_set('install_profile_modules', array_diff($modules, array('system')));
   $install_state['database_tables_exist'] = TRUE;
@@ -1014,10 +1036,10 @@ function install_find_profiles() {
  *   thrown if a profile cannot be chosen automatically.
  */
 function install_select_profile(&$install_state) {
-  $install_state['profiles'] += install_find_profiles();
+  $install_state['profiles_available'] += install_find_profiles();
   if (empty($install_state['parameters']['profile'])) {
     // Try to find a profile.
-    $profile = _install_select_profile($install_state['profiles']);
+    $profile = _install_select_profile($install_state['profiles_available']);
     if (empty($profile)) {
       // We still don't have a profile, so display a form for selecting one.
       // Only do this in the case of interactive installations, since this is
@@ -1027,7 +1049,7 @@ function install_select_profile(&$install_state) {
       if ($install_state['interactive']) {
         include_once DRUPAL_ROOT . '/includes/form.inc';
         drupal_set_title(st('Select an installation profile'));
-        $form = drupal_get_form('install_select_profile_form', $install_state['profiles']);
+        $form = drupal_get_form('install_select_profile_form', $install_state['profiles_available']);
         return drupal_render($form);
       }
       else {
@@ -1342,10 +1364,25 @@ function install_load_profile(&$install_state) {
   $profile_file = DRUPAL_ROOT . '/profiles/' . $install_state['parameters']['profile'] . '/' . $install_state['parameters']['profile'] . '.profile';
   if (file_exists($profile_file)) {
     include_once $profile_file;
-    $install_state['profile_info'] = install_profile_info($install_state['parameters']['profile'], $install_state['parameters']['locale']);
+    $install_state['profiles'][] = $install_state['parameters']['profile'];
+    $install_state['profile_info'] = install_profile_info($install_state['parameters']['profile']);
+    $profile_info = &$install_state['profile_info'];
+    while (isset($profile_info['base profile']) && $profile_info['base profile']) {
+      $profile = $profile_info['base profile'];
+      $profile_file = DRUPAL_ROOT . '/profiles/' . $profile . '/' . $profile . '.profile';
+      if (file_exists($profile_file)) {
+        include_once $profile_file;
+        $install_state['profiles'][] = $profile;
+        $profile_info[$profile] = install_profile_info($profile);
+        $profile_info = &$profile_info[$profile];
+      }
+      else {
+        throw new Exception(install_no_profile_error());
+      }
+    }
   }
   else {
-    throw new Exception(st('Sorry, the profile you have chosen cannot be loaded.'));
+    throw new Exception(install_no_profile_error());
   }
 }
 
@@ -1380,7 +1417,10 @@ function install_profile_modules(&$install_state) {
   // Although the profile module is marked as required, it needs to go after
   // every dependency, including non-required ones. So clear its required
   // flag for now to allow it to install late.
-  $files[$install_state['parameters']['profile']]->info['required'] = FALSE;
+  foreach ($install_state['profiles'] as $profile) {
+    $files[$profile]->info['required'] = FALSE;
+  }
+
   // Add modules that other modules depend on.
   foreach ($modules as $module) {
     if ($files[$module]->requires) {
@@ -1541,13 +1581,19 @@ function install_finished(&$install_state) {
 
   // Remember the profile which was used.
   variable_set('install_profile', drupal_get_profile());
+  variable_set('install_profiles', drupal_get_profiles());
 
   // Installation profiles are always loaded last
-  db_update('system')
-    ->fields(array('weight' => 1000))
-    ->condition('type', 'module')
-    ->condition('name', drupal_get_profile())
-    ->execute();
+  $profiles = drupal_get_profiles();
+  $weight = 1000 + count($profiles);
+  foreach (drupal_get_profiles() as $profile) {
+    db_update('system')
+      ->fields(array('weight' => $weight))
+      ->condition('type', 'module')
+      ->condition('name', $profile)
+      ->execute();
+    $weight = $weight - 1;
+  }
 
   // Cache a fully-built schema.
   drupal_get_schema(NULL, TRUE);
@@ -1586,10 +1632,12 @@ function _install_profile_modules_finished($success, $results, $operations) {
  * Checks installation requirements and reports any errors.
  */
 function install_check_requirements($install_state) {
-  $profile = $install_state['parameters']['profile'];
+  $requirements = array();
 
   // Check the profile requirements.
-  $requirements = drupal_check_profile($profile);
+  foreach ($install_state['profiles'] as $profile) {
+    $requirements += drupal_check_profile($profile);
+  }
 
   // If Drupal is not set up already, we need to create a settings file.
   if (!$install_state['settings_verified']) {
diff --git a/includes/install.inc b/includes/install.inc
index 3631c36..60b976c 100644
--- a/includes/install.inc
+++ b/includes/install.inc
@@ -669,18 +669,31 @@ function drupal_rewrite_settings($settings = array(), $prefix = '') {
  *   The list of modules to install.
  */
 function drupal_verify_profile($install_state) {
-  $profile = $install_state['parameters']['profile'];
+  $profiles = $install_state['profiles'];
   $locale = $install_state['parameters']['locale'];
 
   include_once DRUPAL_ROOT . '/includes/file.inc';
   include_once DRUPAL_ROOT . '/includes/common.inc';
 
-  $profile_file = DRUPAL_ROOT . "/profiles/$profile/$profile.profile";
-
-  if (!isset($profile) || !file_exists($profile_file)) {
+  if (!empty($profiles)) {
+    foreach ($profiles as $profile) {
+      $profile_file = DRUPAL_ROOT . '/profiles/' . $profile . '/' . $profile . '.profile';
+      if (!file_exists($profile_file)) {
+        throw new Exception(install_no_profile_error());
+      }
+    }
+  }
+  else {
     throw new Exception(install_no_profile_error());
   }
+
   $info = $install_state['profile_info'];
+  $dependencies = $info['dependencies'];
+
+  while (isset($info['base profile']) && $info[$info['base profile']]) {
+    $info = $info[$info['base profile']];
+    $dependencies += $info['dependencies'];
+  }
 
   // Get a list of modules that exist in Drupal's assorted subdirectories.
   $present_modules = array();
@@ -690,10 +703,10 @@ function drupal_verify_profile($install_state) {
 
   // The installation profile is also a module, which needs to be installed
   // after all the other dependencies have been installed.
-  $present_modules[] = drupal_get_profile();
+  $present_modules = array_merge($present_modules, drupal_get_profiles());
 
   // Verify that all of the profile's required modules are present.
-  $missing_modules = array_diff($info['dependencies'], $present_modules);
+  $missing_modules = array_diff($dependencies, $present_modules);
 
   $requirements = array();
 
@@ -1287,6 +1300,7 @@ function install_profile_info($profile, $locale = 'en') {
       'dependencies' => array(),
       'description' => '',
       'distribution_name' => 'Drupal',
+      'base profile' => NULL,
       'version' => NULL,
       'hidden' => FALSE,
       'php' => DRUPAL_MINIMUM_PHP,
diff --git a/modules/system/system.module b/modules/system/system.module
index 2bbcd7f..ab5e996 100644
--- a/modules/system/system.module
+++ b/modules/system/system.module
@@ -2363,14 +2363,20 @@ function _system_rebuild_module_data() {
   $modules = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.module$/', 'modules', 'name', 0);
 
   // Include the installation profile in modules that are loaded.
-  $profile = drupal_get_profile();
-  $modules[$profile] = new stdClass();
-  $modules[$profile]->name = $profile;
-  $modules[$profile]->uri = 'profiles/' . $profile . '/' . $profile . '.profile';
-  $modules[$profile]->filename = $profile . '.profile';
+  $profiles = drupal_get_profiles();
+  $weight = 1000 + count($profiles);
+
+  foreach ($profiles as $profile) {
+    $modules[$profile] = new stdClass();
+    $modules[$profile]->name = $profile;
+    $modules[$profile]->uri = 'profiles/' . $profile . '/' . $profile . '.profile';
+    $modules[$profile]->filename = $profile . '.profile';
+
+    // Installation profile hooks are always executed last.
+    $modules[$profile]->weight = $weight;
+    $weight = $weight - 1;
+  }
 
-  // Installation profile hooks are always executed last.
-  $modules[$profile]->weight = 1000;
 
   // Set defaults for module info.
   $defaults = array(
@@ -2422,7 +2428,11 @@ function _system_rebuild_module_data() {
     drupal_alter('system_info', $modules[$key]->info, $modules[$key], $type);
   }
 
-  if (isset($modules[$profile])) {
+  foreach ($profiles as $profile) {
+    if (!isset($modules[$profile])) {
+      continue;
+    }
+
     // The installation profile is required, if it's a valid module.
     $modules[$profile]->info['required'] = TRUE;
     // Add a default distribution name if the profile did not provide one. This
