diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2007-10-18 06:04:52 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-18 17:37:19 -0400 |
commit | d307c4a8e826c44f9633bd3f7e60d0491e7d885a (patch) | |
tree | 1e381840363594557c5e31b1bcdc3f491d474039 /kernel/power/snapshot.c | |
parent | 50a1efe14fd56a273cdbe53bf1c7fc12099d2e1a (diff) |
Hibernation: Arbitrary boot kernel support - generic code
Add the bits needed for supporting arbitrary boot kernels to the common
hibernation code.
To support arbitrary boot kernels, make it possible to replace the 'struct
new_utsname' and the kernel version in the hibernation image header by some
architecture specific data that will be used to verify if the image is valid
and to restore the image.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/power/snapshot.c')
-rw-r--r-- | kernel/power/snapshot.c | 53 |
1 files changed, 35 insertions, 18 deletions
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index a686590d88c1..ccc95ac07bed 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c | |||
@@ -1239,17 +1239,39 @@ asmlinkage int swsusp_save(void) | |||
1239 | return 0; | 1239 | return 0; |
1240 | } | 1240 | } |
1241 | 1241 | ||
1242 | static void init_header(struct swsusp_info *info) | 1242 | #ifndef CONFIG_ARCH_HIBERNATION_HEADER |
1243 | static int init_header_complete(struct swsusp_info *info) | ||
1243 | { | 1244 | { |
1244 | memset(info, 0, sizeof(struct swsusp_info)); | 1245 | memcpy(&info->uts, init_utsname(), sizeof(struct new_utsname)); |
1245 | info->version_code = LINUX_VERSION_CODE; | 1246 | info->version_code = LINUX_VERSION_CODE; |
1247 | return 0; | ||
1248 | } | ||
1249 | |||
1250 | static char *check_image_kernel(struct swsusp_info *info) | ||
1251 | { | ||
1252 | if (info->version_code != LINUX_VERSION_CODE) | ||
1253 | return "kernel version"; | ||
1254 | if (strcmp(info->uts.sysname,init_utsname()->sysname)) | ||
1255 | return "system type"; | ||
1256 | if (strcmp(info->uts.release,init_utsname()->release)) | ||
1257 | return "kernel release"; | ||
1258 | if (strcmp(info->uts.version,init_utsname()->version)) | ||
1259 | return "version"; | ||
1260 | if (strcmp(info->uts.machine,init_utsname()->machine)) | ||
1261 | return "machine"; | ||
1262 | return NULL; | ||
1263 | } | ||
1264 | #endif /* CONFIG_ARCH_HIBERNATION_HEADER */ | ||
1265 | |||
1266 | static int init_header(struct swsusp_info *info) | ||
1267 | { | ||
1268 | memset(info, 0, sizeof(struct swsusp_info)); | ||
1246 | info->num_physpages = num_physpages; | 1269 | info->num_physpages = num_physpages; |
1247 | memcpy(&info->uts, init_utsname(), sizeof(struct new_utsname)); | ||
1248 | info->cpus = num_online_cpus(); | ||
1249 | info->image_pages = nr_copy_pages; | 1270 | info->image_pages = nr_copy_pages; |
1250 | info->pages = nr_copy_pages + nr_meta_pages + 1; | 1271 | info->pages = nr_copy_pages + nr_meta_pages + 1; |
1251 | info->size = info->pages; | 1272 | info->size = info->pages; |
1252 | info->size <<= PAGE_SHIFT; | 1273 | info->size <<= PAGE_SHIFT; |
1274 | return init_header_complete(info); | ||
1253 | } | 1275 | } |
1254 | 1276 | ||
1255 | /** | 1277 | /** |
@@ -1303,7 +1325,11 @@ int snapshot_read_next(struct snapshot_handle *handle, size_t count) | |||
1303 | return -ENOMEM; | 1325 | return -ENOMEM; |
1304 | } | 1326 | } |
1305 | if (!handle->offset) { | 1327 | if (!handle->offset) { |
1306 | init_header((struct swsusp_info *)buffer); | 1328 | int error; |
1329 | |||
1330 | error = init_header((struct swsusp_info *)buffer); | ||
1331 | if (error) | ||
1332 | return error; | ||
1307 | handle->buffer = buffer; | 1333 | handle->buffer = buffer; |
1308 | memory_bm_position_reset(&orig_bm); | 1334 | memory_bm_position_reset(&orig_bm); |
1309 | memory_bm_position_reset(©_bm); | 1335 | memory_bm_position_reset(©_bm); |
@@ -1394,22 +1420,13 @@ duplicate_memory_bitmap(struct memory_bitmap *dst, struct memory_bitmap *src) | |||
1394 | } | 1420 | } |
1395 | } | 1421 | } |
1396 | 1422 | ||
1397 | static inline int check_header(struct swsusp_info *info) | 1423 | static int check_header(struct swsusp_info *info) |
1398 | { | 1424 | { |
1399 | char *reason = NULL; | 1425 | char *reason; |
1400 | 1426 | ||
1401 | if (info->version_code != LINUX_VERSION_CODE) | 1427 | reason = check_image_kernel(info); |
1402 | reason = "kernel version"; | 1428 | if (!reason && info->num_physpages != num_physpages) |
1403 | if (info->num_physpages != num_physpages) | ||
1404 | reason = "memory size"; | 1429 | reason = "memory size"; |
1405 | if (strcmp(info->uts.sysname,init_utsname()->sysname)) | ||
1406 | reason = "system type"; | ||
1407 | if (strcmp(info->uts.release,init_utsname()->release)) | ||
1408 | reason = "kernel release"; | ||
1409 | if (strcmp(info->uts.version,init_utsname()->version)) | ||
1410 | reason = "version"; | ||
1411 | if (strcmp(info->uts.machine,init_utsname()->machine)) | ||
1412 | reason = "machine"; | ||
1413 | if (reason) { | 1430 | if (reason) { |
1414 | printk(KERN_ERR "swsusp: Resume mismatch: %s\n", reason); | 1431 | printk(KERN_ERR "swsusp: Resume mismatch: %s\n", reason); |
1415 | return -EPERM; | 1432 | return -EPERM; |