suspend-utils/0000755000175500017550000000000012075743453012071 5ustar kixkixsuspend-utils/splashy_funcs.h0000644000175500017550000000074712075743442015131 0ustar kixkix/* * splashy.h * * Boot splash related definitions for splashy method * * Copyright (C) 2006 Tim Dijkstra * * This file is released under the GPLv2. * */ #ifndef SPLASHY_FUNCS_H #define SPLASHY_FUNCS_H #ifdef CONFIG_SPLASHY int splashy_open(int mode); int splashy_finish(void); int splashy_progress(int p); void splashy_read_password(char *, int); int splashy_dialog(const char *); void splashy_print(const char *); #endif #endif /* SPLASHY_FUNCS_H */ suspend-utils/loglevel.c0000644000175500017550000000234412075743442014047 0ustar kixkix/* loglevel.c - routines to modify kernel console loglevel * * Released under GPL v2. * (c) 2007 Tim Dijkstra */ #include "config.h" #include #include #include #include #include #include static FILE *printk_file; static int proc_mounted = 0; inline void open_printk(void) { struct stat stat_buf; char *procname = "/proc/sys/kernel/printk"; if (stat(procname, &stat_buf) && errno == ENOENT) { if (mount("none", "/proc", "proc", 0, NULL)) { fprintf(stderr, "resume: Could not mount proc\n"); return; } else proc_mounted = 1; } printk_file = fopen(procname, "r+"); } inline int get_kernel_console_loglevel(void) { int level = -1; if (printk_file) { rewind(printk_file); fscanf(printk_file, "%d", &level); } return level; } inline void set_kernel_console_loglevel(int level) { if (printk_file) { rewind(printk_file); fprintf(printk_file, "%d\n", level); fflush(printk_file); } } inline void close_printk(void) { if (printk_file) fclose(printk_file); if (proc_mounted) umount("/proc"); } suspend-utils/COPYING.GPL0000644000175500017550000004313012075743442013544 0ustar kixkix GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program 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 2 of the License, or (at your option) any later version. This program 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 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. suspend-utils/encrypt.c0000644000175500017550000000420412075743442013717 0ustar kixkix/* * encrypt.c * * Encryption initialization for the suspend and resume tools * * Copyright (C) 2006 Rafael J. Wysocki * * This file is released under the GPLv2. * */ #include "config.h" #ifdef CONFIG_ENCRYPT #include #include #include #include #include #include #include #include "md5.h" #include "encrypt.h" gcry_cipher_hd_t cipher_handle; struct key_data key_data; /** * read_password - get non-empty, \0-terminated password from stdin * passbuf - buffer of at least PASS_SIZE * 2 chars * vrfy - if verify the password or not */ void read_password(char *pass_buf, int vrfy) { struct termios termios; char *vrfy_buf = vrfy ? pass_buf + PASS_SIZE : pass_buf; int len; tcgetattr(0, &termios); termios.c_lflag &= ~ECHO; termios.c_lflag |= ICANON | ECHONL; tcsetattr(0, TCSANOW, &termios); do { do { printf("Passphrase please (must be non-empty): "); fgets(pass_buf, PASS_SIZE, stdin); len = strlen(pass_buf) - 1; } while (len <= 0); if (pass_buf[len] == '\n') pass_buf[len] = '\0'; if (vrfy) { printf("Verify passphrase: "); fgets(vrfy_buf, PASS_SIZE, stdin); if (vrfy_buf[len] == '\n') vrfy_buf[len] = '\0'; } } while (vrfy && strncmp(pass_buf, vrfy_buf, PASS_SIZE)); termios.c_lflag |= ECHO; tcsetattr(0, TCSANOW, &termios); } /** * encrypt_init - set up the encryption key, initialization vector and mumber * @pass_buf - auxiliary buffer that must be at least 2*PASS_SIZE bytes long * if @vrfy is non-zero or at least PASS_SIZE long otherwise * @key_buf - auxiliary buffer that must be at least max(KEY_SIZE,16) bytes * long */ void encrypt_init(unsigned char *key, unsigned char *ivec, char *pass_buf) { struct md5_ctx ctx; memset(ivec, 0, CIPHER_BLOCK); strncpy((char *)ivec, pass_buf, CIPHER_BLOCK); md5_init_ctx(&ctx); md5_process_bytes(pass_buf, strlen(pass_buf), &ctx); md5_finish_ctx(&ctx, key); } void get_random_salt(unsigned char *salt, size_t size) { int fd; memset(salt, 0, size); fd = open("/dev/urandom", O_RDONLY); if (fd >= 0) { read(fd, salt, size); close(fd); } } #endif suspend-utils/vt.h0000644000175500017550000000035012075743442012667 0ustar kixkix/* vt.h - VT specific routines */ #include int is_a_console(int fd); int open_a_console(const char *fnam); int getconsolefd(void); int fgconsole(void); int chvt(int num); int is_framebuffer(void); char *get_fbname(void); suspend-utils/md5.h0000644000175500017550000000720112075743442012725 0ustar kixkix/* md5.h - Declaration of functions and data types used for MD5 sum computing library functions. Copyright (C) 1995, 1996, 1999, 2000, 2003, 2004 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. This program 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 2, or (at your option) any later version. This program 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 this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _MD5_H #define _MD5_H 1 #include #if HAVE_INTTYPES_H # include #endif #if HAVE_STDINT_H || _LIBC # include #endif typedef uint32_t md5_uint32; /* Structure to save state of computation between the single steps. */ struct md5_ctx { md5_uint32 A; md5_uint32 B; md5_uint32 C; md5_uint32 D; md5_uint32 total[2]; md5_uint32 buflen; char buffer[128]; }; /* * The following three functions are build up the low level used in * the functions `md5_stream' and `md5_buffer'. */ /* Initialize structure containing state of computation. (RFC 1321, 3.3: Step 3) */ extern void md5_init_ctx (struct md5_ctx *ctx); /* Starting with the result of former calls of this function (or the initialization function update the context for the next LEN bytes starting at BUFFER. It is necessary that LEN is a multiple of 64!!! */ extern void md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx); /* Starting with the result of former calls of this function (or the initialization function update the context for the next LEN bytes starting at BUFFER. It is NOT required that LEN is a multiple of 64. */ extern void md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx); /* Process the remaining bytes in the buffer and put result from CTX in first 16 bytes following RESBUF. The result is always in little endian byte order, so that a byte-wise output yields to the wanted ASCII representation of the message digest. IMPORTANT: On some systems it is required that RESBUF be correctly aligned for a 32 bits value. */ extern void *md5_finish_ctx (struct md5_ctx *ctx, void *resbuf); /* Put result from CTX in first 16 bytes following RESBUF. The result is always in little endian byte order, so that a byte-wise output yields to the wanted ASCII representation of the message digest. IMPORTANT: On some systems it is required that RESBUF is correctly aligned for a 32 bits value. */ extern void *md5_read_ctx (const struct md5_ctx *ctx, void *resbuf); /* Compute MD5 message digest for bytes read from STREAM. The resulting message digest number will be written into the 16 bytes beginning at RESBLOCK. */ extern int md5_stream (FILE *stream, void *resblock); /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The result is always in little endian byte order, so that a byte-wise output yields to the wanted ASCII representation of the message digest. */ extern void *md5_buffer (const char *buffer, size_t len, void *resblock); #define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) #endif suspend-utils/Makefile.am0000644000175500017550000000725012075743442014127 0ustar kixkix# # Makefile.am # # Copyright (C) 2007 Alon Bar-Lev # # This file is released under the GPLv2. # AUTOMAKE_OPTIONS=foreign dist-bzip2 MAINTAINERCLEANFILES = \ config.log config.status \ $(srcdir)/Makefile.in \ $(srcdir)/config.h.in $(srcdir)/config.h.in~ $(srcdir)/configure \ $(srcdir)/install-sh $(srcdir)/ltmain.sh $(srcdir)/missing \ $(srcdir)/depcomp $(srcdir)/aclocal.m4 \ $(srcdir)/config.guess $(srcdir)/config.sub SUBDIRS=\ doc \ manpages \ scripts sysconf_DATA=#required in order to create dir if ENABLE_CREATE_DEVICE dev_DATA= endif noinst_PROGRAMS= if ENABLE_DEBUG if ENABLE_FBSPLASH noinst_PROGRAMS+=fbsplash-test endif endif noinst_LIBRARIES=\ libsuspend-common.a sbin_PROGRAMS=\ s2disk \ swap-offset dist_noinst_DATA= \ conf/suspend.conf if !ENABLE_MINIMAL sbin_PROGRAMS+=\ s2ram \ s2both if ENABLE_ENCRYPT sbin_PROGRAMS+=\ suspend-keygen endif initramfs_PROGRAMS=\ resume dist_doc_DATA=\ HOWTO \ $(srcdir)/README* \ $(srcdir)/COPYING* endif install-data-hook: install-sysconfDATA if [ -f $(DESTDIR)$(sysconfdir)/suspend.conf ]; then \ $(INSTALL_DATA) $(srcdir)/conf/suspend.conf $(DESTDIR)$(sysconfdir)/suspend.conf.new; \ else \ $(INSTALL_DATA) $(srcdir)/conf/suspend.conf $(DESTDIR)$(sysconfdir)/suspend.conf; \ fi if ENABLE_CREATE_DEVICE $(MKNOD) $(DESTDIR)$(devdir)/snapshot c 10 231 endif AM_CFLAGS=\ -DS2RAM \ -D_LARGEFILE64_SOURCE \ $(LZO_CFLAGS) \ $(LIBGCRYPT_CFLAGS) common_s2disk_libs=\ $(LZO_LIBS) \ $(LIBGCRYPT_LIBS) \ $(PTHREAD_LIBS) common_s2ram_libs= if ENABLE_SPLASHY AM_CFLAGS+=\ ${SPLASHY_CFLAGS} common_s2disk_libs+=\ ${SPLASHY_LIBS} endif if ENABLE_FBSPLASH AM_CFLAGS+=\ ${FBSPLASH_CFLAGS} common_s2disk_libs+=\ ${FBSPLASH_LIBS} endif libsuspend_common_a_SOURCES=\ swsusp.h \ vt.h vt.c \ config_parser.h config_parser.c \ md5.h md5.c \ encrypt.h encrypt.c \ loglevel.h loglevel.c \ splash.h splash.c \ splashy_funcs.h splashy_funcs.c \ fbsplash_funcs.h fbsplash_funcs.c \ bootsplash.h bootsplash.c \ memalloc.h memalloc.c load.c if ARCH_X86 libsuspend_common_a_SOURCES+=\ s2ram.h s2ram.c \ whitelist.h whitelist.csv whitelist.c \ s2ram-x86.h s2ram-x86.c \ dmidecode.c \ radeontool.c \ vbetool/vbetool.h vbetool/vbetool.c AM_CFLAGS+=\ $(LIBX86_CFLAGS) \ $(LIBPCI_CFLAGS) common_s2ram_libs+=\ $(LIBX86_LIBS) \ $(LIBPCI_LIBS) endif if ARCH_PPC libsuspend_common_a_SOURCES+=\ s2ram.h s2ram.c \ whitelist.h whitelist.csv whitelist.c \ s2ram-ppc.h s2ram-ppc.c endif resume_CFLAGS=\ $(AM_CFLAGS) \ -D_GNU_SOURCE resume_SOURCES=\ resume.c resume_LDADD=\ libsuspend-common.a \ $(common_s2disk_libs) if ENABLE_RESUME_STATIC resume_LDFLAGS=\ $(AM_LDFLAGS) \ -all-static endif s2disk_SOURCES=\ suspend.c s2disk_LDADD=\ libsuspend-common.a \ $(common_s2disk_libs) s2both_SOURCES=\ suspend.c s2both_CFLAGS=\ $(AM_CFLAGS) \ -DCONFIG_BOTH s2both_LDADD=\ libsuspend-common.a \ $(common_s2ram_libs) \ $(common_s2disk_libs) s2ram_SOURCES=\ s2ram-main.c s2ram_LDADD=\ libsuspend-common.a \ $(common_s2ram_libs) swap_offset_SOURCES=\ swap-offset.c suspend_keygen_SOURCES=\ keygen.c suspend_keygen_LDADD=\ libsuspend-common.a \ $(LIBGCRYPT_LIBS) fbsplash_test_SOURCES=\ fbsplash_funcs.c \ fbsplash-test.c fbsplash_test_LDADD=\ $(FBSPLASH_LIBS) whitelist.c: whitelist.csv $(PERL) wlcsv2c.pl whitelist.csv whitelist.c clean-local: rm -f whitelist.c # # Misc functions # install-resume-new-initrd: resume @if test -z "$(RESUME_DEVICE)"; then \ echo "Please specify --with-resume-device"; \ false; \ else \ BOOT_DIR=$(DESTDIR)$(bootdir) ./scripts/create-resume-initrd.sh $(RESUME_DEVICE); \ fi install-resume-on-initrd: resume BOOT_DIR=$(DESTDIR)$(bootdir) ./scripts/install-resume.sh suspend-utils/s2ram-ppc.h0000644000175500017550000000007412075743442014045 0ustar kixkix/* No additional options for PPC */ #define HACKS_LONG_OPTS suspend-utils/HOWTO0000644000175500017550000006175612075743442012731 0ustar kixkixSuspend to disk HOWTO ~~~~~~~~~~~~~~~~~~~~~ Copyright (C) 2006 Pavel Machek Copyright (C) 2006-2011 Rafael J. Wysocki I. Quick start 1) Necessary items (a) This package (b) Linux kernel supporting the swsusp userland interface (2.6.17 or above) (c) Swap partition or a swap file, approximately as big as 1/2 of RAM (d) Special device file for the snapshot device (character, 10, 231), e.g. crw-r--r-- 1 root root 10, 231 Jan 13 21:21 /dev/snapshot (e) libx86, a hardware-independent library for executing real-mode x86 code (f) [optionally] Markus F.X.J. Oberhumer's lzo library (for lzo image compression) (g) [optionally] libgcrypt (for image encryption) (h) [optionally] libsplashy (for user space splash) (i) [optionally] splashutils (for user space splash) 2) Basic steps (a) Configure, build and install the kernel The kernel has to be configured to support software suspend. It is also highly recommended to configure it to support RAM disks, initial RAM disks, loopback block devices, and the ext2 filesystem, at least for initial testing. Later on, you can use initramfs instead of initrd (please see Section II of this document for details). If you already use initrd or initramfs, you'll need to integrate the resume binary with it eventually. However, it's better to postpone this until you have verified that the suspend utilities work on your system. Thus it is recommended to initially build the kernel with all of the drivers needed to mount the root filesystem (most importantly the drivers needed to access your hard disk drive) compiled in. Then, you will only need the initrd to run the resume binary itself and you will be able to use the resume initrd installation script provided in this package. The kernel installation procedure will depend on what Linux distribution you use and should be documented elsewhere. (b) Install libx86 developement packages If libx86 is not installed on your system (Debian: libx86-dev) you can download the tarball from http://www.codon.org.uk/~mjg59/libx86/downloads/. Unpack it, change into the resulting directory. Then run $ make or if you're building for an x86_64 $ make BACKEND=x86emu Next, become root and run # make install DESTDIR=/usr/local (c) [optionally] Install the Markus F.X.J. Oberhumer's lzo library If you want to use the image lzo compression functionality and lzo it's not installed on your system, download the tarball from http://www.oberhumer.com/opensource/lzo, unpack it, go to the directory containing the source and run $ ./configure $ make Next, become root and run # make install [This will put the lzo files into /usr/local/include/lzo, the library into /usr/local/lib.] (d) [optionally] Install libgrypt If you want to use the image encryption functionality of the suspend tools, you'll need libgcrypt to build them. If you have installed GnuPG, libgcrypt is present on your system, but you'll also need the development package for it. On a SUSE system you can verify if the package has been installed by running $ rpm -q libgcrypt-devel and it should give you the version of the package if so (there are similar methods for any other distribution). If not, you'll need to install it. The majority of modern Linux distributions provide a binary package with it and you should install it in a way that's appropriate for your distribution. Still, if your distribution doesn't provide the binary package, you can refer to the documentation at http://www.gnupg.org/ for installation instructions. (d) [optionally] install libsplashy-dev or fbsplash (for user space splash screens) For now you need the experimental version of splashy, which can be found at svn://svn.debian.org/svn/splashy/branches/0.3 . fbsplash may be found at http://fbsplash.berlios.de . (e) Configure, build and install the suspend utilities - Examine available options by running: $ ./configure --help The following major options are available: --enable-minimal Enable minimal build --enable-compress Enable compress support --enable-encrypt Enable encryption support --enable-create-device Enable creating the necessary device files (if you use udev, this option should not be needed) --enable-splashy Enable splashy support --enable-fbsplash Enable fbsplash support --enable-threads Enable multithreaded image saving (helps with image compression and encryption enabled at the same time if you have 2 or more CPUs) --disable-resume-static Do not link the resume tool statically (this should be used on openSUSE and other distros putting the requisite libraries into their initramfs images) If you want to generate an initramfs image using the provided script, the following options are available: --with-resume-device=DEVICE Define resume device --with-bootdir=DIR Define boot directory, default /boot Please note, however, that this scripts may not work with your configuration. Moreover, if you use openSUSE 10.2 or 10.3 and you want to replace the s2disk and resume binaries provided by the distribution, it is better to use the distribution's original mkinitrd script. - Configure the package $ ./configure - Build the suspend tools in the usual way: $ make - To install the tools, become root and run: # make install This will also create the snapshot device file in /dev/, if the --enable-create-device option of configure has been used. (f) Optinally create initramfs image - Edit conf/suspend.conf file to reflect the configuration of your system (please refer to Section II of this document for details). [There should be just one resume partition, for now. You'll need at most 1/2 of your RAM of free space on it, but in some cases it may be smaller, too. The s2disk tool may be configured to create quite small snapshot images but then some contents of the RAM will have to be swapped out before suspend. It also is possible to use a swap file for suspending, but this only works with the 2.6.18-mm3 kernel (or later). In such a case the resume partition is the partition that holds the swap file, and there is an additional configuration parameter "resume offset" that has to be set, as described below.] # make install-resume-new-initrd This will place the file resume-initrd in the /boot directory. [If you already use an initrd or initramfs, the resume binary will need to be integrated with it, but initially it's better to use a separate "resume" initrd image. Unfortunately the procedure of installing the resume binary in the exsiting initrd or initramfs image depends on the Linux distribution used, but one exaple is given at the end of Section II.] You will also need to make the kernel use the resume initrd image. Unfortunately this depends on the Linux distribution too, but if you use GRUB and the entry in the GRUB configuration file (usually /boot/grub/menu.lst) corresponding to your newly installed kernel is similar to following one: title Linux (2.6.18-rc2) root (hd0,0) kernel /vmlinuz-2.6.18-rc2 root=/dev/md1 vga=792 ... where "..." represents some additional kernel command line options, you will only need to add the line: initrd /resume-initrd right next to the "kernel" line. [The paths in the above example correspond to the situation in which there is a separate boot partition. However, if the /boot directory is located in the root partition, the only difference will be the appearance of /boot in the paths, e.g. title Linux (2.6.18-rc2) root (hd0,0) kernel /boot/vmlinuz-2.6.18-rc2 root=/dev/md1 vga=792 ... initrd /boot/resume-initrd where we have shown the complete configuration. The (hd0,0) identifies the partition that GRUB will use to read the kernel and the initrd image from, but please refer to the GRUB documentation for more details.] (g) To suspend to disk, run # s2disk NOTE: For this to work you must be running _exactly_ the same kernel that will be used for resuming. Otherwise the kernel will refuse to accept the suspend image. To resume, just boot the kernel you were running when the image was created and if the initrd is properly installed, the resume tool will be run automatically out of it. II. Installation of suspend tools 1) Kernel configuration (a) The kernel must support the swsusp userland interface, so it's most recommended to use the 2.6.17 kernel or above. (b) The kernel has to be configured to support software suspend, i.e. the kernel configuration file (.config) has to contain CONFIG_SOFTWARE_SUSPEND=y (c) The kernel should be configured with CONFIG_BLK_DEV_INITRD=y, which will allow you to run the resume binary out of an iniramfs/initrd image. [It is possible to use the suspend tools without any initramfs/initrd images, but it's dangerous and will not be documented here.] (d) It is recommended to configure the kernel with CONFIG_BLK_DEV_RAM=y and set CONFIG_BLK_DEV_RAM_SIZE to at lease 2048 Kbytes. [This will make it possible to use initrd images.] (e) It is recommended to configure the kernel with CONFIG_BLK_DEV_LOOP=y, or the resume initrd installation script provided in this package will not work. Also the loopback device support may be needed for manual configuration of the initrd image. (f) The automatic resume initrd installation script provided in this package installs an ext2 filesystem in the initrd image, so the kernel has to be configure with CONFIG_EXT2_FS=y for it to work. (g) For initial testing it's better to compile all of the drivers needed to mount the root filesystem into the kernel, install the kernel without an initrd/initramfs, and use the automatically-generated resume initrd (see below) with it. 2) Installation of optional packages If you want to use the compression and/or encryption capabilities of the suspend tools, you'll need the Markus F.X.J. Oberhumer's lzo library and/or libgcrypt, respectively. Short instructions related to these packages have been given in Secion I above. If you want a user space splash screen you will need a splashy or fbsplash theme, you also have to copy the theme files to your initramfs/initrd. 3) Configuration and compilation of suspend tools (a) [optional] If you want to use the compression, encryption and/or user space splash capabilities of the suspend tools and you have installed the necessary packages referred to in subsection 2), you need to set --enable-compress, --enable-encrypt, --enable-splashy and/or --enable-fbsplash when your run the configure script. (b) Compile the s2disk and resume binaries by running: $ ./configure $ make in the directory where you have placed the sources. 4) Create the configuration file for the s2disk tool. Its default name is /etc/suspend.conf, but this can be customized by changing CONFIG_FILE in config_parser.h. It is also possible to specify the configuration file name from the command line, by using the -f option, eg. # s2disk -f The configuration file must contain the resume device specification, eg. resume device = /dev/ Optionally, it can contain the snapshot device specification, eg. snapshot device = /dev/snapshot and the following parameters: resume offset = image size = shutdown method = suspend loglevel = compute checksum = compress = encrypt = RSA key file = max loglevel = early writeout = splash = threads = The "resume offset" parameter is necessary if a swap file is used for suspending. In such a case the device identified by the "resume device" parameter is regarded as the partition that contains the swap file, and "resume offset" must be equal to the offset from the beginning of this partition at which the swap file's header is located, in units. The value of this parameter for given swap file can be determined by the swap-offset program (has to be run as root) included in this package. [For this feature to work, you will need an -mm kernel, 2.6.18-mm3 or newer.] The "image size" parameter may be used to limit the size of the system snapshot image created by the s2disk tool, but it's not mandatory. Namely, the s2disk tool will do its best to limit the image size as required by this parameter, but if that's not possible, it will suspend the system anyway, with a bigger image. If "image size" is set to 0, the snapshot image will be as small as possible. The "shutdown method" parameter defines the operation that will be carried out after the suspend image has been created and the machine is ready to be powered off. If it is set to "reboot", the machine will be rebooted immediately. If it is set to "platform", the machine will be shut down using special power management operations available from the kernel that may be necessary for the hardware to be properly reinitialized after the resume, and may cause the system to resume faster (this is the recommended shutdown method on the majority of systems). For any other value the machine will be powered off. The default is to use the "platform" method. [For this feature to work, you will need an -mm kernel, 2.6.18-mm3 or newer.] If the "compute checksum" parameter is set to 'y', the s2disk and resume tools will use the MD5 algorithm to verify the image integrity. If the "compress" parameter is set to 'y', the s2disk and resume tools will use the LZF compression algorithm to compress/decompress the image. If the "encrypt" parameter is set to 'y', the s2disk and resume tools will use the AES encryption algorithm to encrypt/decrypt the image. If the "RSA key file" option is also used, the s2disk tool will generate a random key for the AES encryption that will be passed to the resume tool within the image header with the help of the RSA cipher. However, for this purpose you will need an additional RSA key file the path to which should be the value of "RSA key file" parameter. For more details refer to Section IV ("Advanced encryption") of this document. If the "early writeout" parameter is set to 'y', the s2disk utility will start syncing the resume device early in the process of writing the image to it. [This has been reported to speed up the suspend on some boxes and eliminates the "fast progress meter and long fsync wait" effect.] The "splash" parameter is used to make s2disk and/or resume use a splash system (when set to 'y'). Currently the bootsplash.org, splashy and fbsplash splash systems are supported. Note that for both systems your initrd or initramfs will need additional files. See the documentation of your splash system for more information. The "threads" parameter, if set to 'y', causes s2disk to use 3 threads for saving the image, which generally reduces the time necessary to save it if both image compression and encryption are used at the same time (one thread compresses the image, one thread encrypts it and one writes the data to the storage). The resume tool can use the same configuration file that is used by the s2disk tool, but it will ignore most of the above parameters. It will use the value of "suspend loglevel" as the kernel console loglevel during resume. Additionally it will use the value of "max loglevel" as the kernel console loglevel to switch to in case the resume fails (this parameter is ignored by the s2disk tool). It is not necessary to set "compute checksum = y" and/or "compress = y", and/or "encrypt = y" for the resume tool. The appropriate information related to these options will be passed to it in the image header by the s2disk tool. However, the resume tool will only use the splash system if "splash = y" is set for it explicitly. In order to create the configuration file for s2disk and/or resume, it is recommended to edit the file suspend.conf in the conf/ subdirectory of the package source. Then this file will be automatically placed in /etc and in the resume initrd file by scripts provided in this package. 5) Install s2disk To install the s2disk tool, run: # make install as root. This will place the s2disk binary in the destination directory specified to configure (/usr/local/sbin by default). It will also create the special device file for the suspend device in /dev, if requested, and copy the configuration file from the conf/ subdirectory of the source package to /etc (or somewhere else, depending on the settings specified to configure). If the configuration file already exists, it will not be overwritten and a new file with the suffix ".new" appended to its name will be created. If --enable-encrypt is set, the suspend-keygen tool used for generating RSA keys for s2disk (see Section IV of this document for details) will also be built and installed in the destination bin directory. If you don't want to use "make install", you can copy the s2disk binary and the configuration file to wherever you like, but you'll also need to make sure the snapshot device file is present (if you have set --enable-encrypt in configure, you may also need to copy the suspend-keygen binary to its final destination manually). You can also use a tool called "checkinstall" to prepare a package file according to the distribution of your choice (checkinstall supports Slackware, RPM distributions and DEB distributions). To download it: http://asic-linux.com.mx/~izto/checkinstall/download.php To create your package, run "make" and then (as root user) simply type "checkinstall" and answer the questions. This will not install anything: instead it will create a package file you can install with rpm, dpkg or whatever tool your distribution provides. 4) Create snapshot device file If you don't use "make install", you may need to create the snapshot device file: # mknod /dev/snapshot c 10 231 If the name of this file is equal to SNAPSHOT_DEVICE in swsusp.h, it is not necessary to specify it in the configuration file. Now you should be able to use the s2disk tool. It is recommended, however, to put the tool into a directory located directly on the root filesystem, for safe testing. 5) Install resume It is recommended to place the resume tool on an initrd/initramfs image. For the latter, see instructions for yaird under (6) below. For an initrd, this may be done using "make install-resume-new-initrd", but I'll describe the full procedure in case you want to do something in a different way. For simplicity I will only cover the fastest method of setting it up that will allow you to get the resume tool up and running quickly. [The described procedure reflects the actions performed by "make install-resume-new-initrd".] (a) Configure the kernel to support RAM disks, initial RAM disks, loopback block devices, and the ext2 filesystem, and install it as described in 1). (b) Create the /initrd directory if it doesn't exist already. (c) Create a blank file, as large as to accommodate all files you'll be placing on the initrd filesystem. In the simplest case that will be the resume tool itself, some directories and some device files. The resume tool is linked statically, so you won't need any libraries to run it. On my box the size of it was smaller that 2 MB, so I could do: $ dd if=/dev/zero of=initrd bs=2000k count=1 (d) Run mke2fs on this file, eg. $ /sbin/mke2fs -F -m0 initrd (e) Become root and mount the filesystem, eg. # mount -t ext2 -o loop initrd /mnt (f) Create the console device, the snapshot device, and the resume device on it, eg. # mkdir /mnt/dev # mknod /mnt/dev/console c 5 1 # mknod /mnt/dev/snapshot c 10 231 # mknod /mnt/dev/hda2 b 3 2 [The initrd filesystem will be mounted as the root filesystem, so the paths with respect to it must be the same as in your "normal" root filesystem.] (g) [optional] If you want to use the RSA encryption mechanism described in Section IV, you'll need to create the random and urandom device files on the resume initrd: # mknod /dev/random c 1 8 # mknod /dev/urandom c 1 9 (h) Create the proc and etc directories on it (the resume tool will use them), eg. # mkdir /mnt/proc # mkdir /mnt/etc (i) Copy the resume tool to the initrd filesystem and link it to linuxrc, eg. # cp resume /mnt/ # cd /mnt # ln -s resume linuxrc (j) Put the configuration file for the resume tool in the etc directory on the initrd filesystem, eg. # cp /etc/suspend.conf /mnt/etc/ (k) Unmount the initrd filesystem and move the file containing it to your /boot directory, eg. # umount /mnt # mv initrd /boot/resume-initrd (l) In the GRUB configuration file add the initrd to the configuration of the newly installed kernel, eg. initrd (hd0,0)/resume-initrd (if you use LILO, please refer to its documentation). (m) If you already have the resume initrd file which is called resume-initrd and located in the /boot directory, you can install the resume tool on it by using "make install-resume-on-initrd". 6) Install resume on initramfs with yaird For an initramfs made by yaird, you can make yaird load the resume binary. For this purpose, copy install the resume binary in /usr/local/sbin (for example) and edit /etc/yaird/Templates.cfg to reflect your configuration. Namely, find "Template RESUME" in there and make it read as follows: TEMPLATE resume BEGIN FILE "/usr/local/sbin/resume" FILE "/etc/suspend.conf" SCRIPT "/init" BEGIN !if [ -z "$noresume" ] !then ! # for suspend2 (>= 2.2-rc8) ! if [ -w /proc/suspend2/do_resume ]; then ! echo > /proc/suspend2/do_resume ! fi ! # for suspend2 (< 2.2-rc8) ! if [ -w /proc/software_suspend/do_resume ]; then ! echo > /proc/software_suspend/do_resume ! fi ! if [ -x /usr/local/sbin/resume ] ! then ! mkcdev /dev/snapshot misc/snapshot ! /usr/local/sbin/resume ! fi Here, the two "FILE" lines and the last if-then statement are new. Furthermore, yaird needs to know what the resume partition is. You can either edit /etc/yaird/Default.cfg and add that to the RESUME goal, or add an option "resume" to your swap partition in /etc/fstab, as follows /dev/hda3 none swap sw,resume 0 0 With all the above done, run yaird (or if you are a lazy Debian user, just reinstall linux-image-2.6.17-...). III. Testing Before you start using the s2disk and resume tools for real, you should test your setup. For this purpose it is recommended to boot the new kernel with the "init=/bin/bash" command line argument. Then, the kernel should run bash instead of init and you should get a (root) command prompt with the root filesystem mounted read-only and with no other filesystems. If this happens, mount the sysfs and proc filesystems and enable swap: # mount /sys # mount /proc # swapon -a Next, go to the directory where the s2disk tool is and do: # ./s2disk If this fails, the tool will return to the command prompt with a (hopefully instructive) message. Otherwise you should be able to see some messages from it on the screen and finally the progress meter, and the box should be powered off. If that happens, you can start it again and let the resume utility run from the initrd. If everything is fine, it will read the image and restore the system state from it, and you will get the command prompt back. If so, your setup works. Otherwise there's something wrong and you'll need to find out what and why. The next step is to check whether your device drivers suspend and resume correctly. To do this, it is reasonable to boot the kernel to the runlevel 2 and run the suspend tool. If it suspends successfully, the resume tool is able to restore the system memory state, and you get the command prompt back, the drivers are most probably fine. Otherwise please report the problem. Finally, you can start X and try to suspend from an xterm. If this works, you're done. IV. Advanced encryption If the s2disk and resume tools are compiled with the encryption support, the RSA cipher may be used to pass the AES encryption key from the s2disk tool to the resume tool within the suspend image. This way the s2disk tool need not ask the user for a passphrase. For this purpose you need to generate the RSA key pair using the suspend-keygen tool provided along with the s2disk and resume tools. The output file of suspend-keygen should be saved as /etc/suspend.key (or something else pointed to by the "RSA key file =" configuration parameter of s2disk). This file contains the public modulus (n), public exponent (e), the AES-encrypted private exponent (d), the AES-encrypted primes (p), (q) and the (AES-encrypted) component (u) of the RSA key pair. The components (d), (p), (q), (u) of the RSA key pair are encrypted with a key derived from a user-provided passphrase. Then, the s2disk utility will load the contents of this file, generate a random session key (k) and initialization vector (i) for the image encryption and use (n, e) to encrypt these values with RSA. The encrypted (k, i) as well as the contents of the RSA key file will be saved in the image header. The resume utility will read (n, e) and (AES-encrypted) (d, p, q, u) as well as (RSA-encrypted) (k, i) from the image header. Then it will ask the user for the passphrase needed to decrypt (d, p, q, u). Next, if the user provides the right passphrase, the resume tool will decrypt (k, i) needed for decrypting the image. suspend-utils/splashy_funcs.c0000644000175500017550000000265312075743442015122 0ustar kixkix/* * splashy.c * * Splashy (userspace splash) splash method support * * Copyright (C) 2006 Tim Dijkstra * * This file is released under the GPLv2. * */ #include "config.h" #ifdef CONFIG_SPLASHY #include #include #include #include "splash.h" #include "encrypt.h" #include "splashy_funcs.h" int splashy_open(int mode) { int ret; if ((ret = splashy_init (NULL,(mode==SPL_RESUME?"resume":"suspend"))) < 0) { fprintf(stderr,"splashy_init: error %d",ret); return -1; } if ((ret = splashy_start_splash ()) < 0) { fprintf(stderr,"splashy_start_splash: error %d",ret); return -2; } return 0; } inline int splashy_finish(void) { splashy_stop_splash(); return 0; } inline int splashy_progress(int p) { splashy_update_progressbar (p); return 0; } void splashy_read_password(char *buf, int vrfy) { #if CONFIG_ENCRYPT char *vrfy_buf = vrfy ? buf + PASS_SIZE : buf; do { while (splashy_get_password(buf,PASS_SIZE, "Passphrase please (must be non-empty): ") <= 0); if (vrfy) while (splashy_get_password(vrfy_buf,PASS_SIZE, "Verify passphrase: ") <= 0); } while (vrfy && strncmp(buf, vrfy_buf, PASS_SIZE)); #endif } int splashy_dialog(const char *prompt) { splashy_printline(prompt); return splashy_getchar(); } #endif suspend-utils/radeontool.c0000644000175500017550000002225012075743442014402 0ustar kixkix /* Radeontool v1.4 * by Frederick Dean * Copyright 2002-2004 Frederick Dean * Use hereby granted under the zlib license. * * Warning: I do not have the Radeon documents, so this was engineered from * the radeon_reg.h header file. * * USE RADEONTOOL AT YOUR OWN RISK * * Thanks to Deepak Chawla, Erno Kuusela, Rolf Offermanns, and Soos Peter * for patches. * * Stripped down to bare bones by Pavel Machek -- for use in s2ram.c * Rework of the map_radeon_cntl_mem function and various cleanups * by Stefan Seyfried */ #include "config.h" #include #include #include #include #include #include #include #include #include #define RADEON_LVDS_GEN_CNTL 0x02d0 # define RADEON_LVDS_ON (1 << 0) # define RADEON_LVDS_DISPLAY_DIS (1 << 1) # define RADEON_LVDS_PANEL_TYPE (1 << 2) # define RADEON_LVDS_PANEL_FORMAT (1 << 3) # define RADEON_LVDS_EN (1 << 7) # define RADEON_LVDS_DIGON (1 << 18) # define RADEON_LVDS_BLON (1 << 19) # define RADEON_LVDS_SEL_CRTC2 (1 << 23) /* *radeon_cntl_mem is mapped to the actual device's memory mapped control area. */ /* Not the address but what it points to is volatile. */ volatile unsigned char * radeon_cntl_mem; static unsigned long radeon_get(unsigned long offset) { unsigned long value; if(radeon_cntl_mem == NULL) { fprintf(stderr, "radeon_get: radeon_cntl_mem == NULL"); return 0; } value = *(volatile unsigned long *)(radeon_cntl_mem+offset); return value; } static void radeon_set(unsigned long offset, unsigned long value) { if(radeon_cntl_mem == NULL) { fprintf(stderr, "radeon_set: radeon_cntl_mem == NULL"); return; } *(volatile unsigned long *)(radeon_cntl_mem+offset) = value; } /* Ohh, life would be good if we could simply address all memory addresses */ /* with /dev/mem, then I could write this whole program in perl, */ /* but sadly this is only the size of physical RAM. If you */ /* want to be truely bad and poke into device memory you have to mmap() */ static volatile unsigned char * map_device_memory(unsigned int base,unsigned int length) { int mem_fd; volatile unsigned char *device_mem; /* open /dev/mem */ if ((mem_fd = open("/dev/mem", O_RDWR) ) < 0) { perror("radeontool /dev/mem"); return NULL; } /* mmap graphics memory */ if ((device_mem = malloc(length + (getpagesize()-1))) == NULL) { perror("radeontool malloc"); close(mem_fd); return NULL; } if ((unsigned long)device_mem % getpagesize()) device_mem += getpagesize() - ((unsigned long)device_mem % getpagesize()); device_mem = (volatile unsigned char *)mmap( (caddr_t)device_mem, length, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, mem_fd, base ); if (device_mem == (volatile unsigned char *)-1) { perror("radeontool mmap"); return NULL; } return device_mem; } void radeon_cmd_light(int param) { unsigned long lvds_gen_cntl; lvds_gen_cntl = radeon_get(RADEON_LVDS_GEN_CNTL); if (param) lvds_gen_cntl |= RADEON_LVDS_ON; else lvds_gen_cntl &= ~ RADEON_LVDS_ON; radeon_set(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); } /* I have not got much feedback on my radeontool rework, hence i leave the old * code #if 0-ed in for reference. * Once some time passes without complaints about the new code, i will remove it. * Sorry for the clutter - seife. */ #if 0 /* Here we fork() and exec() the lspci command to look for the Radeon hardware address. */ void map_radeon_cntl_mem(void) { int pipefd[2]; int forkrc; FILE *fp; char line[1000]; int base; if(pipe(pipefd)) { fatal("pipe failure\n"); } forkrc = fork(); if(forkrc == -1) { fatal("fork failure\n"); } else if(forkrc == 0) { /* if child */ close(pipefd[0]); dup2(pipefd[1],1); /* stdout */ setenv("PATH","/sbin:/usr/sbin:/bin:/usr/bin",1); execlp("lspci","lspci","-v",NULL); fatal("exec lspci failure\n"); } close(pipefd[1]); fp = fdopen(pipefd[0],"r"); if(fp == NULL) { fatal("fdopen error\n"); } #if 0 This is an example output of "lspci -v" ... 00:1f.6 Modem: Intel Corp. 82801CA/CAM AC 97 Modem (rev 01) (prog-if 00 [Generic]) Subsystem: PCTel Inc: Unknown device 4c21 Flags: bus master, medium devsel, latency 0, IRQ 11 I/O ports at d400 [size=256] I/O ports at dc00 [size=128] 01:00.0 VGA compatible controller: ATI Technologies Inc Radeon Mobility M6 LY (prog-if 00 [VGA]) Subsystem: Dell Computer Corporation: Unknown device 00e3 Flags: bus master, VGA palette snoop, stepping, 66Mhz, medium devsel, latency 32, IRQ 11 Memory at e0000000 (32-bit, prefetchable) [size=128M] I/O ports at c000 [size=256] Memory at fcff0000 (32-bit, non-prefetchable) [size=64K] Expansion ROM at [disabled] [size=128K] Capabilities: 02:00.0 Ethernet controller: 3Com Corporation 3c905C-TX/TX-M [Tornado] (rev 78) Subsystem: Dell Computer Corporation: Unknown device 00e3 Flags: bus master, medium devsel, latency 32, IRQ 11 I/O ports at ec80 [size=128] Memory at f8fffc00 (32-bit, non-prefetchable) [size=128] Expansion ROM at f9000000 [disabled] [size=128K] Capabilities: We need to look through it to find the smaller region base address f8fffc00. #endif while(1) { /* for every line up to the "Radeon" string */ if(fgets(line,sizeof(line),fp) == NULL) { /* if end of file */ fatal("Radeon hardware not found in lspci output.\n"); } if(strstr(line,"Radeon") || strstr(line,"ATI Tech")) { /* if line contains a "radeon" string */ break; } }; if(debug) printf("%s",line); while(1) { /* for every line up till memory statement */ if(fgets(line,sizeof(line),fp) == NULL || line[0] != '\t') { /* if end of file */ fatal("Radeon control memory not found.\n"); } if(debug) printf("%s",line); if(strstr(line,"emory") && strstr(line,"K")) { /* if line contains a "Memory" and "K" string */ break; } }; if(sscanf(line,"%*s%*s%x",&base) == 0) { /* third token as hex number */ fatal("parse error of lspci output (control memory not found)\n"); } if(debug) printf("Radeon found. Base control address is %x.\n",base); radeon_cntl_mem = map_device_memory(base,0x2000); } #else static u32 get_conf_long(unsigned char *d, unsigned int pos) { return d[pos] | (d[pos+1] << 8) | (d[pos+2] << 16) | (d[pos+3] << 24); } /* Find out where the radeon memory is. The idea is taken from radeontool-1.5, * but we no longer fork lspci and parse its output :-) * The logic seems to be: the memory range that is not I/O space and smaller * than 1 MB is the radeon chip control range. Let's hope that this is true. */ void map_radeon_cntl_mem(void) { struct pci_access *pacc; struct pci_dev *dev; unsigned int class; int i; int base = -1; unsigned char *config; radeon_cntl_mem = NULL; config = malloc(64); if (!config) { perror("map_radeon_cntl_mem malloc(64)"); return; } pacc = pci_alloc(); /* Get the pci_access structure */ pci_init(pacc); /* Initialize the PCI library */ pci_scan_bus(pacc); /* We want to get the list of devices */ for (dev=pacc->devices; dev; dev=dev->next) { /* Iterate over all devices */ pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES);/* Fill in header info we need */ class = pci_read_word(dev, PCI_CLASS_DEVICE); /* Read config register directly */ if (dev->vendor_id == 0x1002 && class == 0x300) { /* ATI && Graphics card */ pci_read_block(dev, 0, config, 64); for (i=0; i<6; i++){ u32 flag = get_conf_long(config, PCI_BASE_ADDRESS_0 + 4*i); if (flag & PCI_BASE_ADDRESS_SPACE_IO) /* I/O-Ports, not memory */ continue; /* the original code parsed lspci for "emory" and "K", so it * has to be at least 1K and less than 1M */ if (dev->size[i] >=1024 && dev->size[i] < 1024*1024) { base = dev->base_addr[i]; goto found; } } } } found: pci_cleanup(pacc); free(config); if (base == -1) { fprintf(stderr, "radeontool: Radeon not found.\n"); return; } radeon_cntl_mem = map_device_memory(base,0x2000); } #endif #ifndef S2RAM int main(int argc,char *argv[]) { map_radeon_cntl_mem(); if (radeon_cntl_mem == NULL) { fprintf(stderr, "Fatal error: radeon_cntl_mem == NULL.\n"); return 1; } if (argc == 3) { if(strcmp(argv[1],"light") == 0) { radeon_cmd_light(strcmp(argv[2],"off")); return 0; } }; return 1; } #endif suspend-utils/vt.c0000644000175500017550000000423012075743442012663 0ustar kixkix/* vt.c - VT specific routines * most of these are simplified versions of routines that can * be found in the kbd package. * * Released under GPL V2. * (C) 2006 Stefan Seyfried */ #include "config.h" #include #include #include #include #include #include #include #include #include int is_a_console(int fd) { char arg; arg = 0; return (ioctl(fd, KDGKBTYPE, &arg) == 0 && ((arg == KB_101) || (arg == KB_84))); } int open_a_console(const char *fnam) { int fd; fd = open(fnam, O_RDWR); if (fd < 0) return -1; if (!is_a_console(fd)) { close(fd); return -1; } return fd; } int getconsolefd(void) { int fd; fd = open_a_console("/dev/tty"); if (fd >= 0) return fd; fd = open_a_console("/dev/tty0"); if (fd >= 0) return fd; fd = open_a_console("/dev/vc/0"); if (fd >= 0) return fd; fd = open_a_console("/dev/console"); if (fd >= 0) return fd; for (fd = 0; fd < 3; fd++) if (is_a_console(fd)) return fd; return -1; } int fgconsole(void) { int fd; struct vt_stat vtstat; fd = getconsolefd(); if (fd < 0) { perror("fgconsole: getconsolefd"); return -1; } if (ioctl(fd, VT_GETSTATE, &vtstat)) { perror("fgconsole: VT_GETSTATE"); return -1; } return vtstat.v_active; } int chvt(int num) { #define USER_WAIT_SLEEP_US 100000 #define USER_WAIT_MAX_ITERATIONS 50 int i, fd, active = 0; for (i = 0; i < USER_WAIT_MAX_ITERATIONS; i++) { if (fgconsole() == num) { active = 1; break; } fd = getconsolefd(); if (ioctl(fd, VT_ACTIVATE, num)) { perror("chvt: VT_ACTIVATE"); } usleep(USER_WAIT_SLEEP_US); } return active; } int is_framebuffer(void) { return !access("/sys/class/graphics/fb0", F_OK); } char *get_fbname(void) { int fd, len; /* id of the driver can be 16bytes long + cr appended by sysfs */ char *id = malloc(17); fd = open("/sys/class/graphics/fb0/name", O_RDONLY); if (fd < 0) { strcpy(id, "error"); goto out; } len = read(fd, id, 17); if (len <= 0) strcpy(id, "error"); else /* strip the cr appended by sysfs */ id[len-1] = '\0'; close(fd); out: return id; } suspend-utils/AUTHORS0000644000175500017550000000050512075743442013137 0ustar kixkixRafael J. Wysocki Pavel Machek Stefan Seyfried Tim Dijkstra Luca Tettamanti Alon Bar-Lev Rodolfo Garcia Holger Macht Alan Jenkins suspend-utils/README.s2ram-whitelist0000644000175500017550000001000412075743442015777 0ustar kixkixHOWTO get suspend to RAM to work out of the box. ================================================ Stefan Seyfried, January 2007 The goal of the s2ram binary is to get suspend to RAM working out of the box on as many machines as possible. Background: ----------- Suspend to RAM is working on many machines already - which means that the machine comes back to life and resumes operation, the keyboard works and the harddisk is still accessible - but to get video working and the backlight back on, you need the one or other "dirty trick". There are some different workarounds for that: * passing acpi_sleep=s3_bios to the kernel * passing acpi_sleep=s3_mode to the kernel * passing both of the above (acpi_sleep=s3_bios,s3_mode) to the kernel * POSTing the video card from userspace after resume using vbetool * getting the video mode number before suspend and setting the same video mode after resume using vbetool * saving the VBE state before suspend and restoring it after resume using vbetool * saving the PCI config space of the VGA card before suspend and restoring it after resume Since kernel 2.6.16, the acpi_sleep parameter can be set during runtime (no reboot needed) in /proc/sys/kernel/acpi_video_flags, with "1" for s3_bios, "2" for s3_mode and "3" for both. More information about those hacks can be found in the kernel-source tarball in the file Documentation/power/video.txt. There are machines that will not resume when using a framebuffer console. Recent Dell and HP models for example very often fall into this category. You can disable the framebuffer in your bootloader configuration by passing "vga=0" to the kernel. If your machine only works without framebuffer, please tell us about this in your report. If none of the methods described here seem to work, it is important to check if the machine is completely dead on resume or only the video is not resumed properly. A good way to check this is to start with a minimal system (init=/bin/bash), run "s2ram -f", and after resume, when the display is still off, check if the "Caps Lock" key still works (you should see a reaction of the Caps Lock LED on the keyboard). If it does, it is most likely really a video initialization problem. If it doesn't, then it is most likely a BIOS problem or a bug in the Linux kernel. Why s2ram? ---------- - vbetool usage for saving the VBE state is not easy: you have to dump the state of the card to a temporary file, before suspend, and restore it from there after resume. This can of course be put into a wrapper script, but having it in one binary is even easier. - you need to know if your machine needs a workaround and which one it needs. s2ram contains a database of known working machines and the workarounds that these machines need, so if your machine is supported, suspending is as easy as calling "s2ram". How to use it? -------------- Install it, then just call s2ram. If your machine is in the whitelist or if the kenel supports KMS (Kernel Mode Switch), it should suspend to RAM. Be careful though, some broken drivers need to be unloaded before suspend and reloaded after resume. If you just want to know if your machine is known and which workarounds (if any) will be used, call s2ram -n. My machine is not in the whitelist, what can i do? -------------------------------------------------- After the suspend version 1.0, with KMS support, no new machines will be added to the whitelist. You don't need to do nothing, the new kernels support KMS. How to contact the authors of s2ram? ------------------------------------ Send a mail to the suspend-devel mailinglist at suspend-devel@lists.sourceforge.net. If this does not work for some reason, you can also email me directly, seife @ suse.de, but the mailing list usually provides faster response times and more knowledgeable people. Any additions / corrections to this document are always welcome. There is also a similar document available online (which might even contain newer information) as http://suspend.sf.net/s2ram-support.html. Have a lot of fun... Stefan Seyfried suspend-utils/s2ram.c0000644000175500017550000000570712075743442013270 0ustar kixkix/* * Suspend-to-RAM * * Copyright 2006 Pavel Machek * Copyright 2011 Rodolfo García Peñas (kix) * Distribute under GPLv2. */ #include #include "config.h" #include #include #include #include #include #include #include #ifndef S2RAM #define S2RAM #endif #include "vt.h" #include "s2ram.h" #include "config_parser.h" static char s2ram_force; static char s2ram_quirks[MAX_STR_LEN]; static struct config_par s2ram_parameters[] = { { .name = "s2ram_force", .fmt = "%c", .ptr = &s2ram_force, }, { .name = "s2ram_quirks", .fmt = "%s", .ptr = s2ram_quirks, .len = MAX_STR_LEN }, { .name = NULL, .fmt = NULL, .ptr = NULL, .len = 0, } }; int s2ram_check_kms(void) { DIR *sysfs_dir; struct dirent *dentry; int ret = -ENOENT; sysfs_dir = opendir("/sys/class/drm"); if (!sysfs_dir) return errno; while ((dentry = readdir(sysfs_dir))) { if (!strncmp(dentry->d_name, "card0-", 6)) { ret = 0; break; } } closedir(sysfs_dir); return ret; } /* Actually enter the suspend. May be ran on frozen system. */ int s2ram_generic_do(void) { int ret = 0; FILE *f = fopen("/sys/power/state", "w"); if (!f) { printf("/sys/power/state does not exist; what kind of ninja mutant machine is this?\n"); return ENODEV; } if (fprintf(f, "mem") < 0) { ret = errno; perror("s2ram_do"); } /* usually only fclose fails, not fprintf, so it does not matter * that we might overwrite the previous error. */ if (fclose(f) < 0) { ret = errno; perror("s2ram_do"); } return ret; } /* Parse the configuration file */ int get_s2ram_config(void) { int error; char *conf_name = CONFIG_FILE; struct stat stat_buf; char *ret_name = NULL; if (stat(conf_name, &stat_buf)) { fprintf(stderr, "%s: Could not stat configuration file\n", conf_name); return -ENOENT; } else { error = parse(ret_name, conf_name, s2ram_parameters); if (error) { fprintf(stderr, "%s: Could not parse config file\n", ret_name); return error; } if (s2ram_force == 'y') { force = 1; if (strlen(s2ram_quirks) != 0) { printf("Using s2ram_quirks %s\n", s2ram_quirks); s2ram_add_quirks(s2ram_quirks); } return 0; } return -1; } } void s2ram_add_quirks(char *s2ram_quirks) { int i; /* Move to lowercase */ for (i=0; s2ram_quirks[i]; i++) s2ram_quirks[i] = tolower(s2ram_quirks[i]); if (strstr(s2ram_quirks, "vbe_post") != NULL) flags |= VBE_POST; if (strstr(s2ram_quirks, "vbe_save") != NULL) flags |= VBE_POST; if (strstr(s2ram_quirks, "vbe_mode") != NULL) flags |= VBE_MODE; if (strstr(s2ram_quirks, "radeon_off") != NULL) flags |= RADEON_OFF; if (strstr(s2ram_quirks, "pci_save") != NULL) flags |= PCI_SAVE; if (strstr(s2ram_quirks, "s3_bios") != NULL) flags |= S3_BIOS; if (strstr(s2ram_quirks, "s3_mode") != NULL) flags |= S3_MODE; if (strstr(s2ram_quirks, "fb_nosuspend") != NULL) fb_nosuspend = 1; } suspend-utils/time_test0000755000175500017550000000014312075743442014010 0ustar kixkix#!/bin/bash date cd /sys/class/rtc/rtc0 echo $(( $(cat since_epoch) + 20 )) > wakealarm s2ram date suspend-utils/s2ram-main.c0000644000175500017550000000567612075743442014217 0ustar kixkix/* * Suspend-to-RAM * * Copyright 2006 Pavel Machek * Copyright 2009 Rodolfo Garcia * Copyright 2011 Rafael J. Wysocki , Novell Inc. * Distribute under GPLv2. */ #include "config.h" #include #include #include #include #include #ifndef S2RAM #define S2RAM #endif #include "vt.h" #include "whitelist.h" #include "s2ram.h" #include "config_parser.h" int main(int argc, char *argv[]) { int i, ret = 0; int active_console = -1; struct option options[] = { { "help\0\tthis text.", no_argument, NULL, 'h' }, { "version\0\t\t\tversion information", no_argument, NULL, 'V' }, { "test\0\ttest if the machine is in the database.", no_argument, NULL, 'n' }, { "kmstest\0\ttest if the kernel has KMS support.", no_argument, NULL, 'K' }, { "identify\0prints a string that identifies the machine.", no_argument, NULL, 'i' }, HACKS_LONG_OPTS { NULL, 0, NULL, 0 } }; const char *optstring = "hVnKi" "fspmrva:k"; while ((i = getopt_long(argc, argv, optstring, options, NULL)) != -1) { switch (i) { case 'h': usage("s2ram", options, optstring); exit(0); case 'V': version("s2ram", whitelist_version); exit(EXIT_SUCCESS); case 'i': identify_machine(); exit(0); case 'n': ret = machine_known(); exit(ret); case 'K': ret = s2ram_check_kms(); if (!ret) printf("This kernel has KMS support.\n"); else printf("This kernel doesn't have KMS support.\n"); exit(ret); case '?': usage("s2ram", options, optstring); exit(1); break; default: s2ram_add_flag(i, optarg); break; } } /* Check if the KMS support is disabled by user */ if (!no_kms_flag) { /* KMS */ ret = s2ram_check_kms(); if (!ret) { printf("KMS graphics driver is in use, skipping quirks.\n"); return s2ram_generic_do(); } } else { printf("KMS disabled by user.\n"); } /* Test if s2ram will use quirks from the configuration file */ ret = get_s2ram_config(); if (ret) { /* No configuration file, using quirks form database */ ret = s2ram_is_supported(); if (ret == S2RAM_UNKNOWN) { printf("Machine is unknown.\n"); identify_machine(); goto out; } if (ret == S2RAM_NOFB) printf("This machine can only suspend without framebuffer.\n"); if (ret) goto out; } else { printf("Using quirks from the configuration file.\n"); } /* switch to console 1 first, since we might be in X */ active_console = fgconsole(); printf("switching from vt%d to vt1... ", active_console); if (chvt(1)) printf("succeeded\n"); else printf("failed\n"); ret = s2ram_hacks(); if (ret) goto out; ret = s2ram_do(); s2ram_resume(); out: /* if we switched consoles before suspend, switch back */ if (active_console > 0) { printf("switching back to vt%d... ", active_console); if (chvt(active_console)) printf("succeeded\n"); else printf("failed\n"); } return ret; } suspend-utils/wlcsv2c.pl0000644000175500017550000000402412075743442014007 0ustar kixkix#!/usr/bin/perl # Rodolfo Garcia kix_at_kix.es # suspend database management v1.0 use Switch; switch ($#ARGV) { case 0 { my $fin = $ARGV[0]; open(INF, "<$fin") or die "Could not open input file\n"; open(OUF, ">&STDOUT") or die "Could not open output file\n"; } case 1 { my $fin = $ARGV[0]; my $fout = $ARGV[1]; open(INF, "<$fin") or die "Could not open input file\n"; open(OUF, ">$fout") or die "Could not open output file\n"; } else { my $msg = $0 . " [output-file]"; die $msg; } } &print_c_header; my $sys_vendor = ""; my $sys_product = ""; my $sys_version = ""; my $bios_version = ""; my $flags = ""; my $comments = ""; while() { if (/"([^"]*)",\s*"([^"]*)",\s*"([^"]*)",\s*"([^"]*)",\s*([^,]*),\s*(.*)/) { $sys_vendor = $1; $sys_product = $2; $sys_version = $3; $bios_version = $4; $flags = $5; $comments = $6; printf OUF "\t$comments\n"; printf OUF "\t{ \"" . $sys_vendor . "\",\t\"" . $sys_product . "\",\t\"" . $sys_version . "\",\t\"" . $bios_version . "\",\t" . $flags . " },\n"; } } &print_c_footer; close(INF); close(OUF); sub print_c_header { ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time); printf OUF "/* whitelist.c\n"; printf OUF " * whitelist of machines that are known to work somehow\n"; printf OUF " * and all the workarounds\n"; printf OUF " * Script generated file, please do not edit by hand\n"; printf OUF " */\n"; printf OUF "\n"; printf OUF "\#include \"config.h\"\n"; printf OUF "\#include \\n"; printf OUF "\#include \"whitelist.h\"\n"; printf OUF "\#include \"s2ram.h\"\n"; printf OUF "\n"; printf OUF "char *whitelist_version = \"\$Id: whitelist.c ver. "; printf OUF "%4d%02d%02d %02d:%02d:%02d",$year+1900,$mon+1,$mday,$hour,$min,$sec; printf OUF " automatic generation - kix - Exp \$\";\n"; printf OUF "\n"; printf OUF "struct machine_entry whitelist[] = {\n"; } sub print_c_footer { print OUF "\t{ NULL, NULL, NULL, NULL, 0 }\n"; print OUF "};\n"; } suspend-utils/fbsplash-test.c0000644000175500017550000000302112075743442015006 0ustar kixkix/* * fbsplash.c * * fbsplash (framebuffer splash) splash method support * * Copyright (C) 2007 Alon Bar-Lev * * This file is released under the GPLv2. * */ #include "config.h" #include #include #include #include #include "swsusp.h" #include "splash.h" #include "fbsplash_funcs.h" char fbsplash_theme[] = ""; int main (void) { char c; int r; int i; printf("fbsplashfuncs_open...\n"); r = fbsplashfuncs_open(SPL_SUSPEND); printf("fbsplashfuncs_open=%d\n", r); if (r) { return 1; } for (i=0; i<=100; i+=10) { printf("fbsplashfuncs_progress (%d)...\n", i); fbsplashfuncs_progress(i); sleep(1); if (i == 50) { printf("fbsplashfuncs_dialog()...\n"); printf("fbsplashfuncs_dialog=%c\n", fbsplashfuncs_dialog ("Hello world!\nPlease press a key: ")); } #ifdef CONFIG_ENCRYPT else if (i==60) { char pass[PASS_SIZE]; printf("fbsplashfuncs_read_password(,0)..\n"); fbsplashfuncs_read_password(pass, 0); printf("fbsplashfuncs_read_password=%s\n", pass); } else if (i==80) { char pass[PASS_SIZE]; printf("fbsplashfuncs_read_password(,1)..\n"); fbsplashfuncs_read_password(pass, 1); printf("fbsplashfuncs_read_password=%s\n", pass); } #endif c = fbsplashfuncs_key_pressed(); if (c) { char buffer[SPLASH_GENERIC_MESSAGE_SIZE]; sprintf(buffer, "Key %c (%02x) pressed", c, (unsigned char)c); fbsplashfuncs_set_caption(buffer); } } printf("fbsplashfuncs_finish...\n"); fbsplashfuncs_finish(); return 0; } suspend-utils/s2ram-x86.c0000644000175500017550000002046312075743442013707 0ustar kixkix/* * Suspend-to-RAM * * Copyright 2006 Pavel Machek * 2007 Stefan, Rafael, Tim, Luca * Distribute under GPLv2. */ #include "config.h" #include #include #include #include #include #include #include #include #include "vbetool/vbetool.h" #include "vt.h" #include "s2ram.h" #include "config_parser.h" #include "whitelist.h" /* From dmidecode.c */ void dmi_scan(void); static void *vbe_buffer; static unsigned char vga_pci_state[256]; static struct pci_dev vga_dev; static struct pci_access *pacc; static int vbe_mode = -1, dmi_scanned; /* return codes for s2ram_is_supported */ #define S2RAM_OK 0 #define S2RAM_FAIL 1 #define S2RAM_NOFB 126 #define S2RAM_UNKNOWN 127 void identify_machine(void) { if (!dmi_scanned) { dmi_scan(); dmi_scanned = 1; } printf("This machine can be identified by:\n"); printf(" sys_vendor = \"%s\"\n" " sys_product = \"%s\"\n" " sys_version = \"%s\"\n" " bios_version = \"%s\"\n", sys_vendor, sys_product, sys_version, bios_version); } static int set_acpi_video_mode(int mode) { unsigned long acpi_video_flags; FILE *f = fopen("/proc/sys/kernel/acpi_video_flags", "r"); if (!f) { printf("/proc/sys/kernel/acpi_video_flags does not exist; you need a kernel >=2.6.16.\n"); return S2RAM_FAIL; } /* read the old setting from /proc */ if (fscanf(f, "%ld", &acpi_video_flags) != 1) { printf("/proc/sys/kernel/acpi_video_flags format is invalid\n"); return S2RAM_FAIL; } /* rewind() seems not to work on /proc files, so close and reopen it */ fclose(f); f = fopen("/proc/sys/kernel/acpi_video_flags", "w"); if (!f) { printf("cannot open /proc/sys/kernel/acpi_video_flags " "for writing (not running as root?)\n"); return S2RAM_FAIL; } /* mask out bits 0 and 1 */ acpi_video_flags = acpi_video_flags & (~0UL - S3_BIOS - S3_MODE); fprintf(f, "%ld", acpi_video_flags | mode); fflush(f); fclose(f); return S2RAM_OK; } static int match(const char *t, const char *s) { int len = strlen(s); /* empty string matches always */ if (len == 0) return 1; if (s[len-1] == '*') { len--; return !strncmp(t, s, len); } else { return !strcmp(t,s); } } static int machine_match(void) { if (!dmi_scanned) { dmi_scan(); dmi_scanned = 1; } int i; /* sys_vendor = NULL terminates the whitelist array */ for (i = 0; whitelist[i].sys_vendor; i++) { if (match(sys_vendor, whitelist[i].sys_vendor) && match(sys_product, whitelist[i].sys_product) && match(sys_version, whitelist[i].sys_version) && match(bios_version, whitelist[i].bios_version)) { return i; } } return -1; } static void fbcon_state(int state) { DIR *d; FILE *f; struct dirent *entry; char statefile[255]; if ((d = opendir("/sys/class/graphics")) == NULL) return; while ((entry = readdir(d)) != NULL) { if (entry->d_name[0] == '.') continue; snprintf(statefile, 255, "/sys/class/graphics/%s/state", entry->d_name); if (!access(statefile, W_OK)) { printf("fbcon %s state %d\n", entry->d_name, state); f = fopen(statefile, "w"); if (!f) { printf("s2ram: cannot write to %s\n", statefile); continue; } fprintf(f, "%d", state); fclose(f); } } } static void suspend_fbcon(void) { fbcon_state(1); } static void resume_fbcon(void) { fbcon_state(0); } int s2ram_check(int id) { int ret = S2RAM_OK; if (id < 0) { ret = S2RAM_UNKNOWN; } else { flags = whitelist[id].flags; if ((flags & NOFB) && is_framebuffer()) ret = S2RAM_NOFB; if (flags & UNSURE) printf("ATTENTION:\nYour machine is in the whitelist " " but the entry has not been confirmed.\n" "You may try to find better options " "than previously reported.\n\n"); } return ret; } int machine_known(void) { int i = machine_match(); if (i < 0) { printf("Machine unknown\n"); identify_machine(); return 1; } s2ram_check(i); printf("Machine matched entry %d:\n" " sys_vendor = '%s'\n" " sys_product = '%s'\n" " sys_version = '%s'\n" " bios_version = '%s'\n", i, whitelist[i].sys_vendor, whitelist[i].sys_product, whitelist[i].sys_version, whitelist[i].bios_version); printf("Fixes: 0x%x %s%s%s%s%s%s%s%s%s\n", flags, (flags & VBE_SAVE) ? "VBE_SAVE " : "", (flags & VBE_POST) ? "VBE_POST " : "", (flags & VBE_MODE) ? "VBE_MODE " : "", (flags & RADEON_OFF) ? "RADEON_OFF " : "", (flags & S3_BIOS) ? "S3_BIOS " : "", (flags & S3_MODE) ? "S3_MODE " : "", (flags & NOFB) ? "NOFB " : "", (flags & PCI_SAVE) ? "PCI_SAVE " : "", (flags & UNSURE) ? "UNSURE " : ""); /* in case of a bugreport we might need to find a better match than * the one we already have (additional BIOS version e.g)... */ identify_machine(); return (flags & UNSURE); } static int find_vga(void) { struct pci_dev *dev; unsigned int class; pci_scan_bus(pacc); /* We want to get the list of devices */ for (dev=pacc->devices; dev; dev=dev->next) { pci_fill_info(dev, PCI_FILL_IDENT); class = pci_read_word(dev, PCI_CLASS_DEVICE); if (class == 0x300) break; } if (!dev) return 0; memcpy(&vga_dev, dev, sizeof(*dev)); vga_dev.next = NULL; return 1; } static void save_vga_pci(void) { pci_read_block(&vga_dev, 0, vga_pci_state, 256); } static void restore_vga_pci(void) { pci_write_block(&vga_dev, 0, vga_pci_state, 256); } /* warning: we have to be on a text console when calling this */ int s2ram_hacks(void) { int ret = 0; ret = set_acpi_video_mode(flags & (S3_BIOS | S3_MODE)); if (ret) return ret; if (flags & VBE_SAVE) { int size; vbetool_init(); printf("Calling save_state\n"); vbe_buffer = __save_state(&size); } if (flags & VBE_MODE) { vbetool_init(); printf("Calling get_mode\n"); vbe_mode = __get_mode(); } if (flags & RADEON_OFF) { map_radeon_cntl_mem(); printf("Calling radeon_cmd_light(0)\n"); radeon_cmd_light(0); } if (flags & PCI_SAVE) { pacc = pci_alloc(); /* Get the pci_access structure */ pci_init(pacc); /* Initialize the PCI library */ if (find_vga()) { printf("saving PCI config of device %02x:%02x.%d\n", vga_dev.bus, vga_dev.dev, vga_dev.func); save_vga_pci(); } else /* pci_save requested, no VGA device found => abort */ return 1; } if (fb_nosuspend) printf("ATTENTION: --nofbsuspend is a debugging tool only.\n" "\tIf your machine needs this to work, please report " "this as a bug.\n"); else suspend_fbcon(); return 0; } int s2ram_is_supported(void) { int ret = 0, id; if (!force) { if (flags) { printf("The acpi_sleep, vbe_save, vbe_post, radeontool" " and pci_save parameters must be used with" " --force\n\n"); return EINVAL; } id = machine_match(); ret = s2ram_check(id); } return ret; } /* Actually enter the suspend. May be ran on frozen system. */ int s2ram_do(void) { return s2ram_generic_do(); } void s2ram_resume(void) { if (flags & PCI_SAVE) { printf("restoring PCI config of device %02x:%02x.%d\n", vga_dev.bus, vga_dev.dev, vga_dev.func); restore_vga_pci(); pci_cleanup(pacc); } // FIXME: can we call vbetool_init() multiple times without cleaning up? if (flags & VBE_POST) { vbetool_init(); printf("Calling do_post\n"); do_post(); } if (vbe_buffer) { vbetool_init(); printf("Calling restore_state_from\n"); restore_state_from(vbe_buffer); } if (vbe_mode >= 0) { vbetool_init(); printf("Calling set_vbe_mode\n"); do_set_mode(vbe_mode, 0); } if (!fb_nosuspend) resume_fbcon(); if (flags & RADEON_OFF) { printf("Calling radeon_cmd_light(1)\n"); radeon_cmd_light(1); } } void s2ram_add_flag(int opt, const char *opt_arg) { /* The characters are the `deprecated' short options. They will not * clash with the new labels untill we reach quirk 65... */ switch (opt) { case 1: case 'f': force = 1; break; case 2: case 's': flags |= VBE_SAVE; break; case 3: case 'p': flags |= VBE_POST; break; case 4: case 'm': flags |= VBE_MODE; break; case 5: case 'r': flags |= RADEON_OFF; break; case 6: case 'v': flags |= PCI_SAVE; break; case 7: case 'a': flags |= (atoi(opt_arg) & (S3_BIOS | S3_MODE)); break; case 8: fb_nosuspend = 1; break; case 9: case 'k': no_kms_flag = 1; break; } } suspend-utils/keygen.c0000644000175500017550000001326212075743442013521 0ustar kixkix/* * keygen.c * * RSA key generator for the suspend and resume tools. * * Copyright (C) 2006 Rafael J. Wysocki * * This file is released under the GPLv2. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "md5.h" #include "encrypt.h" #define MIN_KEY_BITS 1024 #define MAX_KEY_BITS 4096 #define MAX_OUT_SIZE (sizeof(struct RSA_data)) #define MAX_STR_LEN 256 #define DEFAULT_FILE "suspend.key" static char in_buffer[MAX_STR_LEN]; static char pass_buf[MAX_STR_LEN]; static struct RSA_data rsa; static unsigned char encrypt_buffer[RSA_DATA_SIZE]; int main(int argc, char *argv[]) { gcry_ac_data_t rsa_data_set; gcry_ac_handle_t rsa_hd; gcry_ac_key_t rsa_priv; gcry_ac_key_pair_t rsa_key_pair; gcry_mpi_t mpi; size_t offset; int len = MIN_KEY_BITS, ret = EXIT_SUCCESS; struct termios termios; char *vrfy_buf; struct md5_ctx ctx; unsigned char key_buf[PK_KEY_SIZE]; gcry_cipher_hd_t sym_hd; unsigned char ivec[PK_CIPHER_BLOCK]; unsigned short size; int j, fd; printf("libgcrypt version: %s\n", gcry_check_version(NULL)); gcry_control(GCRYCTL_INIT_SECMEM, 4096, 0); ret = gcry_ac_open(&rsa_hd, GCRY_AC_RSA, 0); if (ret) return ret; do { printf("Key bits (between %d and %d inclusive) [%d]: ", MIN_KEY_BITS, MAX_KEY_BITS, len); fgets(in_buffer, MAX_STR_LEN, stdin); if (strlen(in_buffer) && *in_buffer != '\n') sscanf(in_buffer, "%d", &len); } while (len < MIN_KEY_BITS || len > MAX_KEY_BITS); Retry: printf("Generating %d-bit RSA keys. Please wait.\n", len); ret = gcry_ac_key_pair_generate(rsa_hd, len, NULL, &rsa_key_pair, NULL); if (ret) { fprintf(stderr, "Key generation failed: %s\n", gcry_strerror(ret)); ret = EXIT_FAILURE; goto Close_RSA; } printf("Testing the private key. Please wait.\n"); rsa_priv = gcry_ac_key_pair_extract(rsa_key_pair, GCRY_AC_KEY_SECRET); ret = gcry_ac_key_test(rsa_hd, rsa_priv); if (ret) { printf("RSA key test failed. Retrying.\n"); goto Retry; } rsa_data_set = gcry_ac_key_data_get(rsa_priv); if (gcry_ac_data_length(rsa_data_set) != RSA_FIELDS) { fprintf(stderr, "Wrong number of key fields\n"); ret = -EINVAL; goto Free_RSA; } /* Copy the public key components to struct RSA_data */ offset = 0; for (j = 0; j < RSA_FIELDS_PUB; j++) { char *str; size_t s; gcry_ac_data_get_index(rsa_data_set, GCRY_AC_FLAG_COPY, j, (const char **)&str, &mpi); ret = gcry_mpi_print(GCRYMPI_FMT_USG, rsa.data + offset, RSA_DATA_SIZE - offset, &s, mpi); if (ret) { fprintf(stderr, "RSA key components too big\n"); goto Free_RSA; } rsa.field[j][0] = str[0]; rsa.field[j][1] = '\0'; rsa.size[j] = s; offset += s; gcry_mpi_release(mpi); gcry_free(str); } tcgetattr(0, &termios); termios.c_lflag &= ~ECHO; termios.c_lflag |= ICANON | ECHONL; tcsetattr(0, TCSANOW, &termios); vrfy_buf = (char *)encrypt_buffer; do { do { printf("Passphrase please (must be non-empty): "); fgets(pass_buf, MAX_STR_LEN, stdin); len = strlen(pass_buf) - 1; } while (len <= 0); if (pass_buf[len] == '\n') pass_buf[len] = '\0'; printf("Confirm passphrase: "); fgets(vrfy_buf, MAX_STR_LEN, stdin); if (vrfy_buf[len] == '\n') vrfy_buf[len] = '\0'; } while (strncmp(pass_buf, vrfy_buf, MAX_STR_LEN)); termios.c_lflag |= ECHO; tcsetattr(0, TCSANOW, &termios); memset(ivec, 0, PK_CIPHER_BLOCK); strncpy((char *)ivec, pass_buf, PK_CIPHER_BLOCK); md5_init_ctx(&ctx); md5_process_bytes(pass_buf, strlen(pass_buf), &ctx); md5_finish_ctx(&ctx, key_buf); /* First, we encrypt the key test */ ret = gcry_cipher_open(&sym_hd, PK_CIPHER, GCRY_CIPHER_MODE_CFB, GCRY_CIPHER_SECURE); if (ret) goto Free_RSA; ret = gcry_cipher_setkey(sym_hd, key_buf, PK_KEY_SIZE); if (!ret) ret = gcry_cipher_setiv(sym_hd, ivec, PK_CIPHER_BLOCK); if (!ret) ret = gcry_cipher_encrypt(sym_hd, rsa.key_test, KEY_TEST_SIZE, KEY_TEST_DATA, KEY_TEST_SIZE); gcry_cipher_close(sym_hd); if (ret) goto Free_RSA; /* Now, we can encrypt the private RSA key */ ret = gcry_cipher_open(&sym_hd, PK_CIPHER, GCRY_CIPHER_MODE_CFB, GCRY_CIPHER_SECURE); if (ret) goto Free_RSA; ret = gcry_cipher_setkey(sym_hd, key_buf, PK_KEY_SIZE); if (!ret) ret = gcry_cipher_setiv(sym_hd, ivec, PK_CIPHER_BLOCK); if (ret) goto Free_sym; /* Copy the private key components (encrypted) to struct RSA_data */ for (j = RSA_FIELDS_PUB; j < RSA_FIELDS; j++) { char *str; size_t s; gcry_ac_data_get_index(rsa_data_set, GCRY_AC_FLAG_COPY, j, (const char **)&str, &mpi); ret = gcry_mpi_print(GCRYMPI_FMT_USG, rsa.data + offset, RSA_DATA_SIZE - offset, &s, mpi); if (ret) { fprintf(stderr, "RSA key components too big\n"); goto Free_sym; } /* We encrypt the data in place */ ret = gcry_cipher_encrypt(sym_hd, rsa.data + offset, s, NULL, 0); if (ret) goto Free_sym; rsa.field[j][0] = str[0]; rsa.field[j][1] = '\0'; rsa.size[j] = s; offset += s; gcry_mpi_release(mpi); gcry_free(str); } size = offset + sizeof(struct RSA_data) - RSA_DATA_SIZE; printf("File name [%s]: ", DEFAULT_FILE); fgets(in_buffer, MAX_STR_LEN, stdin); if (!strlen(in_buffer) || *in_buffer == '\n') strcpy(in_buffer, DEFAULT_FILE); else if (in_buffer[strlen(in_buffer)-1] == '\n') in_buffer[strlen(in_buffer)-1] = '\0'; fd = open(in_buffer, O_RDWR | O_CREAT | O_TRUNC, 00600); if (fd >= 0) { write(fd, &rsa, size); close(fd); } else { fprintf(stderr, "Could not open the file %s\n", in_buffer); ret = EXIT_FAILURE; } Free_sym: gcry_cipher_close(sym_hd); Free_RSA: gcry_ac_data_destroy(rsa_data_set); Close_RSA: gcry_ac_close(rsa_hd); return ret; } suspend-utils/s2ram-x86.h0000644000175500017550000000371712075743442013717 0ustar kixkix/* * s2ram-x86.h * * Copyright 2007 Tim Dijkstra * * Distribute under GPLv2. */ #define S3_BIOS 0x01 /* machine needs acpi_sleep=s3_bios */ #define S3_MODE 0x02 /* machine needs acpi_sleep=s3_mode */ #define VBE_SAVE 0x04 /* machine needs "vbetool save / restore" */ #define VBE_POST 0x08 /* machine needs "vbetool post" */ #define RADEON_OFF 0x10 /* machine needs "radeontool light off" */ #define UNSURE 0x20 /* unverified entries from acpi-support 0.59 */ #define NOFB 0x40 /* must not use a frame buffer */ #define VBE_MODE 0x80 /* machine needs "vbetool vbemode get / set" */ #define PCI_SAVE 0x100 /* we need to save the VGA PCI registers */ /* Item size */ #define ITEMSZ 1024 char bios_version[ITEMSZ], sys_vendor[ITEMSZ], sys_product[ITEMSZ], sys_version[ITEMSZ]; int flags, force, fb_nosuspend, no_kms_flag; #define HACKS_LONG_OPTS \ {\ "nofbsuspend\0\tdo not suspend the framebuffer (debugging only!).",\ no_argument, NULL, 8 \ },\ {\ "force\0\tforce suspending, even on unknown machines.\n\nThe following options are only available with --force:",\ no_argument, NULL, 1 \ },\ {\ "vbe_save\0\tsave VBE state before suspending and restore after resume.",\ no_argument, NULL, 2 \ },\ {\ "vbe_post\0\tVBE POST the graphics card after resume.",\ no_argument, NULL, 3 \ },\ {\ "vbe_mode\0\tget VBE mode before suspend and set it after resume.",\ no_argument, NULL, 4 \ },\ {\ "radeontool\0\tturn off the backlight on radeons before suspending.",\ no_argument, NULL, 5 \ },\ {\ "pci_save\0\tsave the PCI config space for the VGA card.",\ no_argument, NULL, 6 \ },\ {\ "acpi_sleep\0set the acpi_sleep parameter before suspend\n\t\t\t1=s3_bios, 2=s3_mode, 3=both",\ required_argument, NULL, 7 \ },\ {\ "no_kms\0\tdo not set KMS (Kernel Mode Set).",\ required_argument, NULL, 9 \ }, suspend-utils/suspend.c0000644000175500017550000017055112075743442013725 0ustar kixkix/* * suspend.c * * A simple user space suspend handler for swsusp. * * Copyright (C) 2005 Rafael J. Wysocki * * This file is released under the GPLv2. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_THREADS #include #endif #ifdef CONFIG_COMPRESS #include #endif #include "swsusp.h" #include "memalloc.h" #include "config_parser.h" #include "md5.h" #include "splash.h" #include "vt.h" #include "loglevel.h" #ifdef CONFIG_BOTH #include "s2ram.h" #endif static char test_file_name[MAX_STR_LEN] = ""; static loff_t test_image_size; #define suspend_error(msg, args...) \ do { \ fprintf(stderr, "%s: " msg " Reason: %m\n", my_name, ## args); \ } while (0) #ifdef CONFIG_ARCH_S390 #define suspend_warning(msg) #else #define suspend_warning(msg) \ do { \ fprintf(stderr, "%s: " msg "\n", my_name); \ } while (0) #endif static char snapshot_dev_name[MAX_STR_LEN] = SNAPSHOT_DEVICE; static char resume_dev_name[MAX_STR_LEN] = RESUME_DEVICE; static loff_t resume_offset; static loff_t pref_image_size = IMAGE_SIZE; static int suspend_loglevel = SUSPEND_LOGLEVEL; static char compute_checksum; #ifdef CONFIG_COMPRESS static char do_compress; #else #define do_compress 0 #endif #ifdef CONFIG_ENCRYPT static char do_encrypt; static char use_RSA; static char key_name[MAX_STR_LEN] = SUSPEND_KEY_FILE_PATH; static char password[PASSBUF_SIZE]; static unsigned long encrypt_buf_size; #else #define do_encrypt 0 #define key_name NULL #define encrypt_buf_size 0 #endif #ifdef CONFIG_BOTH static char s2ram; static char s2ram_kms; #endif static char early_writeout; static char splash_param; #ifdef CONFIG_FBSPLASH char fbsplash_theme[MAX_STR_LEN] = ""; #endif #define SHUTDOWN_LEN 16 static char shutdown_method_value[SHUTDOWN_LEN] = ""; static enum { SHUTDOWN_METHOD_SHUTDOWN, SHUTDOWN_METHOD_PLATFORM, SHUTDOWN_METHOD_REBOOT } shutdown_method = SHUTDOWN_METHOD_PLATFORM; static int resume_pause; static char verify_image; #ifdef CONFIG_THREADS static char use_threads; #else #define use_threads 0 #endif static int suspend_swappiness = SUSPEND_SWAPPINESS; static struct vt_mode orig_vtm; static int vfd; static struct config_par parameters[] = { { .name = "snapshot device", .fmt = "%s", .ptr = snapshot_dev_name, .len = MAX_STR_LEN }, { .name = "resume device", .fmt ="%s", .ptr = resume_dev_name, .len = MAX_STR_LEN }, { .name = "resume offset", .fmt = "%llu", .ptr = &resume_offset, }, { .name = "image size", .fmt = "%lu", .ptr = &pref_image_size, }, { .name = "suspend loglevel", .fmt = "%d", .ptr = &suspend_loglevel, }, { .name = "max loglevel", .fmt = "%d", .ptr = NULL, }, { .name = "compute checksum", .fmt = "%c", .ptr = &compute_checksum, }, #ifdef CONFIG_COMPRESS { .name = "compress", .fmt = "%c", .ptr = &do_compress, }, #endif #ifdef CONFIG_ENCRYPT { .name = "encrypt", .fmt = "%c", .ptr = &do_encrypt, }, { .name = "RSA key file", .fmt = "%s", .ptr = key_name, .len = MAX_STR_LEN }, #endif { .name = "early writeout", .fmt = "%c", .ptr = &early_writeout, }, { .name = "splash", .fmt = "%c", .ptr = &splash_param, }, { .name = "shutdown method", .fmt = "%s", .ptr = shutdown_method_value, .len = SHUTDOWN_LEN, }, #ifdef CONFIG_FBSPLASH { .name = "fbsplash theme", .fmt = "%s", .ptr = fbsplash_theme, .len = MAX_STR_LEN, }, #endif { .name = "resume pause", .fmt = "%d", .ptr = &resume_pause, }, { .name = "debug test file", .fmt = "%s", .ptr = test_file_name, .len = MAX_STR_LEN }, { .name = "debug verify image", .fmt = "%c", .ptr = &verify_image, }, #ifdef CONFIG_THREADS { .name = "threads", .fmt = "%c", .ptr = &use_threads, }, #endif { .name = NULL, .fmt = NULL, .ptr = NULL, .len = 0, } }; static loff_t check_free_swap(int dev) { int error; loff_t free_swap; error = ioctl(dev, SNAPSHOT_AVAIL_SWAP_SIZE, &free_swap); if (error && errno == ENOTTY) error = ioctl(dev, SNAPSHOT_AVAIL_SWAP, &free_swap); if (!error) return free_swap; suspend_error("check_free_swap failed."); return 0; } static loff_t get_image_size(int dev) { int error; loff_t image_size; error = ioctl(dev, SNAPSHOT_GET_IMAGE_SIZE, &image_size); if (!error) return image_size; suspend_error("get_image_size failed."); return 0; } static inline loff_t get_swap_page(int dev) { int error; loff_t offset; error = ioctl(dev, SNAPSHOT_ALLOC_SWAP_PAGE, &offset); if (error && errno == ENOTTY) error = ioctl(dev, SNAPSHOT_GET_SWAP_PAGE, &offset); if (!error) return offset; return 0; } static inline int free_swap_pages(int dev) { return ioctl(dev, SNAPSHOT_FREE_SWAP_PAGES, 0); } static int set_swap_file(int dev, u_int32_t blkdev, loff_t offset) { struct resume_swap_area swap; int error; swap.dev = blkdev; swap.offset = offset; error = ioctl(dev, SNAPSHOT_SET_SWAP_AREA, &swap); if (error && !offset) error = ioctl(dev, SNAPSHOT_SET_SWAP_FILE, blkdev); return error; } static int atomic_snapshot(int dev, int *in_suspend) { int error; error = ioctl(dev, SNAPSHOT_CREATE_IMAGE, in_suspend); if (error && errno == ENOTTY) error = ioctl(dev, SNAPSHOT_ATOMIC_SNAPSHOT, in_suspend); return error; } static inline int free_snapshot(int dev) { return ioctl(dev, SNAPSHOT_FREE, 0); } static int set_image_size(int dev, loff_t size) { int error; error = ioctl(dev, SNAPSHOT_PREF_IMAGE_SIZE, size); if (error && errno == ENOTTY) error = ioctl(dev, SNAPSHOT_SET_IMAGE_SIZE, size); return error; } static inline int suspend_to_ram(int dev) { return ioctl(dev, SNAPSHOT_S2RAM, 0); } static int platform_enter(int dev) { int error; error = ioctl(dev, SNAPSHOT_POWER_OFF, 0); if (error && errno == ENOTTY) error = ioctl(dev, SNAPSHOT_PMOPS, PMOPS_ENTER); return error; } /** * alloc_swap - allocate a number of swap pages * @dev: Swap device to use for allocations. * @extents: Array of extents to track the allocations. * @nr_extents: Number of extents already in the array. * @size_p: Points to the number of bytes to allocate, used to * return the number of allocated bytes. * * Allocate the number of swap pages sufficient for saving the number of * bytes pointed to by @size_p. Use the array @extents to track the * allocations. This array has to be page_size big and may already * contain some initial elements (in that case @nr_extents must be the * number of these elements). * Each element of the array represents an area of allocated swap space. * These areas may be extended when swap pages that can be added to them * are found. They also can be merged with one another. * The function returns when the requested amount of swap space is * allocated or if there is no room for more extents. In the latter case * the last extent created is put at the end of the array and may be passed * to alloc_swap() as the initial extent when it is invoked next time. */ static int alloc_swap(int dev, struct extent *extents, int nr_extents, loff_t *size_p) { const int max_extents = page_size / sizeof(struct extent) - 1; loff_t size, total_size, offset; total_size = *size_p; if (nr_extents <= 0) { offset = get_swap_page(dev); if (!offset) return -ENOSPC; extents->start = offset; extents->end = offset + page_size; nr_extents = 1; size = page_size; } else { size = 0; } while (size < total_size && nr_extents <= max_extents) { int i, j; offset = get_swap_page(dev); if (!offset) return -ENOSPC; /* Check if we have a matching extent. */ i = 0; j = nr_extents - 1; do { struct extent *ext; int k = (i + j) / 2; Repeat: ext = extents + k; if (offset == ext->start - page_size) { ext->start = offset; /* Check if we can merge extents */ if (k > 0 && extents[k-1].end == offset) { extents[k-1].end = ext->end; /* Pull the 'later' extents forward */ memmove(ext, ext + 1, (nr_extents - k - 1) * sizeof(*ext)); nr_extents--; } offset = 0; break; } else if (offset == ext->end) { ext->end += page_size; /* Check if we can merge extents */ if (k + 1 < nr_extents && ext->end == extents[k+1].start) { ext->end = extents[k+1].end; /* Pull the 'later' extents forward */ memmove(ext + 1, ext + 2, (nr_extents - k - 2) * sizeof(*ext)); nr_extents--; } offset = 0; break; } else if (offset > ext->end) { if (i == k) { if (i < j) { /* This means i == j + 1 */ k = j; i = j; goto Repeat; } } else { i = k; } } else { /* offset < ext->start - page_size */ j = k; } } while (i < j); if (offset > 0) { /* No match. Create a new extent. */ struct extent *ext; if (nr_extents < max_extents) { ext = extents + i; /* * We want to always replace the extent 'i' with * the new one. */ if (offset > ext->end) { i++; ext++; } /* Push the 'later' extents backwards. */ memmove(ext + 1, ext, (nr_extents - i) * sizeof(*ext)); } else { ext = extents + nr_extents; } ext->start = offset; ext->end = offset + page_size; nr_extents++; } size += page_size; } *size_p = size; return nr_extents; } /** * write_page - Write page_size data to given swap location. * @fd: File handle of the resume partition. * @buf: Pointer to the area we're writing. * @offset: Offset of the swap page we're writing to. */ static int write_page(int fd, void *buf, loff_t offset) { int res = 0; ssize_t cnt = 0; if (!offset) return -EINVAL; if (lseek64(fd, offset, SEEK_SET) == offset) cnt = write(fd, buf, page_size); if (cnt != page_size) res = -EIO; return res; } /* * The swap_writer structure is used for handling swap in a file-alike way. * * @extents: Array of extents used for trackig swap allocations. It is * page_size bytes large and holds at most * (page_size / sizeof(struct extent) - 1) extents. The last slot * is used to hold the extent that will be used as an initial one * for the next batch of allocations. * * @nr_extents: Number of entries in @extents actually used. * * @cur_extent: The extent currently used as the source of swap pages. * * @cur_extent_idx: The index of @cur_extent. * * @cur_offset: The offset of the swap page that will be used next. * * @swap_needed: The amount of swap needed for saving the image. * * @written_data: The amount of data actually saved. * * @extents_spc: The swap page to which to save @extents. * * @buffer: Buffer used for storing image data pages. * * @write_buffer: If compression is used, the compressed contents of * @buffer are stored here. Otherwise, it is equal to * @buffer. * * @page_ptr: Address to write the next image page to. * * @dev: Snapshot device handle used for reading image pages and * invoking ioctls. * * @fd: File handle associated with the swap. * * @ctx: Used for checksum computing, if so configured. * * @lzo_work_buffer: Work buffer used for compression. * * @encrypt_buffer: Buffer for storing encrypted data (page_size bytes). * * @encrypt_ptr: Address to store the next encrypted page at. */ struct swap_writer { struct extent *extents; int nr_extents; struct extent *cur_extent; int cur_extent_idx; loff_t cur_offset; loff_t swap_needed; loff_t written_data; loff_t extents_spc; void *buffer; void *write_buffer; void *page_ptr; int dev, fd, input; struct md5_ctx ctx; void *lzo_work_buffer; void *encrypt_buffer; void *encrypt_ptr; }; /** * free_swap_writer - free memory allocated for saving the image * @handle: Structure containing pointers to memory buffers to free. */ static void free_swap_writer(struct swap_writer *handle) { if (handle->write_buffer != handle->buffer) freemem(handle->write_buffer); if (do_compress) freemem(handle->lzo_work_buffer); if (handle->encrypt_buffer) freemem(handle->encrypt_buffer); freemem(handle->buffer); freemem(handle->extents); } /** * init_swap_writer - initialize the structure used for saving the image * @handle: Structure to initialize. * @dev: Special device file to read image pages from. * @fd: File descriptor associated with the swap. * * It doesn't preallocate swap, so preallocate_swap() has to be called on * @handle after this. */ static int init_swap_writer(struct swap_writer *handle, int dev, int fd, int in) { loff_t offset; unsigned int write_buf_size = 0; handle->extents = getmem(page_size); handle->buffer = getmem(buffer_size); handle->page_ptr = handle->buffer; if (do_encrypt) { handle->encrypt_buffer = getmem(encrypt_buf_size); handle->encrypt_ptr = handle->encrypt_buffer; } else { handle->encrypt_buffer = NULL; } if (do_compress) { handle->lzo_work_buffer = getmem(LZO1X_1_MEM_COMPRESS); write_buf_size = compress_buf_size; if (use_threads) write_buf_size += (WRITE_BUFFERS - 1) * compress_buf_size; } if (write_buf_size > 0) handle->write_buffer = getmem(write_buf_size); else if (use_threads) handle->write_buffer = getmem(buffer_size * WRITE_BUFFERS); else handle->write_buffer = handle->buffer; handle->dev = dev; handle->fd = fd; handle->input = (in >= 0) ? in : dev; handle->written_data = 0; memset(handle->extents, 0, page_size); handle->nr_extents = 0; offset = get_swap_page(dev); if (!offset) { free_swap_writer(handle); return -ENOSPC; } handle->extents_spc = offset; if (compute_checksum || verify_image) md5_init_ctx(&handle->ctx); return 0; } /** * preallocate_swap - use alloc_swap() to preallocate the number of pages * given by @handle->swap_needed * @handle: Pointer to the structure in which to store information * about the preallocated swap pool. * * Returns the offset of the first swap page available from the * preallocated pool. */ static loff_t preallocate_swap(struct swap_writer *handle) { const int max = page_size / sizeof(struct extent) - 1; loff_t size; int nr_extents; if (handle->swap_needed < page_size) return 0; size = handle->swap_needed; if (do_compress && size > page_size) size /= 2; nr_extents = alloc_swap(handle->dev, handle->extents, handle->nr_extents, &size); if (nr_extents <= 0) return 0; handle->nr_extents = nr_extents < max ? nr_extents : max; handle->cur_extent = handle->extents; handle->cur_extent_idx = 0; handle->cur_offset = handle->cur_extent->start; return handle->cur_offset; } /** * save_extents - save the array of extents * handle: Structure holding the pointer to the array of extents etc. * finish: If set, the last element of the extents array has to be filled * with zeros. * * Save the buffer (page) holding the array of extents to the swap * location pointed to by @handle->extents_spc (this must be allocated * earlier). Before saving the last element of the array is used to store * the swap offset of the next extents page (we allocate a swap page for * this purpose). */ static int save_extents(struct swap_writer *handle, int finish) { loff_t offset = 0; int error; if (!finish) { struct extent *last_extent; offset = get_swap_page(handle->dev); if (!offset) return -ENOSPC; last_extent = handle->extents + page_size / sizeof(struct extent) - 1; last_extent->start = offset; } error = write_page(handle->fd, handle->extents, handle->extents_spc); handle->extents_spc = offset; return error; } /** * next_swap_page - take one swap page out of the pool allocated using * alloc_swap() before * @handle: Pointer to the structure containing information about * the preallocated swap pool. */ static loff_t next_swap_page(struct swap_writer *handle) { struct extent ext; handle->cur_offset += page_size; if (handle->cur_offset < handle->cur_extent->end) return handle->cur_offset; /* We have exhausted the current extent. Forward to the next one */ handle->cur_extent++; handle->cur_extent_idx++; if (handle->cur_extent_idx < handle->nr_extents) { handle->cur_offset = handle->cur_extent->start; return handle->cur_offset; } /* No more extents. Is there anything to pass to alloc_swap()? */ if (handle->cur_extent->start < handle->cur_extent->end) { ext = *handle->cur_extent; memset(handle->cur_extent, 0, sizeof(struct extent)); handle->nr_extents = 1; } else { memset(&ext, 0, sizeof(struct extent)); handle->nr_extents = 0; } if (save_extents(handle, 0)) return 0; memset(handle->extents, 0, page_size); *handle->extents = ext; return preallocate_swap(handle); } /** * save_page - save one page of data to the swap * @handle: Pointer to the structure containing information about * the swap. * @src: Pointer to the data. */ static int save_page(struct swap_writer *handle, void *src) { loff_t offset; int error; offset = next_swap_page(handle); if (!offset) return -ENOSPC; error = write_page(handle->fd, src, offset); if (error) return error; handle->swap_needed -= page_size; handle->written_data += page_size; return 0; } #ifdef CONFIG_THREADS /* * If threads are used for saving the image with compression and encryption, * there are three of them. * * The main one reads image pages from the kernel and puts them into a work * buffer. When the work buffer is full, it gets compressed, but that's not an * in-place compression, so the result has to be stored somewhere else. There * are four so-called "write" buffers for that and the first empty "write" * buffer is used as the target. If all of the "write" buffers are full, the * thread has to wait (see the rules below). Otherwise, after placing the * (compressed) contents of the work buffer into a "write" buffer, the main * thread regards the work buffer as empty and starts to read more image pages * from the kernel. * * The second thread (call it the "move" thread) encrypts the contents of the * "write" buffers, one buffer at a time. It really encrypts individual pages * and the encryption is not in-place, too. The encrypted pages of data are * placed in yet another buffer (call it the "encrypt" buffer) until it's full, * in which case the "move" thread has to wait. Of course, it also has to wait * for data from the main thread if all of the "write" buffers are empty. * After encrypting an entire "write" buffer, the "move" thread progresses to * the next "write" buffer, in a round-robin manner. * * The synchronization between the main thread and the "move" thread is done * with the help of two index variables, move_start and move_end. �The rule * is that: * (1) the main thread can only put data into write_buffers[move_start], * (2) after putting data into write_buffers[move_start], the main thread * increases move_start, modulo the number of "write" buffers, but * move_start cannot be modified as long as the _next_ "write" buffer is * write_buffers[move_end] (the thread has to wait if that happens), * (3) the "move" thread can only read data from write_buffers[move_end] and * only if move_end != move_start (it has to wait if that's not the case), * (4) after reading data from write_buffers[move_end], the "move" thread * increases move_end, modulo the number of "write" buffers. * This way, move_end always "follows" move_start and the threads don't access * the same buffer at any time. * * The third thread (call it the "save" thread) reads (encrypted) pages of data * from the "encrypt" buffer and writes them out to the swap. This is done if * there are some pages to write in the "encrypt" buffer, otherwise the "save" * thread has to wait for the "move" thread to put more pages in there. * * The synchronization between the "move" thread and the "save" thread is done * with the help of two pointers, save_start and save_end, where save_start * points to the first empty page and save_end points to the last data page * that hasn't been written out yet. Thus, the rule is: * (1) the "move" thread can only put data into the page pointed to by * save_start, * (2) after putting data into the page pointed to by save_start, the "move" * thread increases save_start, modulo the number of pages in the buffer, * provided that the _next_ page is not the one pointed to by save_end (it * has to wait if that happens), * (3) the "save" thread can only read from the page pointed to by save_end, * as long as save_end != save_start (it has to wait if the two pointers * are equal), * (4) after writing data from the page pointed to by save_end, the "save" * thread increases save_end, modulo the number of pages in the buffer. * IOW, the "encrypt" buffer is handled as a typical circular buffer with one * producer (the "move" thread) and one consumer (the "save" thread). * * If encryption is not used, the "save" thread is not started and the "move" * thread writes data to the swap directly out of the "write" buffers. */ static int save_ret; static pthread_mutex_t finish_mutex; static pthread_cond_t finish_cond; static char *encrypt_buf; static char *save_start, *save_end; static pthread_mutex_t save_mutex; static pthread_cond_t save_cond; static pthread_t save_th; struct write_buffer { ssize_t size; void *start; }; static struct write_buffer write_buffers[WRITE_BUFFERS]; static int move_start, move_end; static pthread_mutex_t move_mutex; static pthread_cond_t move_cond; static pthread_t move_th; #define FORCE_EXIT 1 static char *save_inc(char *ptr) { return encrypt_buf + (((ptr - encrypt_buf) + page_size) % encrypt_buf_size); } static int move_inc(int index) { return (index + 1) % WRITE_BUFFERS; } static int wait_for_finish(void) { pthread_mutex_lock(&finish_mutex); while((save_end != save_start || move_start != move_end) && !save_ret) pthread_cond_wait(&finish_cond, &finish_mutex); pthread_mutex_unlock(&finish_mutex); return save_ret; } static void *save_thread(void *arg) { struct swap_writer *handle = arg; int error = 0; for (;;) { /* Wait until there is a buffer ready for processing. */ pthread_mutex_lock(&save_mutex); while(save_end == save_start && !save_ret) pthread_cond_wait(&save_cond, &save_mutex); pthread_mutex_unlock(&save_mutex); if (save_ret) return NULL; error = save_page(handle, save_end); if (error) { pthread_mutex_lock(&finish_mutex); if (!save_ret) save_ret = error; pthread_mutex_unlock(&finish_mutex); pthread_cond_signal(&move_cond); pthread_cond_signal(&save_cond); pthread_cond_signal(&finish_cond); return NULL; } /* Go to the next page */ pthread_mutex_lock(&finish_mutex); pthread_mutex_lock(&save_mutex); save_end = save_inc(save_end); pthread_mutex_unlock(&save_mutex); pthread_mutex_unlock(&finish_mutex); pthread_cond_signal(&save_cond); pthread_cond_signal(&finish_cond); } return NULL; } #ifdef CONFIG_ENCRYPT static void encrypt_and_save_buffer(void) { char *src; ssize_t buf_size, moved_size; /* * The buffer to process is at write_buffers[move_end].start and the * size of it is write_buffers[move_end].size . */ src = write_buffers[move_end].start; buf_size = write_buffers[move_end].size; moved_size = 0; do { int error; void *next_start; /* Encrypt page_size of data. */ error = gcry_cipher_encrypt(cipher_handle, save_start, page_size, src, page_size); if (error) { pthread_mutex_lock(&finish_mutex); if (!save_ret) save_ret = error; pthread_mutex_unlock(&finish_mutex); pthread_cond_signal(&move_cond); pthread_cond_signal(&save_cond); pthread_cond_signal(&finish_cond); break; } moved_size += page_size; src += page_size; pthread_mutex_lock(&save_mutex); next_start = save_inc(save_start); while (next_start == save_end && !save_ret) pthread_cond_wait(&save_cond, &save_mutex); save_start = next_start; pthread_mutex_unlock(&save_mutex); pthread_cond_signal(&save_cond); } while (moved_size < buf_size && !save_ret); } #else /* !CONFIG_ENCRYPT */ static inline void encrypt_and_save_buffer(void) {} #endif /* !CONFIG_ENCRYPT */ static void save_buffer(struct swap_writer *handle) { void *src; ssize_t size; /* * The buffer to process is at write_buffers[move_end].start and the * size of it is write_buffers[move_end].size . */ src = write_buffers[move_end].start; size = write_buffers[move_end].size; while (size > 0) { int error = save_page(handle, src); if (error) { pthread_mutex_lock(&finish_mutex); if (!save_ret) save_ret = error; pthread_mutex_unlock(&finish_mutex); pthread_cond_signal(&move_cond); pthread_cond_signal(&finish_cond); break; } src += page_size; size -= page_size; } } static void *move_thread(void *arg) { struct swap_writer *handle = arg; for (;;) { /* Wait until there is a buffer ready for processing. */ pthread_mutex_lock(&move_mutex); while(move_end == move_start && !save_ret) pthread_cond_wait(&move_cond, &move_mutex); pthread_mutex_unlock(&move_mutex); if (save_ret) break; if (do_encrypt) encrypt_and_save_buffer(); else save_buffer(handle); if (save_ret) break; /* Tell the reader thread that we have processed the buffer */ pthread_mutex_lock(&finish_mutex); pthread_mutex_lock(&move_mutex); move_end = move_inc(move_end); pthread_mutex_unlock(&move_mutex); pthread_mutex_unlock(&finish_mutex); pthread_cond_signal(&move_cond); pthread_cond_signal(&finish_cond); } return NULL; } static inline void *current_write_buffer(void) { return write_buffers[move_start].start; } static int prepare_next_write_buffer(ssize_t size) { int next_start; /* Move to the next buffer and signal that the current one is ready*/ write_buffers[move_start].size = size; pthread_mutex_lock(&move_mutex); next_start = move_inc(move_start); while (next_start == move_end && !save_ret) pthread_cond_wait(&move_cond, &move_mutex); move_start = next_start; pthread_mutex_unlock(&move_mutex); pthread_cond_signal(&move_cond); return save_ret; } static void start_threads(struct swap_writer *handle) { int error; unsigned int write_buf_size; char *write_buf; int j; encrypt_buf = handle->encrypt_buffer; save_start = encrypt_buf; save_end = save_start; write_buf_size = do_compress ? compress_buf_size : buffer_size; write_buf = handle->write_buffer; for (j = 0; j < WRITE_BUFFERS; j++) { write_buffers[j].start = write_buf; write_buf += write_buf_size; } move_start = 0; move_end = move_start; if (do_encrypt) { error = pthread_mutex_init(&save_mutex, NULL); if (error) { perror("pthread_mutex_init() failed:"); goto Error_exit; } error = pthread_cond_init(&save_cond, NULL); if (error) { perror("pthread_cond_init() failed:"); goto Destroy_save_mutex; } } error = pthread_mutex_init(&move_mutex, NULL); if (error) { perror("pthread_mutex_init() failed:"); goto Destroy_save_cond; } error = pthread_cond_init(&move_cond, NULL); if (error) { perror("pthread_cond_init() failed:"); goto Destroy_move_mutex; } if (do_encrypt) { error = pthread_create(&save_th, NULL, save_thread, handle); if (error) { perror("pthread_create() failed:"); goto Destroy_move_cond; } } error = pthread_create(&move_th, NULL, move_thread, handle); if (error) { perror("pthread_create() failed:"); goto Stop_save_thread; } error = pthread_mutex_init(&finish_mutex, NULL); if (error) { perror("pthread_mutex_init() failed:"); goto Stop_move_thread; } error = pthread_cond_init(&finish_cond, NULL); if (error) { perror("pthread_cond_init() failed:"); goto Destroy_finish_mutex; } return; Destroy_finish_mutex: pthread_mutex_destroy(&finish_mutex); Stop_move_thread: save_ret = FORCE_EXIT; pthread_cond_signal(&move_cond); pthread_join(move_th, NULL); Stop_save_thread: if (do_encrypt) { save_ret = FORCE_EXIT; pthread_cond_signal(&save_cond); pthread_join(save_th, NULL); } Destroy_move_cond: pthread_cond_destroy(&move_cond); Destroy_move_mutex: pthread_mutex_destroy(&move_mutex); Destroy_save_cond: if (do_encrypt) pthread_cond_destroy(&save_cond); Destroy_save_mutex: if (do_encrypt) pthread_mutex_destroy(&save_mutex); Error_exit: use_threads = 0; } static void stop_threads(void) { pthread_mutex_lock(&finish_mutex); if (!save_ret) save_ret = FORCE_EXIT; pthread_mutex_unlock(&finish_mutex); pthread_cond_destroy(&finish_cond); pthread_mutex_destroy(&finish_mutex); pthread_cond_signal(&move_cond); pthread_join(move_th, NULL); if (do_encrypt) { pthread_cond_signal(&save_cond); pthread_join(save_th, NULL); } pthread_cond_destroy(&move_cond); pthread_mutex_destroy(&move_mutex); if (do_encrypt) { pthread_cond_destroy(&save_cond); pthread_mutex_destroy(&save_mutex); } } #else /* !CONFIG_THREADS */ static inline int wait_for_finish(void) { return -ENOSYS; } static inline void *current_write_buffer(void) { return NULL; } static inline int prepare_next_write_buffer(ssize_t size) { (void)size; return -ENOSYS; } static inline void start_threads(struct swap_writer *handle) { (void)handle; } static inline void stop_threads(void) {} #endif /* !CONFIG_THREADS */ /** * encrypt_and_save_page - encrypt a page of data and write it to the swap */ static int encrypt_and_save_page(struct swap_writer *handle, void *src) { #ifdef CONFIG_ENCRYPT if (do_encrypt) { int error = gcry_cipher_encrypt(cipher_handle, handle->encrypt_ptr, page_size, src, page_size); if (error) return error; src = handle->encrypt_ptr; handle->encrypt_ptr += page_size; if (handle->encrypt_ptr - handle->encrypt_buffer >= encrypt_buf_size) handle->encrypt_ptr = handle->encrypt_buffer; } #endif return save_page(handle, src); } /** * flush_buffer - flush data stored in the buffer to the swap */ static int flush_buffer(struct swap_writer *handle) { ssize_t size; char *src; int error = 0; /* Check if there is anything to do */ if (handle->page_ptr <= handle->buffer) return 0; size = handle->page_ptr - handle->buffer; if (compute_checksum || verify_image) md5_process_block(handle->buffer, size, &handle->ctx); src = use_threads ? current_write_buffer() : handle->write_buffer; /* Compress the buffer, if necessary */ if (do_compress) { #ifdef CONFIG_COMPRESS struct buf_block *block = (struct buf_block *)src; lzo_uint cnt; lzo1x_1_compress(handle->buffer, size, (lzo_bytep)block->data, &cnt, handle->lzo_work_buffer); block->size = cnt; size = cnt + sizeof(size_t); #endif } else if (use_threads) { memcpy(src, handle->buffer, size); } if (use_threads) return prepare_next_write_buffer(size); /* * If there's no compression and threads are not used, handle->buffer is * equal to handle->write_buffer. In that case, the data are taken * directly out of handle->buffer. */ while (size > 0) { error = encrypt_and_save_page(handle, src); if (error) break; src += page_size; size -= page_size; } return error; } /** * save_image - save the hibernation image data */ static int save_image(struct swap_writer *handle, unsigned int nr_pages) { unsigned int m, writeout_rate; ssize_t ret; struct termios newtrm, savedtrm; int abort_possible, key, error = 0; char message[SPLASH_GENERIC_MESSAGE_SIZE]; /* Switch the state of the terminal so that we can read the keyboard * without blocking and with no echo. * * stdin must be attached to the terminal now. */ abort_possible = !splash.prepare_abort(&savedtrm, &newtrm); sprintf(message, "Saving %u image data pages", nr_pages); if (abort_possible) strcat(message, " (press " ABORT_KEY_NAME " to abort) "); strcat(message, "..."); printf("%s: %s ", my_name, message); splash.set_caption(message); if (use_threads) start_threads(handle); m = nr_pages / 100; if (!m) m = 1; if (early_writeout) writeout_rate = m; else writeout_rate = nr_pages + 1; /* The buffer may be partially filled at this point */ for (nr_pages = 0; ; nr_pages++) { ret = read(handle->input, handle->page_ptr, page_size); if (ret < page_size) { if (ret < 0) { error = -EIO; perror("\nError reading an image page"); } else if (ret > 0) { error = -EFAULT; perror("\nShort read from /dev/snapshot?"); } break; } handle->page_ptr += page_size; if (!(nr_pages % m)) { printf("\b\b\b\b%3d%%", nr_pages / m); splash.progress(20 + (nr_pages / m) * 0.75); while ((key = splash.key_pressed()) > 0) { switch (key) { case ABORT_KEY_CODE: if (abort_possible) { printf(" aborted!\n"); error = -EINTR; goto Exit; } break; case REBOOT_KEY_CODE: printf (" reboot enabled\b\b\b\b\b\b\b" "\b\b\b\b\b\b\b\b"); splash.set_caption("Reboot enabled"); shutdown_method = SHUTDOWN_METHOD_REBOOT; break; } } } if (!((nr_pages + 1) % writeout_rate)) start_writeout(handle->fd); if (handle->page_ptr - handle->buffer >= buffer_size) { /* The buffer is full, flush it */ error = flush_buffer(handle); if (error) break; handle->page_ptr = handle->buffer; } } if (!error) { /* Flush whatever's left in the buffer and save the extents */ error = flush_buffer(handle); if (use_threads) error = wait_for_finish(); if (!error) error = save_extents(handle, 1); if (!error) printf(" done (%u pages)\n", nr_pages); } Exit: if (use_threads) stop_threads(); if (abort_possible) splash.restore_abort(&savedtrm); return error; } /** * enough_swap - Make sure we have enough swap to save the image. * * Returns TRUE or FALSE after checking the total amount of swap * space avaiable from the resume partition. */ static int enough_swap(struct swap_writer *handle) { loff_t free_swap = check_free_swap(handle->dev); loff_t size = do_compress ? handle->swap_needed / 2 : handle->swap_needed; printf("%s: Free swap: %llu kilobytes\n", my_name, (unsigned long long)free_swap / 1024); return free_swap > size; } static struct swsusp_header swsusp_header; static int mark_swap(int fd, loff_t start) { int error = 0; unsigned int size = sizeof(struct swsusp_header); off64_t shift = ((off64_t)resume_offset + 1) * page_size - size; if (lseek64(fd, shift, SEEK_SET) != shift) return -EIO; if (read(fd, &swsusp_header, size) < size) return -EIO; if (!memcmp("SWAP-SPACE", swsusp_header.sig, 10) || !memcmp("SWAPSPACE2", swsusp_header.sig, 10)) { memcpy(swsusp_header.orig_sig, swsusp_header.sig, 10); memcpy(swsusp_header.sig, SWSUSP_SIG, 10); swsusp_header.image = start; if (lseek64(fd, shift, SEEK_SET) != shift) return -EIO; if (write(fd, &swsusp_header, size) < size) error = -EIO; } else { error = -ENODEV; } return error; } /** * write_image - Write entire image and metadata. * @snapshot_fd: File handle of the snapshot device * @resume_fd: File handle of the swap device used for image saving * @test_fd: (Optional) File handle of a file to read the image from * * If @test_fd is not negative, the function works in the test mode in * which the image is read from a regular file instead of the snapshot * device. */ static int write_image(int snapshot_fd, int resume_fd, int test_fd) { static struct swap_writer handle; struct image_header_info *header; loff_t start; loff_t image_size; double real_size; unsigned long nr_pages = 0; int error, test_mode = (test_fd >= 0); struct timeval begin; printf("%s: System snapshot ready. Preparing to write\n", my_name); /* Allocate a swap page for the additional "userland" header */ start = get_swap_page(snapshot_fd); if (!start) return -ENOSPC; header = getmem(page_size); memset(header, 0, page_size); error = init_swap_writer(&handle, snapshot_fd, resume_fd, test_fd); if (error) goto Exit; image_size = test_mode ? test_image_size : get_image_size(snapshot_fd); if (image_size > 0) { nr_pages = (unsigned long)((image_size + page_size - 1) / page_size); } else { /* * The kernel doesn't allow us to get the image size via ioctl, * so we need to read it from the image header. */ struct swsusp_info *image_header; ssize_t ret; /* * Do it in such a way that save_image() will believe it has * already read the header page. */ image_header = handle.page_ptr; ret = read(snapshot_fd, image_header, page_size); if (ret < page_size) { error = ret < 0 ? ret : -EFAULT; goto Free_writer; } handle.page_ptr += page_size; image_size = image_header->size; nr_pages = image_header->pages; if (!nr_pages) { error = -ENODATA; goto Free_writer; } /* We have already read one page */ nr_pages--; } printf("%s: Image size: %lu kilobytes\n", my_name, (unsigned long) image_size / 1024); real_size = image_size; handle.swap_needed = image_size; if (do_compress) { /* This is necessary in case the image is not compressible */ handle.swap_needed += round_up_page_size( (handle.swap_needed >> 4) + 67); } if (!enough_swap(&handle)) { fprintf(stderr, "%s: Not enough free swap\n", my_name); error = -ENOSPC; goto Free_writer; } if (!preallocate_swap(&handle)) { fprintf(stderr, "%s: Failed to allocate swap\n", my_name); error = -ENOSPC; goto Free_writer; } /* Shift handle.cur_offset for the first call to next_swap_page() */ handle.cur_offset -= page_size; header->pages = nr_pages; header->flags = 0; header->map_start = handle.extents_spc; if (compute_checksum) header->flags |= IMAGE_CHECKSUM; if (do_compress) header->flags |= IMAGE_COMPRESSED; #ifdef CONFIG_ENCRYPT if (!do_encrypt) goto Save_image; if (use_RSA) { error = gcry_cipher_setkey(cipher_handle, key_data.key, KEY_SIZE); if (error) goto No_RSA; error = gcry_cipher_setiv(cipher_handle, key_data.ivec, CIPHER_BLOCK); if (error) goto No_RSA; header->flags |= IMAGE_ENCRYPTED | IMAGE_USE_RSA; memcpy(&header->rsa, &key_data.rsa, sizeof(struct RSA_data)); memcpy(&header->key, &key_data.encrypted_key, sizeof(struct encrypted_key)); } else { int j; No_RSA: encrypt_init(key_data.key, key_data.ivec, password); splash.progress(20); get_random_salt(header->salt, CIPHER_BLOCK); for (j = 0; j < CIPHER_BLOCK; j++) key_data.ivec[j] ^= header->salt[j]; error = gcry_cipher_setkey(cipher_handle, key_data.key, KEY_SIZE); if (!error) error = gcry_cipher_setiv(cipher_handle, key_data.ivec, CIPHER_BLOCK); if (!error) header->flags |= IMAGE_ENCRYPTED; } if (error) { fprintf(stderr,"%s: libgcrypt error: %s\n", my_name, gcry_strerror(error)); goto Free_writer; } Save_image: #endif gettimeofday(&begin, NULL); error = save_image(&handle, nr_pages); if (!error) { struct timeval end; fsync(resume_fd); header->image_data_size = handle.written_data; real_size = handle.written_data; /* * NOTICE: This needs to go after save_image(), because the * user may modify the behavior. */ if (shutdown_method == SHUTDOWN_METHOD_PLATFORM) header->flags |= PLATFORM_SUSPEND; if (compute_checksum || verify_image) md5_finish_ctx(&handle.ctx, header->checksum); gettimeofday(&end, NULL); timersub(&end, &begin, &end); header->writeout_time = end.tv_usec / 1000000.0 + end.tv_sec; header->resume_pause = resume_pause; error = write_page(resume_fd, header, start); fsync(resume_fd); } Free_writer: free_swap_writer(&handle); if (!error && (verify_image || test_mode)) { splash.progress(0); if (verify_image) printf("%s: Image verification\n", my_name); error = read_or_verify(snapshot_fd, resume_fd, header, start, verify_image, test_mode); if (verify_image) printf(error ? "%s: Image verification failed\n" : "%s: Image verified successfully\n", my_name); splash.progress(100); } if (!error) { if (do_compress) { printf("%s: Compression ratio %4.2lf\n", my_name, real_size / image_size); } printf("S"); error = mark_swap(resume_fd, start); if (!error) { fsync(resume_fd); printf( "|" ); } printf("\n"); } Exit: freemem(header); return error; } static int reset_signature(int fd) { int ret, error = 0; unsigned int size = sizeof(struct swsusp_header); off64_t shift = ((off64_t)resume_offset + 1) * page_size - size; if (lseek64(fd, shift, SEEK_SET) != shift) return -EIO; memset(&swsusp_header, 0, size); ret = read(fd, &swsusp_header, size); if (ret == size) { if (memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) { /* Impossible? We wrote signature and it is not there?! */ error = -EINVAL; } } else { error = ret < 0 ? ret : -EIO; } if (!error) { /* Reset swap signature now */ memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10); if (lseek64(fd, shift, SEEK_SET) == shift) { ret = write(fd, &swsusp_header, size); if (ret != size) error = ret < 0 ? ret : -EIO; } else { error = -EIO; } } fsync(fd); if (error) { fprintf(stderr, "%s: Error %d resetting the image.\n" "There should be valid image on disk. " "Powerdown and carry out normal resume.\n" "Continuing with this booted system " "will lead to data corruption.\n", my_name, error); while(1) sleep(10); } return error; } static void suspend_shutdown(int snapshot_fd) { splash.set_caption("Done."); if (shutdown_method == SHUTDOWN_METHOD_REBOOT) { reboot(); } else if (shutdown_method == SHUTDOWN_METHOD_PLATFORM) { if (platform_enter(snapshot_fd)) suspend_error("Could not enter the hibernation state, " "calling power_off."); } power_off(); /* Signature is on disk, it is very dangerous to continue now. * We'd do resume with stale caches on next boot. */ fprintf(stderr,"Powerdown failed. That's impossible.\n"); while(1) sleep (60); } int suspend_system(int snapshot_fd, int resume_fd, int test_fd) { loff_t avail_swap; loff_t image_size; int attempts, in_suspend, error = 0; char message[SPLASH_GENERIC_MESSAGE_SIZE]; avail_swap = check_free_swap(snapshot_fd); if (avail_swap > pref_image_size) image_size = pref_image_size; else image_size = avail_swap; if (!avail_swap) { suspend_error("Not enough swap space for suspend"); return ENOSPC; } error = freeze(snapshot_fd); /* This a hack for a bug in bootsplash. Apparently it will * drop to 'verbose mode' after the freeze() call. */ splash.switch_to(); splash.progress(15); if (error) { suspend_error("Freeze failed."); goto Unfreeze; } if (test_fd >= 0) { printf("%s: Running in test mode\n", my_name); error = write_image(snapshot_fd, resume_fd, test_fd); if (error) error = -error; reset_signature(resume_fd); free_swap_pages(snapshot_fd); goto Unfreeze; } if (shutdown_method == SHUTDOWN_METHOD_PLATFORM) { if (platform_prepare(snapshot_fd)) { suspend_error("Unable to use platform hibernation " "support, using shutdown mode."); shutdown_method = SHUTDOWN_METHOD_SHUTDOWN; } } sprintf(message, "Snapshotting system"); printf("%s: %s\n", my_name, message); splash.set_caption(message); attempts = 2; do { if (set_image_size(snapshot_fd, image_size)) { error = errno; break; } if (atomic_snapshot(snapshot_fd, &in_suspend)) { error = errno; break; } if (!in_suspend) { /* first unblank the console, see console_codes(4) */ printf("\e[13]"); printf("%s: returned to userspace\n", my_name); free_snapshot(snapshot_fd); break; } error = write_image(snapshot_fd, resume_fd, -1); if (error) { free_swap_pages(snapshot_fd); free_snapshot(snapshot_fd); image_size = 0; error = -error; if (error != ENOSPC) break; } else { splash.progress(100); #ifdef CONFIG_BOTH if (s2ram_kms || s2ram) { /* If we die (and allow system to continue) * between now and reset_signature(), very bad * things will happen. */ error = suspend_to_ram(snapshot_fd); if (error) goto Shutdown; reset_signature(resume_fd); free_swap_pages(snapshot_fd); free_snapshot(snapshot_fd); if (!s2ram_kms) s2ram_resume(); goto Unfreeze; } Shutdown: #endif close(resume_fd); suspend_shutdown(snapshot_fd); } } while (--attempts); Unfreeze: /* * We get here during the resume or when we failed to suspend. * Remember, suspend_shutdown() never returns! */ unfreeze(snapshot_fd); return error; } /** * console_fd - get file descriptor for given file name and verify * if that's a console descriptor (based on the code of openvt) */ static inline int console_fd(const char *fname) { int fd; char arg; fd = open(fname, O_RDONLY); if (fd < 0 && errno == EACCES) fd = open(fname, O_WRONLY); if (fd >= 0 && (ioctl(fd, KDGKBTYPE, &arg) || (arg != KB_101 && arg != KB_84))) { close(fd); return -ENOTTY; } return fd; } #ifndef TIOCL_GETKMSGREDIRECT #define TIOCL_GETKMSGREDIRECT 17 #endif static int set_kmsg_redirect; /** * prepare_console - find a spare virtual terminal, open it and attach * the standard streams to it. The number of the currently active * virtual terminal is saved via @orig_vc */ static int prepare_console(int *orig_vc, int *new_vc) { int fd, error, vt = -1; char vt_name[GENERIC_NAME_SIZE]; struct vt_stat vtstat; char clear_vt, tiocl[2]; fd = console_fd("/dev/console"); if (fd < 0) return fd; tiocl[0] = TIOCL_GETKMSGREDIRECT; if (!ioctl(fd, TIOCLINUX, tiocl)) { if (tiocl[0] > 0) vt = tiocl[0]; } clear_vt = 0; error = ioctl(fd, VT_GETSTATE, &vtstat); if (!error) { *orig_vc = vtstat.v_active; if (vt < 0) { clear_vt = 1; error = ioctl(fd, VT_OPENQRY, &vt); } } close(fd); if (error || vt < 0) return -1; sprintf(vt_name, "/dev/tty%d", vt); fd = open(vt_name, O_RDWR); if (fd < 0) return fd; error = ioctl(fd, VT_ACTIVATE, vt); if (error) { suspend_error("Could not activate the VT %d.", vt); fflush(stderr); goto Close_fd; } error = ioctl(fd, VT_WAITACTIVE, vt); if (error) { suspend_error("VT %d activation failed.", vt); fflush(stderr); goto Close_fd; } if (clear_vt) { char *msg = "\33[H\33[J"; write(fd, msg, strlen(msg)); } dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); *new_vc = vt; set_kmsg_redirect = !tiocl[0]; if (set_kmsg_redirect) { tiocl[0] = TIOCL_SETKMSGREDIRECT; tiocl[1] = vt; if (ioctl(fd, TIOCLINUX, tiocl)) { suspend_error("Failed to redirect kernel messages " "to VT %d.", vt); fflush(stderr); set_kmsg_redirect = 0; } } return fd; Close_fd: close(fd); return error; } /** * restore_console - switch to the virtual console that was active before * suspend */ static void restore_console(int fd, int orig_vc) { int error; error = ioctl(fd, VT_ACTIVATE, orig_vc); if (error) { suspend_error("Could not activate the VT %d.", orig_vc); fflush(stderr); goto Close_fd; } error = ioctl(fd, VT_WAITACTIVE, orig_vc); if (error) { suspend_error("VT %d activation failed.", orig_vc); fflush(stderr); } if (set_kmsg_redirect) { char tiocl[2]; tiocl[0] = TIOCL_SETKMSGREDIRECT; tiocl[1] = 0; ioctl(fd, TIOCLINUX, tiocl); } Close_fd: close(fd); } static FILE *swappiness_file; static inline void open_swappiness(void) { swappiness_file = fopen("/proc/sys/vm/swappiness", "r+"); } static inline int get_swappiness(void) { int swappiness = -1; if (swappiness_file) { rewind(swappiness_file); fscanf(swappiness_file, "%d", &swappiness); } return swappiness; } static inline void set_swappiness(int swappiness) { if (swappiness_file) { rewind(swappiness_file); fprintf(swappiness_file, "%d\n", swappiness); fflush(swappiness_file); } } static inline void close_swappiness(void) { if (swappiness_file) fclose(swappiness_file); } #ifdef CONFIG_ENCRYPT static void generate_key(void) { gcry_ac_handle_t rsa_hd; gcry_ac_data_t rsa_data_set, key_set; gcry_ac_key_t rsa_pub; gcry_mpi_t mpi; size_t size; int ret, fd, rnd_fd; struct RSA_data *rsa; unsigned char *buf; int j; fd = open(key_name, O_RDONLY); if (fd < 0) return; rsa = &key_data.rsa; if (read(fd, rsa, sizeof(struct RSA_data)) <= 0) goto Close; ret = gcry_ac_open(&rsa_hd, GCRY_AC_RSA, 0); if (ret) goto Close; buf = rsa->data; ret = gcry_ac_data_new(&rsa_data_set); if (ret) goto Free_rsa; for (j = 0; j < RSA_FIELDS_PUB; j++) { size_t s = rsa->size[j]; gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG, buf, s, NULL); ret = gcry_ac_data_set(rsa_data_set, GCRY_AC_FLAG_COPY, rsa->field[j], mpi); gcry_mpi_release(mpi); if (ret) break; buf += s; } if (!ret) ret = gcry_ac_key_init(&rsa_pub, rsa_hd, GCRY_AC_KEY_PUBLIC, rsa_data_set); if (ret) goto Destroy_data_set; ret = gcry_ac_data_new(&key_set); if (ret) goto Destroy_key; rnd_fd = open("/dev/urandom", O_RDONLY); if (rnd_fd <= 0) goto Destroy_key_set; size = KEY_SIZE + CIPHER_BLOCK; for (;;) { unsigned char *res; size_t test; int cmp; if (read(rnd_fd, key_data.key, size) != size) goto Close_urandom; gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG, key_data.key, size, NULL); gcry_mpi_aprint(GCRYMPI_FMT_USG, &res, &test, mpi); cmp = memcmp(key_data.key, res, size); gcry_free(res); if (test == size && !cmp) break; gcry_mpi_release(mpi); } ret = gcry_ac_data_encrypt(rsa_hd, 0, rsa_pub, mpi, &key_set); gcry_mpi_release(mpi); if (!ret) { struct encrypted_key *key = &key_data.encrypted_key; char *str; size_t s; gcry_ac_data_get_index(key_set, GCRY_AC_FLAG_COPY, 0, (const char **)&str, &mpi); gcry_free(str); ret = gcry_mpi_print(GCRYMPI_FMT_USG, key->data, KEY_DATA_SIZE, &s, mpi); gcry_mpi_release(mpi); if (!ret) { key->size = s; use_RSA = 'y'; } } Close_urandom: close(rnd_fd); Destroy_key_set: gcry_ac_data_destroy(key_set); Destroy_key: gcry_ac_key_destroy(rsa_pub); Destroy_data_set: gcry_ac_data_destroy(rsa_data_set); Free_rsa: gcry_ac_close(rsa_hd); Close: close(fd); } #endif static void unlock_vt(void) { ioctl(vfd, VT_SETMODE, &orig_vtm); close(vfd); } static int lock_vt(void) { struct sigaction sa; struct vt_mode vtm; struct vt_stat vtstat; char vt_name[GENERIC_NAME_SIZE]; int fd, error; fd = console_fd("/dev/console"); if (fd < 0) return fd; error = ioctl(fd, VT_GETSTATE, &vtstat); close(fd); if (error < 0) return error; sprintf(vt_name, "/dev/tty%d", vtstat.v_active); vfd = open(vt_name, O_RDWR); if (vfd < 0) return vfd; error = ioctl(vfd, VT_GETMODE, &vtm); if (error < 0) return error; /* Setting vt mode to VT_PROCESS means this process * will handle vt switching requests. * We just ignore all request by installing SIG_IGN. */ sigemptyset(&(sa.sa_mask)); sa.sa_flags = SA_RESTART; sa.sa_handler = SIG_IGN; sigaction(SIGUSR1, &sa, NULL); orig_vtm = vtm; vtm.mode = VT_PROCESS; vtm.relsig = SIGUSR1; vtm.acqsig = SIGUSR1; error = ioctl(vfd, VT_SETMODE, &vtm); if (error < 0) return error; return 0; } /* Parse the command line and/or configuration file */ static inline int get_config(int argc, char *argv[]) { static struct option options[] = { { "help\0\t\t\tthis text", no_argument, NULL, 'h' }, { "version\0\t\t\tversion information", no_argument, NULL, 'V' }, { "config\0\t\talternative configuration file.", required_argument, NULL, 'f' }, { "resume_device\0device that contains swap area", required_argument, NULL, 'r' }, { "resume_offset\0offset of swap file in resume device.", required_argument, NULL, 'o' }, { "image_size\0\tdesired size of the image.", required_argument, NULL, 's' }, { "parameter\0\toverride config file parameter.", required_argument, NULL, 'P' }, #ifdef CONFIG_BOTH HACKS_LONG_OPTS #endif { NULL, 0, NULL, 0 } }; int i, error; char *conf_name = CONFIG_FILE; const char *optstring = "hVf:s:o:r:P:"; struct stat stat_buf; int fail_missing_config = 0; /* parse only config file argument */ while ((i = getopt_long(argc, argv, optstring, options, NULL)) != -1) { switch (i) { case 'h': usage(my_name, options, optstring); exit(EXIT_SUCCESS); case 'V': version(my_name, NULL); exit(EXIT_SUCCESS); case 'f': conf_name = optarg; fail_missing_config = 1; break; } } if (stat(conf_name, &stat_buf)) { if (fail_missing_config) { fprintf(stderr, "%s: Could not stat configuration file\n", my_name); return -ENOENT; } } else { error = parse(my_name, conf_name, parameters); if (error) { fprintf(stderr, "%s: Could not parse config file\n", my_name); return error; } } optind = 0; while ((i = getopt_long(argc, argv, optstring, options, NULL)) != -1) { switch (i) { case 'f': /* already handled */ break; case 's': pref_image_size = atoll(optarg); break; case 'o': resume_offset = atoll(optarg); break; case 'r': strncpy(resume_dev_name, optarg, MAX_STR_LEN -1); break; case 'P': error = parse_line(optarg, parameters); if (error) { fprintf(stderr, "%s: Could not parse config string '%s'\n", my_name, optarg); return error; } break; default: #ifdef CONFIG_BOTH s2ram_add_flag(i, optarg); break; #else usage(my_name, options, optstring); return -EINVAL; #endif } } if (optind < argc) strncpy(resume_dev_name, argv[optind], MAX_STR_LEN - 1); #ifdef CONFIG_BOTH s2ram_kms = !s2ram_check_kms(); if (s2ram_kms) return 0; s2ram = s2ram_is_supported(); /* s2ram_is_supported returns EINVAL if there was something wrong * with the options that where added with s2ram_add_flag. * On any other error (unsupported) we will just continue with s2disk. */ if (s2ram == EINVAL) return -EINVAL; s2ram = !s2ram; #endif return 0; } int main(int argc, char *argv[]) { unsigned int mem_size; struct stat stat_buf; int resume_fd, snapshot_fd, vt_fd, orig_vc = -1, suspend_vc = -1; int test_fd = -1; dev_t resume_dev; int orig_loglevel, orig_swappiness, ret; struct rlimit rlim; static char chroot_path[MAX_STR_LEN]; my_name = basename(argv[0]); /* Make sure the 0, 1, 2 descriptors are open before opening the * snapshot and resume devices */ do { ret = open("/dev/null", O_RDWR); if (ret < 0) { perror(argv[0]); return ret; } } while (ret < 3); close(ret); ret = get_config(argc, argv); if (ret) return -ret; if (compute_checksum != 'y' && compute_checksum != 'Y') compute_checksum = 0; #ifdef CONFIG_COMPRESS if (do_compress != 'y' && do_compress != 'Y') { do_compress = 0; } else if (lzo_init() != LZO_E_OK) { suspend_error("Failed to initialize LZO. " "Compression disabled.\n"); do_compress = 0; } #endif #ifdef CONFIG_ENCRYPT if (do_encrypt != 'y' && do_encrypt != 'Y') do_encrypt = 0; #endif if (splash_param != 'y' && splash_param != 'Y') splash_param = 0; else splash_param = SPL_SUSPEND; if (early_writeout != 'n' && early_writeout != 'N') early_writeout = 1; if (!strcmp (shutdown_method_value, "shutdown")) { shutdown_method = SHUTDOWN_METHOD_SHUTDOWN; } else if (!strcmp (shutdown_method_value, "platform")) { shutdown_method = SHUTDOWN_METHOD_PLATFORM; } else if (!strcmp (shutdown_method_value, "reboot")) { shutdown_method = SHUTDOWN_METHOD_REBOOT; } if (resume_pause > RESUME_PAUSE_MAX) resume_pause = RESUME_PAUSE_MAX; if (verify_image != 'y' && verify_image != 'Y') verify_image = 0; #ifdef CONFIG_THREADS if (use_threads != 'y' && use_threads != 'Y') use_threads = 0; #endif get_page_and_buffer_sizes(); mem_size = 2 * page_size + buffer_size; #ifdef CONFIG_COMPRESS if (do_compress) { /* * The formula below follows from the worst-case expansion * calculation for LZO1 (size / 16 + 67) and the fact that the * size of the compressed data must be stored in the buffer * (sizeof(size_t)). */ compress_buf_size = buffer_size + round_up_page_size((buffer_size >> 4) + 67 + sizeof(size_t)); mem_size += compress_buf_size + round_up_page_size(LZO1X_1_MEM_COMPRESS); } #endif #ifdef CONFIG_ENCRYPT if (do_encrypt) { printf("%s: libgcrypt version: %s\n", my_name, gcry_check_version(NULL)); gcry_control(GCRYCTL_INIT_SECMEM, page_size, 0); ret = gcry_cipher_open(&cipher_handle, IMAGE_CIPHER, GCRY_CIPHER_MODE_CFB, GCRY_CIPHER_SECURE); if (ret) { suspend_error("libgcrypt error %s", gcry_strerror(ret)); do_encrypt = 0; } else { encrypt_buf_size = ENCRYPT_BUF_PAGES * page_size; mem_size += encrypt_buf_size; } } #endif if (use_threads) { mem_size += (compress_buf_size > 0) ? (WRITE_BUFFERS - 1) * compress_buf_size : WRITE_BUFFERS * buffer_size; if (!do_encrypt) mem_size += WRITE_BUFFERS * buffer_size; } ret = init_memalloc(page_size, mem_size); if (ret) { suspend_error("Could not allocate memory."); return ret; } #ifdef CONFIG_ENCRYPT if (do_encrypt) generate_key(); #endif setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); if (mlockall(MCL_CURRENT | MCL_FUTURE)) { ret = errno; suspend_error("Could not lock myself."); return ret; } if (strlen(test_file_name) > 0) { if (stat(test_file_name, &stat_buf)) { ret = errno; suspend_error("Unable to stat test image file %s", test_file_name); return ret; } test_image_size = round_down_page_size(stat_buf.st_size); if (test_image_size < MIN_TEST_IMAGE_PAGES * page_size) { suspend_error("Test image file %s is too small", test_file_name); return ENODATA; } test_fd = open(test_file_name, O_RDONLY); if (test_fd < 0) { ret = errno; suspend_error("Unable to open test image file %s", test_file_name); return ret; } } snprintf(chroot_path, MAX_STR_LEN, "/proc/%d", getpid()); if (mount("none", chroot_path, "tmpfs", 0, NULL)) { ret = errno; suspend_error("Could not mount tmpfs on %s.", chroot_path); return ret; } ret = 0; if (stat(resume_dev_name, &stat_buf)) { suspend_error("Could not stat the resume device file."); ret = ENODEV; goto Umount; } if (!S_ISBLK(stat_buf.st_mode)) { suspend_error("Invalid resume device."); ret = EINVAL; goto Umount; } if (chdir(chroot_path)) { ret = errno; suspend_error("Could not change directory to %s.", chroot_path); goto Umount; } resume_dev = stat_buf.st_rdev; if (mknod("resume", S_IFBLK | 0600, resume_dev)) { ret = errno; suspend_error("Could not create %s/%s.", chroot_path, "resume"); goto Umount; } resume_fd = open("resume", O_RDWR); if (resume_fd < 0) { ret = errno; suspend_error("Could not open the resume device."); goto Umount; } if (stat(snapshot_dev_name, &stat_buf)) { suspend_error("Could not stat the snapshot device file."); ret = ENODEV; goto Close_resume_fd; } if (!S_ISCHR(stat_buf.st_mode)) { suspend_error("Invalid snapshot device."); ret = EINVAL; goto Close_resume_fd; } snapshot_fd = open(snapshot_dev_name, O_RDONLY); if (snapshot_fd < 0) { ret = errno; suspend_error("Could not open the snapshot device."); goto Close_resume_fd; } if (set_swap_file(snapshot_fd, resume_dev, resume_offset)) { ret = errno; suspend_error("Could not use the resume device " "(try swapon -a)."); goto Close_snapshot_fd; } vt_fd = prepare_console(&orig_vc, &suspend_vc); if (vt_fd < 0) { if (vt_fd == -ENOTTY) { suspend_warning("Unable to switch virtual terminals, " "using the current console."); splash_param = 0; } else { suspend_error("Could not open a virtual terminal."); ret = errno; goto Close_snapshot_fd; } } splash_prepare(&splash, splash_param); if (vt_fd >= 0) { if (lock_vt() < 0) { ret = errno; suspend_error("Could not lock the terminal."); goto Restore_console; } } splash.progress(5); #ifdef CONFIG_BOTH /* If s2ram_hacks returns != 0, better not try to suspend to RAM */ if (s2ram) s2ram = !s2ram_hacks(); #endif #ifdef CONFIG_ENCRYPT if (do_encrypt && ! use_RSA) splash.read_password(password, 1); #endif open_printk(); orig_loglevel = get_kernel_console_loglevel(); set_kernel_console_loglevel(suspend_loglevel); open_swappiness(); orig_swappiness = get_swappiness(); set_swappiness(suspend_swappiness); sync(); splash.progress(10); rlim.rlim_cur = 0; rlim.rlim_max = 0; setrlimit(RLIMIT_NOFILE, &rlim); setrlimit(RLIMIT_NPROC, &rlim); setrlimit(RLIMIT_CORE, &rlim); ret = suspend_system(snapshot_fd, resume_fd, test_fd); if (orig_loglevel >= 0) set_kernel_console_loglevel(orig_loglevel); close_printk(); if(orig_swappiness >= 0) set_swappiness(orig_swappiness); close_swappiness(); if (vt_fd >= 0) unlock_vt(); Restore_console: splash.finish(); if (vt_fd >= 0) restore_console(vt_fd, orig_vc); Close_snapshot_fd: close(snapshot_fd); Close_resume_fd: close(resume_fd); Umount: if (chdir("/")) { ret = errno; suspend_error("Could not change directory to /"); } else { umount(chroot_path); } if (test_fd >= 0) close(test_fd); #ifdef CONFIG_ENCRYPT if (do_encrypt) gcry_cipher_close(cipher_handle); #endif free_memalloc(); return ret; } suspend-utils/swap-offset.c0000644000175500017550000000467012075743442014500 0ustar kixkix/* * swap-offset.c * * This program determines the location of the swap offset for given swap file. * * Copyright (C) 2006 Luca Tettamanti * * This file is released under the GPLv2. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #define SWAP_SIG "SWAPSPACE2" #define SWAP_SIG_SIZE 10 int main(int argc, char **argv) { unsigned int block, last_block, first_block, blocks_per_page; unsigned int offset; int size, blk_size; int fd; unsigned int i; ssize_t ret; struct stat stat; unsigned char buf[SWAP_SIG_SIZE]; int err = 0; int const page_size = getpagesize(); if (argc < 2) { fprintf(stderr, "Usage: swap-offset \n"); return EINVAL; } fd = open(argv[1], O_RDONLY); if (fd < 0) { err = errno; perror("open()"); return err; } if (fstat(fd, &stat)) { err = errno; perror("fstat()"); goto out; } if (!S_ISREG(stat.st_mode)) { fprintf(stderr, "Not a regular file\n"); err = EINVAL; goto out; } /* Check swap signature */ if (lseek(fd, page_size - SWAP_SIG_SIZE, SEEK_SET) < 0) { err = errno; perror("lseek()"); goto out; } ret = read(fd, buf, SWAP_SIG_SIZE); if (ret < 0) { err = errno; perror("read()"); goto out; } else if (ret < SWAP_SIG_SIZE) { fprintf(stderr, "Failed to read swap signature: file is too short.\n"); err = EINVAL; goto out; } if (memcmp(buf, SWAP_SIG, SWAP_SIG_SIZE)) { fprintf(stderr, "Swap signature not found.\n"); err = EINVAL; goto out; } if (ioctl(fd, FIGETBSZ, &blk_size)) { err = errno; perror("ioctl(FIGETBSZ) failed"); goto out; } blocks_per_page = page_size / blk_size; /* Check that the header is contiguous */ last_block = 0; first_block = 0; size = 0; for (i = 0; i < blocks_per_page; i++) { block = i; if (ioctl(fd, FIBMAP, &block)) { err = errno; perror("ioctl(FIBMAP) failed"); goto out; } if (last_block && block != last_block + 1) break; if (!first_block) first_block = block; size += blk_size; last_block = block; } if (size < page_size) { fprintf(stderr, "Swapfile header is not contiguous and cannot " "be used for suspension.\n"); err = EINVAL; } else { offset = (unsigned long long)first_block * blk_size / page_size; printf("resume offset = %u\n", offset); } out: close(fd); return err; } suspend-utils/config_parser.c0000644000175500017550000000576112075743442015065 0ustar kixkix/* * config_parser.c * * Configuration file parser for userland suspend tools * * Copyright (C) 2006 Rafael J. Wysocki * * This file is released under the GPLv2. * */ #include "config.h" #include #include #include #include #include #include #include #include #include "config_parser.h" #include "encrypt.h" int parse_line(char *str, struct config_par *parv) { char *fmt, *end; int error = 0; int i, k; /* Skip white space */ while (isspace(*str)) str++; /* Skip the lines containing white space only */ if (!*str) goto cleanup; /* Ignore comments */ if (*str == '#') goto cleanup; /* Compare with parameter names */ for (i=0; parv[i].name; i++) { k = strlen(parv[i].name); if (!strncmp(parv[i].name, str, k)) { if (!parv[i].ptr) break; str += k; while (isblank(*str)) str++; if (*str != ':' && *str != '=') { error = -EINVAL; break; } str++; while (isblank(*str)) str++; end = str + strlen(str); while (end > str && isspace(*--end)) *end = '\0'; if (*str) { fmt = parv[i].fmt; if (!strncmp(fmt, "%s", 2)) strncpy(parv[i].ptr, str, parv[i].len - 1); else { if (sscanf(str, fmt, parv[i].ptr) <= 0) error = -EINVAL; } break; } } } cleanup: return error; } /** * parse - read and parse the configuration file */ int parse(char *my_name, char *file_name, struct config_par *parv) { char buf[MAX_STR_LEN]; char *str; FILE *file; int error, i; file = fopen(file_name, "r"); if (!file) { fprintf(stderr, "%s: Could not open configuration file\n", my_name); return -errno; } error = 0; i = 0; do { str = fgets(buf, MAX_STR_LEN, file); if (!str) break; i++; error = parse_line(str, parv); } while (!error); fclose(file); if (error) fprintf(stderr, "%s: Error in configuration file, line %d\n", my_name, i); return error; } /* We're abusing struct option a bit. usage() expects an \0 in the * name string, and after that a comment. */ void usage(char *my_name, struct option *options, const char *short_options) { struct option *opt; printf("Usage: %s [options]", my_name); for (opt = options; opt->name; opt++) { const char *descr = opt->name + strlen(opt->name) + 1; if (strchr(short_options,opt->val)) printf("\n -%c, --%s", opt->val, opt->name); else printf("\n --%s", opt->name); if (opt->has_arg) printf(" <%s>", opt->name); if (strlen(descr)) printf("\t%s",descr); } printf("\n"); } void version(char *my_name, char *extra_version) { printf( ( "%s (%s) %s %s\n" "\n" "FEATURES: %s\n" "\n" "This is free software. You may redistribute copies of it under the terms of\n" "the GNU General Public License .\n" "There is NO WARRANTY, to the extent permitted by law.\n" ), my_name, PACKAGE_NAME, PACKAGE_VERSION, extra_version ? extra_version : "", CONFIG_FEATURES ); } suspend-utils/load.c0000644000175500017550000004100512075743442013152 0ustar kixkix/* * load.c * * Image loading for s2disk/s2both and resume. * * Copyright (C) 2008 Rafael J. Wysocki * * This file is released under the GPLv2. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_COMPRESS #include #endif #include "swsusp.h" #include "memalloc.h" #include "md5.h" #include "splash.h" char *my_name; static char verify_checksum; #ifdef CONFIG_COMPRESS unsigned int compress_buf_size; static char do_decompress; #else #define do_decompress 0 #endif #ifdef CONFIG_ENCRYPT static char do_decrypt; static char password[PASSBUF_SIZE]; #else #define do_decrypt 0 #endif /** * read_page - Read data from a swap location * @fd: File handle of the resume partition. * @buf: Pointer to the area we're reading into. * @offset: Swap offset of the place to read from. */ static int read_page(int fd, void *buf, loff_t offset) { int res = 0; ssize_t cnt = 0; if (!offset) return 0; if (lseek(fd, offset, SEEK_SET) == offset) cnt = read(fd, buf, page_size); if (cnt < (ssize_t)page_size) res = -EIO; return res; } /* * The swap_reader structure is used for handling swap in a file-alike way. * * @extents: Array of extents used for trackig swap allocations. It is * page_size bytes large and holds at most * (page_size / sizeof(struct extent) - 1) extents. The last slot * must be all zeros and is the end marker. * * @cur_extent: The extent currently used as the source of swap pages. * * @cur_offset: The offset of the swap page that will be used next. * * @total_size: The amount of data to read. * * @buffer: Buffer used for storing image data pages. * * @read_buffer: If compression is used, the compressed contents of * @buffer are stored here. Otherwise, it is equal to * @buffer. * * @fd: File handle associated with the swap. * * @ctx: Used for checksum computing, if so configured. * * @lzo_work_buffer: Work buffer used for decompression. * * @decrypt_buffer: Buffer for storing encrypted pages (page_size bytes). */ struct swap_reader { struct extent *extents; struct extent *cur_extent; loff_t cur_offset; loff_t next_extents; loff_t total_size; void *buffer; void *read_buffer; int fd; struct md5_ctx ctx; void *lzo_work_buffer; char *decrypt_buffer; }; /** * load_extents_page - load the array of extents * handle: Structure holding the pointer to the array of extents etc. * * Read the table of extents from the swap location pointed to by * @handle->next_extents and store it at the address in @handle->extents. * Read the swap location of the next array of extents from the last * element of the array and fill this element with zeros. Initialize * @handle->cur_extent and @handle->cur_offset as appropriate. */ static int load_extents_page(struct swap_reader *handle) { int error, n; error = read_page(handle->fd, handle->extents, handle->next_extents); if (error) return error; n = page_size / sizeof(struct extent) - 1; handle->next_extents = handle->extents[n].start; memset(handle->extents + n, 0, sizeof(struct extent)); handle->cur_extent = handle->extents; handle->cur_offset = handle->cur_extent->start; if (posix_fadvise(handle->fd, handle->cur_offset, handle->cur_extent->end - handle->cur_offset, POSIX_FADV_NOREUSE)) perror("posix_fadvise"); return 0; } /** * free_swap_reader - free memory allocated for loading the image * @handle: Structure containing pointers to memory buffers to free. */ static void free_swap_reader(struct swap_reader *handle) { if (do_decompress) { freemem(handle->lzo_work_buffer); freemem(handle->read_buffer); } if (do_decrypt) freemem(handle->decrypt_buffer); freemem(handle->buffer); freemem(handle->extents); } /** * init_swap_reader - initialize the structure used for loading the image * @handle: Structure to initialize. * @fd: File descriptor associated with the swap. * @start: Swap location (offset) of the first image page. * @image_size: Total size of the image data. * * Initialize buffers and related fields of @handle and load the first * array of extents. */ static int init_swap_reader(struct swap_reader *handle, int fd, loff_t start, loff_t image_size) { int error; if (!start) return -EINVAL; handle->fd = fd; handle->total_size = image_size; handle->extents = getmem(page_size); handle->buffer = getmem(buffer_size); handle->read_buffer = handle->buffer; if (do_decrypt) handle->decrypt_buffer = getmem(page_size); if (do_decompress) { handle->read_buffer = getmem(compress_buf_size); handle->lzo_work_buffer = getmem(LZO1X_1_MEM_COMPRESS); } /* Read the table of extents */ handle->next_extents = start; error = load_extents_page(handle); if (error) { free_swap_reader(handle); return error; } if (verify_checksum) md5_init_ctx(&handle->ctx); return 0; } /** * find_next_image_page - find the next swap location holding image data */ static void find_next_image_page(struct swap_reader *handle) { int error; handle->cur_offset += page_size; if (handle->cur_offset < handle->cur_extent->end) return; /* We have exhausted the current extent. Forward to the next one */ handle->cur_extent++; if (handle->cur_extent->start < handle->cur_extent->end) { handle->cur_offset = handle->cur_extent->start; if (posix_fadvise(handle->fd, handle->cur_offset, handle->cur_extent->end - handle->cur_offset, POSIX_FADV_NOREUSE)) perror("posix_fadvise"); return; } /* No more extents. Load the next extents page. */ error = load_extents_page(handle); if (error) handle->cur_offset = 0; } /** * load_and_decrypt_page - load a page of data from swap and decrypt it, * if necessary. */ static int load_and_decrypt_page(struct swap_reader *handle, void *dst) { int error; void *buf = dst; if (!handle->cur_offset) return -EINVAL; if (do_decrypt) buf = handle->decrypt_buffer; error = read_page(handle->fd, buf, handle->cur_offset); #ifdef CONFIG_ENCRYPT if (!error && do_decrypt) error = gcry_cipher_decrypt(cipher_handle, dst, page_size, buf, page_size); #endif if (!error) { handle->total_size -= page_size; find_next_image_page(handle); } return error; } /** * load_buffer - load (and decrypt, if necessary) a block od data from the * swap, decompress it if necessary and store it in the * image data buffer. */ static ssize_t load_buffer(struct swap_reader *handle) { void *dst; ssize_t size; int error; #ifdef CONFIG_COMPRESS if (do_decompress) { struct buf_block *block = handle->read_buffer; lzo_uint cnt; /* Read the block size from the first block page. */ error = load_and_decrypt_page(handle, block); if (error) return 0; size = page_size; dst = block; dst += page_size; /* Load the rest of the block pages */ while (size < block->size + sizeof(size_t)) { error = load_and_decrypt_page(handle, dst); if (error) return 0; size += page_size; dst += page_size; } /* Decompress block */ error = lzo1x_decompress((lzo_bytep)block->data, block->size, handle->buffer, &cnt, handle->lzo_work_buffer); if (error) return 0; size = cnt; goto Checksum; } #endif dst = handle->buffer; size = 0; while (size < buffer_size && handle->total_size > 0) { error = load_and_decrypt_page(handle, dst); if (error) return 0; size += page_size; dst += page_size; } #ifdef CONFIG_COMPRESS Checksum: #endif if (verify_checksum) md5_process_block(handle->buffer, size, &handle->ctx); return size; } /** * load_image - load a hibernation image * @handle: Structure containing image information. * @dev: Special device file to write image data pages to. * @nr_pages: Number of image data pages. */ static int load_image(struct swap_reader *handle, int dev, unsigned int nr_pages, int verify_only) { unsigned int m, n; ssize_t buf_size; ssize_t ret; void *buf = 0; int error = 0; char message[SPLASH_GENERIC_MESSAGE_SIZE]; sprintf(message, "Loading image data pages (%u pages)...", nr_pages); splash.set_caption(message); printf("%s ", message); m = nr_pages / 100; if (!m) m = 1; n = 0; buf_size = 0; do { if (buf_size <= 0) { buf_size = load_buffer(handle); if (buf_size <= 0) { printf("\n"); return -EIO; } buf = handle->buffer; } ret = verify_only ? page_size : write(dev, buf, page_size); if (ret < page_size) { if (ret < 0) perror("\nError while writing an image page"); else printf("\n"); return -EIO; } buf += page_size; buf_size -= page_size; if (!(n % m)) { printf("\b\b\b\b%3d%%", n / m); if (n / m > 15) splash.progress(n / m); } n++; } while (n < nr_pages); if (!error) printf(" done\n"); return error; } static char *print_checksum(char * buf, unsigned char *checksum) { int j; for (j = 0; j < 16; j++) buf += sprintf(buf, "%02hhx ", checksum[j]); return buf; } #ifdef CONFIG_ENCRYPT static int decrypt_key(struct image_header_info *header, unsigned char *key, unsigned char *ivec) { gcry_ac_handle_t rsa_hd; gcry_ac_data_t rsa_data_set, key_set; gcry_ac_key_t rsa_priv; gcry_mpi_t mpi; unsigned char *buf, *out, *key_buf, *ivec_buf; struct md5_ctx ctx; struct RSA_data *rsa; gcry_cipher_hd_t sym_hd; int j, ret; rsa = &header->rsa; ret = gcry_ac_open(&rsa_hd, GCRY_AC_RSA, 0); if (ret) return ret; ret = gcry_cipher_open(&sym_hd, PK_CIPHER, GCRY_CIPHER_MODE_CFB, GCRY_CIPHER_SECURE); if (ret) goto Free_rsa; key_buf = getmem(PK_KEY_SIZE); ivec_buf = getmem(PK_CIPHER_BLOCK); out = getmem(KEY_TEST_SIZE); do { splash.read_password(password, 0); memset(ivec_buf, 0, PK_CIPHER_BLOCK); strncpy(ivec_buf, password, PK_CIPHER_BLOCK); md5_init_ctx(&ctx); md5_process_bytes(password, strlen(password), &ctx); md5_finish_ctx(&ctx, key_buf); ret = gcry_cipher_setkey(sym_hd, key_buf, PK_KEY_SIZE); if (!ret) ret = gcry_cipher_setiv(sym_hd, ivec_buf, PK_CIPHER_BLOCK); if (!ret) ret = gcry_cipher_encrypt(sym_hd, out, KEY_TEST_SIZE, KEY_TEST_DATA, KEY_TEST_SIZE); if (ret) { fprintf(stderr, "%s: libgcrypt error: %s\n", my_name, gcry_strerror(ret)); break; } ret = memcmp(out, rsa->key_test, KEY_TEST_SIZE); if (ret) printf("%s: Wrong passphrase, try again.\n", my_name); } while (ret); gcry_cipher_close(sym_hd); if (!ret) ret = gcry_cipher_open(&sym_hd, PK_CIPHER, GCRY_CIPHER_MODE_CFB, GCRY_CIPHER_SECURE); if (ret) goto Free_buffers; ret = gcry_cipher_setkey(sym_hd, key_buf, PK_KEY_SIZE); if (!ret) ret = gcry_cipher_setiv(sym_hd, ivec_buf, PK_CIPHER_BLOCK); if (!ret) ret = gcry_ac_data_new(&rsa_data_set); if (ret) goto Close_cypher; buf = rsa->data; for (j = 0; j < RSA_FIELDS; j++) { size_t s = rsa->size[j]; /* We need to decrypt some components */ if (j >= RSA_FIELDS_PUB) { /* We use the in-place decryption */ ret = gcry_cipher_decrypt(sym_hd, buf, s, NULL, 0); if (ret) break; } gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG, buf, s, NULL); ret = gcry_ac_data_set(rsa_data_set, GCRY_AC_FLAG_COPY, rsa->field[j], mpi); gcry_mpi_release(mpi); if (ret) break; buf += s; } if (!ret) ret = gcry_ac_key_init(&rsa_priv, rsa_hd, GCRY_AC_KEY_SECRET, rsa_data_set); if (ret) goto Destroy_data_set; ret = gcry_ac_data_new(&key_set); if (ret) goto Destroy_key; gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG, header->key.data, header->key.size, NULL); ret = gcry_ac_data_set(key_set, GCRY_AC_FLAG_COPY, "a", mpi); if (ret) goto Destroy_key_set; gcry_mpi_release(mpi); ret = gcry_ac_data_decrypt(rsa_hd, 0, rsa_priv, &mpi, key_set); if (!ret) { unsigned char *res; size_t s; gcry_mpi_aprint(GCRYMPI_FMT_USG, &res, &s, mpi); if (s == KEY_SIZE + CIPHER_BLOCK) { memcpy(key, res, KEY_SIZE); memcpy(ivec, res + KEY_SIZE, CIPHER_BLOCK); } else { ret = -ENODATA; } gcry_free(res); } Destroy_key_set: gcry_mpi_release(mpi); gcry_ac_data_destroy(key_set); Destroy_key: gcry_ac_key_destroy(rsa_priv); Destroy_data_set: gcry_ac_data_destroy(rsa_data_set); Close_cypher: gcry_cipher_close(sym_hd); Free_buffers: freemem(out); freemem(ivec_buf); freemem(key_buf); Free_rsa: gcry_ac_close(rsa_hd); return ret; } static int restore_key(struct image_header_info *header) { static unsigned char key[KEY_SIZE], ivec[CIPHER_BLOCK]; int error; if (header->flags & IMAGE_USE_RSA) { error = decrypt_key(header, key, ivec); } else { int j; splash.read_password(password, 0); encrypt_init(key, ivec, password); for (j = 0; j < CIPHER_BLOCK; j++) ivec[j] ^= header->salt[j]; } if (!error) error = gcry_cipher_open(&cipher_handle, IMAGE_CIPHER, GCRY_CIPHER_MODE_CFB, GCRY_CIPHER_SECURE); if (!error) { error = gcry_cipher_setkey(cipher_handle, key, KEY_SIZE); if (!error) error = gcry_cipher_setiv(cipher_handle, ivec, CIPHER_BLOCK); if (error) gcry_cipher_close(cipher_handle); } return error; } #endif int read_or_verify(int dev, int fd, struct image_header_info *header, loff_t start, int verify, int test) { static struct swap_reader handle; static unsigned char orig_checksum[16], checksum[16]; static char csum_buf[48]; int error = 0, test_mode = (verify || test); error = read_page(fd, header, start); if (error) return error; if ((header->flags & IMAGE_CHECKSUM) || verify) { memcpy(orig_checksum, header->checksum, 16); print_checksum(csum_buf, orig_checksum); printf("%s: MD5 checksum %s\n", my_name, csum_buf); verify_checksum = 1; } splash.progress(10); if (header->flags & IMAGE_COMPRESSED) { printf("%s: Compressed image\n", my_name); #ifdef CONFIG_COMPRESS if (lzo_init() == LZO_E_OK) { do_decompress = 1; } else { fprintf(stderr, "%s: Failed to initialize LZO\n", my_name); error = -EFAULT; } #else fprintf(stderr, "%s: Compression not supported\n", my_name); error = -EINVAL; #endif } if (error) return error; if (header->flags & IMAGE_ENCRYPTED) { #ifdef CONFIG_ENCRYPT printf("%s: Encrypted image\n", my_name); error = test_mode ? gcry_cipher_setiv(cipher_handle, key_data.ivec, CIPHER_BLOCK) : restore_key(header); if (error) { fprintf(stderr, "%s: libgcrypt error: %s\n", my_name, gcry_strerror(error)); } else { do_decrypt = 1; splash.progress(15); } #else fprintf(stderr, "%s: Encryption not supported\n", my_name); error = -EINVAL; #endif } if (error) goto Exit_encrypt; error = init_swap_reader(&handle, fd, header->map_start, header->image_data_size); if (!error) { struct timeval begin, end; double delta, mb; gettimeofday(&begin, NULL); error = load_image(&handle, dev, header->pages, test_mode); if (!error && verify_checksum) { md5_finish_ctx(&handle.ctx, checksum); if (memcmp(orig_checksum, checksum, 16)) { fprintf(stderr, "%s: MD5 checksum does not match\n", my_name); print_checksum(csum_buf, checksum); fprintf(stderr, "%s: Computed MD5 checksum %s\n", my_name, csum_buf); error = -EINVAL; } } free_swap_reader(&handle); if (error) goto Exit_encrypt; gettimeofday(&end, NULL); timersub(&end, &begin, &end); delta = end.tv_usec / 1000000.0 + end.tv_sec; mb = (header->pages * (page_size / 1024.0)) / 1024.0; printf("wrote %0.1lf MB in %0.1lf seconds (%0.1lf MB/s)\n", mb, header->writeout_time, mb / header->writeout_time); printf("read %0.1lf MB in %0.1lf seconds (%0.1lf MB/s)\n", mb, delta, mb / delta); mb *= 2.0; delta += header->writeout_time; printf("total image i/o: %0.1lf MB in %0.1lf seconds " "(%0.1lf MB/s)\n", mb, delta, mb / delta); if (do_decompress) { double real_size = header->image_data_size; printf("%s: Compression ratio %4.2lf\n", my_name, real_size / (header->pages * page_size)); real_size /= (1024.0 * 1024.0); delta -= header->writeout_time; printf("wrote %0.1lf MB of compressed data in %0.1lf " "seconds (%0.1lf MB/s)\n", real_size, header->writeout_time, real_size / header->writeout_time); printf("read %0.1lf MB of compressed data in %0.1lf " "seconds (%0.1lf MB/s)\n", real_size, delta, real_size / delta); real_size *= 2.0; delta += header->writeout_time; printf("total compressed data i/o: %0.1lf MB in %0.1lf " "seconds (%0.1lf MB/s)\n", real_size, delta, real_size / delta); } } Exit_encrypt: #ifdef CONFIG_ENCRYPT if (do_decrypt && !test_mode) gcry_cipher_close(cipher_handle); #endif return error; } suspend-utils/dmidecode.c0000644000175500017550000001024112075743442014146 0ustar kixkix/* * DMI decoder for s2ram * * (C) 2000,2001 Alan Cox * * 2-July-2001 Matt Domsch * Additional structures displayed per SMBIOS 2.3.1 spec * * (C) 2006 Pavel Machek * * Licensed under the GNU General Public license v2. */ #include "config.h" #include #include #include #include #include #include #include typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; struct dmi_header { u8 type; u8 length; u16 handle; }; #ifdef S2RAM #define PRINTF(a...) #else #define PRINTF printf #endif static char *dmi_string(struct dmi_header *dm, u8 s) { char *bp=(char *)dm; if (!s) return ""; bp+=dm->length; while (s>1) { bp+=strlen(bp); bp++; s--; } return bp; } /* * Copy a physical memory chunk into a memory buffer. * This function allocates memory. */ void *mem_chunk(size_t base, size_t len) { void *p; int fd; size_t mmoffset; void *mmp; if((fd=open("/dev/mem", O_RDONLY))==-1){ perror("/dev/mem"); return NULL; } if((p=malloc(len))==NULL) { perror("/dev/mem malloc"); return NULL; } mmoffset=base%getpagesize(); /* * Please note that we don't use mmap() for performance reasons here, * but to workaround problems many people encountered when trying * to read from /dev/mem using regular read() calls. */ mmp=mmap(0, mmoffset+len, PROT_READ, MAP_SHARED, fd, base-mmoffset); if(mmp==MAP_FAILED) { perror("mmap"); free(p); return NULL; } memcpy(p, (u8 *)mmp+mmoffset, len); if(munmap(mmp, mmoffset+len)==-1) perror("/dev/mem munmap"); if(close(fd)==-1) perror("/dev/mem"); return p; } static void dmi_table(u32 base, int len, int num) { char *buf; struct dmi_header *dm; char *data; int i=0; if ((buf=mem_chunk(base, len))==0) { printf("DMI Table is unreachable\n"); return; } data = buf; while (itype) { case 0: PRINTF("\tBIOS Information Block\n"); PRINTF("\t\tVendor: %s\n", dmi_string(dm, data[4])); strcpy(bios_version, dmi_string(dm, data[5])); PRINTF("\t\tVersion: %s\n", bios_version); PRINTF("\t\tRelease: %s\n", dmi_string(dm, data[8])); PRINTF("\t\tBIOS base: 0x%04X0\n", data[7]<<8|data[6]); PRINTF("\t\tROM size: %dK\n", 64*data[9]); PRINTF("\t\tCapabilities:\n"); u=data[13]<<24|data[12]<<16|data[11]<<8|data[10]; u2=data[17]<<24|data[16]<<16|data[15]<<8|data[14]; PRINTF("\t\t\tFlags: 0x%08X%08X\n", u2,u); break; case 1: PRINTF("\tSystem Information Block\n"); strcpy(sys_vendor, dmi_string(dm, data[4])); strcpy(sys_product, dmi_string(dm, data[5])); strcpy(sys_version, dmi_string(dm, data[6])); PRINTF("\t\tVendor: %s\n", sys_vendor); PRINTF("\t\tProduct: %s\n", sys_product); PRINTF("\t\tVersion: %s\n", sys_version); PRINTF("\t\tSerial Number: %s\n", dmi_string(dm, data[7])); break; case 2: PRINTF("\tBoard Information Block\n"); PRINTF("\t\tVendor: %s\n", dmi_string(dm, data[4])); PRINTF("\t\tProduct: %s\n", dmi_string(dm, data[5])); PRINTF("\t\tVersion: %s\n", dmi_string(dm, data[6])); PRINTF("\t\tSerial Number: %s\n", dmi_string(dm, data[7])); break; default: break; } data+=dm->length; while(*data || data[1]) data++; data+=2; i++; } free(buf); } void dmi_scan(void) { size_t fp; u8 *buf; if((buf=mem_chunk(0xF0000, 0x10000))==NULL) return; for(fp=0; fp<=0xFFF0; fp+=16) { if(memcmp(buf+fp, "_DMI_", 5)==0) { u8 *cur = buf+fp; u16 num=cur[13]<<8|cur[12]; u16 len=cur[7]<<8|cur[6]; u32 base=cur[11]<<24|cur[10]<<16|cur[9]<<8|cur[8]; PRINTF("DMI %d.%d present.\n", cur[14]>>4, cur[14]&0x0F); PRINTF("%d structures occupying %d bytes.\n", cur[13]<<8|cur[12], cur[7]<<8|cur[6]); PRINTF("DMI table at 0x%08X.\n", cur[11]<<24|cur[10]<<16|cur[9]<<8|cur[8]); dmi_table(base,len,num); } } free(buf); return; } #ifndef S2RAM int main(int argc, char *argv[]) { dmi_scan(); } #endif suspend-utils/config_parser.h0000644000175500017550000000123012075743442015055 0ustar kixkix/* * config_parser.h * * Configuration file-related definitions for user space suspend and resume * tools. * * Copyright (C) 2006 Rafael J. Wysocki * * This file is released under the GPLv2. * */ #include #define MAX_STR_LEN 256 struct config_par { char *name; /* NULL on last record */ char *fmt; void *ptr; unsigned int len; }; int parse_line(char *str, struct config_par *parv); int parse(char *my_name, char *file_name, struct config_par *parv); void usage(char *my_name, struct option options[], const char *short_options); void version(char *my_name, char *extra_version); #define CONFIG_FILE "/etc/suspend.conf" suspend-utils/swsusp.h0000644000175500017550000000771312075743442013614 0ustar kixkix/* * swsusp.h * * Common definitions for user space suspend and resume handlers. * * Copyright (C) 2005 Rafael J. Wysocki * * This file is released under the GPLv2. * */ #include #include #include #include "encrypt.h" #define LINUX_REBOOT_MAGIC1 0xfee1dead #define LINUX_REBOOT_MAGIC2 672274793 #define LINUX_REBOOT_CMD_RESTART 0x01234567 #define LINUX_REBOOT_CMD_HALT 0xCDEF0123 #define LINUX_REBOOT_CMD_POWER_OFF 0x4321FEDC #define LINUX_REBOOT_CMD_RESTART2 0xA1B2C3D4 #define LINUX_REBOOT_CMD_SW_SUSPEND 0xD000FCE2 struct new_utsname { char sysname[65]; char nodename[65]; char release[65]; char version[65]; char machine[65]; char domainname[65]; }; struct swsusp_info { struct new_utsname uts; uint32_t version_code; unsigned long num_physpages; int cpus; unsigned long image_pages; unsigned long pages; unsigned long size; }; #define SNAPSHOT_ATOMIC_SNAPSHOT _IOW(SNAPSHOT_IOC_MAGIC, 3, void *) #define SNAPSHOT_SET_IMAGE_SIZE _IOW(SNAPSHOT_IOC_MAGIC, 6, unsigned long) #define SNAPSHOT_AVAIL_SWAP _IOR(SNAPSHOT_IOC_MAGIC, 7, void *) #define SNAPSHOT_GET_SWAP_PAGE _IOR(SNAPSHOT_IOC_MAGIC, 8, void *) #define SNAPSHOT_SET_SWAP_FILE _IOW(SNAPSHOT_IOC_MAGIC, 10, unsigned int) #define SNAPSHOT_PMOPS _IOW(SNAPSHOT_IOC_MAGIC, 12, unsigned int) #define PMOPS_PREPARE 1 #define PMOPS_ENTER 2 #define PMOPS_FINISH 3 struct image_header_info { unsigned long pages; uint32_t flags; loff_t map_start; loff_t image_data_size; unsigned char checksum[16]; #ifdef CONFIG_ENCRYPT unsigned char salt[CIPHER_BLOCK]; struct RSA_data rsa; struct encrypted_key key; #endif double writeout_time; int resume_pause; }; #define IMAGE_CHECKSUM 0x0001 #define IMAGE_COMPRESSED 0x0002 #define IMAGE_ENCRYPTED 0x0004 #define IMAGE_USE_RSA 0x0008 #define PLATFORM_SUSPEND 0x0010 #define SWSUSP_SIG "ULSUSPEND" struct swsusp_header { loff_t image; char orig_sig[10]; char sig[10]; } __attribute__((packed)); static inline void report_unsupported_ioctl(char *name) { printf("The %s ioctl is not supported by the kernel\n", name); } static inline int freeze(int dev) { return ioctl(dev, SNAPSHOT_FREEZE, 0); } static inline int unfreeze(int dev) { return ioctl(dev, SNAPSHOT_UNFREEZE, 0); } static inline int platform_prepare(int dev) { int error; error = ioctl(dev, SNAPSHOT_PLATFORM_SUPPORT, 1); if (error && errno == ENOTTY) { report_unsupported_ioctl("SNAPSHOT_PLATFORM_SUPPORT"); error = ioctl(dev, SNAPSHOT_PMOPS, PMOPS_PREPARE); } return error; } static inline void reboot(void) { syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART, 0); } static inline void power_off(void) { syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_POWER_OFF, 0); } #ifndef SYS_sync_file_range #ifdef __i386__ #define SYS_sync_file_range 314 #endif #ifdef __x86_64__ #define SYS_sync_file_range 277 #endif #define SYNC_FILE_RANGE_WRITE 2 #endif static inline int start_writeout(int fd) { #ifdef SYS_sync_file_range return syscall(SYS_sync_file_range, fd, (loff_t)0, (loff_t)0, SYNC_FILE_RANGE_WRITE); #else errno = ENOSYS; return -1; #endif } struct extent { loff_t start; loff_t end; }; /* The number 1 below is arbitrary. The actual size of data[] is variable */ struct buf_block { size_t size; char data[1]; } __attribute__((packed)); #define SNAPSHOT_DEVICE "/dev/snapshot" #define RESUME_DEVICE "" #define IMAGE_SIZE (500 * 1024 * 1024) #define SUSPEND_LOGLEVEL 1 #define MAX_LOGLEVEL 8 #define SUSPEND_SWAPPINESS 100 #define RESUME_PAUSE_MAX 60 #define GENERIC_NAME_SIZE 256 #define WRITE_BUFFERS 4 extern char *my_name; #ifdef CONFIG_COMPRESS extern unsigned int compress_buf_size; #else #define LZO1X_1_MEM_COMPRESS 0 #define compress_buf_size 0 #endif #define MIN_TEST_IMAGE_PAGES 1024 int read_or_verify(int dev, int fd, struct image_header_info *header, loff_t start, int verify, int test); suspend-utils/README.encryption0000644000175500017550000000157312075743442015146 0ustar kixkixSuspend encryption ~~~~~~~~~~~~~~~~~~ Encryption in suspend-utils uses RSA internally; the reason is that we want to only prompt for passphrase on resume. So, during suspend, the image is effectively encrypted with a public key, and during resume, the user has to first decrypt the corresponding private key using a passphrase, which then is used to decrypt the image. The image is always encrypted with symmetric algo. If RSA is used (optional) then the key for the symmetric encryption is random and the PK is used to safely store the key in the header of the image; the random key is encrypted with RSA and stored in the header, RSA private key is (encrypted using the password at installation time) is also stored in the header. At resume the password is used to unlock the private key which is then used to decrypt the random key. IOW we don't use RSA to encrypt the whole image ;) suspend-utils/splash.c0000644000175500017550000001233012075743442013524 0ustar kixkix/* * splash.c * * Bootsplash integration into the suspend and resume tools * * Copyright (C) 2006 Holger Macht * * This file is released under the GPLv2. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "splash.h" #include "bootsplash.h" #include "splashy_funcs.h" #include "fbsplash_funcs.h" #include "encrypt.h" #define INPUT_PATH "/dev/input/by-path" #define MAX_INPUT_FD 8 static struct { int fds[MAX_INPUT_FD]; int count; int highest; } input_fds; struct splash splash; /** * dummy functions in case if no splash system was found or * bootsplashing is disabled */ static int splash_dummy_int_void(void) { return 0; } static int splash_dummy_int_int(int p) { return 0; } static void splash_dummy_void_void(void) { return; } static void splash_dummy_set_caption(const char *message) { return; } #ifndef CONFIG_ENCRYPT static void splash_dummy_readpass(char *a, int b) { } #endif static int splash_dialog(const char *prompt) { printf("%s", prompt); return getchar(); } static int prepare_abort(struct termios *oldtrm, struct termios *newtrm) { int ret; ret = tcgetattr(0, oldtrm); if (!ret) { *newtrm = *oldtrm; newtrm->c_cc[VMIN] = 0; newtrm->c_cc[VTIME] = 0; newtrm->c_iflag = IGNBRK | IGNPAR | ICRNL | IMAXBEL; newtrm->c_lflag = 0; ret = tcsetattr(0, TCSANOW, newtrm); } return ret; } static char simple_key_pressed(void) { char c; if (read(0, &c, 1) == 0) return 0; switch (c) { case 127: return KEY_BACKSPACE; case 'r': return KEY_R; case '\n': return KEY_ENTER; } return 0; } static char key_pressed(void) { int err, i, active; struct input_event ev; struct timeval timeout = {0, 0}; fd_set fds; if (!input_fds.count) return 0; active = -1; /* GCC STFU */ FD_ZERO(&fds); for (i = 0; i < input_fds.count; i++) FD_SET(input_fds.fds[i], &fds); err = select(input_fds.highest + 1, &fds, NULL, NULL, &timeout); if (err <= 0) { if (err < 0) perror("select() failed"); return 0; } /* Get only the fist active fd */ for (i = 0; i < input_fds.count; i++) { if (FD_ISSET(input_fds.fds[i], &fds)) { active = input_fds.fds[i]; break; } } while ((err = read(active, &ev, sizeof(ev))) != -1) { /* we only need key release events */ if (ev.type == EV_KEY && ev.value == 0) return ev.code; } return 0; } static void restore_abort(struct termios *oldtrm) { tcsetattr(0, TCSANOW, oldtrm); } static int open_input_fd(void) { int fd, i; struct dirent *it; DIR *dir; char input_dev[PATH_MAX]; int err = 0; if (!(dir = opendir(INPUT_PATH))) { perror("Cannot open input directory"); return -EIO; } i = 0; errno = 0; while ((it = readdir(dir))) { if (i >= MAX_INPUT_FD) break; if (!strstr(it->d_name, "-event-kbd")) continue; snprintf(input_dev, PATH_MAX, "%s/%s", INPUT_PATH, it->d_name); fd = open(input_dev, O_RDONLY | O_NONBLOCK); if (fd < 0) { perror("Unable to open input fd"); continue; } input_fds.fds[i++] = fd; input_fds.count++; if (fd > input_fds.highest) input_fds.highest = fd; } if (!it && errno) { perror("readdir() failed"); err = -errno; } closedir(dir); if (err) fprintf(stderr, "Could not open keyboard input device\n"); return err; } /* Tries to find a splash system and initializes interface functions */ void splash_prepare(struct splash *splash, int mode) { splash->finish = splash_dummy_int_void; splash->progress = splash_dummy_int_int; splash->switch_to = splash_dummy_void_void; splash->dialog = splash_dialog; #ifdef CONFIG_ENCRYPT splash->read_password = read_password; #else splash->read_password = splash_dummy_readpass; #endif splash->prepare_abort = prepare_abort; splash->restore_abort = restore_abort; splash->key_pressed = simple_key_pressed; splash->set_caption = splash_dummy_set_caption; if (!mode) return; printf("Looking for splash system... "); if (!bootsplash_open()) { splash->finish = bootsplash_finish; splash->progress = bootsplash_progress; splash->switch_to = bootsplash_switch_to; splash->dialog = bootsplash_dialog; splash->read_password = bootsplash_read_password; if (!open_input_fd()) splash->key_pressed = key_pressed; #ifdef CONFIG_FBSPLASH } else if (!fbsplashfuncs_open(mode)) { splash->finish = fbsplashfuncs_finish; splash->progress = fbsplashfuncs_progress; splash->dialog = fbsplashfuncs_dialog; splash->read_password = fbsplashfuncs_read_password; splash->key_pressed = fbsplashfuncs_key_pressed; splash->set_caption = fbsplashfuncs_set_caption; #endif #ifdef CONFIG_SPLASHY } else if (!splashy_open(mode)) { splash->finish = splashy_finish; splash->progress = splashy_progress; splash->dialog = splashy_dialog; splash->read_password = splashy_read_password; if (!open_input_fd()) splash->key_pressed = key_pressed; #endif } else if (0) { /* add another splash system here */ } else { printf("none\n"); if (!open_input_fd()) splash->key_pressed = key_pressed; return; } printf("found\n"); splash->progress(0); } suspend-utils/bootsplash.h0000644000175500017550000000075712075743442014427 0ustar kixkix/* * bootsplash.h * * Bootsplash related definitions for bootsplash.org's method * * Copyright (C) 2006 Holger Macht * * This file is released under the GPLv2. * */ #ifndef BOOTSPLASH_H #define BOOTSPLASH_H int bootsplash_open(void); int bootsplash_prepare(void); int bootsplash_finish(void); int bootsplash_progress(int p); void bootsplash_switch_to(void); void bootsplash_read_password(char *, int); int bootsplash_dialog(const char *); #endif /* BOOTSPLASH_H */ suspend-utils/whitelist.h0000644000175500017550000000051012075743442014250 0ustar kixkix/* whitelist.h * whitelist of machines that are known to work somehow * and all the workarounds */ struct machine_entry { const char *sys_vendor; const char *sys_product; const char *sys_version; const char *bios_version; unsigned int flags; }; extern char *whitelist_version; extern struct machine_entry whitelist[]; suspend-utils/splash.h0000644000175500017550000000205112075743442013530 0ustar kixkix/* * splash.h * * Splash related definitions for userspace suspend and resume tools. * * Copyright (C) 2006 Holger Macht * * This file is released under the GPLv2. * */ #ifndef SPLASH_H #define SPLASH_H #include #include #define ABORT_KEY_CODE KEY_BACKSPACE #define ABORT_KEY_NAME "backspace" #define REBOOT_KEY_CODE KEY_R #define REBOOT_KEY_NAME "r" #define ENTER_KEY_CODE KEY_ENTER #define ENTER_KEY_NAME "ENTER" #define SPL_SUSPEND 1 #define SPL_RESUME 2 #define SPLASH_GENERIC_MESSAGE_SIZE 1024 /* generic interface functions for an arbitary splash method */ struct splash { int (*finish) (void); int (*progress) (int p); void (*switch_to) (void); void (*read_password) (char *, int); int (*dialog) (const char *); int (*prepare_abort) (struct termios *, struct termios *); char (*key_pressed) (void); void (*restore_abort) (struct termios *); void (*set_caption) (const char *); }; void splash_prepare(struct splash *splash, int mode); extern struct splash splash; #endif /* SPLASH_H */ suspend-utils/fbsplash_funcs.h0000644000175500017550000000121312075743442015235 0ustar kixkix/* * fbsplash.h * * Boot splash related definitions for fbsplash method * * Copyright (C) 2007 Alon Bar-Lev * * This file is released under the GPLv2. * */ #ifndef FBSPLASH_FUNCS_H #define FBSPLASH_FUNCS_H #ifdef CONFIG_FBSPLASH int fbsplashfuncs_open(int mode); int fbsplashfuncs_finish(void); int fbsplashfuncs_progress(int p); void fbsplashfuncs_read_password(char *, int); int fbsplashfuncs_dialog(const char *); void fbsplashfuncs_print(const char *); char fbsplashfuncs_key_pressed(void); void fbsplashfuncs_set_caption(const char *); void fbsplashfuncs_switch_to(void); #endif #endif /* FBSPLASH_FUNCS_H */ suspend-utils/md5.c0000644000175500017550000003306712075743442012731 0ustar kixkix/* md5.c - Functions to compute MD5 message digest of files or memory blocks according to the definition of MD5 in RFC 1321 from April 1992. Copyright (C) 1995, 1996, 2001, 2003, 2004 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. This program 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 2, or (at your option) any later version. This program 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 this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Written by Ulrich Drepper , 1995. */ #ifdef HAVE_CONFIG_H # include #endif #include "md5.h" #include #include #if USE_UNLOCKED_IO # include "unlocked-io.h" #endif #ifdef _LIBC # include # if __BYTE_ORDER == __BIG_ENDIAN # define WORDS_BIGENDIAN 1 # endif /* We need to keep the namespace clean so define the MD5 function protected using leading __ . */ # define md5_init_ctx __md5_init_ctx # define md5_process_block __md5_process_block # define md5_process_bytes __md5_process_bytes # define md5_finish_ctx __md5_finish_ctx # define md5_read_ctx __md5_read_ctx # define md5_stream __md5_stream # define md5_buffer __md5_buffer #endif #ifdef WORDS_BIGENDIAN # define SWAP(n) \ (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) #else # define SWAP(n) (n) #endif #define BLOCKSIZE 4096 /* Ensure that BLOCKSIZE is a multiple of 64. */ #if BLOCKSIZE % 64 != 0 /* FIXME-someday (soon?): use #error instead of this kludge. */ "invalid BLOCKSIZE" #endif /* This array contains the bytes used to pad the buffer to the next 64-byte boundary. (RFC 1321, 3.1: Step 1) */ static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; /* Initialize structure containing state of computation. (RFC 1321, 3.3: Step 3) */ void md5_init_ctx (struct md5_ctx *ctx) { ctx->A = 0x67452301; ctx->B = 0xefcdab89; ctx->C = 0x98badcfe; ctx->D = 0x10325476; ctx->total[0] = ctx->total[1] = 0; ctx->buflen = 0; } /* Put result from CTX in first 16 bytes following RESBUF. The result must be in little endian byte order. IMPORTANT: On some systems it is required that RESBUF is correctly aligned for a 32 bits value. */ void * md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) { ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A); ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B); ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C); ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D); return resbuf; } /* Process the remaining bytes in the internal buffer and the usual prolog according to the standard and write the result to RESBUF. IMPORTANT: On some systems it is required that RESBUF is correctly aligned for a 32 bits value. */ void * md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) { /* Take yet unprocessed bytes into account. */ md5_uint32 bytes = ctx->buflen; size_t pad; /* Now count remaining bytes. */ ctx->total[0] += bytes; if (ctx->total[0] < bytes) ++ctx->total[1]; pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; memcpy (&ctx->buffer[bytes], fillbuf, pad); /* Put the 64-bit file length in *bits* at the end of the buffer. */ *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3); *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) | (ctx->total[0] >> 29)); /* Process last bytes. */ md5_process_block (ctx->buffer, bytes + pad + 8, ctx); return md5_read_ctx (ctx, resbuf); } /* Compute MD5 message digest for bytes read from STREAM. The resulting message digest number will be written into the 16 bytes beginning at RESBLOCK. */ int md5_stream (FILE *stream, void *resblock) { struct md5_ctx ctx; char buffer[BLOCKSIZE + 72]; size_t sum; /* Initialize the computation context. */ md5_init_ctx (&ctx); /* Iterate over full file contents. */ while (1) { /* We read the file in blocks of BLOCKSIZE bytes. One call of the computation function processes the whole buffer so that with the next round of the loop another block can be read. */ size_t n; sum = 0; /* Read block. Take care for partial reads. */ while (1) { n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); sum += n; if (sum == BLOCKSIZE) break; if (n == 0) { /* Check for the error flag IFF N == 0, so that we don't exit the loop after a partial read due to e.g., EAGAIN or EWOULDBLOCK. */ if (ferror (stream)) return 1; goto process_partial_block; } /* We've read at least one byte, so ignore errors. But always check for EOF, since feof may be true even though N > 0. Otherwise, we could end up calling fread after EOF. */ if (feof (stream)) goto process_partial_block; } /* Process buffer with BLOCKSIZE bytes. Note that BLOCKSIZE % 64 == 0 */ md5_process_block (buffer, BLOCKSIZE, &ctx); } process_partial_block:; /* Process any remaining bytes. */ if (sum > 0) md5_process_bytes (buffer, sum, &ctx); /* Construct result in desired memory. */ md5_finish_ctx (&ctx, resblock); return 0; } /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The result is always in little endian byte order, so that a byte-wise output yields to the wanted ASCII representation of the message digest. */ void * md5_buffer (const char *buffer, size_t len, void *resblock) { struct md5_ctx ctx; /* Initialize the computation context. */ md5_init_ctx (&ctx); /* Process whole buffer but last len % 64 bytes. */ md5_process_bytes (buffer, len, &ctx); /* Put result in desired memory area. */ return md5_finish_ctx (&ctx, resblock); } void md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx) { /* When we already have some bits in our internal buffer concatenate both inputs first. */ if (ctx->buflen != 0) { size_t left_over = ctx->buflen; size_t add = 128 - left_over > len ? len : 128 - left_over; memcpy (&ctx->buffer[left_over], buffer, add); ctx->buflen += add; if (ctx->buflen > 64) { md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx); ctx->buflen &= 63; /* The regions in the following copy operation cannot overlap. */ memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], ctx->buflen); } buffer = (const char *) buffer + add; len -= add; } /* Process available complete blocks. */ if (len >= 64) { #if !_STRING_ARCH_unaligned # define alignof(type) offsetof (struct { char c; type x; }, x) # define UNALIGNED_P(p) (((size_t) p) % alignof (md5_uint32) != 0) if (UNALIGNED_P (buffer)) while (len > 64) { md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); buffer = (const char *) buffer + 64; len -= 64; } else #endif { md5_process_block (buffer, len & ~63, ctx); buffer = (const char *) buffer + (len & ~63); len &= 63; } } /* Move remaining bytes in internal buffer. */ if (len > 0) { size_t left_over = ctx->buflen; memcpy (&ctx->buffer[left_over], buffer, len); left_over += len; if (left_over >= 64) { md5_process_block (ctx->buffer, 64, ctx); left_over -= 64; memcpy (ctx->buffer, &ctx->buffer[64], left_over); } ctx->buflen = left_over; } } /* These are the four functions used in the four steps of the MD5 algorithm and defined in the RFC 1321. The first function is a little bit optimized (as found in Colin Plumbs public domain implementation). */ /* #define FF(b, c, d) ((b & c) | (~b & d)) */ #define FF(b, c, d) (d ^ (b & (c ^ d))) #define FG(b, c, d) FF (d, b, c) #define FH(b, c, d) (b ^ c ^ d) #define FI(b, c, d) (c ^ (b | ~d)) /* Process LEN bytes of BUFFER, accumulating context into CTX. It is assumed that LEN % 64 == 0. */ void md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx) { md5_uint32 correct_words[16]; const md5_uint32 *words = buffer; size_t nwords = len / sizeof (md5_uint32); const md5_uint32 *endp = words + nwords; md5_uint32 A = ctx->A; md5_uint32 B = ctx->B; md5_uint32 C = ctx->C; md5_uint32 D = ctx->D; /* First increment the byte count. RFC 1321 specifies the possible length of the file up to 2^64 bits. Here we only compute the number of bytes. Do a double word increment. */ ctx->total[0] += len; if (ctx->total[0] < len) ++ctx->total[1]; /* Process all bytes in the buffer with 64 bytes in each round of the loop. */ while (words < endp) { md5_uint32 *cwp = correct_words; md5_uint32 A_save = A; md5_uint32 B_save = B; md5_uint32 C_save = C; md5_uint32 D_save = D; /* First round: using the given function, the context and a constant the next context is computed. Because the algorithms processing unit is a 32-bit word and it is determined to work on words in little endian byte order we perhaps have to change the byte order before the computation. To reduce the work for the next steps we store the swapped words in the array CORRECT_WORDS. */ #define OP(a, b, c, d, s, T) \ do \ { \ a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ ++words; \ a = rol (a, s); \ a += b; \ } \ while (0) /* Before we start, one word to the strange constants. They are defined in RFC 1321 as T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64, or perl -e 'foreach(1..64){printf "0x%08x\n", int (4294967296 * abs (sin $_))}' */ /* Round 1. */ OP (A, B, C, D, 7, 0xd76aa478); OP (D, A, B, C, 12, 0xe8c7b756); OP (C, D, A, B, 17, 0x242070db); OP (B, C, D, A, 22, 0xc1bdceee); OP (A, B, C, D, 7, 0xf57c0faf); OP (D, A, B, C, 12, 0x4787c62a); OP (C, D, A, B, 17, 0xa8304613); OP (B, C, D, A, 22, 0xfd469501); OP (A, B, C, D, 7, 0x698098d8); OP (D, A, B, C, 12, 0x8b44f7af); OP (C, D, A, B, 17, 0xffff5bb1); OP (B, C, D, A, 22, 0x895cd7be); OP (A, B, C, D, 7, 0x6b901122); OP (D, A, B, C, 12, 0xfd987193); OP (C, D, A, B, 17, 0xa679438e); OP (B, C, D, A, 22, 0x49b40821); /* For the second to fourth round we have the possibly swapped words in CORRECT_WORDS. Redefine the macro to take an additional first argument specifying the function to use. */ #undef OP #define OP(f, a, b, c, d, k, s, T) \ do \ { \ a += f (b, c, d) + correct_words[k] + T; \ a = rol (a, s); \ a += b; \ } \ while (0) /* Round 2. */ OP (FG, A, B, C, D, 1, 5, 0xf61e2562); OP (FG, D, A, B, C, 6, 9, 0xc040b340); OP (FG, C, D, A, B, 11, 14, 0x265e5a51); OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); OP (FG, A, B, C, D, 5, 5, 0xd62f105d); OP (FG, D, A, B, C, 10, 9, 0x02441453); OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); OP (FG, D, A, B, C, 14, 9, 0xc33707d6); OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); OP (FG, B, C, D, A, 8, 20, 0x455a14ed); OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); OP (FG, C, D, A, B, 7, 14, 0x676f02d9); OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); /* Round 3. */ OP (FH, A, B, C, D, 5, 4, 0xfffa3942); OP (FH, D, A, B, C, 8, 11, 0x8771f681); OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); OP (FH, B, C, D, A, 14, 23, 0xfde5380c); OP (FH, A, B, C, D, 1, 4, 0xa4beea44); OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); OP (FH, B, C, D, A, 6, 23, 0x04881d05); OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); /* Round 4. */ OP (FI, A, B, C, D, 0, 6, 0xf4292244); OP (FI, D, A, B, C, 7, 10, 0x432aff97); OP (FI, C, D, A, B, 14, 15, 0xab9423a7); OP (FI, B, C, D, A, 5, 21, 0xfc93a039); OP (FI, A, B, C, D, 12, 6, 0x655b59c3); OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); OP (FI, C, D, A, B, 10, 15, 0xffeff47d); OP (FI, B, C, D, A, 1, 21, 0x85845dd1); OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); OP (FI, C, D, A, B, 6, 15, 0xa3014314); OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); OP (FI, A, B, C, D, 4, 6, 0xf7537e82); OP (FI, D, A, B, C, 11, 10, 0xbd3af235); OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); OP (FI, B, C, D, A, 9, 21, 0xeb86d391); /* Add the starting values of the context. */ A += A_save; B += B_save; C += C_save; D += D_save; } /* Put checksum in context given as argument. */ ctx->A = A; ctx->B = B; ctx->C = C; ctx->D = D; } suspend-utils/memalloc.c0000644000175500017550000001103512075743442014024 0ustar kixkix/* * memalloc.c * * Memory allocation functions for user land hibernation utilities. * * Copyright (C) 2008 Rafael J. Wysocki * * This file is released under the GPLv2. * */ #include #include #include #include #include "memalloc.h" unsigned int page_size; unsigned int buffer_size; /* Mask used for page aligning */ static size_t page_mask; /* Memory pool used for memory allocations */ static void *mem_pool; /* Size of the pool */ static size_t pool_size; /* The array of objects representig memory allocations */ static struct mem_slot *slots; /* Size of the slots array */ static unsigned int nr_slots; /* The struct mem_slot object to be used next */ static struct mem_slot *cur_slot; void get_page_and_buffer_sizes(void) { page_size = getpagesize(); page_mask = ~((size_t)page_size - 1); buffer_size = page_size * BUFFER_PAGES; } /** * round_up_page_size - round given number up to the closest multiple of * page size * @size: the number to round */ size_t round_up_page_size(size_t size) { return ((size + page_size - 1) & page_mask); } /** * round_down_page_size - round given number down to the closest multiple * of the page size lesser than that number * @size: the number to round */ size_t round_down_page_size(size_t size) { return size & page_mask; } /** * init_memalloc - initialize memory allocation structures * @aux: Number of bytes for the internal use of the allocator * @pool: Number of bytes to preallocate for the users */ int init_memalloc(size_t aux, size_t pool) { void *mem; unsigned long addr; size_t slots_size; slots_size = round_up_page_size(aux); pool_size = round_up_page_size(pool); /* The additional page_size may be necessary for page alignment */ mem = malloc(slots_size + pool_size + page_size); if (!mem) return -ENOMEM; slots = mem; nr_slots = slots_size / sizeof(struct mem_slot); cur_slot = slots; /* Make the pool address be page aligned */ mem += slots_size; addr = ((unsigned long)mem & ~((unsigned long)page_size - 1)); if (addr < (unsigned long)mem) mem = (void *)(addr + page_size); mem_pool = mem; return 0; } /** * getmem - get some memory from the preallocated pool * @size: Number of bytes needed * * Return the address of @size bytes of memory, aligned to the first * natural power of 2 greater than or equal to @size and not greater than * page_size. */ void *getmem(size_t size) { void *addr = mem_pool; size_t used; if (cur_slot - slots >= nr_slots) { fprintf(stderr, "WARNING: Not enough memory slots\n"); return NULL; } if (cur_slot > slots) { unsigned int align_size, align_mask; struct mem_slot *last_slot = cur_slot - 1; if (size >= page_size) { align_size = page_size; align_mask = page_mask; } else { align_size = ALIGN_QWORD; while (align_size < size) align_size <<= 1; align_mask = ~(align_size - 1); } addr += ((last_slot->addr - mem_pool + last_slot->size + align_size - 1) & align_mask); } used = addr - mem_pool; if (used > pool_size || size > pool_size - used) { fprintf(stderr, "WARNING: Not enough memory in the pool\n"); return NULL; } cur_slot->addr = addr; cur_slot->size = size; cur_slot++; return addr; } /** * free_slot - mark given memory slot as freed and try to remove it * @slot: Number of memory slot to free */ static void free_slot(int slot) { struct mem_slot *last_slot = cur_slot - 1; /* * To free the slot, set its size to zero. If this is the most recently * allocated one, remove it from the array along with some other already * freed slots (the size of the last remaining slot must be greater than * zero). */ slots[slot].size = 0; if (slots + slot == last_slot) { do last_slot--; while (!last_slot->size && last_slot >= slots); cur_slot = last_slot + 1; } } /** * freemem - free memory allocated by getmem * @address: Start of the memory area to free */ void freemem(void *address) { int i, j, k; /* Check if there is anything to do */ if (cur_slot <= slots) return; /* Find the slot to free, using the observation that they are sorted */ i = 0; j = cur_slot - slots - 1; do { k = (i + j) / 2; if (slots[k].addr == address) { free_slot(k); break; } else if (address > slots[k].addr) { if (i != k) { i = k; } else { if (slots[j].addr == address) free_slot(j); break; } } else { j = k; } } while (i < j); } /** * end_memalloc - free memory used by the allocator */ void free_memalloc(void) { if (slots) free(slots); } suspend-utils/bootsplash.c0000644000175500017550000000410212075743442014406 0ustar kixkix/* * bootsplash.c * * Bootsplash.org splash method support * * Copyright (C) 2006 Holger Macht * * This file is released under the GPLv2. * */ #include "config.h" #include #include #include #include #include #include "vt.h" #include "encrypt.h" #define BOOTSPLASH_PROC "/proc/splash" #define MAX_LINE_SIZE 1024 static FILE *splash_file = NULL; int bootsplash_finish(void) { if (splash_file) { fclose(splash_file); splash_file = NULL; } return 0; } static int bootsplash_write(const char *buf) { int error = 0; if (!splash_file) return -1; error = fputs(buf, splash_file); if (error == EOF) { fprintf(stderr, "Could not write '%s' to %s: %s\n", buf, BOOTSPLASH_PROC, strerror(errno)); bootsplash_finish(); return error; } fflush(splash_file); return 0; } static int bootsplash_to_silent(void) { return bootsplash_write("silent\n"); } static int bootsplash_to_verbose(void) { return bootsplash_write("verbose\n"); } int bootsplash_open(void) { char *str, buf[MAX_LINE_SIZE]; splash_file = fopen(BOOTSPLASH_PROC, "r+"); if (!splash_file) return -1; str = fgets(buf, MAX_LINE_SIZE, splash_file); if (!str) goto close; if (!strstr(buf, ": on")) goto close; bootsplash_to_silent(); return 0; close: bootsplash_finish(); return -1; } void bootsplash_switch_to(void) { if (splash_file) { /* assume that bootsplash is on console 1, there's no way * to figure this out AFAIK */ chvt(1); } } inline int bootsplash_progress(int p) { char buf[MAX_LINE_SIZE]; if (!splash_file) return -1; /* 65535 corresponds to 100 % on the progress bar */ snprintf(buf, MAX_LINE_SIZE, "show %d\n", p * (65535 / 100)); return bootsplash_write(buf); } void bootsplash_read_password(char * buf, int vrfy) { #if CONFIG_ENCRYPT bootsplash_to_verbose(); read_password(buf, vrfy); bootsplash_to_silent(); #endif } int bootsplash_dialog(const char *prompt) { int ret; bootsplash_to_verbose(); printf("%s", prompt); ret = getchar(); bootsplash_to_silent(); return ret; } suspend-utils/vbetool/0000755000175500017550000000000012075743442013541 5ustar kixkixsuspend-utils/vbetool/Makefile.am0000644000175500017550000000054412075743442015600 0ustar kixkixAUTOMAKE_OPTIONS = foreign sbin_PROGRAMS = vbetool vbetool_LDADD = $(libdir)/libpci.a man_MANS = vbetool.1 vbetool_SOURCES = vbetool.c $(x86) noinst_HEADERS = vbetool.h EXTRA_DIST = vbetool.1 LRMI maintainer-clean-local: $(RM) Makefile.in aclocal.m4 config.h.in stamp-h.in configure AM_CFLAGS = -g -Wall -pedantic -std=gnu99 AM_LDFLAGS = -lz -lx86 suspend-utils/vbetool/vbetool.c0000644000175500017550000002710512075743442015364 0ustar kixkix/* Run video BIOS code for various purposes Copyright Matthew Garrett , heavily based on vbetest.c from the lrmi package and read-edid.c by John Fremlin This program is released under the terms of the GNU General Public License, version 2 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "vbetool.h" #define access_ptr_register(reg_frame,reg) (reg_frame -> reg) #define access_seg_register(reg_frame,es) reg_frame.es #define real_mode_int(interrupt,reg_frame_ptr) !LRMI_int(interrupt,reg_frame_ptr) #define DPMS_STATE_ON 0x0000 #define DPMS_STATE_STANDBY 0x0100 #define DPMS_STATE_SUSPEND 0x0200 #define DPMS_STATE_OFF 0x0400 #define DPMS_STATE_LOW 0x0800 static struct pci_access *pacc; void vbetool_init(void) { if (!LRMI_init()) { fprintf(stderr, "Failed to initialise LRMI (Linux Real-Mode Interface).\n"); exit(1); } ioperm(0, 1024, 1); iopl(3); pacc = pci_alloc(); pacc->numeric_ids = 1; pci_init(pacc); } #ifndef S2RAM int main(int argc, char *argv[]) { /* Don't bother checking for privilege if they only want usage() */ if (argc < 2) goto usage; vbetool_init(); if (!strcmp(argv[1], "vbestate")) { /* VBE save/restore tends to break when done underneath X */ int err = check_console(); if (err) { return err; } if (!strcmp(argv[2], "save")) { save_state(); } else if (!strcmp(argv[2], "restore")) { restore_state(); } else { goto usage; } } else if (!strcmp(argv[1], "dpms")) { if (!strcmp(argv[2], "on")) { return do_blank(DPMS_STATE_ON); } else if (!strcmp(argv[2], "suspend")) { return do_blank(DPMS_STATE_SUSPEND); } else if (!strcmp(argv[2], "standby")) { return do_blank(DPMS_STATE_STANDBY); } else if (!strcmp(argv[2], "off")) { return do_blank(DPMS_STATE_OFF); } else if (!strcmp(argv[2], "reduced")) { return do_blank(DPMS_STATE_LOW); } else { goto usage; } } else if (!strcmp(argv[1], "vbemode")) { if (!strcmp(argv[2], "set")) { return do_set_mode(atoi(argv[3]),0); } else if (!strcmp(argv[2], "get")) { return do_get_mode(); } else { goto usage; } } else if (!strcmp(argv[1], "vgamode")) { if (!strcmp(argv[2], "set")) { return do_set_mode(atoi(argv[3]),1); } else { return do_set_mode(atoi(argv[2]),1); } } else if (!strcmp(argv[1], "post")) { /* Again, we don't really want to do this while X is in control */ int err = check_console(); if (err) { return err; } return do_post(); } else if (!strcmp(argv[1], "vgastate")) { if (!strcmp(argv[2], "on")) { return enable_vga(); } else { return disable_vga(); } } else if (!strcmp(argv[1], "vbefp")) { if (!strcmp(argv[2], "id") || !strcmp(argv[2], "panelid")) { return do_get_panel_id(0); } else if (!strcmp(argv[2], "panelsize")) { return do_get_panel_id(1); } else if (!strcmp(argv[2], "getbrightness")) { return do_get_panel_brightness(); } else if (!strcmp(argv[2], "setbrightness")) { return do_set_panel_brightness(atoi(argv[3])); } else if (!strcmp(argv[2], "invert")) { return do_invert_panel(); } else { return 1; } } else { usage: fprintf(stderr, "%s: Usage %s [[vbestate save|restore]|[vbemode set|get]|[vgamode]|[dpms on|off|standby|suspend|reduced]|[post]|[vgastate on|off]|[vbefp panelid|panelsize|getbrightness|setbrightness|invert]]\n", argv[0], argv[0]); return 1; } return 0; } #endif int do_vbe_service(unsigned int AX, unsigned int BX, reg_frame * regs) { const unsigned interrupt = 0x10; unsigned function_sup; unsigned success; regs->ds = 0x0040; access_ptr_register(regs, eax) = AX; access_ptr_register(regs, ebx) = BX; if (real_mode_int(interrupt, regs)) { fprintf(stderr, "Error: something went wrong performing real mode interrupt\n"); return -1; } AX = access_ptr_register(regs, eax); function_sup = ((AX & 0xff) == 0x4f); success = ((AX & 0xff00) == 0); if (!success) { fprintf(stderr, "Real mode call failed\n"); return -2; } if (!function_sup) { fprintf(stderr, "Function not supported?\n"); return -3; } return access_ptr_register(regs, ebx); } int do_real_post(unsigned pci_device) { int error = 0; struct LRMI_regs r; memset(&r, 0, sizeof(r)); /* Several machines seem to want the device that they're POSTing in here */ r.eax = pci_device; /* 0xc000 is the video option ROM. The init code for each option ROM is at 0x0003 - so jump to c000:0003 and start running */ r.cs = 0xc000; r.ip = 0x0003; /* This is all heavily cargo culted but seems to work */ r.edx = 0x80; r.ds = 0x0040; if (!LRMI_call(&r)) { fprintf(stderr, "Error: something went wrong performing real mode call\n"); error = 1; } return error; } int do_post(void) { struct pci_dev *p; unsigned int c; unsigned int pci_id; int error; pci_scan_bus(pacc); for (p = pacc->devices; p; p = p->next) { c = pci_read_word(p, PCI_CLASS_DEVICE); if (c == 0x300) { pci_id = (p->bus << 8) + (p->dev << 3) + (p->func & 0x7); error = do_real_post(pci_id); if (error != 0) { return error; } } } return 0; } void restore_state_from(char *data) { struct LRMI_regs r; /* VGA BIOS mode 3 is text mode */ do_set_mode(3,1); memset(&r, 0, sizeof(r)); r.eax = 0x4f04; r.ecx = 0xf; /* all states */ r.edx = 2; /* restore state */ r.es = (unsigned int) (data - LRMI_base_addr()) >> 4; r.ebx = (unsigned int) (data - LRMI_base_addr()) & 0xf; r.ds = 0x0040; if (!LRMI_int(0x10, &r)) { fprintf(stderr, "Can't restore video state (vm86 failure)\n"); } else if ((r.eax & 0xffff) != 0x4f) { fprintf(stderr, "Restore video state failed\n"); } LRMI_free_real(data); ioctl(0, KDSETMODE, KD_TEXT); } #ifndef S2RAM void restore_state(void) { char *data = NULL; char tmpbuffer[524288]; int i, length = 0; /* We really, really don't want to fail to read the entire set */ while ((i = read(0, tmpbuffer + length, sizeof(tmpbuffer)-length))) { if (i == -1) { if (errno != EAGAIN && errno != EINTR) { perror("Failed to read state - "); return; } } else { length += i; } } data = LRMI_alloc_real(length); memcpy(data, tmpbuffer, length); restore_state_from(data); } #endif char *__save_state(int *psize) { struct LRMI_regs r; char *buffer; unsigned int size; memset(&r, 0, sizeof(r)); r.eax = 0x4f04; r.ecx = 0xf; /* all states */ r.edx = 0; /* get buffer size */ r.ds = 0x0040; if (!LRMI_int(0x10, &r)) { fprintf(stderr, "Can't get video state buffer size (vm86 failure)\n"); } if ((r.eax & 0xffff) != 0x4f) { fprintf(stderr, "Get video state buffer size failed\n"); } *psize = size = (r.ebx & 0xffff) * 64; buffer = LRMI_alloc_real(size); if (buffer == NULL) { fprintf(stderr, "Can't allocate video state buffer\n"); return NULL; } memset(&r, 0, sizeof(r)); fprintf(stderr, "Allocated buffer at %p (base is 0x%x)\n", buffer, LRMI_base_addr()); r.eax = 0x4f04; r.ecx = 0xf; /* all states */ r.edx = 1; /* save state */ r.es = (unsigned int) (buffer - LRMI_base_addr()) >> 4; r.ebx = (unsigned int) (buffer - LRMI_base_addr()) & 0xf; r.ds = 0x0040; fprintf(stderr, "ES: 0x%04X EBX: 0x%04X\n", r.es, r.ebx); if (!LRMI_int(0x10, &r)) { fprintf(stderr, "Can't save video state (vm86 failure)\n"); } if ((r.eax & 0xffff) != 0x4f) { fprintf(stderr, "Save video state failed\n"); } return buffer; } #ifndef S2RAM void save_state(void) { int size; char *buffer = __save_state(&size); if (buffer) write(1, buffer, size); /* FIXME: should retry on short write); */ } int do_blank(int state) { reg_frame regs; int error; memset(®s, 0, sizeof(regs)); error = do_vbe_service(0x4f10, state |= 0x01, ®s); if (error<0) { return error; } return 0; } #endif int do_set_mode (int mode, int vga) { reg_frame regs; int error; memset(®s, 0, sizeof(regs)); if (vga) { error = do_vbe_service(mode, 0, ®s); } else { error = do_vbe_service(0x4f02, mode, ®s); } if (error<0) { return error; } return 0; } #ifndef S2RAM int do_get_panel_brightness() { reg_frame regs; int error; memset(®s, 0, sizeof(regs)); error = do_vbe_service(0x4f11, 0x05, ®s); if (error<0) { return error; } printf("%d\n",regs.ecx); return 0; } int do_invert_panel() { reg_frame regs; int error; memset(®s, 0, sizeof(regs)); error = do_vbe_service(0x4f11, 0x02, ®s); if (error<0) { return error; } if ((regs.ebx & 0xff) == 0) regs.ecx = 3; else regs.ecx = 0; error = do_vbe_service(0x4f11, 0x0102, ®s); if (error<0) { return error; } return 0; } int do_set_panel_brightness(int brightness) { reg_frame regs; int error; memset(®s, 0, sizeof(regs)); regs.ecx = brightness; error = do_vbe_service(0x4f11, 0x0105, ®s); if (error<0) { return error; } printf("%d\n",regs.ecx); return 0; } #endif int __get_mode() { reg_frame regs; int error; memset(®s, 0, sizeof(regs)); error = do_vbe_service(0x4f03, 0, ®s); return error; } int do_get_mode() { int error = __get_mode(); if (error<0) { return error; } printf("%d\n",error); return 0; } #ifndef S2RAM int check_console() { struct stat stat; return 0; if (fstat(0, &stat) != 0) { fprintf(stderr, "Can't stat() stdin\n"); return 10; } if ((stat.st_rdev & 0xff00) != 0x400 || (stat.st_rdev & 0xff) > 63) { fprintf(stderr, "To perform this operation, " "this program must be run from the console\n"); return 11; } ioctl(0, KDSETMODE, KD_GRAPHICS); return 0; } int enable_vga() { outb(0x03 | inb(0x3CC), 0x3C2); outb(0x01 | inb(0x3C3), 0x3C3); outb(0x08 | inb(0x46e8), 0x46e8); outb(0x01 | inb(0x102), 0x102); return 0; } int disable_vga() { outb(~0x03 & inb(0x3CC), 0x3C2); outb(~0x01 & inb(0x3C3), 0x3C3); outb(~0x08 & inb(0x46e8), 0x46e8); outb(~0x01 & inb(0x102), 0x102); return 0; } /* Based on xserver-xorg-driver-i810/src/i830_driver.c */ struct panel_id { int hsize:16, vsize:16; int fptype:16; int redbpp:8, greenbpp:8, bluebpp:8, reservedbpp:8; int rsvdoffscrnmemsize:32, rsvdoffscrnmemptr:32; char reserved[14]; } __attribute__((packed)); int do_get_panel_id(int just_dimensions) { reg_frame r = { .eax = 0x4f11, .ebx = 0x0001 }; struct panel_id *id = LRMI_alloc_real(sizeof(struct panel_id)); r.es = (unsigned short)(((int)(id-LRMI_base_addr()) >> 4) & 0xffff); r.edi = (unsigned long)(id-LRMI_base_addr()) & 0xf; if(sizeof(struct panel_id) != 32) return fprintf(stderr, "oops: panel_id, sizeof struct panel_id != 32, it's %ld...\n", sizeof(struct panel_id)), 7; if(real_mode_int(0x10, &r)) return fprintf(stderr, "Can't get panel id (vm86 failure)\n"), 8; if((r.eax & 0xff) != 0x4f) return fprintf(stderr, "Panel id function not supported\n"), 9; if(r.eax & 0xff00) { if((r.eax & 0xff00) == 0x100) fprintf(stderr, "Panel id read failed\n"); else fprintf(stderr, "Panel id function not successful\n"); return 10; } if(!just_dimensions) printf("size:\t%d %d\n" "type:\t%d\n" "bpp:\t%d %d %d %d\n", id->hsize, id->vsize, id->fptype, id->redbpp, id->greenbpp, id->bluebpp, id->reservedbpp); else printf("%dx%d\n", id->hsize, id->vsize); #if 0 /* Don't have a use for these and they don't seem to be documented. * 320 appears to be 320kB of mapped memory and the following * pointer is 0x1ffb8000 which is kernel mapping + 0xb8000 offset. */ printf("ram:\t%dkB\n" "offset:\t%p\n", id->rsvdoffscrnmemsize, (void *)id->rsvdoffscrnmemptr); #endif return 0; } #endif suspend-utils/vbetool/vbetool.10000644000175500017550000000656512075743442015311 0ustar kixkix.TH VBETOOL "1" "31 December 2004" "vbetool 0.2" "User Commands" .SH NAME vbetool - run real-mode video BIOS code to alter hardware state .SH SYNOPSIS .B "vbetool [[vbestate save|restore]|[vbemode set|get]|[vgamode]|[dpms on|off|standby|suspend|reduced]|[post]|[vgastate on|off]|[vbefp panelid|panelsize|getbrightness|setbrightness|invert]]" .SH DESCRIPTION .B vbetool uses lrmi in order to run code from the video BIOS. Currently, it is able to alter DPMS states, save/restore video card state and attempt to initialize the video card from scratch. .SH OPTIONS .B vbetool takes the following options: .IP "vbestate" .B vbetool will use the VESA 0x4f0f extensions to save or restore hardware state. This will be sent to or read from stdin. This information is highly hardware specific - do not attempt to restore state saved from a different machine. This command will not work unless you are at a text console, as it interferes badly with X. .IP "dpms" .B vbetool will use the VESA 0x4f10 extensions to alter the power management state of your screen. "On", "off", "standby", "suspend" and "reduced" are acceptable further options and determine which state will be activated. .IP "vbemode" .B vbetool will get or set the current VESA mode. "get" will return the current mode number on stdout - "set" will set the mode to the next argument. .IP "vgamode" .B vbetool will set the legacy VGA mode to the following numeric argument. .IP "post" .B vbetool will attempt to run BIOS code located at c000:0003. This is the code run by the system BIOS at boot in order to intialise the video hardware. Note that on some machines (especially laptops), not all of this code is present after system boot - as a result, executing this command may result in undefined behaviour. This command must be run from a text console, as it will otherwise interfere with the operation of X. .IP "vgastate" .B vbetool will enable or disable the current video card. On most hardware, disabling will cause the hardware to stop responding until it is reenabled. You probably don't want to do this if you're using a framebuffer. .IP "vbefp" .B vbetool will execute a VESA flat panel interface call. .IP panelid will provide information about the panel .IP panelsize will provide the size of the panel .IP getbrightness will provide the current screen brightness as an integer .IP setbrightness accepts an integer as an argument and will set the screen brightness to that .IP invert will invert the colours of the screen .SH BUGS Switching dpms modes may interact badly with X on some systems. .PP The vbestate command may behave in strange ways. .PP The post command may result in the execution of arbitrary code that happens to be lying around in the area where chunks of your video BIOS used to be. .PP The VESA specification does not require that "vbemode get" provides the correct mode if the current mode was set via some means other than the VESA BIOS extensions. .PP The VESA flat panel interface ceased development at the proposal stage. panelid and panelsize will work on many machines, but the other arguments are unlikely to be implemented on available hardware. .SH AUTHOR vbetool was written by Matthew Garrett , based on code from read-edid by John Fremlin , LRMI (http://sourceforge.net/projects/lrmi/) and XFree (http://www.xfree86.org). It is released under the terms of the GNU General Public License. suspend-utils/vbetool/x86-common.h0000644000175500017550000000300712075743442015625 0ustar kixkix/* Common routines for x86emu/lrmi interfaces. Taken from lrmi.c. Copyright (C) 1998 by Josh Vanderhoof Copyright (C) 2005 by Jonathan McDowell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL JOSH VANDERHOOF BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include "include/lrmi.h" #define REAL_MEM_BASE ((void *)0x10000) #define REAL_MEM_SIZE 0x40000 #define REAL_MEM_BLOCKS 0x100 void *LRMI_alloc_real(int size); void LRMI_free_real(void *m); int LRMI_common_init(void); suspend-utils/vbetool/vbetool.h0000644000175500017550000000116512075743442015367 0ustar kixkixtypedef struct LRMI_regs reg_frame; int do_vbe_service(unsigned int AX, unsigned int BX, reg_frame *regs); int do_real_post(unsigned pci_device); int do_blank(int state); int do_set_mode (int mode, int vga); int do_get_mode(void); int do_get_panel_brightness(void); int do_set_panel_brightness(int brightness); int do_invert_panel(void); int do_post(void); void restore_state(void); void save_state(void); void text_mode(void); int check_console(void); int enable_vga(void); int disable_vga(void); int do_get_panel_id(); void vbetool_init(void); char *__save_state(int *); void restore_state_from(char *); int __get_mode(void); suspend-utils/vbetool/configure.in0000644000175500017550000000054312075743442016054 0ustar kixkix dnl Process this file with autoconf to produce a configure script. AC_INIT(vbetool.c) AM_INIT_AUTOMAKE(vbetool, 0.3) dnl Checks for programs AC_PROG_CC dnl Simple, huh? AC_ARG_WITH([x86emu], AC_HELP_STRING([--with-x86emu],[build with x86emu support]), [USEX86EMU=true]) AM_CONDITIONAL(WITH_X86EMU, test x$USEX86EMU = xtrue) AC_OUTPUT([Makefile]) suspend-utils/vbetool/x86-common.c0000644000175500017550000001131212075743442015616 0ustar kixkix/* Linux Real Mode Interface - A library of DPMI-like functions for Linux. Copyright (C) 1998 by Josh Vanderhoof Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL JOSH VANDERHOOF BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include "include/lrmi.h" #define REAL_MEM_BASE ((void *)0x10000) #define REAL_MEM_SIZE 0x90000 #define REAL_MEM_BLOCKS 0x100 struct mem_block { unsigned int size : 20; unsigned int free : 1; }; static struct { int ready; int count; struct mem_block blocks[REAL_MEM_BLOCKS]; } mem_info = { 0 }; static int real_mem_init(void) { void *m; int fd_zero; if (mem_info.ready) return 1; fd_zero = open("/dev/zero", O_RDWR); if (fd_zero == -1) { perror("open /dev/zero"); return 0; } m = mmap((void *)REAL_MEM_BASE, REAL_MEM_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_SHARED, fd_zero, 0); if (m == (void *)-1) { perror("mmap /dev/zero"); close(fd_zero); return 0; } close(fd_zero); mem_info.ready = 1; mem_info.count = 1; mem_info.blocks[0].size = REAL_MEM_SIZE; mem_info.blocks[0].free = 1; return 1; } static void real_mem_deinit(void) { if (mem_info.ready) { munmap((void *)REAL_MEM_BASE, REAL_MEM_SIZE); mem_info.ready = 0; } } static void insert_block(int i) { memmove( mem_info.blocks + i + 1, mem_info.blocks + i, (mem_info.count - i) * sizeof(struct mem_block)); mem_info.count++; } static void delete_block(int i) { mem_info.count--; memmove( mem_info.blocks + i, mem_info.blocks + i + 1, (mem_info.count - i) * sizeof(struct mem_block)); } void * LRMI_alloc_real(int size) { int i; char *r = (char *)REAL_MEM_BASE; if (!mem_info.ready) return NULL; if (mem_info.count == REAL_MEM_BLOCKS) return NULL; size = (size + 15) & ~15; for (i = 0; i < mem_info.count; i++) { if (mem_info.blocks[i].free && size < mem_info.blocks[i].size) { insert_block(i); mem_info.blocks[i].size = size; mem_info.blocks[i].free = 0; mem_info.blocks[i + 1].size -= size; return (void *)r; } r += mem_info.blocks[i].size; } return NULL; } void LRMI_free_real(void *m) { int i; char *r = (char *)REAL_MEM_BASE; if (!mem_info.ready) return; i = 0; while (m != (void *)r) { r += mem_info.blocks[i].size; i++; if (i == mem_info.count) return; } mem_info.blocks[i].free = 1; if (i + 1 < mem_info.count && mem_info.blocks[i + 1].free) { mem_info.blocks[i].size += mem_info.blocks[i + 1].size; delete_block(i + 1); } if (i - 1 >= 0 && mem_info.blocks[i - 1].free) { mem_info.blocks[i - 1].size += mem_info.blocks[i].size; delete_block(i); } } #define DEFAULT_STACK_SIZE 0x1000 static inline void set_bit(unsigned int bit, void *array) { unsigned char *a = array; a[bit / 8] |= (1 << (bit % 8)); } static inline unsigned int get_int_seg(int i) { return *(unsigned short *)(i * 4 + 2); } static inline unsigned int get_int_off(int i) { return *(unsigned short *)(i * 4); } int LRMI_common_init(void) { void *m; int fd_mem; if (!real_mem_init()) return 0; /* Map the Interrupt Vectors (0x0 - 0x400) + BIOS data (0x400 - 0x502) and the ROM (0xa0000 - 0x100000) */ fd_mem = open("/dev/mem", O_RDWR); if (fd_mem == -1) { real_mem_deinit(); perror("open /dev/mem"); return 0; } m = mmap((void *)0, 0x502, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_SHARED, fd_mem, 0); if (m == (void *)-1) { close(fd_mem); real_mem_deinit(); perror("mmap /dev/mem"); return 0; } m = mmap((void *)0xa0000, 0x100000 - 0xa0000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, fd_mem, 0xa0000); if (m == (void *)-1) { munmap((void *)0, 0x502); close(fd_mem); real_mem_deinit(); perror("mmap /dev/mem"); return 0; } close(fd_mem); return 1; } suspend-utils/vbetool/include/0000755000175500017550000000000012075743442015164 5ustar kixkixsuspend-utils/vbetool/include/regs.h0000644000175500017550000002430512075743442016301 0ustar kixkix/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation, and that the name of the authors not be used * in advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The authors makes no * representations about the suitability of this software for any purpose. * It is provided "as is" without express or implied warranty. * * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * ======================================================================== * * Language: ANSI C * Environment: Any * Developer: Kendall Bennett * * Description: Header file for x86 register definitions. * ****************************************************************************/ /* $XFree86: xc/extras/x86emu/include/x86emu/regs.h,v 1.5 2003/10/22 20:03:05 tsi Exp $ */ #ifndef __X86EMU_REGS_H #define __X86EMU_REGS_H /*---------------------- Macros and type definitions ----------------------*/ /* * General EAX, EBX, ECX, EDX type registers. Note that for * portability, and speed, the issue of byte swapping is not addressed * in the registers. All registers are stored in the default format * available on the host machine. The only critical issue is that the * registers should line up EXACTLY in the same manner as they do in * the 386. That is: * * EAX & 0xff === AL * EAX & 0xffff == AX * * etc. The result is that alot of the calculations can then be * done using the native instruction set fully. */ #ifdef __BIG_ENDIAN__ typedef struct { u32 e_reg; } I32_reg_t; typedef struct { u16 filler0, x_reg; } I16_reg_t; typedef struct { u8 filler0, filler1, h_reg, l_reg; } I8_reg_t; #else /* !__BIG_ENDIAN__ */ typedef struct { u32 e_reg; } I32_reg_t; typedef struct { u16 x_reg; } I16_reg_t; typedef struct { u8 l_reg, h_reg; } I8_reg_t; #endif /* BIG_ENDIAN */ typedef union { I32_reg_t I32_reg; I16_reg_t I16_reg; I8_reg_t I8_reg; } i386_general_register; struct i386_general_regs { i386_general_register A, B, C, D; }; typedef struct i386_general_regs Gen_reg_t; struct i386_special_regs { i386_general_register SP, BP, SI, DI, IP; u32 FLAGS; }; /* * Segment registers here represent the 16 bit quantities * CS, DS, ES, SS. */ struct i386_segment_regs { u16 CS, DS, SS, ES, FS, GS; }; /* 8 bit registers */ #define R_AH gen.A.I8_reg.h_reg #define R_AL gen.A.I8_reg.l_reg #define R_BH gen.B.I8_reg.h_reg #define R_BL gen.B.I8_reg.l_reg #define R_CH gen.C.I8_reg.h_reg #define R_CL gen.C.I8_reg.l_reg #define R_DH gen.D.I8_reg.h_reg #define R_DL gen.D.I8_reg.l_reg /* 16 bit registers */ #define R_AX gen.A.I16_reg.x_reg #define R_BX gen.B.I16_reg.x_reg #define R_CX gen.C.I16_reg.x_reg #define R_DX gen.D.I16_reg.x_reg /* 32 bit extended registers */ #define R_EAX gen.A.I32_reg.e_reg #define R_EBX gen.B.I32_reg.e_reg #define R_ECX gen.C.I32_reg.e_reg #define R_EDX gen.D.I32_reg.e_reg /* special registers */ #define R_SP spc.SP.I16_reg.x_reg #define R_BP spc.BP.I16_reg.x_reg #define R_SI spc.SI.I16_reg.x_reg #define R_DI spc.DI.I16_reg.x_reg #define R_IP spc.IP.I16_reg.x_reg #define R_FLG spc.FLAGS /* special registers */ #define R_SP spc.SP.I16_reg.x_reg #define R_BP spc.BP.I16_reg.x_reg #define R_SI spc.SI.I16_reg.x_reg #define R_DI spc.DI.I16_reg.x_reg #define R_IP spc.IP.I16_reg.x_reg #define R_FLG spc.FLAGS /* special registers */ #define R_ESP spc.SP.I32_reg.e_reg #define R_EBP spc.BP.I32_reg.e_reg #define R_ESI spc.SI.I32_reg.e_reg #define R_EDI spc.DI.I32_reg.e_reg #define R_EIP spc.IP.I32_reg.e_reg #define R_EFLG spc.FLAGS /* segment registers */ #define R_CS seg.CS #define R_DS seg.DS #define R_SS seg.SS #define R_ES seg.ES #define R_FS seg.FS #define R_GS seg.GS /* flag conditions */ #define FB_CF 0x0001 /* CARRY flag */ #define FB_PF 0x0004 /* PARITY flag */ #define FB_AF 0x0010 /* AUX flag */ #define FB_ZF 0x0040 /* ZERO flag */ #define FB_SF 0x0080 /* SIGN flag */ #define FB_TF 0x0100 /* TRAP flag */ #define FB_IF 0x0200 /* INTERRUPT ENABLE flag */ #define FB_DF 0x0400 /* DIR flag */ #define FB_OF 0x0800 /* OVERFLOW flag */ /* 80286 and above always have bit#1 set */ #define F_ALWAYS_ON (0x0002) /* flag bits always on */ /* * Define a mask for only those flag bits we will ever pass back * (via PUSHF) */ #define F_MSK (FB_CF|FB_PF|FB_AF|FB_ZF|FB_SF|FB_TF|FB_IF|FB_DF|FB_OF) /* following bits masked in to a 16bit quantity */ #define F_CF 0x0001 /* CARRY flag */ #define F_PF 0x0004 /* PARITY flag */ #define F_AF 0x0010 /* AUX flag */ #define F_ZF 0x0040 /* ZERO flag */ #define F_SF 0x0080 /* SIGN flag */ #define F_TF 0x0100 /* TRAP flag */ #define F_IF 0x0200 /* INTERRUPT ENABLE flag */ #define F_DF 0x0400 /* DIR flag */ #define F_OF 0x0800 /* OVERFLOW flag */ #define TOGGLE_FLAG(flag) (M.x86.R_FLG ^= (flag)) #define SET_FLAG(flag) (M.x86.R_FLG |= (flag)) #define CLEAR_FLAG(flag) (M.x86.R_FLG &= ~(flag)) #define ACCESS_FLAG(flag) (M.x86.R_FLG & (flag)) #define CLEARALL_FLAG(m) (M.x86.R_FLG = 0) #define CONDITIONAL_SET_FLAG(COND,FLAG) \ if (COND) SET_FLAG(FLAG); else CLEAR_FLAG(FLAG) #define F_PF_CALC 0x010000 /* PARITY flag has been calced */ #define F_ZF_CALC 0x020000 /* ZERO flag has been calced */ #define F_SF_CALC 0x040000 /* SIGN flag has been calced */ #define F_ALL_CALC 0xff0000 /* All have been calced */ /* * Emulator machine state. * Segment usage control. */ #define SYSMODE_SEG_DS_SS 0x00000001 #define SYSMODE_SEGOVR_CS 0x00000002 #define SYSMODE_SEGOVR_DS 0x00000004 #define SYSMODE_SEGOVR_ES 0x00000008 #define SYSMODE_SEGOVR_FS 0x00000010 #define SYSMODE_SEGOVR_GS 0x00000020 #define SYSMODE_SEGOVR_SS 0x00000040 #define SYSMODE_PREFIX_REPE 0x00000080 #define SYSMODE_PREFIX_REPNE 0x00000100 #define SYSMODE_PREFIX_DATA 0x00000200 #define SYSMODE_PREFIX_ADDR 0x00000400 #define SYSMODE_INTR_PENDING 0x10000000 #define SYSMODE_EXTRN_INTR 0x20000000 #define SYSMODE_HALTED 0x40000000 #define SYSMODE_SEGMASK (SYSMODE_SEG_DS_SS | \ SYSMODE_SEGOVR_CS | \ SYSMODE_SEGOVR_DS | \ SYSMODE_SEGOVR_ES | \ SYSMODE_SEGOVR_FS | \ SYSMODE_SEGOVR_GS | \ SYSMODE_SEGOVR_SS) #define SYSMODE_CLRMASK (SYSMODE_SEG_DS_SS | \ SYSMODE_SEGOVR_CS | \ SYSMODE_SEGOVR_DS | \ SYSMODE_SEGOVR_ES | \ SYSMODE_SEGOVR_FS | \ SYSMODE_SEGOVR_GS | \ SYSMODE_SEGOVR_SS | \ SYSMODE_PREFIX_DATA | \ SYSMODE_PREFIX_ADDR) #define INTR_SYNCH 0x1 #define INTR_ASYNCH 0x2 #define INTR_HALTED 0x4 typedef struct { struct i386_general_regs gen; struct i386_special_regs spc; struct i386_segment_regs seg; /* * MODE contains information on: * REPE prefix 2 bits repe,repne * SEGMENT overrides 5 bits normal,DS,SS,CS,ES * Delayed flag set 3 bits (zero, signed, parity) * reserved 6 bits * interrupt # 8 bits instruction raised interrupt * BIOS video segregs 4 bits * Interrupt Pending 1 bits * Extern interrupt 1 bits * Halted 1 bits */ u32 mode; volatile int intr; /* mask of pending interrupts */ int debug; #ifdef DEBUG int check; u16 saved_ip; u16 saved_cs; int enc_pos; int enc_str_pos; char decode_buf[32]; /* encoded byte stream */ char decoded_buf[256]; /* disassembled strings */ #endif u8 intno; u8 __pad[3]; } X86EMU_regs; /**************************************************************************** REMARKS: Structure maintaining the emulator machine state. MEMBERS: mem_base - Base real mode memory for the emulator mem_size - Size of the real mode memory block for the emulator private - private data pointer x86 - X86 registers ****************************************************************************/ typedef struct { unsigned long mem_base; unsigned long mem_size; void* private; X86EMU_regs x86; } X86EMU_sysEnv; /*----------------------------- Global Variables --------------------------*/ #ifdef __cplusplus extern "C" { /* Use "C" linkage when in C++ mode */ #endif /* Global emulator machine state. * * We keep it global to avoid pointer dereferences in the code for speed. */ extern X86EMU_sysEnv _X86EMU_env; #define M _X86EMU_env /*-------------------------- Function Prototypes --------------------------*/ /* Function to log information at runtime */ void printk(const char *fmt, ...); #ifdef __cplusplus } /* End of "C" linkage for C++ */ #endif #endif /* __X86EMU_REGS_H */ suspend-utils/vbetool/include/xf86int10.h0000644000175500017550000001473112075743442017012 0ustar kixkix/* $XFree86: xc/programs/Xserver/hw/xfree86/int10/xf86int10.h,v 1.23 2002/04/04 14:05:51 eich Exp $ */ /* * XFree86 int10 module * execute BIOS int 10h calls in x86 real mode environment * Copyright 1999 Egbert Eich */ #ifndef _XF86INT10_H #define _XF86INT10_H #define SEG_ADDR(x) (((x) >> 4) & 0x00F000) #define SEG_OFF(x) ((x) & 0x0FFFF) #define SET_BIOS_SCRATCH 0x1 #define RESTORE_BIOS_SCRATCH 0x2 #define CARD8 unsigned char #define CARD16 unsigned short #define CARD32 unsigned long #define pointer void * #define IOADDRESS void * #define Bool int #define X86_TF_MASK 0x00000100 #define X86_IF_MASK 0x00000200 #define X86_IOPL_MASK 0x00003000 #define X86_NT_MASK 0x00004000 #define X86_VM_MASK 0x00020000 #define X86_AC_MASK 0x00040000 #define X86_VIF_MASK 0x00080000 /* virtual interrupt flag */ #define X86_VIP_MASK 0x00100000 /* virtual interrupt pending */ #define X86_ID_MASK 0x00200000 /* int10 info structure */ typedef struct { int entityIndex; int scrnIndex; pointer cpuRegs; CARD16 BIOSseg; CARD16 inb40time; char * BIOSScratch; int Flags; pointer private; struct _int10Mem* mem; int num; int ax; int bx; int cx; int dx; int si; int di; int es; int bp; int flags; int stackseg; //PCITAG Tag; IOADDRESS ioBase; } xf86Int10InfoRec, *xf86Int10InfoPtr; typedef struct _int10Mem { CARD8(*rb)(xf86Int10InfoPtr, int); CARD16(*rw)(xf86Int10InfoPtr, int); CARD32(*rl)(xf86Int10InfoPtr, int); void(*wb)(xf86Int10InfoPtr, int, CARD8); void(*ww)(xf86Int10InfoPtr, int, CARD16); void(*wl)(xf86Int10InfoPtr, int, CARD32); } int10MemRec, *int10MemPtr; typedef struct { CARD8 save_msr; CARD8 save_pos102; CARD8 save_vse; CARD8 save_46e8; } legacyVGARec, *legacyVGAPtr; //typedef struct { //BusType bus; //union { //struct { //int bus; //int dev; //int func; ////} pci; //int legacy; //} location; ////} xf86int10BiosLocation, *xf86int10BiosLocationPtr; /* OS dependent functions */ xf86Int10InfoPtr xf86InitInt10(int entityIndex); xf86Int10InfoPtr xf86ExtendedInitInt10(int entityIndex, int Flags); void xf86FreeInt10(xf86Int10InfoPtr pInt); void *xf86Int10AllocPages(xf86Int10InfoPtr pInt, int num, int *off); void xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num); pointer xf86int10Addr(xf86Int10InfoPtr pInt, CARD32 addr); /* x86 executor related functions */ void xf86ExecX86int10(xf86Int10InfoPtr pInt); #ifdef _INT10_PRIVATE #define I_S_DEFAULT_INT_VECT 0xFF065 #define SYS_SIZE 0x100000 #define SYS_BIOS 0xF0000 #if 1 #define BIOS_SIZE 0x10000 #else /* a bug in DGUX requires this - let's try it */ #define BIOS_SIZE (0x10000 - 1) #endif #define LOW_PAGE_SIZE 0x600 #define V_RAM 0xA0000 #define VRAM_SIZE 0x20000 #define V_BIOS_SIZE 0x10000 #define V_BIOS 0xC0000 #define BIOS_SCRATCH_OFF 0x449 #define BIOS_SCRATCH_END 0x466 #define BIOS_SCRATCH_LEN (BIOS_SCRATCH_END - BIOS_SCRATCH_OFF + 1) #define HIGH_MEM V_BIOS #define HIGH_MEM_SIZE (SYS_BIOS - HIGH_MEM) #define SEG_ADR(type, seg, reg) type((seg << 4) + (X86_##reg)) #define SEG_EADR(type, seg, reg) type((seg << 4) + (X86_E##reg)) #define X86_TF_MASK 0x00000100 #define X86_IF_MASK 0x00000200 #define X86_IOPL_MASK 0x00003000 #define X86_NT_MASK 0x00004000 #define X86_VM_MASK 0x00020000 #define X86_AC_MASK 0x00040000 #define X86_VIF_MASK 0x00080000 /* virtual interrupt flag */ #define X86_VIP_MASK 0x00100000 /* virtual interrupt pending */ #define X86_ID_MASK 0x00200000 #define MEM_RB(name, addr) (*name->mem->rb)(name, addr) #define MEM_RW(name, addr) (*name->mem->rw)(name, addr) #define MEM_RL(name, addr) (*name->mem->rl)(name, addr) #define MEM_WB(name, addr, val) (*name->mem->wb)(name, addr, val) #define MEM_WW(addr, val) wrw(addr, val) #define MEM_WL(name, addr, val) (*name->mem->wl)(name, addr, val) /* OS dependent functions */ Bool MapCurrentInt10(xf86Int10InfoPtr pInt); /* x86 executor related functions */ Bool xf86Int10ExecSetup(xf86Int10InfoPtr pInt); /* int.c */ extern xf86Int10InfoPtr Int10Current; int int_handler(xf86Int10InfoPtr pInt); /* helper_exec.c */ int setup_int(xf86Int10InfoPtr pInt); void finish_int(xf86Int10InfoPtr, int sig); CARD32 getIntVect(xf86Int10InfoPtr pInt, int num); void pushw(CARD16 val); int run_bios_int(int num, xf86Int10InfoPtr pInt); void dump_code(xf86Int10InfoPtr pInt); void dump_registers(xf86Int10InfoPtr pInt); void stack_trace(xf86Int10InfoPtr pInt); xf86Int10InfoPtr getInt10Rec(int entityIndex); CARD8 bios_checksum(CARD8 *start, int size); void LockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga); void UnlockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga); #if defined (_PC) void xf86Int10SaveRestoreBIOSVars(xf86Int10InfoPtr pInt, Bool save); #endif int port_rep_inb(xf86Int10InfoPtr pInt, CARD16 port, CARD32 base, int d_f, CARD32 count); int port_rep_inw(xf86Int10InfoPtr pInt, CARD16 port, CARD32 base, int d_f, CARD32 count); int port_rep_inl(xf86Int10InfoPtr pInt, CARD16 port, CARD32 base, int d_f, CARD32 count); int port_rep_outb(xf86Int10InfoPtr pInt, CARD16 port, CARD32 base, int d_f, CARD32 count); int port_rep_outw(xf86Int10InfoPtr pInt, CARD16 port, CARD32 base, int d_f, CARD32 count); int port_rep_outl(xf86Int10InfoPtr pInt, CARD16 port, CARD32 base, int d_f, CARD32 count); CARD8 x_inb(CARD16 port); CARD16 x_inw(CARD16 port); void x_outb(CARD16 port, CARD8 val); void x_outw(CARD16 port, CARD16 val); CARD32 x_inl(CARD16 port); void x_outl(CARD16 port, CARD32 val); CARD8 Mem_rb(CARD32 addr); CARD16 Mem_rw(CARD32 addr); CARD32 Mem_rl(CARD32 addr); void Mem_wb(CARD32 addr, CARD8 val); void Mem_ww(CARD32 addr, CARD16 val); void Mem_wl(CARD32 addr, CARD32 val); /* helper_mem.c */ void setup_int_vect(xf86Int10InfoPtr pInt); int setup_system_bios(void *base_addr); void reset_int_vect(xf86Int10InfoPtr pInt); void set_return_trap(xf86Int10InfoPtr pInt); //void * xf86HandleInt10Options(ScrnInfoPtr pScrn, int entityIndex); Bool int10skip(void* options); Bool int10_check_bios(int scrnIndex, int codeSeg, unsigned char* vbiosMem); Bool initPrimary(void* options); //void xf86int10ParseBiosLocation(void* options, //xf86int10BiosLocationPtr bios); #ifdef DEBUG void dprint(unsigned long start, unsigned long size); #endif /* pci.c */ int mapPciRom(char *filename, unsigned char *address); #endif /* _INT10_PRIVATE */ #endif /* _XF86INT10_H */ suspend-utils/vbetool/include/xf86x86emu.h0000644000175500017550000000236712075743442017215 0ustar kixkix/* $XFree86: xc/programs/Xserver/hw/xfree86/int10/xf86x86emu.h,v 1.1 2000/01/23 04:44:35 dawes Exp $ */ /* * XFree86 int10 module * execute BIOS int 10h calls in x86 real mode environment * Copyright 1999 Egbert Eich */ #ifndef XF86X86EMU_H_ #define XF86X86EMU_H_ #include "x86emu.h" #define M _X86EMU_env #define X86_EAX M.x86.R_EAX #define X86_EBX M.x86.R_EBX #define X86_ECX M.x86.R_ECX #define X86_EDX M.x86.R_EDX #define X86_ESI M.x86.R_ESI #define X86_EDI M.x86.R_EDI #define X86_EBP M.x86.R_EBP #define X86_EIP M.x86.R_EIP #define X86_ESP M.x86.R_ESP #define X86_EFLAGS M.x86.R_EFLG #define X86_FLAGS M.x86.R_FLG #define X86_AX M.x86.R_AX #define X86_BX M.x86.R_BX #define X86_CX M.x86.R_CX #define X86_DX M.x86.R_DX #define X86_SI M.x86.R_SI #define X86_DI M.x86.R_DI #define X86_BP M.x86.R_BP #define X86_IP M.x86.R_IP #define X86_SP M.x86.R_SP #define X86_CS M.x86.R_CS #define X86_DS M.x86.R_DS #define X86_ES M.x86.R_ES #define X86_SS M.x86.R_SS #define X86_FS M.x86.R_FS #define X86_GS M.x86.R_GS #define X86_AL M.x86.R_AL #define X86_BL M.x86.R_BL #define X86_CL M.x86.R_CL #define X86_DL M.x86.R_DL #define X86_AH M.x86.R_AH #define X86_BH M.x86.R_BH #define X86_CH M.x86.R_CH #define X86_DH M.x86.R_DH #endif suspend-utils/vbetool/include/x86emu.h0000644000175500017550000001603712075743442016500 0ustar kixkix/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation, and that the name of the authors not be used * in advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The authors makes no * representations about the suitability of this software for any purpose. * It is provided "as is" without express or implied warranty. * * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * ======================================================================== * * Language: ANSI C * Environment: Any * Developer: Kendall Bennett * * Description: Header file for public specific functions. * Any application linking against us should only * include this header * ****************************************************************************/ /* $XFree86$ */ #ifndef __X86EMU_X86EMU_H #define __X86EMU_X86EMU_H #ifdef SCITECH #include "scitech.h" #define X86API _ASMAPI #define X86APIP _ASMAPIP typedef int X86EMU_pioAddr; #else #include "types.h" #define X86API #define X86APIP * #endif #include "regs.h" /*---------------------- Macros and type definitions ----------------------*/ /* #pragma pack(1) */ /* Don't pack structs with function pointers! */ /**************************************************************************** REMARKS: Data structure containing ponters to programmed I/O functions used by the emulator. This is used so that the user program can hook all programmed I/O for the emulator to handled as necessary by the user program. By default the emulator contains simple functions that do not do access the hardware in any way. To allow the emualtor access the hardware, you will need to override the programmed I/O functions using the X86EMU_setupPioFuncs function. HEADER: x86emu.h MEMBERS: inb - Function to read a byte from an I/O port inw - Function to read a word from an I/O port inl - Function to read a dword from an I/O port outb - Function to write a byte to an I/O port outw - Function to write a word to an I/O port outl - Function to write a dword to an I/O port ****************************************************************************/ typedef struct { u8 (X86APIP inb)(X86EMU_pioAddr addr); u16 (X86APIP inw)(X86EMU_pioAddr addr); u32 (X86APIP inl)(X86EMU_pioAddr addr); void (X86APIP outb)(X86EMU_pioAddr addr, u8 val); void (X86APIP outw)(X86EMU_pioAddr addr, u16 val); void (X86APIP outl)(X86EMU_pioAddr addr, u32 val); } X86EMU_pioFuncs; /**************************************************************************** REMARKS: Data structure containing ponters to memory access functions used by the emulator. This is used so that the user program can hook all memory access functions as necessary for the emulator. By default the emulator contains simple functions that only access the internal memory of the emulator. If you need specialised functions to handle access to different types of memory (ie: hardware framebuffer accesses and BIOS memory access etc), you will need to override this using the X86EMU_setupMemFuncs function. HEADER: x86emu.h MEMBERS: rdb - Function to read a byte from an address rdw - Function to read a word from an address rdl - Function to read a dword from an address wrb - Function to write a byte to an address wrw - Function to write a word to an address wrl - Function to write a dword to an address ****************************************************************************/ typedef struct { u8 (X86APIP rdb)(u32 addr); u16 (X86APIP rdw)(u32 addr); u32 (X86APIP rdl)(u32 addr); void (X86APIP wrb)(u32 addr, u8 val); void (X86APIP wrw)(u32 addr, u16 val); void (X86APIP wrl)(u32 addr, u32 val); } X86EMU_memFuncs; /**************************************************************************** Here are the default memory read and write function in case they are needed as fallbacks. ***************************************************************************/ extern u8 X86API rdb(u32 addr); extern u16 X86API rdw(u32 addr); extern u32 X86API rdl(u32 addr); extern void X86API wrb(u32 addr, u8 val); extern void X86API wrw(u32 addr, u16 val); extern void X86API wrl(u32 addr, u32 val); /* #pragma pack() */ /*--------------------- type definitions -----------------------------------*/ typedef void (X86APIP X86EMU_intrFuncs)(int num); extern X86EMU_intrFuncs _X86EMU_intrTab[256]; /*-------------------------- Function Prototypes --------------------------*/ #ifdef __cplusplus extern "C" { /* Use "C" linkage when in C++ mode */ #endif void X86EMU_setupMemFuncs(X86EMU_memFuncs *funcs); void X86EMU_setupPioFuncs(X86EMU_pioFuncs *funcs); void X86EMU_setupIntrFuncs(X86EMU_intrFuncs funcs[]); void X86EMU_prepareForInt(int num); /* decode.c */ void X86EMU_exec(void); void X86EMU_halt_sys(void); #ifdef DEBUG #define HALT_SYS() \ printk("halt_sys: file %s, line %d\n", __FILE__, __LINE__), \ X86EMU_halt_sys() #else #define HALT_SYS() X86EMU_halt_sys() #endif /* Debug options */ #define DEBUG_DECODE_F 0x000001 /* print decoded instruction */ #define DEBUG_TRACE_F 0x000002 /* dump regs before/after execution */ #define DEBUG_STEP_F 0x000004 #define DEBUG_DISASSEMBLE_F 0x000008 #define DEBUG_BREAK_F 0x000010 #define DEBUG_SVC_F 0x000020 #define DEBUG_FS_F 0x000080 #define DEBUG_PROC_F 0x000100 #define DEBUG_SYSINT_F 0x000200 /* bios system interrupts. */ #define DEBUG_TRACECALL_F 0x000400 #define DEBUG_INSTRUMENT_F 0x000800 #define DEBUG_MEM_TRACE_F 0x001000 #define DEBUG_IO_TRACE_F 0x002000 #define DEBUG_TRACECALL_REGS_F 0x004000 #define DEBUG_DECODE_NOPRINT_F 0x008000 #define DEBUG_SAVE_IP_CS_F 0x010000 #define DEBUG_SYS_F (DEBUG_SVC_F|DEBUG_FS_F|DEBUG_PROC_F) void X86EMU_trace_regs(void); void X86EMU_trace_xregs(void); void X86EMU_dump_memory(u16 seg, u16 off, u32 amt); int X86EMU_trace_on(void); int X86EMU_trace_off(void); #ifdef __cplusplus } /* End of "C" linkage for C++ */ #endif #endif /* __X86EMU_X86EMU_H */ suspend-utils/vbetool/include/lrmi.h0000644000175500017550000000477512075743442016315 0ustar kixkix/* Linux Real Mode Interface - A library of DPMI-like functions for Linux. Copyright (C) 1998 by Josh Vanderhoof Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL JOSH VANDERHOOF BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef LRMI_H #define LRMI_H struct LRMI_regs { unsigned int edi; unsigned int esi; unsigned int ebp; unsigned int reserved; unsigned int ebx; unsigned int edx; unsigned int ecx; unsigned int eax; unsigned short int flags; unsigned short int es; unsigned short int ds; unsigned short int fs; unsigned short int gs; unsigned short int ip; unsigned short int cs; unsigned short int sp; unsigned short int ss; }; #ifndef LRMI_PREFIX #define LRMI_PREFIX LRMI_ #endif #define LRMI_CONCAT2(a, b) a ## b #define LRMI_CONCAT(a, b) LRMI_CONCAT2(a, b) #define LRMI_MAKENAME(a) LRMI_CONCAT(LRMI_PREFIX, a) /* Initialize returns 1 if sucessful, 0 for failure */ #define LRMI_init LRMI_MAKENAME(init) int LRMI_init(void); /* Simulate a 16 bit far call returns 1 if sucessful, 0 for failure */ #define LRMI_call LRMI_MAKENAME(call) int LRMI_call(struct LRMI_regs *r); /* Simulate a 16 bit interrupt returns 1 if sucessful, 0 for failure */ #define LRMI_int LRMI_MAKENAME(int) int LRMI_int(int interrupt, struct LRMI_regs *r); /* Allocate real mode memory The returned block is paragraph (16 byte) aligned */ #define LRMI_alloc_real LRMI_MAKENAME(alloc_real) void * LRMI_alloc_real(int size); /* Free real mode memory */ #define LRMI_free_real LRMI_MAKENAME(free_real) void LRMI_free_real(void *m); /* * Get the base address of the real memory address space block. */ size_t LRMI_base_addr(void); #endif suspend-utils/vbetool/include/fpu_regs.h0000644000175500017550000000746712075743442017165 0ustar kixkix/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation, and that the name of the authors not be used * in advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The authors makes no * representations about the suitability of this software for any purpose. * It is provided "as is" without express or implied warranty. * * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * ======================================================================== * * Language: ANSI C * Environment: Any * Developer: Kendall Bennett * * Description: Header file for FPU register definitions. * ****************************************************************************/ /* $XFree86: xc/extras/x86emu/include/x86emu/fpu_regs.h,v 1.2 2003/10/22 20:03:05 tsi Exp $ */ #ifndef __X86EMU_FPU_REGS_H #define __X86EMU_FPU_REGS_H #ifdef X86_FPU_SUPPORT /* Basic 8087 register can hold any of the following values: */ union x86_fpu_reg_u { s8 tenbytes[10]; double dval; float fval; s16 sval; s32 lval; }; struct x86_fpu_reg { union x86_fpu_reg_u reg; char tag; }; /* * Since we are not going to worry about the problems of aliasing * registers, every time a register is modified, its result type is * set in the tag fields for that register. If some operation * attempts to access the type in a way inconsistent with its current * storage format, then we flag the operation. If common, we'll * attempt the conversion. */ #define X86_FPU_VALID 0x80 #define X86_FPU_REGTYP(r) ((r) & 0x7F) #define X86_FPU_WORD 0x0 #define X86_FPU_SHORT 0x1 #define X86_FPU_LONG 0x2 #define X86_FPU_FLOAT 0x3 #define X86_FPU_DOUBLE 0x4 #define X86_FPU_LDBL 0x5 #define X86_FPU_BSD 0x6 #define X86_FPU_STKTOP 0 struct x86_fpu_registers { struct x86_fpu_reg x86_fpu_stack[8]; int x86_fpu_flags; int x86_fpu_config; /* rounding modes, etc. */ short x86_fpu_tos, x86_fpu_bos; }; /* * There are two versions of the following macro. * * One version is for opcode D9, for which there are more than 32 * instructions encoded in the second byte of the opcode. * * The other version, deals with all the other 7 i87 opcodes, for * which there are only 32 strings needed to describe the * instructions. */ #endif /* X86_FPU_SUPPORT */ #ifdef DEBUG # define DECODE_PRINTINSTR32(t,mod,rh,rl) \ DECODE_PRINTF(t[(mod<<3)+(rh)]); # define DECODE_PRINTINSTR256(t,mod,rh,rl) \ DECODE_PRINTF(t[(mod<<6)+(rh<<3)+(rl)]); #else # define DECODE_PRINTINSTR32(t,mod,rh,rl) # define DECODE_PRINTINSTR256(t,mod,rh,rl) #endif #endif /* __X86EMU_FPU_REGS_H */ suspend-utils/vbetool/include/types.h0000644000175500017550000000635112075743442016506 0ustar kixkix/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation, and that the name of the authors not be used * in advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The authors makes no * representations about the suitability of this software for any purpose. * It is provided "as is" without express or implied warranty. * * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * ======================================================================== * * Language: ANSI C * Environment: Any * Developer: Kendall Bennett * * Description: Header file for x86 emulator type definitions. * ****************************************************************************/ /* $XFree86: xc/extras/x86emu/include/x86emu/types.h,v 1.6 2003/06/12 14:12:26 eich Exp $ */ #ifndef __X86EMU_TYPES_H #define __X86EMU_TYPES_H #ifndef IN_MODULE #include #endif /* * The following kludge is an attempt to work around typedef conflicts with * . */ #define u8 x86emuu8 #define u16 x86emuu16 #define u32 x86emuu32 #define u64 x86emuu64 #define s8 x86emus8 #define s16 x86emus16 #define s32 x86emus32 #define s64 x86emus64 #define uint x86emuuint #define sint x86emusint /*---------------------- Macros and type definitions ----------------------*/ /* Currently only for Linux/32bit */ #undef __HAS_LONG_LONG__ #if defined(__GNUC__) && !defined(NO_LONG_LONG) #define __HAS_LONG_LONG__ #endif /* Taken from Xmd.h */ #undef NUM32 #if defined (_LP64) || \ defined(__alpha) || defined(__alpha__) || \ defined(__ia64__) || defined(ia64) || \ defined(__sparc64__) || \ defined(__s390x__) || \ (defined(__hppa__) && defined(__LP64)) || \ defined(__amd64__) || defined(amd64) || \ (defined(__sgi) && (_MIPS_SZLONG == 64)) #define NUM32 int #else #define NUM32 long #endif typedef unsigned char u8; typedef unsigned short u16; typedef unsigned NUM32 u32; #ifdef __HAS_LONG_LONG__ typedef unsigned long long u64; #endif typedef char s8; typedef short s16; typedef NUM32 s32; #ifdef __HAS_LONG_LONG__ typedef long long s64; #endif typedef unsigned int uint; typedef int sint; typedef u16 X86EMU_pioAddr; #undef NUM32 #endif /* __X86EMU_TYPES_H */ suspend-utils/vbetool/COPYING0000644000175500017550000004336412075743442014606 0ustar kixkixvbetool-0.1 The lrmi.* files were written by Josh Vanderhoof. See the LRMI file and their source code for license. This package is distributed under the license below: GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program 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 2 of the License, or (at your option) any later version. This program 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 this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. suspend-utils/memalloc.h0000644000175500017550000000127412075743442014035 0ustar kixkix/* * memalloc.h * * Memory allocation definitions for user land hibernation utilities. * * Copyright (C) 2008 Rafael J. Wysocki * * This file is released under the GPLv2. * */ struct mem_slot { void *addr; size_t size; }; #define ALIGN_QWORD 8 #define BUFFER_PAGES 32 extern unsigned int page_size; /* This MUST be an multipe of page_size */ extern unsigned int buffer_size; extern void get_page_and_buffer_sizes(void); extern size_t round_up_page_size(size_t size); extern size_t round_down_page_size(size_t size); extern int init_memalloc(size_t aux, size_t pool); extern void *getmem(size_t size); extern void freemem(void *address); extern void free_memalloc(void); suspend-utils/test-s2ram0000755000175500017550000000304012075743442014013 0ustar kixkix#!/bin/bash # # Assisted s2ram testing # # Author: # Released as public domain. # touch s2ram.log || (echo "C" exit 1) # Need a read-write filesystem for logging. mount / -oremount,rw # Need swap for s2disk swapon -a # Commands are logged to "s2ram.log". Mark start of run. echo "--- Starting s2ram test run ---" >> s2ram.log # Routine to test a set of s2ram options test-s2ram() { echo "Now trying command: s2ram $@" echo echo "s2ram $@" >> s2ram.log s2ram $@ | tee -a s2ram.log || exit 1 # User: once suspended, hit power button to resume # User: if display remains blank then just wait 10 seconds, or hit return echo "If you can read this, then suspend succeeded (using the command above)." echo "Press Ctrl-C NOW - timeout in 10 seconds" read -t 10 clear echo "Assuming display failed to restore (with s2ram $@)" echo "Restoring display using s2disk" echo s2disk | tee -a s2ram.log || exit 1 # TODO - if s2disk fails? We want to reboot / shutdown - # but init is not running } test-s2ram -f test-s2ram -f -a 3 test-s2ram -f -a 2 test-s2ram -f -a 1 test-s2ram -f -p -m test-s2ram -f -p -s test-s2ram -f -m test-s2ram -f -s test-s2ram -f -p test-s2ram -f -a 1 -m test-s2ram -f -a 1 -s # Second round - try again with -v test-s2ram -f -v test-s2ram -f -v -a 3 test-s2ram -f -v -a 2 test-s2ram -f -v -a 1 test-s2ram -f -v -p -m test-s2ram -f -v -p -s test-s2ram -f -v -m test-s2ram -f -v -s test-s2ram -f -v -p test-s2ram -f -v -a 1 -m test-s2ram -f -v -a 1 -s suspend-utils/README0000644000175500017550000000754012075743442012755 0ustar kixkixUserland support for suspend ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Copyright (C) 2005 Rafael J. Wysocki Copyright (C) 2006 Pavel Machek This package contains some userland tools allowing you to suspend a Linux system either to disk or to RAM. These tools provide some capabilities that are not available in the vanilla Linux kernel. The suspend to disk can be carried out with the help of s2disk and resume utilities which use the software suspend userland interface available in the Linux kernel 2.6.17 or above. Among other things, they provide the following features: - suspend image checksumming - suspend image compression - suspend image encryption - (limited) support for splash screens and graphical progress meters that are not provided by the in-kernel software suspend code (swsusp). Please refer to the HOWTO document in this package for more information about these utilities and installation instructions. The s2ram tool allows you to suspend the system to RAM and restore the state of the graphics adapter after the resume automatically. For this purpose it uses the code out of vbetool and radeontool utilities, needed for handling quite a lot of graphics cards after the resume from RAM. The s2ram tool uses three different methods to suspend the machine: - KMS: s2ram try first suspend the machine using KMS (Kernel Mode Set) if the kernel supports it. With this method s2ram don't need extra parameters (quirks). - Whitelist: s2ram has a whitelist of machines that are known to work with it. This whitelist includes the quirks to suspend known machines. The whitelist was used prior to suspend-utils version 1.0, and now the whitelist is not updated. The database is used because has a lot of machines included and many users are using it. Please refer to the document README.s2ram-whitelist in this package for more information about the s2ram whitelist. - Configuration file: s2ram can use the configuration file to read the extra parameters (quirks). This option is useful if the kernel don't support KMS (for example, kernel compiled without support), if the machine is not included in the whitelist (for example, new machines) or if the user wants to override the quirks of the whitelist file. The flow of options is: 1. If the kernel supports KMS, then use it. This option can be overriding using the argument "-k" in s2ram (s2ram -k). 2. If the kernel don't support KMS, or the user override it, then s2ram checks if the configuration file has the parameters. If the parameters are included, s2ram use them, else, the whitelist is used. You need libx86 installed to build s2ram, the HOWTO document explains how to install it. The s2both tool combines the functionalities of s2disk and s2ram. With the help of it the system may be suspended to RAM after the suspend-to-disk image has been created instead of being powered off. Then, if there's enough battery power, you can resume from RAM and discard the saved image, or you can resume the system from disk using the resume tool otherwise However, this is only possible if your box is present in the s2ram whitelist. To build the s2ram and s2both tools you will need the pciutils-devel (pciutils-dev) package and the libx86-dev package (which you can get from http://www.codon.org.uk/~mjg59/libx86/downloads/). They are necessary to compile the vbetool code (the vbetool code is based on vbetool-1.0 from http://www.codon.org.uk/~mjg59/vbetool/). With newer pciutils (2.2.4 and above) you also have to install the zlib development package (zlib-devel on SUSE, zlib1g-dev on Debian). For debugging, see http://suspend.sf.net/s2ram-support.html. acpi-support package from Ubuntu has *very* long whitelist of machines: http://packages.ubuntu.org.cn/dapper/admin/acpi-support that are likely to work with s2ram. To compile this beast from CVS, do: ./autogen.sh ./configure make suspend-utils/conf/0000755000175500017550000000000012075743442013014 5ustar kixkixsuspend-utils/conf/suspend.conf0000644000175500017550000000031412075743442015342 0ustar kixkixsnapshot device = /dev/snapshot resume device = #image size = 350000000 #suspend loglevel = 2 #compute checksum = y #compress = y #encrypt = y #early writeout = y #splash = y suspend-utils/fbsplash_funcs.c0000644000175500017550000000732612075743442015243 0ustar kixkix/* * fbsplash.c * * fbsplash (framebuffer splash) splash method support * * Copyright (C) 2007 Alon Bar-Lev * * This file is released under the GPLv2. * */ #include "config.h" #ifdef CONFIG_FBSPLASH #include #include #include #include #include #include #include #include "swsusp.h" #include "splash.h" #include "fbsplash_funcs.h" extern char fbsplash_theme[]; static struct fbspl_theme *theme; static int was_silent; static int have_input; static int force_verbose; int fbsplashfuncs_open(int mode) { fbspl_cfg_t *cfg; int have_render = 0; int ret = 0; cfg = fbsplash_lib_init((mode==SPL_RESUME) ? fbspl_resume : fbspl_suspend); if (!cfg) { ret = -1; goto cleanup; } cfg->verbosity = FBSPL_VERB_QUIET; fbsplash_parse_kcmdline(false); if (strlen(fbsplash_theme)) fbsplash_acc_theme_set(fbsplash_theme); if (fbsplashr_init(false)) { ret = -3; goto cleanup; } have_render = 1; theme = fbsplashr_theme_load(); if (!theme) { ret = -4; goto cleanup; } was_silent = fbsplash_is_silent(); if (!was_silent) { fbsplash_set_silent(); } fbsplashr_tty_silent_init(true); fbsplashr_tty_silent_update(); fbsplashr_message_set(theme, (mode==SPL_RESUME) ? "Resuming..." : "Suspending..." ); fbsplashr_render_screen(theme, true, false, was_silent ? FBSPL_EFF_NONE : FBSPL_EFF_FADEIN); have_input = !fbsplashr_input_init(); cleanup: if (ret) { if (have_input) { fbsplashr_input_cleanup(); have_input = 0; } if (have_render) { fbsplashr_cleanup(); have_render = 0; } if (cfg) { fbsplash_lib_cleanup(); cfg = NULL; } } return ret; } int fbsplashfuncs_finish(void) { if (have_input) { fbsplashr_input_cleanup(); have_input = 0; } if (fbsplash_is_silent()) { fbsplashr_render_screen(theme, true, false, was_silent ? FBSPL_EFF_NONE : FBSPL_EFF_FADEOUT); } fbsplashr_tty_silent_cleanup(); if (!was_silent && fbsplash_is_silent()) fbsplash_set_verbose(0); fbsplashr_theme_free(theme); theme = NULL; fbsplashr_cleanup(); fbsplash_lib_cleanup(); return 0; } int fbsplashfuncs_progress(int p) { static int old = 0; if (p < old || p - old >= 10) { old = p; fbsplashr_progress_set(theme, FBSPL_PROGRESS_MAX/100*p); if (fbsplash_is_silent()) fbsplashr_render_screen(theme, true, false, FBSPL_EFF_NONE); } return 0; } void fbsplashfuncs_read_password(char *buf, int vrfy) { #if CONFIG_ENCRYPT char *pass; if (fbsplash_is_silent()) fbsplash_set_verbose(0); do { do { pass = getpass("Passphrase please (must be non-empty): "); } while (strlen(pass) == 0 || strlen(pass) >= PASS_SIZE); strcpy(buf, pass); if (vrfy) pass = getpass("Verify passphrase: "); } while (vrfy && strcmp(buf, pass)); if (!force_verbose) { fbsplash_set_silent(); fbsplashr_tty_silent_update(); } #endif } int fbsplashfuncs_dialog(const char *prompt) { int c; if (fbsplash_is_silent()) fbsplash_set_verbose(0); printf("%s", prompt); c = getchar(); if (!force_verbose) { fbsplash_set_silent(); fbsplashr_tty_silent_update(); } return c; } char fbsplashfuncs_key_pressed(void) { if (!have_input) return 0; else { char c; c = (char)fbsplashr_input_getkey(false); /* * Well... maybe someday it will work... * But currently we cannot switch to different vt */ if (c == KEY_V) { force_verbose = !force_verbose; if (force_verbose) fbsplash_set_verbose(0); else fbsplash_set_silent(); return 0; } else { return c; } } } void fbsplashfuncs_set_caption(const char *message) { fbsplashr_message_set(theme, message); if (fbsplash_is_silent()) fbsplashr_render_screen(theme, true, false, FBSPL_EFF_NONE); } #endif suspend-utils/whitelist.csv0000644000175500017550000034014312075743442014625 0ustar kixkix"4MBOL&S", "7521 *", "REV. A0", "", 0, /* Michael Wagner */ "Acer *", "AcerPower 2000", "", "", 0, /* Klaus Ade Johnstad */ "Acer ", "AO532h ", "V1.25", "V1.25", 0, /* Tomáš Kaluža */ "Acer ", "AO751h ", "Not Applicable", "V0.32*", 0, /* Jan 29, 2010 - Luca Rei */ "Acer", "AOA110", "", "", 0, /* Jan Matuska , Aspire One 110 */ "Acer", "AOA150", "", "", 0, /* Matt Harlum Aspire One 150 + Dec 29, 2009 - Scott Lees */ "Acer *", "Aspire 1500 *", "", "", VBE_POST|VBE_SAVE, /* Simon Bachmann works with proprietary ATI driver */ "Acer", "Aspire 1520", "", "", VBE_POST|VBE_MODE, /* Andreas Wagner */ "Acer ", "Aspire 1551 ", "V1.11 ", "V1.11 ", S3_BIOS|VBE_SAVE, /* Mario J. Borgnia */ "Acer ", "Aspire 1620 ", "0100 ", "V1.05 ", 0, /* Acer Aspire 1620, Sascha Warner */ "Acer *", "Aspire 1670 ", "", "", S3_BIOS|S3_MODE, /* Stefano Sabatini https://bugzilla.novell.com/show_bug.cgi?id=415675 */ "Acer", "Aspire 1810TZ", "v0.3115", "v0.3115", 0, /* Acer 1810TZ, tom */ "Acer", "Aspire 2000*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Acer *", "Aspire 2920 *", "", "", 0, /* Eberhard Niendorf , kernel 2.6.25.9 */ "Acer *", "Aspire 3100 *", "", "", 0, /* Marek Stopka (M4r3k) */ "Acer", "Aspire 3610", "", "", S3_BIOS|S3_MODE, /* From: Bontemps Camille */ "Acer", "Aspire 3620", "", "", S3_BIOS|S3_MODE, /* From: Saul Mena Avila */ "Acer ", "Aspire 3690 *", "", "", S3_BIOS|S3_MODE, /* From: Witmaster */ "Acer", "Aspire 4810T", "", "", 0, /* Martin Luethi, luethi@vaw.baug.ethz.ch + Mar 21, 2010 - Theo Band */ "Acer", "Aspire 4820T", "V1.17", "V1.17", 0, /* Oct 29, 2010 - Deepak Nayak */ "Acer", "Aspire 5020", "", "", VBE_POST, /* Carlos Corbacho */ "Acer *", "Aspire 5100 *", "", "", VBE_SAVE|PCI_SAVE|S3_MODE, /* Fadain Tariq reported S3_BIOS|S3_MODE, but for Donald Curtis only VBE_* works... NEW: Jun 23, 2010 - Max Sydorenko , KMS shoud be disabled */ "Acer *", "Aspire 5110 *", "", "", VBE_POST|VBE_MODE, /* Damyan Ivanov */ "Acer ", "Aspire 5500Z *", "", "", 0, /* Paul Kretek */ "Acer ", "Aspire 5610Z *", "", "", S3_BIOS|S3_MODE, /* Vadim Dashkevich */ "Acer *", "Aspire 5630 *", "", "", S3_BIOS|S3_MODE, /* Andrey Popov */ "Acer *", "Aspire 5670 *", "", "v1.3219", RADEON_OFF, /* Eduardo Bach */ "Acer ", "Aspire 5730 ", "0100 ", "V1.07 ", 0, /* Acer Aspire 5730Z, Will Donnelly */ "Acer", "Aspire One 753", "V1.11", "V1.11", 0, /* Vladimir Zapolskiy */ "Acer", "Extensa 2900", "", "", VBE_POST|VBE_MODE, /* Christine Upadek <5upadek@informatik.uni-hamburg.de> */ "Acer", "Extensa 3000 *", "", "", S3_BIOS|S3_MODE, /* Paolo Herms */ "Acer ", "Extensa 4150 *", "", "", S3_BIOS|S3_MODE, /* seife */ "Acer ", "Extensa 5620 *", "", "", S3_BIOS|S3_MODE, /* Xavier Douville */ "Acer ", "Extensa 6220 *", "", "", S3_BIOS, /* Libor Plucnar */ "Acer,Inc.", "Aspire 1350", "", "", VBE_POST|VBE_MODE|NOFB, /* Felix Rommel, https://bugzilla.novell.com/show_bug.cgi?id=228572 */ "Acer, inc.", "Aspire 1640 ", "", "", VBE_SAVE, /* Giorgio Lando */ "Acer, inc.", "Aspire 1650 ", "", "", VBE_POST|VBE_MODE, /* Stefano Costa */ "Acer, inc.", "Aspire 1690 ", "", "", VBE_POST|VBE_SAVE, /* */ "Acer, inc.", "Aspire 3000 *", "", "", VBE_POST|VBE_MODE, /* Ricardo Garcia */ "Acer, inc.", "Aspire 4520 *", "", "", 0, /* */ "Acer, inc.", "Aspire 5050 *", "", "", S3_BIOS, /* Jim Hague */ "Acer, inc.", "Aspire 5570 *", "", "", VBE_POST|VBE_MODE, /* From: "cj.yap" */ "Acer, inc.", "Aspire 5580 *", "", "", 0, /* , probably only with nvidia driver :-( */ "Acer, inc.", "Aspire 5920G *", "", "", 0, /* Adrian Levi . S3_BIOS reported by: Jun 29, 2010 - morpheus . No flags: Feb 10, 2010 - Juraj Misur */ "Acer, inc.", "Aspire 5920 *", "", "", VBE_POST|VBE_MODE, /* Ronny Dahl */ "Acer, inc.", "Ferrari 1000 ", "", "", VBE_POST|VBE_SAVE, /* Hannes Reinecke https://bugzilla.novell.com/show_bug.cgi?id=354728 */ "Acer, inc.", "Ferrari 4000 ", "", "", VBE_POST|VBE_SAVE|NOFB, /* */ "Acer, inc.", "Ferrari 5000 ", "", "", VBE_POST|VBE_MODE, /* Russ Dill * does not work with fglrx, trenn@suse.de */ "Acer, inc.", "TravelMate 2310 ", "", "", VBE_POST|VBE_MODE, /* Quentin Denis */ "Acer, inc.", "TravelMate 3000 ", "", "", VBE_POST|VBE_SAVE, /* */ "Acer, inc.", "TravelMate 3010 ", "", "", VBE_POST|VBE_MODE, /* Norbert Preining , kernel 2.6.23-rc2++ needed */ "Acer, inc.", "TravelMate 3020 ", "", "", VBE_POST|VBE_MODE, /* Momsen Reincke */ "Acer, inc.", "TravelMate 3260 ", "", "", VBE_POST|VBE_MODE, /* Rohan Dhruva */ "Acer, inc.", "TravelMate 4100 ", "", "", VBE_POST|VBE_SAVE, /* From: LucaB */ "Acer, inc.", "TravelMate 6291 ", "", "", VBE_POST|VBE_MODE, /* Paul Korossy */ "Acer, inc.", "TravelMate 8100*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Acer, inc.", "TravelMate C200 ", "", "", 0, /* Sven Foerster */ "Acer, inc.", "Xspire 1650 *", "", "", 0, /* decoder */ "Acer", "TravelMate 2300", "", "", VBE_POST|VBE_MODE, /* Arkadiusz Miskiewicz */ "Acer ", "TravelMate 230 ", "", "", S3_BIOS|S3_MODE, /* Sridar Dhandapani */ "Acer", "TravelMate 2350 *", "", "", S3_BIOS|S3_MODE, /* Arjan Oosting */ "Acer ", "TravelMate 240 ", "", "", VBE_POST|VBE_SAVE, /* */ "Acer", "TravelMate 2410", "", "", S3_BIOS|S3_MODE, /* jan sekal */ "Acer", "TravelMate 2420", "", "", S3_BIOS|S3_MODE, /* Peter Stolz */ "Acer ", "TravelMate 2450 ", "", "", 0, /* Erki Ferenc */ "Acer ", "TravelMate 2490 ", "", "", S3_BIOS|S3_MODE, /* Vit Cepela */ "Acer ", "TravelMate 3220 *", "", "", S3_BIOS|S3_MODE, /* */ "Acer", "TravelMate 4000", "", "", S3_BIOS|S3_MODE, /* Andreas Juch */ "Acer", "TravelMate 4400", "", "", 0, /* gebu@seznam.cz */ "Acer ", "TravelMate 4650 *", "", "", S3_BIOS|S3_MODE, /* */ "Acer *", "TravelMate 5320 *", "", "", S3_BIOS|S3_MODE, /* Adrian C. */ "Acer ", "TravelMate 630 ", "", "", S3_BIOS|S3_MODE, /* TravelMate 630Lci Tim Dijkstra */ "Acer", "TravelMate 6492", "", "", 0, /* Hubert Lepicki */ "Acer", "TravelMate 650", "", "", VBE_POST|VBE_SAVE, /* Norbert Preining */ "Acer", "TravelMate 660*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Acer", "TravelMate 7520", "", "", S3_BIOS, /* */ "Acer", "TravelMate 800", "", "", VBE_POST, /* Martin Sack, this one may be NOFB, to be verified */ "Acer ", "TravelMate C300", "", "", VBE_SAVE, /* */ "Acer ", "TravelMate C310 ", "0100 ", "V1.08 ", 0, /* Mar 15, 2010 - Robert Jason Meerman */ "American Megatrends Inc.", "Uknown", "1.0", "P2.00", 0, /* AMI :-), Mario Maas */ "AnabelleB", "Claro TW7M", "", "", S3_BIOS|S3_MODE, /* Ian ASI Claro TW7M Notebook */ "Apple Computer, Inc.", "MacBook1,1", "", "", VBE_POST|VBE_MODE, /* Alexander Wirt reported "VBE_SAVE", but Penny Leach needs VBE_POST|VBE_MODE */ "Apple Computer, Inc.", "MacBook2,1", "", "", VBE_POST, /* Marvin Stark */ "Apple Computer, Inc.", "MacBookPro2,2", "", "", VBE_MODE, /* Brian Kroth , newer BIOS does not like VBE_POST?, (sys_ver:" MBP22.88Z.00A5.B00.0610192105", VBE_POST|VBE_MODE, Julien BLACHE jb@jblache.org) */ "Apple Inc.", "MacBook2,1", "1.0", "", 0, /* Mildred , needs VBE_SAVE from console, but that slows resuming */ "Apple Inc.", "MacBook3,1", "1.0", "", 0, /* Kernel 2.6.26-rc9, probably with i910 */ "Apple Inc.", "MacBookPro4,1", "", "", 0, /* Tilman Vogel , only works from X */ "Apple Inc.", "MacBookPro5,1", "1.0", " MBP51.88Z.007E.B00.0902031928", 0, /* Giovanni Toraldo , no flags tested */ "Apple Inc.", "MacBookPro5,5", "1.0", " MBP55.88Z.00AC.B03.0906151708", 0, /* Macbook 5,5, Giorgio */ "Apple Inc.", "MacBookPro6,2", "1.0", " MBP61.88Z.0057.B0A.1005121001", 0, /* Aug 18, 2010 - Michel Bauer (nvidia propietary driver */ "", "", "", "ASUS A7V600 ACPI BIOS Revision *", S3_BIOS|S3_MODE, /* ASUS a7v600 motherboard, has no usable sys_* entries besides bios_version :-( reported by James Spencer */ "", "", "", "ASUS A7V8X-X ACPI BIOS Revision *", VBE_POST|VBE_MODE, /* Gabriel */ "", "", "", "ASUS A7V ACPI BIOS Revision *", 0, /* ASUS A7V Mainboard, Michael Klein */ "", "", "", "ASUS M2A-VM ACPI BIOS Revision *", VBE_POST|VBE_MODE, /* Tristan Hoffmann Newer bios revisions (1705) seem to need VBE_POST, bios_ver: "ASUS M2A-VM ACPI BIOS Revision 1101", S3_BIOS|VBE_MODE, Andreas Bolsch , Lajos Bor�czki reports S3_BIOS|S3_MODE because -f fails on console */ "", "", "", "ASUS M2A-VM HDMI ACPI BIOS Revision 1603", VBE_POST|VBE_MODE, /* Jan Schaefer */ "", "", "", "ASUS M2N32-SLI DELUXE ACPI BIOS Revision 1101", VBE_POST|VBE_MODE, /* */ "", "", "", "ASUS M2N32-SLI DELUXE ACPI BIOS Revision 1201", VBE_POST|VBE_MODE, /* another ASUS Mainboard, reported by mailinglist@prodigy7.de */ "", "", "", "ASUS M2N-E ACPI BIOS Revision *", 0, /* ASUS M2N-E motherboars, not much usable in DMI :-( reported by Ingo */ "", "", "", "ASUS Striker ACPI BIOS Revision *", 0, /* another ASUS Mainboard, RidewithStyle */ "ASUSTEK ", "A2H/L ", "", "", 0, /* Cristian Rigamonti */ "ASUSTeK Computer INC.", "1000H", "", "", 0, /* Daniel Willkomm EEE 1000H */ "ASUSTeK Computer INC.", "1002HA", "x.x", "0802 ", 0, /* ASUS Eeepc 1002HA, Miguel Figueiredo */ "ASUSTeK Computer INC.", "1005HA", "x.x", "", 0, /* ASUS Eeepc 1005HA, Raphael Scholer (bios_version="0703 ", J�r�me H�nin , (bios_version="0505 ") */ "ASUSTeK Computer INC.", "1005PR", "x.x", "0201 ", S3_BIOS|S3_MODE, /* James Dewar */ "ASUSTeK Computer INC.", "1015PE", "x.x", "0601 ", S3_BIOS, /* Oct 5, 2010 - Brandon Kase */ "ASUSTeK Computer INC.", "1201T", "x.x", "0317 ", 0, /* Jul 2, 2010 - Brian Harkness */ "ASUSTeK Computer INC.", "701", "", "", VBE_POST|VBE_MODE, /* Andrea Zucchelli EEE-PC 4G */ "ASUSTeK Computer INC.", "900", "0704", "0802*", 0, /* Jul 3, 2010 - */ "ASUSTeK Computer INC.", "900A", "x.x", "0403 ", 0, /* Apr 10, 2010 - Bernhard M. Wiedemann */ "ASUSTeK Computer Inc.", "A2D ", "", "", S3_BIOS|S3_MODE, /* From: Julien Puydt */ "ASUSTeK Computer Inc. ", "A3N ", "1.0 ", "0215 ", S3_BIOS, /* Asus A3N, Stephan Schaller */ "ASUSTeK Computer Inc.*", "A6G ", "", "", 0, /* Thomas Thrainer */ "ASUSTeK Computer Inc. ", "A6JC *", "", "", 0, /* Piotr Drozdek */ "ASUSTeK Computer Inc. ", "A6J *", "", "", VBE_POST|VBE_MODE, /* Arnout Boelens */ "ASUSTeK Computer Inc. ", "A6K *", "", "", 0, /* Tom Gruben , maybe only with nvidia? */ "ASUSTeK Computer Inc. ", "A6Km ", "", "", 0, /* Patryk Zawadzki */ "ASUSTeK Computer Inc. ", "A6Kt ", "", "", S3_BIOS|S3_MODE, /* Tom Malfrere */ "ASUSTeK Computer Inc. ", "A6M", "", "", VBE_POST, /* Szalai Akos */ "ASUSTeK Computer INC. ", "A6T", "", "", 0, /* Anthony Mahe */ "ASUSTeK Computer Inc. ", "A6U ", "", "", VBE_POST|VBE_MODE, /* tias@ulyssis.org */ "ASUSTeK Computer INC. ", "A6VA ", "", "", 0, /* Daniel Bumke */ "ASUSTeK Computer Inc. ", "A8He *", "", "", S3_BIOS|S3_MODE, /* Alex Myltsev */ "ASUSTeK Computer Inc. ", "A8JS *", "", "", 0, /* Oliver Moessinger */ "ASUSTeK Computer Inc. ", "F2J *", "", "", S3_BIOS, /* Arkadiusz Miskiewicz */ "ASUSTeK Computer Inc. ", "F3F *", "", "", 0, /* Julien Puydt works from console and with nvidia driver, S3_BIOS|S3_MODE (q0mw3fk02@sneakemail.com) */ "ASUSTeK Computer Inc. ", "F3JC *", "", "", S3_BIOS|S3_MODE, /* Daniel Kinzler */ "ASUSTeK Computer Inc. ", "F3JP *", "", "", VBE_POST|VBE_MODE, /* Marco Jorge */ "ASUSTeK Computer Inc. ", "F3Ka *", "", "", VBE_POST|VBE_SAVE|NOFB, /* Oliver Neukum, only works without FB, https://bugzilla.novell.com/show_bug.cgi?id=425071 */ "ASUSTeK Computer INC. *", "F3Sg *", "", "", 0, /* Anghinolfi Luca */ "ASUSTeK Computer INC. ", "F3T", "", "", 0, /* Vladimir Pouzanov , probably only with nvidia and from X */ "ASUSTeK Computer Inc. ", "F80L ", "1.0 ", "204 ", VBE_POST, /* Asus F80L laptop, Manuel P�gouri�-Gonnard */ "ASUSTeK Computer Inc. *", "F9E *", "", "", 0, /* Enrico Zini */ "ASUSTeK Computer Inc. *", "G1S *", "", "", 0, /* Paul Cousins */ "ASUSTek Computer Inc.", "K8N-E-Deluxe", "", "", S3_BIOS, /* ASUS Mainboard, Christoph Jaeschke */ "ASUSTeK Computer Inc.", "K8V-MX", "", "", 0, /* Asus Mainboard, Ian McAnena */ "ASUSTeK Computer Inc.", "L7000G series Notebook PC*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "ASUSTeK Computer Inc. ", "M2N ", "", "", S3_BIOS|S3_MODE, /* Guenther Schwarz */ "ASUSTeK Computer Inc. ", "M3N ", "", "", VBE_POST|VBE_SAVE, /* Peter Suetterlin , VBE_MODE does not work */ "ASUSTeK Computer Inc. ", "M51Sr *", "", "", S3_MODE, /* Galeffi Christian gallochri2@alice.it */ "ASUSTeK Computer Inc. ", "M5N ", "", "", S3_BIOS|S3_MODE, /* Charles de Miramon */ "ASUSTeK Computer Inc. ", "M6Ne ", "", "", S3_MODE, /* */ "ASUSTeK Computer Inc. ", "M6N ", "", "", S3_BIOS|S3_MODE, /* Manfred Tremmel, https://bugzilla.novell.com/show_bug.cgi?id=171107 */ "ASUSTeK Computer Inc. ", "M6VA ", "", "", S3_BIOS|S3_MODE, /* M6VA, seraphim@glockenbach.net */ "ASUSTeK Computer Inc. ", "M7A ", "", "", S3_BIOS|S3_MODE, /* M7N, Xavier Douville */ "ASUSTeK Computer Inc. ", "N50Vc ", "1.0 ", "211 ", 0, /* Mar 4, 2010 - Igor Ternovsky */ "ASUSTeK Computer Inc. ", "S5N ", "", "", S3_BIOS|S3_MODE, /* ASUS S5200N Philip Frei */ "ASUSTeK Computer Inc. ", "U3S *", "", "", VBE_POST|VBE_SAVE, /* Tobias Rothe */ "ASUSTeK Computer Inc. ", "U5F *", "", "", S3_BIOS, /* ASUS U5F, Krzysztof Krzyzaniak */ "ASUSTeK Computer Inc. ", "UL30A ", "1.0 ", "206 ", S3_MODE, /* Oct 20, 2010 - Simon Hafner */ "ASUSTeK Computer Inc. ", "UL30A ", "1.0 ", "212 ", 0, /* Apr 22, 2010 - Florian Ragwitz */ "ASUSTeK Computer Inc. ", "V1J *", "", "", VBE_POST|VBE_MODE|NOFB, /* Szymon Olko */ "ASUSTeK Computer INC.", "V6V", "", "", S3_MODE, /* ASUS V6V, Johannes Engel */ "ASUSTeK Computer INC.", "W3A", "", "", S3_BIOS|S3_MODE, /* Kanru Chen */ "ASUSTeK Computer Inc. ", "W5A ", "", "", S3_BIOS|S3_MODE, /* ASUS W5A, Riccardo Sama' */ "ASUSTeK Computer Inc.", "W5A*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "ASUSTeK Computer Inc.", "W7J *", "", "", VBE_MODE, /* ASUS W7J, https://bugzilla.novell.com/show_bug.cgi?id=351661 */ "ASUSTeK Computer Inc. ", "W7Sg ", "1.0 ", "309 ", 0, /* Mar 11, 2010 - 易松林 */ "ASUSTeK Computer Inc.", "X51RL *", "", "", VBE_POST|VBE_SAVE, /* Bernhard M. Wiedemann , works with radeon and fglrx */ "ASUSTeK Computer Inc. ", "Z35FM *", "", "", S3_BIOS|PCI_SAVE, /* ASUS Z35Fm, Francois Marier */ "ASUSTEK ", "L2000D", "", "", S3_MODE, /* */ "ASUSTEK ", "L3000D", "", "", VBE_POST|VBE_SAVE, /* */ "ASUSTEK ", "M2000E", "", "", S3_BIOS, /* Carl Troein */ "AVERATEC", "1000 Series", "", "", S3_BIOS|S3_MODE, /* Ross Patterson */ "AVERATEC", "3700 Series", "", "", S3_BIOS|S3_MODE, /* Mark Stillwell */ "AVERATEC", "5500 Series", "", "", S3_MODE, /* Joel Dare */ "BENQ", "JoyBook 7000", "GRASSHOPPER2", "", S3_BIOS|S3_MODE, /* Sebastian Maus */ "BenQ ", "Joybook R22", "", "", S3_BIOS|S3_MODE, /* Andreas Schmitz */ "BenQ", "Joybook S32", "", "", VBE_POST|VBE_MODE, /* Miroslav Hruz */ "BenQ", "Joybook S52", "", "", VBE_POST|VBE_MODE, /* Paul Duncan */ "BIOSTAR Group", "N61PB-M2S", " ", "6.00 PG", 0, /* Apr 6, 2010 - John Rusnak */ "BIOSTAR Group", "TA780G M2+", "6.0", "080014 ", 0, /* Feb 11, 2010 - Gernot Schilling */ "CLEVO CO. ", "M570TU ", "Not Applicable ", "1.00.10", 0, /* Noah Romer */ "CLEVO CO. ", "M860TU ", "Not Applicable", "1.00.06", 0, /* Roel van den Berg */ "CLEVO CO.", "TN120R", "", "", 0, /* Alexandre Viard */ "CLEVO CO. ", "W760T/M740T/M760T ", "Not Applicable", "1.00.03", 0, /* John K Pate */ "CLEVO", "D500P", "", "", VBE_POST|NOFB, /* Gilles Grandou */ "CLEVO ", "M5X0JE ", "", "", S3_BIOS, /* Francisco Neto */ "COMPAL", "HEL80C ", "", "", 0, /* Justin Lewis */ "COMPAL ", "HEL80I ", "", "", 0, /* Leszek Kubik */ "COMPAL *", "HEL81I *", "", "", 0, /* Jason Clinton */ "Compaq", "Armada ", "", "1.35", 0, /* This Armada m300, reported by benoit.monin@laposte.net seems not to have a useful model description, so to make sure i also added the bios_version */ "Compaq", "Armada E500 *", "", "", 0, /* seife has some of those */ "Compaq", "Armada M700 *", "", "", 0, /* */ "Compaq", "Armada M70 *", "", "", 0, /* Rod Schafter rschaffter@comcast.net */ "Compaq", "Evo D510 USDT", "", "", 0, /* Martin Heimes */ "Compaq", "Evo N400c *", "", "", 0, /* Viktor Placek */ "Compaq ", "Evo N800w *", "", "", S3_BIOS|S3_MODE|VBE_POST|VBE_MODE, /* Joel Schaerer has a later BIOS and needs different Options :-/ sys_ver:"F.05", VBE_POST|VBE_SAVE, Chris AtLee , VBE_MODE does not work, text size changes. */ "Compaq*", "N620c *", "", "", S3_BIOS|S3_MODE, /* */ "Compaq", "Presario 2701EA *", "", "", VBE_POST|VBE_SAVE|NOFB, /* Paolo Saggese */ "Dell Computer Corp.", "Latitude LS ", "", "", 0, /* Ed Barrett */ "Dell Computer Corp.", "Latitude X200", "", "", VBE_POST|VBE_SAVE, /* Alain Prignet */ "Dell Computer Corporation", "Dimension 2400 *", "", "", VBE_POST|VBE_MODE, /* Michael Witten mfwitten@MIT.EDU */ "Dell Computer Corporation", "Dimension 3000 *", "", "", VBE_POST|VBE_MODE, /* Allen , Desktop with onboard grephics */ "Dell Computer Corporation", "Inspiron 1100 *", "", "", VBE_POST|VBE_MODE, /* Eitan Mosenkis */ "Dell Computer Corporation", "Inspiron 1150*", "", "", 0, /* From bug 1544913@sf.net, Andrei - amaces */ "Dell Computer Corporation", "Inspiron 1200*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Computer Corporation", "Inspiron 500m*", "", "", VBE_POST|VBE_MODE, /* Dell Inspiron 500m, Georg Zumstrull */ "Dell Computer Corporation", "Inspiron 5100 *", "", "", NOFB, /* Eric Sandall */ "Dell Computer Corporation", "Inspiron 5100", "Revision A0", "", VBE_SAVE|VBE_MODE|PCI_SAVE, /* Another Inspiron 5100, Tony Ernst */ "Dell Computer Corporation", "Inspiron 5150*", "", "", VBE_SAVE, /* VBE_POST|VBE_SAVE works on text console, but not under X. Tested by Chirag Rajyaguru */ "Dell Computer Corporation", "Inspiron 5160*", "", "", VBE_POST|VBE_MODE, /* Felipe Alvarez https://bugzilla.novell.com/show_bug.cgi?id=364429 */ "Dell Computer Corporation", "Inspiron 6000*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Computer Corporation", "Inspiron 600m *", "", "", VBE_POST|VBE_MODE, /* Dell Inspiron 600m, Gavrie Philipson */ "Dell Computer Corporation", "Inspiron 700m*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Computer Corporation", "Inspiron 8000 *", "", "", VBE_POST|VBE_SAVE, /* */ "Dell Computer Corporation", "Inspiron 8100*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Computer Corporation", "Inspiron 8200*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Computer Corporation", "Inspiron 8500 *", "", "", VBE_POST|VBE_SAVE, /* by Henare Degan 8500 w. NVidia card. There are also 8500s w. ATI cards */ "Dell Computer Corporation", "Inspiron 8600*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Computer Corporation", "Inspiron 9300*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Computer Corporation", "Latitude 110L*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Computer Corporation", "Latitude C400 *", "", "", VBE_POST|VBE_SAVE, /* Bernie du Breuil */ "Dell Computer Corporation", "Latitude C600 *", "", "", RADEON_OFF, /* */ "Dell Computer Corporation", "Latitude C610 *", "", "", VBE_POST|VBE_MODE, /* */ "Dell Computer Corporation", "Latitude C840 *", "", "", VBE_POST|VBE_SAVE, /* Tom Lear */ "Dell Computer Corporation", "Latitude CPx J650GT*", "", "", 0, /* Manuel Jander */ "Dell Computer Corporation", "Latitude CPx J800GT*", "", "", VBE_POST|VBE_MODE, /* Luke Myers */ "Dell Computer Corporation", "Latitude D400 *", "", "", VBE_POST|VBE_MODE, /* https://bugzilla.novell.com/show_bug.cgi?id=366460 */ "Dell Computer Corporation", "Latitude D410*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Computer Corporation", "Latitude D500 *", "", "", VBE_POST|VBE_SAVE, /* Roland Hagemann */ "Dell Computer Corporation", "Latitude D510*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Computer Corporation", "Latitude D600 *", "", "", VBE_POST|VBE_SAVE|NOFB, /* */ "Dell Computer Corporation", "Latitude D800 *", "", "", VBE_POST|VBE_SAVE, /* */ "Dell Computer Corporation", "Latitude D810*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Computer Corporation", "Latitude X1*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Computer Corporation", "Latitude X300*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Computer Corporation", "OptiPlex 170L *", "", "", 0, /* Seppe Hoogzaad */ "Dell Computer Corporation", "OptiPlex GX260 *", "", "", VBE_POST|VBE_MODE, /* Ian McAnena , zhengdao@iastate.edu */ "Dell Computer Corporation", "OptiPlex GX270 ", "", "A07", VBE_POST|VBE_MODE, /* Aug 28, 2010 - Klaviersegler */ "Dell Computer Corporation", "Precision M20*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Computer Corporation", "Precision M60*", "", "", VBE_SAVE, /* Per Øyvind Karlsen VBE_POST will get console working, but break X */ "Dell Computer Corporation", "Precision WorkStation 360*", "", "", 0, /* Christoph Pacher , maybe only with nvidia driver :-( */ "Dell Inc. *", "Dell DM061 *", "", "", 0, /* Richard Osborne , Dimension E520 */ "Dell Inc. ", "Dell DXP051 *", "", "", 0, /* Struan Bartlett */ "Dell Inc. *", "Dimension 9100 *", "", "", VBE_POST|VBE_MODE, /* Edward Webb https://bugzilla.novell.com/show_bug.cgi?id=428181 */ "Dell Inc.", "Inspiron 1010 ", "A09", "A09", VBE_POST|VBE_SAVE, /* Dell Inspiron 1010, Alfredo Rezinovsky */ "Dell Inc.", "Inspiron 1011", "A06", "A06", 0, /* Alex Palecek + May 23, 2010 - Graeme Roberts */ "Dell Inc.", "Inspiron 1120 ", "A03", "A03", 0, /* Jamie Kitson */ "Dell Inc.", "Inspiron 1200*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Inc.", "Inspiron 1420 *", "", "", VBE_POST|VBE_MODE, /* joey */ "Dell Inc.", "Inspiron 1501 ", "", "", S3_BIOS|S3_MODE, /* Dell Inspiron 1501, https://bugzilla.novell.com/show_bug.cgi?id=304281 */ "Dell Inc.", "Inspiron 1520 *", "", "", 0, /* Sebastian Rittau */ "Dell Inc.", "Inspiron 1525 *", "", "", VBE_SAVE, /* Horvath Andras / Log69.com previously Klaus Thoennissen (VBE_POST|VBE_MODE) */ "Dell Inc.", "Inspiron 1720 *", "", "", 0, /* Christophe Gay , maybe only with binary only driver */ "Dell Inc.", "Inspiron 510m *", "", "", VBE_POST, /* Dell Inspiron 510m, Jose Carlos Garcia Sogo */ "Dell Inc.", "Inspiron 531", "00", "1.0.13", VBE_POST|VBE_MODE, /* Rob OpenSuSE */ "Dell Inc.", "Inspiron 6000*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Inc.", "Inspiron 700m*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Inc.", "Inspiron 8100*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Inc.", "Inspiron 8200*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Inc.", "Inspiron 8600*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Inc.", "Inspiron 9300*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Inc.", "Inspiron N5010", "A08", "A08", 0, /* Adams Micsku */ "Dell Inc.", "Latitude 110L*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Inc.", "Latitude D410 *", "", "", VBE_POST|VBE_MODE, /* https://bugzilla.novell.com/show_bug.cgi?id=220865 */ "Dell Inc.", "Latitude D420 *", "", "", VBE_POST|VBE_MODE, /* tested by seife and Nenad ANTONIC */ "Dell Inc.", "Latitude D430 *", "", "", VBE_POST|VBE_MODE, /* Benoit Gschwind */ "Dell Inc.", "Latitude D505 *", "", "", VBE_POST|VBE_SAVE, /* Ian Samule, https://bugzilla.novell.com/show_bug.cgi?id=175568 */ "Dell Inc.", "Latitude D510*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Inc.", "Latitude D520 *", "", "", VBE_POST|VBE_MODE, /* tested by seife */ "Dell Inc.", "Latitude D530 *", "", "", VBE_POST|VBE_MODE, /* Jim */ "Dell Inc.", "Latitude D610 *", "", "", VBE_POST|VBE_SAVE|NOFB, /* */ "Dell Inc.", "Latitude D620 *", "", "", VBE_POST|VBE_MODE, /* D620 reported by Miroslav Ruda , */ "Dell Inc.", "Latitude D630 *", "", "", VBE_POST|VBE_MODE, /* D630 Ian Bezanson and tested by seife */ "Dell Inc.", "Latitude D810*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Inc.", "Latitude D820 *", "", "", VBE_POST|VBE_MODE, /* Johannes Engel */ "Dell Inc.", "Latitude D830 *", "", "", VBE_POST|VBE_MODE, /* Gabriel Ambuehl , version with intel graphics */ "Dell Inc.", "Latitude E4200 ", "", "A16", 0, /* Nov 24, 2010 - */ "Dell Inc.", "Latitude E4300 ", "", "", 0, /* Dell Latitude E4300, Nicolas Estibals & Frank Ploss */ "Dell Inc.", "Latitude E5400", "", "A15", 0, /* Jul 9, 2010 - João Santiago */ "Dell Inc.", "Latitude E5510", "0001", "A04", 0, /* Sep 19, 2010 - TOOTAI */ "Dell Inc.", "Latitude E6400 ", "", "A15", 0, /* Feb 9, 2010 - Krzysztof SOCHA */ "Dell Inc.", "Latitude E6400 ", "", "A20", 0, /* Apr 25, 2010 - George B. */ "Dell Inc.", "Latitude E6500 ", "", "A23", 0, /* Martin Jungmann <74258byme@gmx.de> */ "Dell Inc.", "Latitude X1*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Inc.", "Latitude X300*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Inc.", "ME051 *", "", "", 0, /* Dell inspiron 1300, Tim Dijkstra */ "Dell Inc.", "MM061 *", "", "", VBE_POST|VBE_MODE, /* Dell e1505, Alexander Antoniades / Inspiron 6400, James Cherryh */ "Dell Inc.", "MP061 *", "", "", 0, /* Dell Inspiron E1702, Julian Krause */ "Dell Inc.", "MP061", "", "", 0, /* Dell Inspiron E1705, Paul Hummel */ "Dell Inc.", "MXC051 *", "", "", 0, /* Dell Inspiron 630m, Fredrik Edemar */ "Dell Inc.", "MXC061 *", "", "", VBE_POST, /* Dell Inspiron 640m, Daniel Drake */ "Dell Inc.", "MXC062 *", "", "", S3_BIOS|S3_MODE, /* Dell XPS M1210 BryanL */ "Dell Inc.", "MXG061 *", "", "", 0, /* Dell XPS M1710 Harry Kuiper , console only resumes with vesafb! */ "Dell Inc.", "OptiPlex 755 *", "", "", VBE_POST|NOFB, /* Ted Percival , ATI Graphics, no FB :( */ "Dell Inc.", "OptiPlex FX160 *", "", "", S3_BIOS|S3_MODE, /* */ "Dell Inc.", "Optiplex FX160 *", "", "", S3_BIOS|S3_MODE, /* Dell FX160, James Willcox https://bugzilla.novell.com/show_bug.cgi?id=379774 */ "Dell Inc. ", "OptiPlex GX520 *", "", "", VBE_POST|VBE_MODE, /* Desktop with Intel graphics, Sitsofe Wheeler */ "Dell Inc. *", "OptiPlex GX620 *", "", "", 0, /* Jon Dowland */ "Dell Inc.", "Precision M20*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Dell Inc.", "Precision M4300 *", "", "", 0, /* Bruno Friedmann */ "Dell Inc.", "Precision M6300 *", "", "", VBE_POST|VBE_MODE, /* Chris Debrunner */ "Dell Inc.", "Precision M65 *", "", "", VBE_POST|VBE_MODE, /* gaofi@gaofi.com */ "Dell Inc.", "Precision M90 *", "", "", 0, /* Manoj Srivastava */ "Dell Inc.", "Studio 1555", "A08", "A08", S3_MODE, /* Orel Weinstock */ "Dell Inc.", "Studio XPS 1640", "A113", "A11", 0, /* JackDesBwa */ "Dell Inc.", "Studio XPS 1645", "A08 ", "A08", 0, /* Apr 6, 2010 - Jon Arne Jørgensen Not minimal mode */ "Dell Inc.", "Vostro 1000 ", "", "", S3_BIOS|S3_MODE, /* Florian Buether */ "Dell Inc.", "Vostro 1500 *", "", "", VBE_POST|VBE_MODE, /* Kyle Kearney */ "Dell Inc.", "Vostro1710", "", "", 0, /* Luciano A. Ferrer */ "Dell Inc.", "Vostro 3300", "Not Specified", "A01 ", VBE_POST|VBE_MODE, /* Oct, 2010 - Mathias Teugels */ "Dell Inc.", "Vostro 3500", "Not Specified", "A01 ", 0, /* Aug 9, 2010 - Anton Olsson */ "Dell Inc.", "Vostro 3700", "", "A09 ", 0, /* Petr Morávek [Xificurk] */ "Dell Inc.", "XPS M1330 *", "", "", VBE_POST|VBE_MODE, /* Dell XPS M1330, Danny Kukawka */ "Dell Inc.", "XPS M1530 *", "", "", 0, /* Pierre maybe only with nvidia driver... Elie Roux */ "DIXONSXP", "To be filled by O.E.M.", "Ver.001", "", 0, /* Jarek Grzys */ "ECS", "536", "", "", VBE_POST|NOFB, /* Michael Dickson */ "ECS", "G556 Centrino*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Elitegroup Co.", "ECS G320", "", "", VBE_POST|VBE_MODE, /* Michael Bunk */ "eMachines", "ET1831", "", "P01-A1", 0, /* Jan 9, 2010 - Andreas Balser */ "ERGOUK ", "M2N ", "", "", S3_BIOS|S3_MODE, /* ASUS M2400N, Daniel Gollub */ " EVGA ", "nForce 750i SLI", "1", "6.00 PG", 0, /* Jan 20, 2010 - John Gallagher */ "Foxconn", "nT-330i", "To Be Filled By O.E.M.", "080015 ", 0, /* Oct 31, 2010 - Markus Mayer */ "FUJITSO", "FMVLT70R", "", "", S3_BIOS|S3_MODE|PCI_SAVE, /* Aurelien Jacobs */ "FUJITSU", "0000000000", " ", "Version 1.04 ", 0, /* Fujitsu S6120, Andre Kusuma */ "FUJITSU", "Amilo M*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "FUJITSU ", "D2950-A1 ", " ", "6.00 R1.05.2950.A1 ", 0, /* Feb 7, 2010 - Eckehardt Luhm */ "FUJITSU", "FMVMGG75N7", " ", "Version 1.12 ", S3_MODE, /* rmmod xhci; s2ram -f -a 2; modprobe xhci - May 18, 2010 - Michael Fellinger */ "FUJITSU", "LifeBook P7010D", "", "", S3_BIOS, /* Stephen Gildea */ "FUJITSU", "LIFEBOOK P7010*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "FUJITSU", "LifeBook S2110", "", "", S3_BIOS, /* Andi Kleen, reported to work in 64bit mode */ "FUJITSU", "LIFEBOOK S6120*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "FUJITSU", "LIFEBOOK S710", " ", "Version 1.08 ", S3_MODE, /* Oct 6, 2010 - Andreas Tille */ "FUJITSU", "LifeBook S7110", "", "", 0, /* Srinath Madhavan */ "FUJITSU", "LifeBook S Series*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "FUJITSU", "LifeBook T2010", "", "", S3_BIOS|S3_MODE, /* Duy Nguyen */ "FUJITSU", "LifeBook T Series", "", "", 0, /* David Nolden */ "FUJITSU SIEMENS", "Amilo A1645 ", "", "", S3_BIOS|S3_MODE, /* Loki Harfagr */ "FUJITSU SIEMENS", "Amilo A1650G", "", "", VBE_MODE, /* Ramon Schenkel */ "FUJITSU SIEMENS", "Amilo A1667G Serie", "", "", S3_BIOS, /* stan ioan-eugen */ "FUJITSU SIEMENS", "Amilo A7640 ", "", "", S3_BIOS|S3_MODE, /* Holger Macht , with kernel 2.6.22+, x86_64 */ "FUJITSU SIEMENS", "Amilo A7645 ", "", "", VBE_SAVE|S3_BIOS|S3_MODE, /* reported by Thomas Halva Labella */ "FUJITSU SIEMENS", "Amilo A Series", "0.01", "", VBE_POST|VBE_SAVE, /* Chris Hammond Amilo A 1630 */ "FUJITSU SIEMENS", "Amilo D Series", "", "", VBE_POST|VBE_MODE, /* Hendrik Golzke */ "FUJITSU SIEMENS", "AMILO L Series", "", "", VBE_POST|VBE_MODE, /* Marcel Klemmer */ "FUJITSU SIEMENS", "AMILO M ", "-1 *", "R01-S0N *", VBE_POST|VBE_SAVE|PCI_SAVE, /* Simon Maurer again, match exactly. */ "FUJITSU SIEMENS", "AMILO M ", "-1 *", "R01-S0Z *", VBE_POST|VBE_SAVE, /* Reiner Herrmann , this one realls needs VBE_SAVE since there are many different models of the "AMILO M" series, i do a very exact match */ "FUJITSU SIEMENS", "AMILO M Series", "", "1.0G*", VBE_SAVE, /* Moritz Heidkamp */ "FUJITSU SIEMENS", "Amilo M*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "FUJITSU SIEMENS", "AMILO Pi 1505", "", "", S3_BIOS|S3_MODE, /* Sab */ "FUJITSU SIEMENS", "AMILO Pi 1536", "", "", VBE_POST|VBE_MODE, /* Giorgos Mavrikas */ "FUJITSU SIEMENS", "AMILO Pi 2515", "", "", VBE_POST|VBE_MODE, /* Yasen Pramatarov */ "FUJITSU SIEMENS", "AMILO Pro Edition V3405", "", "", S3_BIOS|S3_MODE, /* Alexandr Kara */ "FUJITSU SIEMENS", "AMILO Pro Edition V3505 *", "", "", S3_BIOS|S3_MODE, /* Igor A. Goncharovsky */ "FUJITSU SIEMENS", "AMILO Pro Series V3525 *", "", "", 0, /* Juhasz Adam */ "FUJITSU SIEMENS", "AMILO PRO V2030", "", "", VBE_POST|VBE_MODE, /* Aleksandar Markovic */ "FUJITSU SIEMENS", "AMILO PRO V2035", "", "", VBE_POST|VBE_MODE, /* some unknown contributor */ "FUJITSU SIEMENS", "AMILO Pro V2040", "", "", 0, /* Florian Herrmann */ "FUJITSU SIEMENS", "AMILO Pro V3205", "", "", S3_BIOS|S3_MODE, /* / https://bugzilla.novell.com/show_bug.cgi?id=279944 */ "FUJITSU SIEMENS", "AMILO PRO V3515", "20", "1.0M-2309-8A20", VBE_POST|VBE_MODE, /* AmiloPro V3515, Julian Wollrath */ "FUJITSU SIEMENS", "AMILO PRO V8010 *", "", "", VBE_POST|VBE_MODE, /* Steffen */ "FUJITSU SIEMENS", "Amilo Si 1520", "", "", S3_BIOS|S3_MODE, /* Markus Meyer , Christian Illy */ "FUJITSU SIEMENS", "AMILO Xi 1546", "", "", S3_BIOS|S3_MODE, /* */ "FUJITSU SIEMENS", "AMILO Xi 2550", " ", "1.11C", VBE_POST|VBE_MODE, /* Elmar Stellnberger */ "FUJITSU SIEMENS", "ESPRIMO Mobile D9500", "", "", 0, /* Guilhem Bonnefille */ "FUJITSU SIEMENS", "ESPRIMO Mobile M9400", "", "", 0, /* Martin Wilck */ "FUJITSU SIEMENS", "ESPRIMO Mobile U9200", "1.0", "1.11 - 067 - 1566", 0, /* Aug 15, 2010 - Ondřej Caletka */ "FUJITSU SIEMENS", "ESPRIMO P*", "", "", 0, /* Jan Schaefer */ "FUJITSU SIEMENS", "ESPRIMO Q5030", "None", "R2.03TFS", 0, /* Nov 16, 2010 - Michael Franz */ "FUJITSU SIEMENS", "LIFEBOOK B Series", "", "", 0, /* Clement LAGRANGE */ "FUJITSU SIEMENS", "LIFEBOOK E4010", "", "", VBE_SAVE, /* wolfgang.aigner@gmx.de */ "FUJITSU SIEMENS", "LIFEBOOK E8020", "", "", VBE_POST|VBE_MODE, /* Robin Knapp */ "FUJITSU SIEMENS", "LIFEBOOK E8110", "", "", 0, /* Florian Lohoff */ "FUJITSU SIEMENS", "LIFEBOOK E8410", "", "", S3_BIOS|S3_MODE, /* seife. Without Flags: Apr 13, 2010 - Gabriel Sailer */ "FUJITSU SIEMENS", "LIFEBOOK P7010*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "FUJITSU SIEMENS", "LIFEBOOK P7230", "", "", S3_BIOS|S3_MODE|PCI_SAVE, /* Michael Hillerstrom */ "FUJITSU SIEMENS", "LIFEBOOK P8010", "", "", S3_BIOS|S3_MODE, /* Bernd Speiser */ "FUJITSU SIEMENS", "LIFEBOOK S6120*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "FUJITSU SIEMENS", "LIFEBOOK S6410", "", "", VBE_POST|VBE_MODE, /* Fred Lahuis */ "FUJITSU SIEMENS", "LIFEBOOK S7010", "", "", 0, /* , tested with X only */ "FUJITSU SIEMENS", "LIFEBOOK S7020", "", "", S3_BIOS|S3_MODE|PCI_SAVE, /* Antonio Cardoso Martins */ "FUJITSU SIEMENS", "LIFEBOOK S7110", "", "", 0, /* Samuel Tardieu */ "FUJITSU SIEMENS", "LifeBook S Series*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "FUJITSU SIEMENS", "LifeBook T2010", "", "", VBE_POST|VBE_SAVE|PCI_SAVE, /* Alexander Clouter , needs vbe_save or the vga mode is upset */ "FUJITSU SIEMENS", "LIFEBOOK T3010", "", "", 0, /* arnold seiler */ "FUJITSU SIEMENS", "LIFEBOOK T4010", "", "", S3_BIOS|S3_MODE, /* Eckhart Woerner */ "FUJITSU SIEMENS", "LIFEBOOK T4210", "", "", S3_BIOS|S3_MODE|PCI_SAVE, /* Jay */ "FUJITSU SIEMENS", "LifeBook T4310", "10601127925", "Version 1.05 ", 0, /* Apr 27, 2010 - H.-Dirk Schmitt */ "FUJITSU SIEMENS", "P5GD1-FM", "", "1004.001", 0, /* Dennis Koll */ "Fujitsu Siemens", "P6VAP-AP", "", "", 0, /* Tomas Pospisek */ "FUJITSU SIEMENS", "SCENIC N300/N600", "", "", VBE_POST|VBE_MODE, /* Ulf Lange */ "FUJITSU SIEMENS", "SCENIC P / SCENICO P", "", "", VBE_POST|VBE_MODE, /* Guenther Schwarz */ "FUJITSU SIEMENS", "SCENIC W300/W600", "", "", VBE_POST|VBE_MODE, /* This is a desktop with onboard i810 video */ "FUJITSU SIEMENS", "SCENIC W", "", "", VBE_POST|VBE_MODE, /* Peer Heinlein */ "FUJITSU SIEMENS", "Stylistic ST5000", "", "", S3_BIOS|S3_MODE, /* */ "Gateway ", "LT31 ", "Not Applicable", "v1.3201 ", S3_BIOS|S3_MODE, /* Jan 30, 2010 - Jay Logan */ "Gateway *", "MT6707 *", "", "", S3_BIOS|S3_MODE, /* Mario Nigrovic */ "Gateway", "MX3228", "73.08 ", "73.08 ", VBE_POST|VBE_MODE, /* Gateway MX3228, The Space Man */ "Gateway *", "MX6922B *", "", "", 0, /* Ilya Eremin */ "GERICOM", "259IA1", "", "", 0, /* Christoph Wiesmeyr */ "Gericom", "G730", "Revision A0", "6.00", 0, /* Jan 9, 2010 - Andreas Balser */ "Gericom", "HUMMER", "", "1.03 ", VBE_POST|VBE_MODE, /* booiiing@gmail.com */ "Gericom", "Montara-GML ", "FAB-2", "", 0, /* From: Einon , seems to work only from X :-( */ "Gigabyte Technology Co., Ltd.", "945GCM-S2L", "", "", 0, /* Nik Tripp https://bugzilla.novell.com/show_bug.cgi?id=400356 */ "Gigabyte Technology Co., Ltd.", "945GCMX-S2", "", "", VBE_POST|VBE_MODE, /* Art Mitskevich */ "Gigabyte Technology Co., Ltd.", "945GZM-S2", "", "", 0, /* Josef Zenisek */ "Gigabyte Technology Co., Ltd.", "EP45-UD3R", " ", "F12", 0, /* Jul 4, 2010 - tuxfusion */ "Gigabyte Technology Co., Ltd.", "GA-MA69G-S3H", " ", "F5", 0, /* Florian Sesser */ "Gigabyte Technology Co., Ltd.", "GA-MA785GMT-UD2H", " ", "F5", 0, /* Apr 9, 2010 - Eri Johnson */ "Gigabyte Technology Co., Ltd.", "GA-MA785GM-US2H", " ", "F5", S3_BIOS|S3_MODE, /* Andi Valachi */ "Gigabyte Technology Co., Ltd.", "GA-MA78G-DS3H", " ", "FC", S3_BIOS|S3_MODE, /* Sebastian Koerner */ "Gigabyte Technology Co., Ltd.", "GA-MA78GPM-DS2H", " ", "F1", S3_BIOS, /* Ian-Xue Li */ "Gigabyte Technology Co., Ltd.", "GA-MA790XT-UD4P", " ", "F4", 0, /* Mar 12, 2010 - Vit */ "Gigabyte Technology Co., Ltd.", "M61PM-S2", " ", "Beta F9c", 0, /* Mar 5, 2010 - Márcio Spezani */ "Gigabyte Technology Co., Ltd.", "P35-DS3", " ", "F6", 0, /* Thorsten Goetzke */ "Gigabyte Technology Co., Ltd.", "P35-DS3L", " ", "F8", 0, /* Gigabyte P35-DS3L, Kainr�th Roland */ "Gigabyte Technology Co., Ltd.", "P35-DS4", "", "", VBE_POST|VBE_MODE, /* Roberto Lumbreras */ "Gigabyte Technology Co., Ltd.", "P55M-UD2", "", "F11", 0, /* Andreas Mueller */ "Gigabyte Technology Co., Ltd.", "X58A-UD7", " ", "F6", 0, /* Jun 7, 2010 - Damir Perisa */ "Hewlett-Packard", "", "", "68YDU*", 0, /* Michal Sedkowski , VBE_POST (Michal Vyskocil ), VBE_POST|VBE_MODE (Danny Kukawka ), Hendrik Tews "HP Compaq nc6320 (RH367ET*" */ "Hewlett-Packard", "", "", "68YGU*", VBE_POST, /* Michael Meskes , this is a NX 7400 */ "Hewlett-Packard", "Compaq 515", "F.06", "68GVV Ver. F.06", 0, /* May 4, 2010 - Peter Becker */ "Hewlett-Packard", "Compaq nc4000 (DA762AV) ", "F.30 ", "68BAS Ver. F.30", S3_BIOS|S3_MODE, /* Oct 10, 2010 - John Thiga */ "Hewlett-Packard", "Compaq nc6000 *", "", "68BDD*", S3_BIOS|S3_MODE, /* Jan Adlen */ "Hewlett-Packard*", "Compaq nx5000 *", "", "68BCU*", VBE_POST|VBE_MODE, /* */ "Hewlett-Packard ", "Compaq nx 7010 (DU394T#*", "", "68BAL*", S3_BIOS|S3_MODE, /* Philippe Marzouk */ "Hewlett-Packard ", "Compaq nx 7010 (PG588EA#*", "", "", S3_BIOS, /* François Münch */ "Hewlett-Packard ", "Compaq Presario CQ60 Notebook PC", "F.32", "F.32", 0, /* egelor */ "Hewlett-Packard ", "Compaq Presario X1000 (DK454AV)*", "", "", S3_BIOS, /* "Zirkel, Timothy K" */ "Hewlett-Packard", "EW434AVABA *", "", "", S3_BIOS|S3_MODE, /* Marcos Pinto , HP dv6000 */ "Hewlett-Packard", "HP 2133", "", "68VGU*", S3_BIOS|S3_MODE, /* hp compaq 2133, https://bugzilla.novell.com/show_bug.cgi?id=409246 */ "Hewlett-Packard", "HP 550", "", "68MVU*", VBE_POST|VBE_MODE, /* arideyla@web.de */ "Hewlett-Packard", "HP Compaq 2133", "", "68VGU*", S3_BIOS|S3_MODE, /* hp compaq 2133, https://bugzilla.novell.com/show_bug.cgi?id=363240 */ "Hewlett-Packard", "HP Compaq 2230s (FU312EA)", "F.0D", "68PHU Ver. F.0D", 0, /* Wouter Verhelst */ "Hewlett-Packard", "HP Compaq 2510p *", "", "68MSP*", VBE_POST|VBE_MODE, /* Stefan Kulow https://bugzilla.novell.com/show_bug.cgi?id=362928 */ "Hewlett-Packard", "HP Compaq 2710*", "", "68MOU*", VBE_POST|VBE_MODE, /* Holger Sickenberg https://bugzilla.novell.com/show_bug.cgi?id=376715 */ "Hewlett-Packard", "HP Compaq 6510b (GB863EA*", "", "68DDU*", VBE_POST|VBE_MODE, /* Jamil Djadala */ "Hewlett-Packard", "HP Compaq 6510b (KE134EA*", "", "68DDU*", 0, /* peeetax@googlemail.com */ "Hewlett-Packard", "HP Compaq 6520s", "F.0A", "68MDU Ver. F.0A", 0, /* Jamalulkhair Khairedin , tested on console and X */ "Hewlett-Packard", "HP Compaq 6710b", "F.15", "68DDU Ver. F.15", 0, /* Jun 21, 2010 - Luiz Kuwabara */ "Hewlett-Packard", "HP Compaq 6710b (GB893EA*", "", "68DDU*", VBE_POST|VBE_MODE, /* Michal Sojka */ "Hewlett-Packard", "HP Compaq 6710b (GB893ET*", "", "68DDU*", VBE_POST|VBE_MODE, /* Harry ten Berge */ "Hewlett-Packard", "HP Compaq 6710b (GR681EA*", "", "68DDU*", VBE_POST|VBE_MODE, /* Michal Skrzypek */ "Hewlett-Packard", "HP Compaq 6710b (KE123EA*", "", "68DDU*", 0, /* Jaromrir Cervenka */ "Hewlett-Packard", "HP Compaq 6710b (KE124EA*", "", "68DDU*", VBE_POST|VBE_MODE, /* Jakub Talas */ "Hewlett-Packard", "HP Compaq 6710s (GC014ET*", "", "68DDU*", VBE_POST|VBE_MODE, /* Alberto Gonzalez */ "Hewlett-Packard", "HP Compaq 6715b (GB834EA*", "", "68YTT*", VBE_POST|VBE_MODE, /* Darek Nawrocki */ "Hewlett-Packard", "HP Compaq 6715b (GB835EA*", "", "68YTT*", S3_BIOS|S3_MODE, /* Radu Benea */ "Hewlett-Packard", "HP Compaq 6715b (RK156AV*", "", "68YTT*", S3_BIOS|S3_MODE, /* Andrey Petrov */ "Hewlett-Packard", "HP Compaq 6715b (RM174UT*", "", "68YTT*", S3_BIOS|VBE_MODE, /* Matthias Hopf, https://bugzilla.novell.com/show_bug.cgi?id=390271, needs strange combination */ "Hewlett-Packard", "HP Compaq 6715s (GR656ET*", "", "68YTT*", S3_BIOS, /* Petteri Tolonen works with radeonhd and fglrx */ "Hewlett-Packard", "HP Compaq 6720s", "", "68MDU*", VBE_POST|VBE_MODE, /* Paul Smet */ "Hewlett-Packard", "HP Compaq 6820s", "", "68MDD*", S3_BIOS, /* Babarovic Ivica */ "Hewlett-Packard", "HP Compaq 6910p", "", "68MCD*", S3_BIOS|S3_MODE, /* Robert Norris , tested with fglrx */ "Hewlett-Packard", "HP Compaq 6910p", "", "68MCU*", VBE_POST|VBE_MODE, /* Daniele Frijia , this machine has no model number in DMI. BIOS F.14 */ "Hewlett-Packard", "HP Compaq 6910p (GB951EA*", "", "68MCD*", VBE_MODE, /* Ola Widlund , works with proprietary ATI driver, to be verified without */ "Hewlett-Packard", "HP Compaq 6910p (GH717AW#UUG)", "F.15", "68MCD Ver. F.15", VBE_POST|VBE_MODE, /* HP Compaq 6910p, Alexander Mikhailian */ "Hewlett-Packard", "HP Compaq 6910p (RH241AV)", "", "68MCU*", VBE_POST|VBE_MODE, /* Tomas Kejzlar */ "Hewlett-Packard", "HP Compaq 8510p ", "", "68MVD*", VBE_POST|VBE_MODE, /* Krisztian Loki , does not work with proprietary ATI driver */ "Hewlett-Packard", "HP Compaq 8710p (GC102EA*", "", "68MAD*", 0, /* Milan Znamenacek , only from X */ "Hewlett-Packard", "HP Compaq 8710p (GT647PA*", "", "68MAD*", 0, /* Tim Harris */ "Hewlett-Packard", "HP Compaq dc5800 Small Form Factor", "", "786F2*", 0, /* Marek Stopka , kernel 2.6.25 */ "Hewlett-Packard", "HP Compaq nc2400*", "", "68YOP*", VBE_POST|VBE_MODE, /* hp compaq nc2400, tested by seife. sometimes has keyboard problems after resume */ "Hewlett-Packard", "HP Compaq nc4200*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Hewlett-Packard", "HP Compaq nc4400*", "", "68YHV*", VBE_POST|VBE_MODE, /* Antti Laine , "did not work with older BIOS", now has F.09 sys_ver="F.08": VBE_POST|VBE_SAVE, Rene Seindal */ "Hewlett-Packard*", "HP Compaq nc6000 *", "", "68BDD*", S3_BIOS|S3_MODE, /* there seem to be versions with a " " after Hewlett-Packard and without. */ "Hewlett-Packard", "HP Compaq nc6120 *", "", "", VBE_POST|VBE_MODE, /* Winfried Dobbe, https://bugzilla.novell.com/show_bug.cgi?id=159688 */ "Hewlett-Packard", "HP Compaq nc6220*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Hewlett-Packard", "HP Compaq nc6230 *", "", "", VBE_SAVE|NOFB, /* */ "Hewlett-Packard", "HP Compaq nc6400 (EH522AV)", "", "68YCU*", VBE_POST|VBE_MODE, /* https://bugzilla.novell.com/show_bug.cgi?id=260451 */ "Hewlett-Packard", "HP Compaq nc6400 (EY582ES*", "", "68YCU*", VBE_POST|VBE_MODE, /* https://bugzilla.novell.com/show_bug.cgi?id=295489 */ "Hewlett-Packard", "HP Compaq nc6400 (RH560EA*", "", "68YCU*", VBE_POST|VBE_MODE, /* https://bugzilla.novell.com/show_bug.cgi?id=326526 */ "Hewlett-Packard", "HP Compaq nc8230*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Hewlett-Packard", "HP Compaq nc8430 (ES591EA#ABD)", "F.16", "68YVD Ver. F.16", VBE_MODE, /* Jan 19, 2010 - Stefan Schneider */ "Hewlett-Packard", "HP Compaq nw8440 *", "", "68YVD*", VBE_POST|VBE_MODE, /* Stefan Seyfried novell bug 259831, this machine is only available in one configuration (ATI Graphics) */ "Hewlett-Packard", "HP Compaq nw9440 *", "", "68YAF*", 0, /* Magnus Hoglund */ "Hewlett-Packard*", "hp compaq nx5000 *", "", "68BCU*", VBE_POST|VBE_MODE, /* */ "Hewlett-Packard*", "hp Compaq nx5000 *", "", "68BCU*", VBE_POST|VBE_MODE, /* Ed Hoo */ "Hewlett-Packard", "HP Compaq nx6110 *", "", "68DTD", VBE_POST|VBE_MODE, /* */ "Hewlett-Packard", "HP Compaq nx6120 *", "", "68DTD*", VBE_POST|VBE_MODE, /* Niv aharonovich */ "Hewlett-Packard", "HP Compaq nx6125 *", "", "", VBE_SAVE|NOFB, /* */ "Hewlett-Packard", "HP Compaq nx6315", "", "68MOU*", S3_BIOS|S3_MODE, /* Pavel Machek */ "Hewlett-Packard", "HP Compaq nx6325 *", "", "68TT2*", VBE_POST|VBE_SAVE, /* Benedikt Nimmervoll , EY350EA#ABD also works with version RD115AA#ABA */ "Hewlett-Packard ", "HP compaq nx7000 *", "", "", VBE_POST|VBE_SAVE, /* Michael Biebl */ "Hewlett-Packard", "HP Compaq nx7300 (RU374ES#*", "", "", VBE_POST|VBE_MODE, /* Valent Turkovic */ "Hewlett-Packard", "HP Compaq nx7400 (RH412EA#)", "", "", VBE_POST|VBE_MODE, /* Slawomir Skrzyniarz */ "Hewlett-Packard", "HP Compaq nx8220 *", "", "", VBE_SAVE|NOFB, /* */ "Hewlett-Packard", "HP Compaq nx9420 (RB549UT#ABA)", "F.1D", "68YAF Ver. F.1D", S3_BIOS|S3_MODE, /* HP Compaq nx9420, Adam */ "Hewlett-Packard", "HP d330 uT*", "", "", 0, /* Georg Walser Model DG286A */ "Hewlett-Packard", "HP d530 SFF*", "", "", 0, /* Ryan Bair */ "Hewlett-Packard", "HP EliteBook 8530w", "F.0F", "68PDV Ver. F.0F", 0, /* Works with -a 1, -a 2 and -a 3 too. Jir� Nov�cek 26/12/2009 */ "Hewlett-Packard", "HP G60 Notebook PC", "F.54", "F.54", 0, /* Jan 5, 2010 - Tom Petit */ "Hewlett-Packard", "HP Mini 5101", "F.02", "68DGI Ver. F.02", 0, /* Oct 6, 2010 - Zdeněk Janeček */ "Hewlett-Packard", "HP OmniBook PC ", "HP OmniBook 500 FA ", "FA.M2.71", 0, /* HP OmniBook 500, Oliver Redner */ "Hewlett Packard", "", "HP OmniBook XE3 GC *", "", VBE_POST|VBE_SAVE, /* Frederic Mothe */ "Hewlett Packard", "", "HP OmniBook XE3 GF *", "", VBE_POST|VBE_SAVE, /* */ "Hewlett Packard", "", "HP OmniBook XT1000 *", "", S3_MODE, /* Bernd Rinn */ "Hewlett-Packard", "HP Pavilion dm1 Notebook PC", "048C110000241B00000320000", "F.11", 0, /* Feb 18, 2010 - Stefano Z. */ "Hewlett-Packard", "HP Pavilion dm3t Notebook PC ", "039F100000240000110320000", "F.0A", S3_BIOS|S3_MODE, /* Jan 20, 2010 - Michael Cheah */ "Hewlett-Packard", "HP Pavilion dv1000*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Hewlett-Packard", "HP Pavilion dv2000 (GA534UA#*", "", "", 0, /* Tarek Soliman */ "Hewlett-Packard", "HP Pavilion dv2000 (GF759EA#*", "", "", 0, /* S.Çağlar Onur , works only from X! */ "Hewlett-Packard", "HP Pavilion dv2000 (RN066EA#*", "", "", 0, /* Daniel Forrer and Jimmi */ "Hewlett-Packard", "HP Pavilion dv2500 Notebook PC", "", "", 0, /* Robert Hart */ "Hewlett-Packard", "HP Pavilion dv2 Notebook PC ", "F.03 ", "F.03 ", VBE_POST|VBE_SAVE, /* HP Pavilion dv2, Mike Leimon . VBE_POST only Mar 9, 2010 - Andre Pereira */ "Hewlett-Packard", "HP Pavilion dv6000 (EW434AV#*", "", "", S3_BIOS|S3_MODE, /* Benjamin Kudria */ "Hewlett-Packard", "HP Pavilion dv6000 (EY798AV*", "", "", 0, /* Carlos Andrade */ "Hewlett-Packard", "HP Pavilion dv6000 (GA378UA#*", "", "", S3_MODE, /* Valent Turkovic */ "Hewlett-Packard", "HP Pavilion dv6000 (GF688EA*", "", "", 0, /* Marlin Forbes */ "Hewlett-Packard", "HP Pavilion dv6000 (GH907EA#*", "", "", S3_MODE, /* Eric Brasseur */ "Hewlett-Packard", "HP Pavilion dv6000 (RM469EA#*", "", "", 0, /* Antony Dovgal */ "Hewlett-Packard", "HP Pavilion dv6000 (RP153UA#*", "", "", S3_BIOS|S3_MODE, /* Jens Kaiser , maybe only with binary nvidia module? */ "Hewlett-Packard", "HP Pavilion dv6000 (RP980EA#*", "", "", 0, /* John Soros "HP dv6120ea" */ "Hewlett-Packard", "HP Pavilion dv6500 Notebook PC *", "", "", S3_BIOS, /* Fran Firman , no hacks, maybe only works due to the Nvidia driver? Marco Nenciarini needs S3_BIOS */ "Hewlett-Packard", "HP Pavilion dv6700 Notebook PC *", "", "", S3_BIOS|S3_MODE, /* fsuzzi@libero.it, dv6855el. No flags from: Jun 27, 2010 - Stanila Sorin-Valer */ "Hewlett-Packard", "HP Pavilion dv7 Notebook PC*", "", "", 0, /* Wael Nasreddine */ "Hewlett-Packard", "HP Pavilion Notebook PC", "HP Pavilion Notebook *", " IC.M1.02", 0, /* hp pavilion xz275 */ "Hewlett-Packard", "HP Pavilion tx1000 Notebook PC *", "", "", 0, /* */ "Hewlett-Packard", "HP Pavilion tx2500 Notebook PC", "", "", S3_BIOS|S3_MODE, /* Joachim Deguara */ "Hewlett-Packard", "HP Pavilion ze2000 (EK791EA#*", "", "", 0, /* Chris Polderman */ "Hewlett-Packard ", "hp pavilion ze4900 (*", "", "", 0, /* Fuad Tabba , only available with integr. gfx */ "Hewlett-Packard", "HP Pavilion zt3000*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Hewlett-Packard", "HP ProBook 4515s", "", "", S3_BIOS|VBE_SAVE, /* Nov 6, 2010 - Marc Wirz | Sep 4, 2010 - Damien Kesteman */ "Hewlett-Packard", "HP Tablet PC TR1105*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Hewlett-Packard", "HP Tablet PC Tx1100*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Hewlett-Packard", "HP xw4300 Workstation", " ", "786D3 v01.11", 0, /* HP xw4300 Workstation, Florian Reitmeir */ "Hewlett-Packard", "HP xw4550 Workstation", "", "786F7*", 0, /* tested by HP https://bugzilla.novell.com/show_bug.cgi?id=436284 */ "Hewlett-Packard", "HP xw6600 Workstation", "", "786F4*", 0, /* tested by HP https://bugzilla.novell.com/show_bug.cgi?id=436284 */ "Hewlett-Packard", "HP xw8600 Workstation", "", "786F5*", 0, /* tested by HP https://bugzilla.novell.com/show_bug.cgi?id=436284 */ "Hewlett-Packard", "HP xw9400 Workstation", "", "786D6*", 0, /* tested by HP https://bugzilla.novell.com/show_bug.cgi?id=436284 */ "Hewlett-Packard", "Pavilion dv4000 (EB911EA#*", "", "", S3_BIOS, /* Damien Raude-Morvan , This is a dv4052ea, i915GM */ "Hewlett-Packard", "Pavilion dv4000 (ES973EA#*", "", "", VBE_POST|VBE_SAVE|NOFB, /* Fabio Comolli , dv4378ea, ATI X700 */ "Hewlett-Packard", "Pavilion dv4000 (PX306UA#*", "", "", S3_BIOS|S3_MODE, /* Daniel L Wells */ "Hewlett-Packard", "Pavilion dv5000 (ET805UA#ABA) ", "F.33", "", VBE_SAVE, /* Sep 27, 2010 - William Welch */ "Hewlett-Packard", "Pavilion dv5000 (EZ535UA#*", "", "", 0, /* Wally Valters */ "Hewlett-Packard", "Pavilion dv5000 (RA648EA#ABU) ", "F.42", "F.42", 0, /* HP Pavilion dv5244eu, Adrian Connolly */ "Hewlett-Packard", "Pavilion dv6000 (EY798AV#*", "", "", 0, /* Arun Gupta */ "Hewlett-Packard", "Pavilion zd7000*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Hewlett-Packard", "Pavilion zd8000 (EL030EA#*", "", "", VBE_POST, /* Etienne URBAH */ "Hewlett-Packard ", "Pavilion zt3300 *", "", "68BAL*", S3_BIOS, /* Karthik */ "Hewlett-Packard ", "Pavilion zt3300 (PF083UA#*", "", "", 0, /* Frank Schröder , zt3380us */ "Hewlett-Packard", "Pavilion ZV6100 (EK848EA#*", "F.1B", "F.1B", 0, /* Feb 2011 - Pierre Hilson */ "Hewlett-Packard*", "Presario 2100 (DP835E)*", "", "", 0, /* Jari Turkia */ "Hewlett-Packard*", "Presario 2200 (PR309UA#*", "", "", 0, /* Frederic Koehler */ "Hewlett-Packard", "Presario C500 (RZ341UA#*", "", "", 0, /* Matto Marjanovic */ "Hewlett-Packard", "Presario C700 (GV681LA#*", "", "", 0, /* Igor Tamara */ "Hewlett-Packard", "Presario F500 (GF596UA#*", "", "", 0, /* Robert Gomulka */ "Hewlett-Packard", "Presario M2000 (EQ547PA#*", "", "", S3_BIOS|VBE_MODE, /* Fatih Alabas https://bugzilla.novell.com/show_bug.cgi?id=230528 */ "Hewlett-Packard ", "Presario R3000 *", "", "", S3_BIOS|S3_MODE, /* Sitsofe Wheeler */ "Hewlett-Packard*", "Presario R3200 *", "", "", VBE_POST|VBE_SAVE, /* Arthur Peters */ "Hewlett-Packard", "Presario R4100 *", "", "", S3_BIOS|S3_MODE, /* */ "Hewlett-Packard", "Presario V2000 (EP381UA#*", "", "", S3_BIOS, /* iamnoah@gmail.com */ "Hewlett-Packard", "Presario V3000 (EZ674UA#*", "", "", S3_BIOS|S3_MODE, /* Cristian S. Rocha crocha@dc.uba.ar */ "Hewlett-Packard", "Presario V3000 (EZ755UA#*", "", "", 0, /* JEROME HAYNES-SMITH */ "Hewlett-Packard", "Presario V3000 (RL377PA#*", "", "", S3_BIOS|S3_MODE, /* From: "Lim Chuen Ee, Mike" */ "Hewlett-Packard", "Presario V3700 Notebook PC", "", "", S3_BIOS|S3_MODE, /* Adi Nugroho https://bugzilla.novell.com/show_bug.cgi?id=364456 */ "Hewlett-Packard", "Presario V5000 (ET826UA#*", "", "", 0, /* Michael Kimsal */ "Hewlett-Packard", "PY507ET#*", "", "68DTD*", VBE_POST|VBE_MODE, /* Battle Nick , also a nc6120 */ "HP Pavilion 061", "D7223K-ABA A650E", "", "", 0, /* Benjamin Cherian */ "HP Pavilion 061", "EJ192AA-ABS t3250.se", "", "", 0, /* A desktop with integrated graphics, Bo Thysell */ "HP Pavilion 061", "EP198AA-UUZ t3335.ch", "", "", 0, /* Michael Zaugg */ "HP Pavilion 061", "ES061AA-ABD t3320*", "", "", 0, /* Stefan Friedrich */ "HP Pavilion 061", "PC098A-ABA M1070N", "", "", 0, /* Levi Larsen */ "HP-Pavilion", "NB965AA-ABF s3715fr", " ", "5.08 ", 0, /* Philippe LEBOURG */ "HP-Pavilion", "RP829AV-ABA d4790y", "", "", 0, /* Arun Gupta , works only with nvidia driver :( */ "HP-Pavilion", "RZ418AA-ABH s3020*", "", "", VBE_MODE, /* Gijs van Gemert */ "IBM", "1830*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R50/p imported from acpi-support 0.59 "half known". */ "IBM", "1831*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R50/p imported from acpi-support 0.59 "half known". */ "IBM", "1832*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R50/p imported from acpi-support 0.59 "half known". */ "IBM", "1833*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R50/p imported from acpi-support 0.59 "half known". */ "IBM", "1834S5G", "ThinkPad R50e", "1WET90WW (2.10 )", 0, /* ThinkPad R50e, Ferenc Wagner */ "IBM", "1836*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R50/p imported from acpi-support 0.59 "half known". */ "IBM", "1840*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R50/p imported from acpi-support 0.59 "half known". */ "IBM", "1841*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R50/p imported from acpi-support 0.59 "half known". */ "IBM", "1846*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R52 imported from acpi-support 0.59 "half known". */ "IBM", "1847*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R52 imported from acpi-support 0.59 "half known". */ "IBM", "1848*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R52 imported from acpi-support 0.59 "half known". */ "IBM", "1849*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R52 imported from acpi-support 0.59 "half known". */ "IBM", "1850*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R52 imported from acpi-support 0.59 "half known". */ "IBM", "1860*", "", "", S3_BIOS|S3_MODE, /* R52, reported by Joscha Arenz */ "IBM", "1864*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* X41 imported from acpi-support 0.59 "half known". */ "IBM", "1865*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* X41 imported from acpi-support 0.59 "half known". */ "IBM", "1870*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R52 imported from acpi-support 0.59 "half known". */ "IBM", "1871*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* T43 imported from acpi-support 0.59 "half known". */ "IBM", "1872*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* T43 imported from acpi-support 0.59 "half known". */ "IBM", "1873*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* T43 imported from acpi-support 0.59 "half known". */ "IBM", "1874*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* T43 imported from acpi-support 0.59 "half known". */ "IBM", "1875*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* T43 imported from acpi-support 0.59 "half known". */ "IBM", "1876*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* T43 imported from acpi-support 0.59 "half known". */ "IBM", "2366*", "", "", RADEON_OFF, /* T30 */ "IBM", "2369*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* X40 imported from acpi-support 0.59 "half known". */ "IBM", "2370*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* X40 imported from acpi-support 0.59 "half known". */ "IBM", "2371*", "ThinkPad X40", "", S3_BIOS|S3_MODE, /* X40 confirmed by Christian Deckelmann */ "IBM", "2372*", "ThinkPad X40", "", S3_BIOS, /* X40, Confirmed by Ville Kov�cs (From X and console) */ "IBM", "2373*", "", "", S3_BIOS|S3_MODE, /* T42p confirmed by Joe Shaw, T41p by Christoph Thiel (both 2373) */ "IBM", "2374*", "", "", S3_BIOS|S3_MODE, /* T41p, Stefan Gerber */ "IBM", "2375*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* T40/T41/T42/p imported from acpi-support 0.59 "half known". */ "IBM", "2376*", "", "", S3_BIOS|S3_MODE, /* T42, Bjorn Mork */ "IBM", "2378*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* T40/T41/T42/p imported from acpi-support 0.59 "half known". */ "IBM", "2379*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* T40/T41/T42/p imported from acpi-support 0.59 "half known". */ "IBM", "2382*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* X40 imported from acpi-support 0.59 "half known". */ "IBM", "2386*", "", "", S3_BIOS|S3_MODE, /* X40, Andrew Pimlott */ "IBM", "2388*", "", "", 0, /* G40 confirmed by David Härdeman */ "IBM", "2511*", "", "", S3_BIOS|S3_MODE, /* Z60t, Sascha Hunold */ "IBM", "2525*", "", "", S3_BIOS|S3_MODE, /* X41, Florian Ragwitz , */ "IBM", "2526*", "", "", S3_BIOS|S3_MODE, /* X41, Johannes Zellner */ "IBM", "2527*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* X41 imported from acpi-support 0.59 "half known". */ "IBM", "2528*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* X41 imported from acpi-support 0.59 "half known". */ "IBM", "2529*", "", "", S3_BIOS|S3_MODE, /* Z60m, reported by Arkadiusz Miskiewicz */ "IBM", "2628*", "", "", 0, /* A21m, Raymund Will */ "IBM", "2629*", "", "", 0, /* A21p, Holger Sickenberg */ "IBM", "2645*", "", "", VBE_SAVE, /* George says the newer BIOS INET36WW / kernel 2.6.22 works fine with these options / without X VBE_POST|VBE_MODE, George Tellalov with X */ "IBM", "2647*", "", "", S3_BIOS|S3_MODE, /* T23 Gernot Schilling */ "IBM", "2648*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* T21 imported from acpi-support 0.59 "half known". */ "IBM", "2652*", "", "", S3_BIOS|S3_MODE, /* A30, Axel Braun. https://bugzilla.novell.com/show_bug.cgi?id=309742 Backlight stays on, but RADEON_OFF kills the machine on second suspend :-( */ "IBM", "2653*", "", "", RADEON_OFF, /* A31p, Till D"orges */ "IBM", "2658*", "", "", 0, /* R32 */ "IBM", "2662*", "", "", S3_BIOS|S3_MODE|RADEON_OFF, /* X22, confirmed by Richard Neill */ "IBM", "2672*", "", "", S3_BIOS|S3_MODE|RADEON_OFF, /* X31, confirmed by Bjoern Jacke */ "IBM", "2673*", "", "", S3_BIOS|S3_MODE, /* X31, Vladislav Korecky , bios_version="1QET73WW (2.11 )" */ "IBM", "2681*", "", "", 0, /* R40 */ "IBM", "2682*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R40 imported from acpi-support 0.59 "half known". */ "IBM", "2683*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R40 imported from acpi-support 0.59 "half known". */ "IBM", "2692*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R40 imported from acpi-support 0.59 "half known". */ "IBM", "2693*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R40 imported from acpi-support 0.59 "half known". */ "IBM", "2696*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R40 imported from acpi-support 0.59 "half known". */ "IBM", "2698*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R40 imported from acpi-support 0.59 "half known". */ "IBM", "2699*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R40 imported from acpi-support 0.59 "half known". */ "IBM", "2722*", "", "", 0, /* R40 */ "IBM", "2723*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R40 imported from acpi-support 0.59 "half known". */ "IBM", "2724*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R40 imported from acpi-support 0.59 "half known". */ "IBM", "2884*", "", "", VBE_POST|VBE_SAVE|UNSURE|RADEON_OFF, /* X30 imported from acpi-support 0.59 "half known". */ "IBM", "2885*", "", "", VBE_POST|VBE_SAVE|UNSURE|RADEON_OFF, /* X30 imported from acpi-support 0.59 "half known". */ "IBM", "2886*", "", "", VBE_POST|VBE_MODE, /* G41, Steven Rostedt */ "IBM", "2890*", "", "", VBE_POST|VBE_SAVE|UNSURE|RADEON_OFF, /* X30 imported from acpi-support 0.59 "half known". */ "IBM", "2891*", "", "", VBE_POST|VBE_SAVE|UNSURE|RADEON_OFF, /* X30 imported from acpi-support 0.59 "half known". */ "IBM", "2897*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* R40 imported from acpi-support 0.59 "half known". */ "IBM", "475S*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* T23 imported from acpi-support 0.59 "half known". */ "IBM", "", "ThinkPad R51", "", 0, /* R51 confirmed by Christian Zoz and Sitsofe Wheeler */ "IBM", "", "ThinkPad R51e", "", S3_BIOS|S3_MODE, /* R51e, reported by nemec.jiri@gmail.com */ "IBM", " ", "ThinkPad T40 ", "1RETDRWW*", 0, /* Joerg Platte jplatte@naasa.net, again emtpy sys_product... */ "IBM", "", "ThinkPad T43p", "", S3_BIOS|S3_MODE, /* T43p reported by Magnus Boman */ "IBM", "", "ThinkPad T43", "", S3_BIOS|S3_MODE, /* Some T43's reported by Sebastian Nagel */ "IBM", "", "ThinkPad X32", "", RADEON_OFF|S3_BIOS|S3_MODE, /* */ "IBM", " ", "ThinkPad X40", "1UETD2WW*", 0, /* Ralph Thormann, notice the empty sys_product :-( */ "IBM", "", "ThinkPad X41 Tablet", "", S3_BIOS|S3_MODE, /* X41 Tablet, tested by Danny Kukawka */ "Infomash", "RoverBook", "", "", VBE_POST|VBE_MODE, /* Andrey Melentyev */ "JVC", "J2N ", "", "", VBE_SAVE, /* Christian Beier */ "LENOVO", "019624U", "ThinkPad Edge", "6YET29WW (1.12 )", 0, /* May 29, 2010 - rousta bout */ "LENOVO", "0657*", "", "", S3_BIOS|VBE_MODE, /* Dave Royal , R60e 32bit works with S3_MODE, 64bit needs VBE_MODE */ "LENOVO", "068928U", "3000 N100 *", "", 0, /* Leo G */ "LENOVO", "0761*", "3000 C100 *", "", 0, /* AFAICT the 3000 C100 is only available with intel graphics Luc Levain , works with old and new kernel. */ "LENOVO", "0763*", "LENOVO3000 V100", "", 0, /* Sebastian Schleehauf , 3000V100 */ "LENOVO", "076804U", "3000 N100 *", "", S3_BIOS|VBE_MODE, /* these Lenovo 3000 N100 model 768 are available with different graphics chips, so i do not dare to wildcard anything here :-( https://bugzilla.novell.com/show_bug.cgi?id=299099 */ "LENOVO", "076831G", "3000 N100 *", "", 0, /* Bogdan */ "LENOVO", "076835U", "3000 N100 *", "", 0, /* Tim Creech */ "LENOVO", "07686VG", "3000 N100 *", "", 0, /* Aviv Ben-Yosef */ "LENOVO", "07687MM", "3000 N100 *", "", S3_MODE, /* Ted Percival */ "LENOVO", "0768BYG", "3000 N100 *", "", 0, /* Johannes Rohr */ "LENOVO", "0769AC6", "3000 N200 *", "", S3_BIOS|S3_MODE, /* I'm not sure how to handle the 3000 N200 models... Thorsten Frey reported no options, michael.monreal@gmail.com reports -a3 */ "LENOVO", "0769AH9", "3000 N200 *", "", 0, /* Moritz Schaefer */ "LENOVO", "0769AVU", "3000 N200 ", "68ET31WW", 0, /* Lenovo 3000 N200, Kyle Jones -- Hotelicom */ "LENOVO", "0769B9G", "3000 N200 *", "", 0, /* Hans Gunnarsson */ "LENOVO", "0769BBG", "3000 N200 *", "", S3_BIOS|S3_MODE, /* Stojan Jakotic */ "LENOVO", "0769BEG", "3000 N200 *", "", 0, /* ozon */ "LENOVO", "0769ESG", "3000 N200 *", "", 0, /* Jes�s Malo Poyatos */ "LENOVO", "1702*", "", "", S3_BIOS|S3_MODE, /* X60 / X60s */ "LENOVO", "1704*", "", "", S3_BIOS|S3_MODE, /* X60 / X60s */ "LENOVO", "1706*", "", "", S3_BIOS|S3_MODE, /* X60 / X60s */ "LENOVO", "20021,2959", "Lenovo Ideapad S12", "19CN21WW", 0, /* Nov 1, 2010 - Markus Bauer-Sommerfeld */ "LENOVO", "2007*", "", "", S3_BIOS|S3_MODE, /* T60p, Stephane Liardet */ "LENOVO", "20828WG", "ThinkPad T500", "7VET81WW (3.11 )", 0, /* Apr 12, 2010 - Johannes Engel */ "LENOVO", "20828WG", "ThinkPad T500", "7VET86WW (3.16 )", 0, /* Tanuva */ "LENOVO", "2242CTO", "ThinkPad T500", "6FET79WW (3.09 )", 0, /* Lenovo ThinkPad T500, Maciej Piechotka */ "LENOVO", "2478*", "", "", S3_BIOS|S3_MODE, /* LENOVO X300, 2008-04-03 https://bugzilla.novell.com/show_bug.cgi?id=370690 */ "LENOVO", "2479*", "", "", S3_BIOS|S3_MODE, /* LENOVO X300, 2008-04-03 https://bugzilla.novell.com/show_bug.cgi?id=370690 */ "LENOVO", "273232G", "ThinkPad R500", "7YET70WW (3.00 )", VBE_POST|VBE_MODE, /* Dec 29, 2009 - Slawek Gocan */ "LENOVO", "2764CTO", "ThinkPad T400", "", VBE_POST|VBE_MODE, /* Lenovo T400, Chris Cain ; Whitelist all bioses Arkadiusz Miskiewicz */ "LENOVO", "2767*", "ThinkPad T400", "", 0, /* Michael Düll Thinkpad T400 | Michael Düll */ "LENOVO", "2768EB7", "ThinkPad T400", "7UET71WW (3.01 )", VBE_SAVE|VBE_MODE|PCI_SAVE, /* IBM T400, Erez Zarum */ "LENOVO", "28477MG", "ThinkPad SL510", "6JET73WW (1.31 )", S3_BIOS|S3_MODE, /* Jul 18, 2010 - Mathias Lorenz */ "LENOVO", "2985ETG", "ThinkPad X201 Tablet", "6QET61WW (1.31 )", 0, /* Moritz Augsburger */ "LENOVO", "3241 ", "Lenovo IdeaPad Y550P ", "1ECN33WW(V5.07)", 0, /* Jun 10, 2010 - Kevin Brosnan */ "LENOVO", "4108*", "", "", S3_BIOS|S3_MODE, /* T61 / R61 2008-01-29, bug https://bugzilla.novell.com/show_bug.cgi?id=334522#c10 */ "LENOVO", "4141*", "", "", S3_BIOS|S3_MODE, /* T61 / R61 2008-01-29, bug https://bugzilla.novell.com/show_bug.cgi?id=334522#c10 */ "LENOVO", "4143*", "", "", S3_BIOS|S3_MODE, /* T61 / R61 2008-01-29, bug https://bugzilla.novell.com/show_bug.cgi?id=334522#c10 */ "LENOVO", "4391B76", "ThinkPad W510", "6LET63WW (1.26 )", 0, /* Vladimir Zapolskiy */ "LENOVO", "6088*", "", "", 0, /* ThinkCentre M57p, , intel gfx, kernel 2.6.25.5 */ "LENOVO", "6363*", "", "", S3_BIOS|S3_MODE, /* X60 Tablet, Carlos Lange, https://bugzilla.novell.com/show_bug.cgi?id=265613#c12 */ "LENOVO", "6364*", "", "", S3_BIOS|S3_MODE, /* X60 Tablet, Gary Ekker, https://bugzilla.novell.com/show_bug.cgi?id=265613 */ "LENOVO", "6365*", "", "", S3_BIOS|S3_MODE, /* X60 Tablet, Aaron Denney , needs at least BIOS "7JET25WW (1.10 )"*/ "LENOVO", "6366*", "", "", S3_BIOS|S3_MODE, /* Florian Wagner , X60 Tablet */ "LENOVO", "6378*", "", "", S3_BIOS|S3_MODE, /* T61 */ "LENOVO", "6379*", "", "", S3_BIOS|S3_MODE, /* T61 */ "LENOVO", "6457*", "", "", VBE_POST|VBE_MODE, /* Christian Borntraeger , VBE_POST|VBE_MODE works without binary driver */ "LENOVO", "6458*", "", "", VBE_POST|VBE_MODE, /* confirmed to work with VESA by Ryan Kensrod */ "LENOVO", "6459*", "", "", 0, /* T61p, leighton 5 , ... what's the difference to the other T61p? */ "LENOVO", "6460*", "", "", S3_BIOS|VBE_MODE, /* T61p, leighton 5 , ... what's the difference to the other T61p? */ "LENOVO", "6463*", "", "", S3_BIOS|S3_MODE, /* T61 */ "LENOVO", "6464*", "", "", S3_BIOS|S3_MODE, /* T61 */ "LENOVO", "6465*", "", "", 0, /* T61: Amit Joshi (S3_BIOS|S3_MODE), No flags KyuHwa Lee + Michael Henry */ "LENOVO", "6466*", "", "", S3_BIOS|S3_MODE, /* T61 */ "LENOVO", "6467*", "", "", S3_BIOS|S3_MODE, /* T61 */ "LENOVO", "6468*", "", "", S3_BIOS|S3_MODE, /* T61 */ "LENOVO", "6471*", "", "", S3_BIOS|S3_MODE, /* T61 */ "LENOVO", "6476*", "", "", S3_BIOS|S3_MODE, /* LENOVO X300, 2008-04-03 https://bugzilla.novell.com/show_bug.cgi?id=370690 */ "LENOVO", "6477*", "", "", S3_BIOS|S3_MODE, /* LENOVO X300, 2008-04-03 https://bugzilla.novell.com/show_bug.cgi?id=370690 */ "LENOVO", "6478*", "", "", S3_BIOS|S3_MODE, /* LENOVO X300, 2008-04-03 https://bugzilla.novell.com/show_bug.cgi?id=370690 */ "LENOVO", "6480*", "", "", S3_BIOS|S3_MODE, /* T61 */ "LENOVO", "7439W8A", "ThinkPad R400", "7UET79WW (3.09 )", 0, /* Mar 5, 2010 - Max Zimmermann */ "LENOVO", "7458*", "", "", 0, /* "Lenovo X200", "7458AD9", "ThinkPad X200", "6DET30WW (1.07 )", penma@penma.de */ "LENOVO", "7459W37", "ThinkPad X200", "6DET63WW (3.13 )", 0, /* Nine Cholas */ "LENOVO", "74665EG", "ThinkPad X200s", "6DET60WW (3.10 )", 0, /* Dec 27, 2009 - Lars Stoltenow */ "LENOVO", "7642*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "7643*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "7644*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "7645*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "7646*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "7647*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "7648*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "7649*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "7650*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "7657*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "7658*", "", "", S3_BIOS|S3_MODE, /* T61, Joe Nahmias , debian bug #432018, 7658Q4U Frank Seidel */ "LENOVO", "7659*", "", "", S3_BIOS|S3_MODE, /* T61 */ "LENOVO", "7660*", "", "", S3_BIOS|S3_MODE, /* T61 */ "LENOVO", "7661*", "", "", S3_BIOS|S3_MODE, /* T61 */ "LENOVO", "7663*", "", "", S3_MODE, /* T61 with NVidia card, https://bugzilla.novell.com/show_bug.cgi?id=290618 */ "LENOVO", "7664*", "", "", 0, /* Jeremiah Mahler | T61, Aku Pietikainen , works with console and X */ "LENOVO", "7666*", "", "", S3_BIOS|S3_MODE, /* Rasmus Borup Hansen , X61s reported 7666 w. S3_BIOS Anders Engstrom reported 7666 w. S3_BIOS|S3_MODE */ "LENOVO", "7667*", "", "", S3_BIOS|S3_MODE, /* X61s */ "LENOVO", "7668*", "", "", S3_BIOS|S3_MODE, /* X61s */ "LENOVO", "7669*", "", "", S3_BIOS, /* X61s, Hendrik-Jan Heins . Probably does not restore the framebuffer mode correctly, but S3_MODE as well as VBE_MODE seem to fail sometimes on x86_64 on this machine :-( */ "LENOVO", "7670*", "", "", S3_BIOS|S3_MODE, /* X61s */ "LENOVO", "7671*", "", "", S3_BIOS|S3_MODE, /* X61s */ "LENOVO", "7673*", "", "", 0, /* X61, Marco Barreno , works without any hack | kix: S3_BIOS|S3_MODE */ "LENOVO", "7674*", "", "", S3_BIOS|S3_MODE, /* X61, Holger Hetterich */ "LENOVO", "7675*", "", "", S3_BIOS|S3_MODE, /* X61, Jan Grmela */ "LENOVO", "7676*", "", "", S3_BIOS|S3_MODE, /* X61*/ "LENOVO", "7678*", "", "", S3_BIOS|S3_MODE, /* X61*/ "LENOVO", "7679*", "", "", S3_BIOS|S3_MODE, /* X61*/ "LENOVO", "7732*", "", "", S3_BIOS, /* Thinkpad R61, Calvin Walton , | kix: probably needs S3_MODE */ "LENOVO", "7733*", "", "", S3_BIOS|S3_MODE, /* R61 */ "LENOVO", "7734*", "", "", S3_BIOS|S3_MODE, /* R61 */ "LENOVO", "7735*", "", "", S3_BIOS|S3_MODE, /* R61 */ "LENOVO", "7736*", "", "", S3_BIOS|S3_MODE, /* R61 */ "LENOVO", "7737*", "", "", S3_BIOS|S3_MODE, /* R61 */ "LENOVO", "7738*", "", "", S3_BIOS|S3_MODE, /* Thinkpad R61, */ "LENOVO", "7762*", "", "", S3_BIOS|S3_MODE, /* Stephane Delcroix https://bugzilla.novell.com/show_bug.cgi?id=362945 */ "LENOVO", "7763*", "", "", S3_BIOS|S3_MODE, /*ThinkPad X61 Tablet https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "7764*", "", "", S3_BIOS|S3_MODE, /*ThinkPad X61 Tablet https://bugzilla.novell.com/show_bug.cgi?id=353896 or VBE_POST|VBE_MODE Baylis Shanks , possible problems with video */ "LENOVO", "7767*", "", "", S3_BIOS|S3_MODE, /*ThinkPad X61 Tablet https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "7768*", "", "", S3_BIOS|S3_MODE, /* Danny Kukawka ThinkPad X61 Tablet */ "LENOVO", "7769*", "", "", S3_BIOS|S3_MODE, /*ThinkPad X61 Tablet https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "8808*", "", "", S3_BIOS|S3_MODE, /* ThinkCentre M55, Mansfield Jordan */ "LENOVO", "8889*", "", "", 0, /* R61 Discrete moritz.rogalli@student.uni-tuebingen.de, works with and without nvidia drivers */ "LENOVO", "8895*", "", "", S3_BIOS|VBE_MODE, /* T61, intel card 32bit works with S3_MODE, but 64bit needs VBE_MODE */ "LENOVO", "8896*", "", "", S3_BIOS|S3_MODE, /* T61 */ "LENOVO", "8897*", "", "", S3_BIOS|S3_MODE, /* T61 */ "LENOVO", "8898*", "", "", S3_BIOS|S3_MODE, /* T61 */ "LENOVO", "8899*", "", "", S3_BIOS|S3_MODE, /* T61 */ "LENOVO", "8900*", "", "", S3_BIOS|S3_MODE, /* T61 */ "LENOVO", "8918*", "", "", 0, /* Grzegorz Piektiewicz , R61, with nvidia driver */ "LENOVO", "8919*", "", "", S3_BIOS|S3_MODE, /* , R61, 64bit, NVidia driver does not work */ "LENOVO", "8930*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "8932*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "8933*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "8934*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "8935*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "8936*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "8937*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "8938*", "", "", S3_BIOS|S3_MODE, /* T61 */ "LENOVO", "8939*", "", "", S3_BIOS|S3_MODE, /* T61 */ "LENOVO", "8942*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "8943*", "", "", S3_BIOS|VBE_MODE, /* ThinkPad R61, peter.pille@tektronix.com */ "LENOVO", "8944*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "8945*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "8946*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "8947*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "8948*", "", "", S3_BIOS|S3_MODE, /*ThinkPad R61 https://bugzilla.novell.com/show_bug.cgi?id=353896 */ "LENOVO", "9452*", "", "", S3_BIOS|S3_MODE, /* Rick van Hattem , Z61p*/ "LENOVO", "9456*", "", "", S3_BIOS|S3_MODE, /* https://bugzilla.novell.com/show_bug.cgi?id=210928, Thinkpad R60, 32bit? */ "Lenovo", "Soleil E660P *", "", "", 0, /* Xu Zhe */ "LENOVO", "", "Thinkpad R60e", "", S3_BIOS|S3_MODE, /* From: gregor herrmann */ "LENOVO", "", "ThinkPad R60", "", S3_BIOS|S3_MODE, /* Marcus Better , this time with a capital "P" */ "LENOVO", "", "ThinkPad T60p", "", S3_BIOS|S3_MODE, /* T60p, had a report from a 2007* and a 2008* model */ "LENOVO", "", "ThinkPad T60", "", S3_BIOS|S3_MODE, /* T60 From: Jeff Nichols and Kristofer Hallgren */ "LENOVO", "", "ThinkPad X201", "", S3_BIOS|S3_MODE, /* Daniel Corson */ "LENOVO", "", "ThinkPad X60", "", S3_BIOS|S3_MODE, /* At least 1709 series thinkpads can be whitelisted by name, and we can probably delete entries above, too.... */ "LENOVO", "", "ThinkPad Z61m", "", S3_BIOS|S3_MODE, /* Z61m From: Roderick Schertler */ "LENOVO", "", "ThinkPad Z61p", "", S3_BIOS|S3_MODE, /* Paul Wilkinson */ "LG Electronics", "LM50-DGHE", "", "", S3_BIOS|S3_MODE, /* merkur@users.sourceforge.net LM50a */ "LG Electronics", "LW20-JNMV", "", "WINRSF03", S3_BIOS|S3_MODE, /* Ragnar Seton */ "LG Electronics", "LW75-SGGV1", "", "", S3_BIOS|S3_MODE, /* jsusiluo@mappi.helsinki.fi */ "LG Electronics", "M1-3DGBG", "", "", S3_BIOS|S3_MODE, /* jsusiluo@mappi.helsinki.fi */ "LG Electronics", "R500-U.CPCBG", "", "", 0, /* Neysan Schaefer */ " ", "M37EW", "None", "", S3_BIOS, /* simon kaucic */ "Matsushita Electric Industrial Co.,Ltd.", "CF-51E*", "", "", VBE_POST|VBE_MODE, /* seife */ "Matsushita Electric Industrial Co.,Ltd.", "CF-R2C*", "0032", "", VBE_POST|VBE_MODE, /* https://sourceforge.net/tracker/index.php?func=detail&aid=1601715&group_id=45483&atid=443088 */ "Matsushita Electric Industrial Co.,Ltd.", "CF-R3E*", "002", "", VBE_POST|VBE_MODE, /* Hanspeter Kunz */ "Matsushita Electric Industrial Co.,Ltd.", "CF-R6A*", "", "", VBE_POST|VBE_MODE, /* Hanspeter Kunz */ "Matsushita Electric Industrial Co.,Ltd.", "CF-R6M*", "", "", VBE_POST|VBE_MODE, /* Itsuo HATONO */ "Matsushita Electric Industrial Co.,Ltd.", "CF-W4G*", "", "", 0, /* Michal Krasucki */ "MAXDATA", "IMPERIO4045A *", "", "", 0, /* Joost Witteveen */ "MAXDATA", "PRO600IW", "", "", S3_BIOS|S3_MODE, /* Jan Gerrit */ "MaxSelect", "Mission_A330", "", "", VBE_POST|VBE_SAVE, /* Oleg Broytmann */ "MEDION", "M295M", "", "", 0, /* Nicolas HENRY , nvidia binary driver */ "MEDIONNB ", "WID2010 ", "", "", VBE_POST|VBE_MODE, /* Leszek Lesner Medion MD43100 */ "MEDIONNB ", "WIM 2000 ", "", "", 0, /* Ralf Auer , tested both with nv and binary nvidia */ "MEDIONPC", "MS-6714", "", "", S3_BIOS|S3_MODE, /* Alberto Gonzalez */ "MEDIONPC", "MS-7012", "", "", 0, /* Mike Galbraith needs X to get text console back */ "MEDION", "WIM 2140", "", "", 0, /* Axel Braun */ "MICRO-STAR INTERNATIONAL CO.,LTD", "MS-7514", "1.0", "V1.10", 0, /* Apr 4, 2010 - Mark van Dijk */ "MICRO-STAR INTERNATIONAL CO.,LTD", "MS-7596", "1.0", "V2.3", 0, /* Aug 1, 2010 - Tristan Hoffmann */ "MICRO-STAR INTERNATIONAL CO., LTD", "MS-9632", "1.0", "6.00 PG", 0, /* Oct 13, 2010 - Matti Ropo */ "MICRO-STAR INTERNATIONAL CO., LTD", "MS-N014", "REV:1.0", "EN014IMS.10B", 0, /* Jan 21, 2010 - Paul Slater */ "MICRO-STAR INTERNATIONAL CO., LTD", "U-100", "", "", S3_BIOS|S3_MODE, /* MSI Wind U100, fseidel@suse.de */ "Micro-Star International", "EX610", "", "", VBE_POST|VBE_MODE, /* Frank Thomas */ "Micro-Star International", "MS-1412", "", "", VBE_POST|VBE_SAVE|NOFB, /* Baruch Even */ "Micro-Star International", "PR210", "MS-1222X", "", VBE_POST, /* Enno Wein */ "Micro-Star International", "U210", "Ver 1.000", "080015 ", VBE_POST|VBE_MODE, /* Daniel */ "Micro-Star International", "X320", "Ver 1.000", "A1351IMS Ver1.01 ", VBE_SAVE, /* Feb 12, 2010 - Zach Foresta */ "MICRO-STAR INT'L CO.,LTD", "MS-1003", "", "", 0, /* Branislav Gajdos */ "MICRO-STAR INT'L CO.,LTD", "MS-1012", "", "", S3_BIOS, /* Andreas Kostyrka */ "MICRO-STAR INT'L CO.,LTD", "MS-1013", "", "", S3_BIOS, /* Matthijs Kooijman */ "MICRO-STAR INT'L CO.,LTD.", "MS-1057", "", "", S3_BIOS|S3_MODE, /* Gergely Csepany */ " ", " ", " ", "MOPNV10N.86A.0155.2009.1106.0430", 0, /* May 24, 2010 - Carl van Tonder */ " ", " ", " ", "MQ96510J.86A.0816.2006.0716.2308", VBE_POST|VBE_MODE, /* Armin Braunstein */ "MSI", "A9830IMS", "11", "080015 ", S3_BIOS|S3_MODE, /* MSI IM-945GSE, Martin Teufel */ "MSI", "MS-6417", "", "", 0, /* Matej Tyc */ "MSI", "MS-6702", "", "", 0, /* Petric Frank MSI K8T Neo-FIS2R */ "MSI.", "MS-7207PV", "", "", 0, /* uswsusp@faxm0dem.org */ "MSI", "MS-7350", "", "", 0, /* Nicholas T , mainboard */ "MSI", "MS-7522", "3.0", "V8.10", 0, /* Apr 9, 2010 - Dâniel Fraga */ "MTC", "Montara-GML ", "FAB-2", "", 0, /* S.Çağlar Onur , only works from X */ "NCA_GROUP_LTD", "iRU_Notebook", "0106", "", VBE_POST|VBE_MODE, /* "Alex V. Myltsev" */ "NEC Computers International *", "VC2", "", "", S3_BIOS|S3_MODE, /* Nicky Gerritsen */ "NEC ", "L4B ", " ", "NOTE BIOS Version /358A1200 ", 0, /* Apr 20, 2010 - René Gabriëls */ "NOTEBOOK", "MIM2080", "", "", S3_BIOS|S3_MODE, /* Ronny Radke medion MIM2080 */ "NOTEBOOK", "SAM2000", "0131", "", 0, /* Jan Willies medion md 96400 */ "Notebook", "SAM2010", "1058", "A1058AM7 V7.23", VBE_SAVE, /* Tomas Groth */ "OEM", "P53IN4", "", "", 0, /* Thomas Braun , rebranded Uniwill P53IN */ "OQO", "ZEPTO", "00", "", VBE_POST|VBE_SAVE, /* Wolf Geldmacher */ "Packard Bell NEC", "00000000000000000000000", "", "A03 ", 0, /* Angelo Anfossi "Easy Note A6010" */ "Packard Bell NEC", "00000000000000000000000", "P820008416", "", 0, /* Per Waago */ "Quanta", "TW8/SW8/DW8", "", "", 0, /* Mar 1, 2010 - Jan-Matthias Braun */ "SAMSUNG", "CoronaR", "03RK", "", 0, /* Florian Tham Samsung P35 */ "SAMSUNG ELECTRONICS CO., LTD.", "N130 ", "Not Applicable", "05CM.M011.20091013.JIP", 0, /* Aug 11, 2010 - Jan Bessai */ "SAMSUNG ELECTRONICS CO., LTD.", "Q330 ", "Not Applicable", "02UU.M001.20100611.WZW", 0, /* Aug 31, 2010 - Marco Maso */ "SAMSUNG ELECTRONICS CO., LTD.", "Q35/Q36", "", "", S3_BIOS|S3_MODE, /* Jeremie Delaitre */ "SAMSUNG ELECTRONICS CO., LTD.", "R40/R41", "", "", VBE_SAVE, /* Eduardo Robles Elvira */ "SAMSUNG ELECTRONICS CO.,LTD", "R50/R51 *", "", "", 0, /* Tim Fischer works with and without ATI binary driver */ "SAMSUNG ELECTRONICS CO., LTD.", "R520/R522/R620 ", "Not Applicable", "06LL.M026.20091029.Jay", VBE_POST|VBE_MODE, /* Jan 22, 2010 - Rafał Miłecki */ "SAMSUNG ELECTRONICS CO., LTD.", "R55S *", "", "", 0, /* Daniel Koester does not yet work from text mode */ "SAMSUNG ELECTRONICS CO., LTD.", "SQ1US", "01ME", "", VBE_SAVE, /* Pavel Machek, Samsung UMPC */ "SAMSUNG ELECTRONICS CO., LTD.", "SQ35S", "", "", VBE_POST, /* Maximilian Mehnert */ "SAMSUNG ELECTRONICS CO., LTD.", "SQ45S70S", "", "", S3_BIOS|S3_MODE, /* Frank Ruell or J�r�mie no flags */ "SAMSUNG ELECTRONICS CO., LTD.", "SR700", "", "", 0, /* Jens Ott */ "SAMSUNG ELECTRONICS CO., LTD.", "SX22S", "07AJ", "", VBE_SAVE, /* Konstantin Krasnov , only with kernel 2.6.24++ */ "Samsung Electronics", "NX05S*", "", "", VBE_POST|VBE_MODE, /* Arnim Laeuger */ "SAMSUNG Electronics", "SENS V25", "", "", VBE_POST|VBE_MODE, /* Stephen Denham */ "Samsung Electronics", "SM40S", "", "", S3_BIOS|S3_MODE, /* Gautier Hattenberger */ "Samsung Electronics", "SX20S", "", "", VBE_POST|VBE_MODE, /* https://bugzilla.novell.com/show_bug.cgi?id=290734 */ "Samsung Electronics", "SX25S", "Revision MP", "04ZA", 0, /* Mar 4, 2010 - Christoph Schäfer */ "Samsung Electronics", "SX50S", "Revision MP", "", VBE_POST, /* Martin Wilck */ "Samsung", "SQ10", "", "", VBE_POST|VBE_SAVE, /* */ "SHARP Corporation", "PC-MM20 Series*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "SHARP ", "PC-AR10 *", "", "", 0, /* */ "Shuttle Inc", "SD11V10", "", "", S3_BIOS|S3_MODE, /* & Frederic Boiteux */ "Shuttle Inc", "SD30V10", "", "", S3_BIOS|S3_MODE, /* Tejun Heo, https://bugzilla.novell.com/show_bug.cgi?id=390127 */ "Shuttle Inc", "SD32V10", " ", "6.00 PG", 0, /* Dave Buckler */ "Shuttle Inc", "SG33", "V10", "6.00 PG", 0, /* Rodolfo kix Garcia */ "Shuttle Inc", "SN41UV10", "", "", VBE_POST|VBE_MODE, /* foren@nuxli.ch */ "Shuttle Inc", "SN85V10", "", "", 0, /* Thomas Peuss */ "Sony Corporation ", "PCG-F430(UC) ", "", "", 0, /* Russ Dill */ "Sony Corporation", "PCG-FR215E*", "", "", 0, /* Brice Mealier */ "Sony Corporation", "PCG-FX340*", "", "", VBE_SAVE, /* Eric Wasylishen , really needs VBE_SAVE */ "Sony Corporation", "PCG-FX405*", "", "", S3_BIOS, /* Sitsofe Wheeler */ "Sony Corporation", "PCG-FX601*", "", "", S3_BIOS|S3_MODE, /* Stefan Nobis */ "Sony Corporation", "PCG-FX802*", "", "", VBE_SAVE|VBE_MODE, /* Loki Harfagr */ "Sony Corporation", "PCG-FX805*", "", "", VBE_POST|VBE_SAVE, /* Stefan Friedrich */ "Sony Corporation ", "PCG-GR7_K(J) ", "", "", 0, /* Mattia Dongili */ "Sony Corporation", "PCG-GRT916Z*", "", "", 0, /* Marco Nenciarini */ "Sony Corporation", "PCG-GRT995MP*", "", "", 0, /* */ "Sony Corporation ", "PCG-GRX500(UC) ", "R2715195 ", "R0202B0", 0, /* Jan 17, 2010 - Killua Zaoldyeck */ "Sony Corporation", "PCG-TR2A(UC)", "", "", VBE_MODE, /* Bruce Perens */ "Sony Corporation", "PCG-U101*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "Sony Corporation", "PCG-Z1RMP*", "", "", VBE_POST|VBE_MODE, /* mathieu bouillaguet */ "Sony Corporation", "PCG-Z505HSK(UC)", "", "", 0, /* Tom Lear */ "Sony Corporation", "PCV-RX612*", "", "", S3_BIOS|S3_MODE, /* jmj_sf@freenet.de */ "Sony Corporation", "VGN-A115B*", "", "", 0, /* Daniel Sabanes Bove */ "Sony Corporation", "VGN-AR31S", "", "", S3_BIOS|S3_MODE, /* Dean Darlison , maybe only with nvidia driver */ "Sony Corporation", "VGN-B1VP(GB)", "J000L04A", "R0042G9", S3_BIOS|S3_MODE, /* Sony VGN-B1VP, M. Vefa Bicakci */ "Sony Corporation", "VGN-B1XP*", "", "", S3_BIOS, /* Daniel Morris */ "Sony Corporation", "VGN-B55G(I)", "", "", 0, /* Dhananjaya Rao */ "Sony Corporation", "VGN-C140G", "", "", S3_BIOS|S3_MODE, /* Jorge Visca */ "Sony Corporation", "VGN-C210E", "C3LNT131", "R0080J4", S3_BIOS, /* May 25, 2010 - kriZ */ "Sony Corporation", "VGN-C240E", "", "", S3_BIOS|S3_MODE, /* Marc Collin https://bugzilla.novell.com/show_bug.cgi?id=410723 */ "Sony Corporation", "VGN-C2S_G", "", "", S3_BIOS, /* Tijn Schuurmans */ "Sony Corporation", "VGN-C2S_H", "", "", 0, /* Gerhard Riener */ "Sony Corporation", "VGN-CR11Z_R", "C10191M5", "R0220Q0", 0, /* May 29, 2010 - Duane Griffin */ "Sony Corporation", "VGN-CS290J", "A222DVFY", "R1080Q2", 0, /* Apr 2, 2010 - joshua bowles */ "Sony Corporation", "VGN-FE11M", "", "", 0, /* David Durrleman , only from X :-( */ "Sony Corporation", "VGN-FE21B", "", "", S3_BIOS, /* Gert Huizenga */ "Sony Corporation", "VGN-FE31M", "", "", 0, /* , only from X, S3_MODE hangs the machine, all other leave the screen blank */ "Sony Corporation", "VGN-FE890E", "", "", 0, /* Bernardo Freitas Paulo da Costa */ "Sony Corporation", "VGN-FS115B", "", "", S3_BIOS|S3_MODE, /* */ "Sony Corporation", "VGN-FS115Z", "", "", S3_MODE, /* Olivier Saier , apparently S3_BIOS locks the machine hard */ "Sony Corporation", "VGN-FS215B", "", "", 0, /* S.Çağlar Onur */ "Sony Corporation", "VGN-FS215M", "", "", 0, /* Chris deLuXCios */ "Sony Corporation", "VGN-FS485B", "", "", S3_BIOS|S3_MODE, /* Tim Felgentreff */ "Sony Corporation", "VGN-FS660_W", "", "", 0, /* Joseph Smith */ "Sony Corporation", "VGN-FS920", "", "", S3_BIOS|S3_MODE, /* phantomlrrp@gmail.com */ "Sony Corporation", "VGN-FW11*", "", "", VBE_POST|VBE_MODE, /* Rafal Milecki and Thomas Bayen */ "Sony Corporation", "VGN-FW31J", "C601640W", "R2060Y0", VBE_POST|VBE_MODE, /* Jan 18, 2010 - Michael Bunk */ "Sony Corporation", "VGN-FZ39VN", "", "", 0, /* Stefano Avallone */ "Sony Corporation", "VGN-N21Z_W", "", "", 0, /* 03/08/2009, Sony Vaio VGN-N21Z_W, Raphael Scholer */ "Sony Corporation", "VGN-N320E", "", "", 0, /* Fredrik Roubert */ "Sony Corporation", "VGN-NW130D", "", "", 0, /* 26/12/2009 Adriano Vilela Barbosa */ "Sony Corporation", "VGN-P11Z_Q", "J003NNCC", "R2073U3", S3_MODE, /* Martin Hamilton */ "Sony Corporation", "VGN-S150(UC)", "J0007XLN", "R0041G4", 0, /* Feb 2, 2010 - Thom Siragusa */ "Sony Corporation", "VGN-SZ340P", "", "", 0, /* daryl@mail.bg */ "Sony Corporation", "VGN-SZ38GP_C", "J0022RTD", "R0091N0", 0, /* Jan 9, 2010 - neo */ "Sony Corporation", "VGN-SZ5XN_C", "", "", 0, /* Pedro M. S. Oliveira , machine has two gfx cards, works only well with the intel, not with the nvidia */ "Sony Corporation", "VGN-SZ61XN_C", "", "", S3_BIOS|S3_MODE, /* Michal Bozek */ "Sony Corporation", "VGN-SZ770N", "J0035SEN", "R0122S5", S3_BIOS|S3_MODE, /* Apr 3, 2010 - Konstantin Starodubtsev */ "Sony Corporation", "VGN-T250P", "", "", S3_BIOS|S3_MODE, /* Anton Zahlheimer */ "Sony Corporation", "VGN-TX3HP", "", "", 0, /* Timo Hoenig VGN-TX3HP */ "Sony Corporation", "VGN-TX3XP_L", "", "", S3_BIOS|S3_MODE, /* Stephan Martin */ "Sony Corporation", "VGN-TX5MN_W", "", "", VBE_MODE, /* Danny Kukawka , TX5MN from Michael Matz */ "Sony Corporation", "VGN-TX670P", "", "", VBE_POST|VBE_MODE, /* rbm@math.mit.edu */ "Sony Corporation", "VGN-TX770P", "", "", VBE_POST|VBE_MODE, /* */ "Sony Corporation", "VGN-TZ11*", "", "", 0, /* Pier Paolo Pittavino , Timo Hoenig */ "Sony Corporation", "VGN-TZ170N", "", "", S3_BIOS|S3_MODE, /* Raymond Russell */ "Sony Corporation", "VGN-TZ21XN_B", "", "", 0, /* Hans Gunnarsson */ "Sony Corporation", "VGN-TZ37*", "", "", S3_BIOS|S3_MODE, /* matt@thewaffleproject.com */ "Sony Corporation", "VGN-TZ91HS", "", "", 0, /* Jan P. O. Schuemann" */ "Sony Corporation", "VGN-UX50", "", "", VBE_MODE, /* Mattia Dongili */ "Sony Corporation", "VGN-Z90S", "", "", 0, /* ISHIKAWA Mutsumi */ "Sony Corporation", "VPCF11E4E", "C603V8KU", "R0280Y6", S3_BIOS, /* Oct 28, 2010 - Benoit Vidis */ "Sony Corporation", "VPCP111KX", "C606NMD8", "R0110U5", VBE_POST|VBE_SAVE, /* Stephan Mueller */ "Sony Corporation", "VPCZ128GG", "J0049W8Q", "R2074C3", S3_BIOS|S3_MODE, /* Oct, 2010 - Jason O'Neil */ "System manufacturer", "P5KR", "System Version", "", 0, /* ASUS Mainboard, also broken DMI strings... Luis Valino */ "System manufacturer", "P5Q DELUXE", "System Version", "", S3_BIOS|S3_MODE, /* ASUS Mainboard, Gary Andrew https://bugzilla.novell.com/show_bug.cgi?id=419813 */ "System manufacturer", "System name", "1.XX ", "ASUS A8N-SLI ACPI BIOS Revision 1001", 0, /* May 3, 2010 - */ "System Manufacturer", "System Name", "System Version", "ASUS P4B266 ACPI BIOS Revision 1010", S3_BIOS|S3_MODE, /* Asus P4B266, s2ram -f -a 3 Olivier Berger */ "System manufacturer", "System Product Name", "System Version", "0208 ", 0, /* June 12, 2010 - Donald Jenkins */ "System manufacturer", "System Product Name", "System Version", "0705 ", 0, /* Mar 1, 2010 - ali mofasa */ "System manufacturer", "System Product Name", "System Version", "ASUS M2A-VM HDMI ACPI BIOS Revision 0902", 0, /* Feb 28, 2010 - Christian Hammers */ "To Be Filled By O.E.M.", "259IA1", "To Be Filled By O.E.M.", "080010 ", S3_MODE, /* Pavol Otcenas , "Prestigio Nobile 159W" */ "To Be Filled By O.E.M.", "MS-7210", "100", "", 0, /* Petr Pudlak */ "TOSHIBA", "EQUIUM A100", "", "", S3_BIOS|S3_MODE, /* Kevin Fullerton */ "TOSHIBA", "Libretto L5/TNK", "", "", 0, /* */ "TOSHIBA", "Libretto L5/TNKW", "", "", 0, /* */ "TOSHIBA", "libretto U100*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "TOSHIBA", "P3490", "", "", VBE_SAVE, /* Pavel Borzenkov , Toshiba Portege 3490CT, works correctly for me */ "TOSHIBA", "P4000*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "TOSHIBA", "Portable PC", "Version 1.0", "Version 1.20", 0, /* Hans-Hermann Jopski Tecra A2 PTA20E-4M301VGR */ "TOSHIBA", "Portable PC", "Version 1.0", "Version 1.60", S3_MODE, /* a PORTEGE 100 :-( mykhal@centrum.cz */ "TOSHIBA", "Portable PC", "Version 1.0", "Version 7.80", S3_MODE, /* this is a Toshiba Satellite 4080XCDT, believe it or not :-( */ "TOSHIBA", "PORTEGE 3500", "PP350E-002F6-EN", "Version 1.40", 0, /* Toshiba Portege 3500, James Le Cuirot */ "TOSHIBA", "PORTEGE A100*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "TOSHIBA", "PORTEGE A200*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "TOSHIBA", "PORTEGE A600", "PPA61E-01700EGR", "Version 1.50", 0, /* Toshiba Portege A600-13Y, Gregor Zattler */ "TOSHIBA", "PORTEGE M200*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "TOSHIBA", "PORTEGE M300", "", "", S3_MODE, /* Alan Mycroft */ "TOSHIBA", "Portege M400", "000000", "Version 3.80", 0, /* Oct 26, 2010 - Alexander Gehrke */ "TOSHIBA", "PORTEGE R100", "", "", 0, /* Mathieu Lacage */ "TOSHIBA", "PORTEGE R200", "", "", S3_BIOS|S3_MODE, /* hole@gmx.li */ "TOSHIBA", "PORTEGE R500", "", "", S3_BIOS|S3_MODE, /* Bernhard Kausler */ "TOSHIBA", "Qosmio G40", "PQG40E-01G019FR", "Version 2.20", 0, /* Nov 15, 2010 - Didier Marion */ "TOSHIBA", "Satellite 1130", "", "", VBE_SAVE, /* Kai-Ove Pietsch */ "TOSHIBA", "Satellite 1900*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "TOSHIBA", "Satellite A100", "", "", S3_BIOS|S3_MODE, /* From: a.maurizi@isac.cnr.it */ "TOSHIBA", "Satellite A105", "", "", S3_BIOS|S3_MODE, /* Eric Siegel , intel chipset, sys_version="PSAA8U-0MD02K" */ "TOSHIBA", "Satellite A10", "", "", S3_BIOS|S3_MODE, /* Fabio Olivares sys_version = "PSA10E-018EZ-6A" */ "TOSHIBA", "Satellite A200", "", "", S3_BIOS|S3_MODE, /* Jan Urbanski , sys_version="PSAE0E-04600TPL" */ "TOSHIBA", "Satellite A205", "", "", S3_BIOS|S3_MODE, /* Brian Conn sys_version="PSAE3U-087023" Andrew Barilla "PSAE3U-07R025" */ "TOSHIBA", "Satellite A210", "", "", S3_BIOS|S3_MODE, /* Gavin Kinsey */ "TOSHIBA", "Satellite A215", "", "", S3_BIOS|S3_MODE|PCI_SAVE, /* David Picella sys_version = "PSAFGU-048002" */ "TOSHIBA", "Satellite A300D", "", "", VBE_POST|VBE_SAVE, /* Grzegorz Konopko sys_version = "PSAK0E-00600GPL" */ "TOSHIBA", "Satellite A305D", "PSAH0U-00Q009", "1.90 ", S3_MODE, /* Jan 10, 2010 - Chris Olin */ "TOSHIBA", "Satellite A30", "", "", VBE_SAVE, /* */ "TOSHIBA", "Satellite A45", "PSA40U-000HNV", "Version 1.30", 0, /* TOSHIBA Satellite A45, Shawn A. Wilson */ "TOSHIBA", "Satellite A80", "", "", 0, /* Diego Ocampo */ "TOSHIBA", "Satellite L10", "", "", VBE_POST|VBE_MODE, /* Christian Schneeman */ "TOSHIBA", "Satellite L300", "PSLB8U-0NQ069", "1.80", 0, /* Jesse Taylor */ "TOSHIBA", "Satellite L305", "PSLB8U-13T038", "1.80", VBE_POST|VBE_MODE, /* Toshiba Satellite L305-S5955, Dan */ "TOSHIBA", "Satellite L30", "", "", S3_BIOS|S3_MODE, /* Gijs van Gemert */ "TOSHIBA", "Satellite L655D", "PSK2LU-00G001", "1.70", 0, /* Andrey Petrov */ "TOSHIBA", "SATELLITE M100", "PSMA0E-030014CZ", "V1.60", 0, /* Toshiba Satellite M100, Ji.� Appl */ "TOSHIBA", "Satellite M105", "", "", S3_BIOS|S3_MODE, /* Krzysztof Lubanski , sys_version = "PSMA0U-0F301U" */ "TOSHIBA", "Satellite M30X", "", "", S3_BIOS, /* tnt.rocket@freenet.de, need to verify if S3_MODE is needed too */ "TOSHIBA", "Satellite M35X", "", "", S3_BIOS|S3_MODE, /* Michaell Gurski */ "TOSHIBA", "Satellite M40", "PSM43U-*", "Version 1.50", 0, /* Feng.Charles@inventec.com */ "TOSHIBA", "Satellite M55", "", "", VBE_POST|VBE_MODE, /* Mike Gilliam */ "TOSHIBA", "Satellite M60", "PSM60E-0C801GGR", "V1.40", VBE_POST|VBE_MODE, /* Peter Ingold */ "TOSHIBA", "Satellite M645", "PSMPMU-00G001", "1.10", S3_MODE, /* Oct 29, 2010 - Ulrich Englich */ "TOSHIBA", "Satellite M70", "", "", 0, /* (BAD: clist@uah.es S3_BIOS|S3_MODE) */ "TOSHIBA", "Satellite P100", "", "", 0, /* zu@ten.ch sys_version = "PSPAGE-00H00RS4" */ "TOSHIBA", "Satellite P10", "", "", S3_BIOS|S3_MODE, /* Antonis Tsolomitis */ "TOSHIBA", "Satellite P200", "", "", S3_BIOS|S3_MODE, /* From: mire */ "TOSHIBA", "Satellite P205D", "", "", S3_BIOS|S3_MODE, /* cl.kerr@gmail.com */ "TOSHIBA", "Satellite P300", "PSPCCE-02C006FR", "V2.40 ", VBE_POST|VBE_SAVE, /* From: deap */ "TOSHIBA", "SatellitePro4600", "", "", 0, /* From: Jim */ "TOSHIBA", "Satellite Pro A120", "", "", S3_BIOS|S3_MODE, /* Stephen Jarrett-Sprague sys_version="PSAC1E-0J3021EN" */ "TOSHIBA", "Satellite Pro M15", "PS630U-G205HV", "Version 1.50", 0, /* Toshiba Satellite Pro M15, Mark Chace */ "TOSHIBA", "Satellite Pro M70", "", "", S3_BIOS|S3_MODE, /* Francisco Palomo Lozano sys_version="PSM75E-00G00TSP" */ "TOSHIBA", "Satellite Pro U300", "", "", 0, /* Neil Symington, https://bugzilla.novell.com/show_bug.cgi?id=386505, kernel 2.6.25-x86_64 */ "TOSHIBA", "Satellite R630", "PT31LE_00V006CE", "Version1.60 ", 0, /* Luis Nieto Piña */ "TOSHIBA", "SATELLITE U200", "", "", 0, /* Jean-Pierre Bergamin , kernel 2.6.25.3, sys_version "PLUA0E-01C007S4" */ "TOSHIBA", "SATELLITE U300", "", "", 0, /* Robin James, sys_version="PSU30E-04L02QKS" */ "TOSHIBA", "Satellite U305", "", "", VBE_POST|VBE_MODE, /* Romano Giannetti sys_version "PSU34U-00L003" */ "TOSHIBA", "SP4600", "Version 1.0", "", 0, /* Bram Senders */ "TOSHIBA", "T9000", "", "", VBE_MODE, /* Silverio Santos , Tecra 9000 */ "TOSHIBA", "TECRA8100", "", "", S3_MODE, /* From: a v */ "TOSHIBA", "TECRA 8200", "", "", S3_MODE, /* Stefan Seyfried has one of those :-) S3_BIOS leads to "melting screen" */ "TOSHIBA", "TECRA A2*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "TOSHIBA", "TECRA A5*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "TOSHIBA", "TECRA A8", "", "", 0, /* Thomas Zander sys_version "PTA83E-0E303LDU" */ "TOSHIBA", "TECRA A9", "", "", 0, /* Arne Salveter sys_version "PTS52E-00X00GGR" */ "TOSHIBA", "TECRA M2*", "", "", VBE_POST|VBE_SAVE|UNSURE, /* imported from acpi-support 0.59 "half known". */ "TOSHIBA", "TECRA M4", "", "", VBE_POST|VBE_MODE, /* Alexandru Romanescu https://bugzilla.novell.com/show_bug.cgi?id=398270 */ "TOSHIBA", "TECRA M9", "", "", S3_MODE, /* Dr. Stephan Buehne */ "TOSHIBA", "TECRA S1", "", "", 0, /* Jad Naous */ "TOSHIBA", "TECRA S2", "", "", VBE_POST|VBE_SAVE, /* Arjen Dragt sys_version="PTS20C-SX501E" */ "TOSHIBA", "TECRA S3", "", "", 0, /* */ "transtec AG", "MS-1034", "", "", S3_BIOS|S3_MODE, /* Joachim Gleissner */ "transtec AG", "MS-1057", "", "", S3_BIOS|S3_MODE, /* Gregory Colpart 'Transtec Levio 210' */ "VIA", "K8N800", "VT8204B ", "", VBE_POST|VBE_SAVE, /* Clevo D410J, Márton Németh */ "VIA", "K8T400", "VT8204B ", "", S3_BIOS|S3_MODE, /* Clevo D470K, Jasper Mackenzie */ "VIA Technologies, Inc.", "KT400-8235", "", "", S3_BIOS|S3_MODE, /* Dolezal Lukas */ "VIA Technologies, Inc.", "KT400A-8235", "", "", S3_BIOS|S3_MODE, /* */ "VIA Technologies, Inc.", "VT8623-8235", "", "", S3_MODE, /* VIA EPIA M Mini-ITX Motherboard with onboard gfx, reported by Monica Schilling */ "wortmann", "M7x0S ", "Rev. A1 ", "6.00", VBE_SAVE, /* Feb 15, 2010 - Jonas Schwabe */ "Zepto", "Nox", "A14H", "A14H", 0, /* May 18, 2010 - Damien Thébault */ suspend-utils/s2ram-ppc.c0000644000175500017550000000326012075743443014041 0ustar kixkix/* * Suspend-to-RAM - PPC code * * Copyright 2006 Tim Dijkstra * Copyright 2006 Luca Tettamanti * Distribute under GPLv2. */ #include "config.h" #include #include #include #include #include #include #include #include #include "s2ram.h" void s2ram_add_flag(int opt, const char *arg) { /* We don't take any options */ } int s2ram_prepare(void) { return 0; } void s2ram_resume(void) { /* nop */ } void identify_machine(void) { printf("We don't have quirks and hence no whitelist on powerpc\n"); } int machine_known(void) { printf("We don't have quirks and hence no whitelist on powerpc\n"); return 0; } int s2ram_hacks(void) { return 0; } int s2ram_is_supported(void) { int fd, ret = 0; unsigned long arg = 0; /* PMU_IOC_CAN_SLEEP is going away, so we only say unsupported * if PMU_IOC_CAN_SLEEP explicitly says we can't */ fd = open("/dev/pmu", O_RDWR); if (fd < 0) return 0; ret = ioctl(fd, PMU_IOC_CAN_SLEEP, &arg); if (!ret && arg != 1) ret = ENOTSUP; close(fd); return 0; } static int s2ram_do_pmu (void) { int fd; int ret = 0; unsigned long arg = 0; fd = open("/dev/pmu", O_RDWR); if (fd < 0) return errno; ret = ioctl(fd, PMU_IOC_CAN_SLEEP, &arg); if (!ret && arg != 1) ret = ENOTSUP; if (!ret) ret = ioctl(fd, PMU_IOC_SLEEP, 0); if (ret) ret = errno; close(fd); return ret; } int s2ram_do(void) { int ret; /* If this works we're done. Else we just continue as if nothing * happened, future kernels will work with /s/p/s. */ ret = s2ram_do_pmu(); if (!ret) return ret; return s2ram_generic_do(); } suspend-utils/manpages/0000755000175500017550000000000012075743443013663 5ustar kixkixsuspend-utils/manpages/Makefile.am0000644000175500017550000000034112075743443015715 0ustar kixkix# Makefile.am for manpages # Rodolfo García Peñas (kix) 20120312 man_MANS = \ s2disk.8 \ s2ram.8 \ suspend.conf.5 \ suspend-keygen.8 \ swap-offset.8 EXTRA_DIST = $(man_MANS) suspend-utils/manpages/swap-offset.80000644000175500017550000000503612075743443016216 0ustar kixkix'\" t .\" Title: swap-offset .\" Author: Tim Dijkstra .\" Updated: Rodolfo García Peñas (kix) .\" Date: Feb 29, 2012 .\" Manual: swap-offset .\" Source: suspend-utils .\" Language: English .\" .TH "SWAP\-OFFSET" "8" "Feb 29, 2012" "suspend-utils" "swap-offset" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" swap-offset \- program to calculate the offset of a swap file in a partition .SH "SYNOPSIS" .HP \w'\fBswap\-offset\fR\ 'u \fBswap\-offset\fR [] .SH "DESCRIPTION" .PP This manual page documents briefly the \fBswap\-offset\fR\&. .PP The programs \fBs2disk\fR and \fBs2both\fR can be used to save the state of the whole system to a swap partition or file and power off or suspend your system\&. After restarting your system it will be put back in the exact system state you left it (this is sometimes called hibernation)\&. .PP In the case of using a swap file you will have to specify the location of the swap file\*(Aqs header as the offset from the beginning of the partition that contains the swap file\&. The \fBswap\-offset\fR utility can be used to determine this value\&. .SH "SEE ALSO" .PP suspend\&.conf(8), s2disk(8) .PP For more information see the README file. .SH "AUTHOR" .PP This manual page was written by Tim Dijkstra \&.org for the Debian(TM) system (but may be used by others)\&. Was updated by Rodolfo García . Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 any later version published by the Free Software Foundation\&. .RE .SH "COPYRIGHT" .br Copyright \(co 2006 Tim Dijkstra Copyright \(co 2012 Rodolfo García (kix) .br suspend-utils/manpages/s2ram.80000644000175500017550000001020512075743443014776 0ustar kixkix'\" t .\" Title: s2ram .\" Author: Tim Dijkstra .\" Updated: Rodolfo García Peñas (kix) .\" Date: Feb 29, 2012 .\" Manual: s2ram .\" Source: suspend-utils .\" Language: English .\" .TH "S2RAM" "8" "Feb 29, 2012" "suspend-utils" "s2ram" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" s2ram \- program to suspend to ram (suspend) .SH "SYNOPSIS" .HP \w'\fBs2ram\fR\ 'u \fBs2ram\fR [\-h,\ \-\-help] [\-V,\ \-\-version] [\-n,\ \-\-test] [\-i,\ \-\-identify] [\-\-nofbsuspend] [\-\-force] [\-\-vbe_save] [\-\-vbe_mode] [\-\-radeontool] [\-\-acpi_sleep\ \fInr\fR] [\-\-pci_save] .SH "DESCRIPTION" .PP This manual page documents briefly the \fBs2ram\fR command\&. .PP \fBs2ram\fR is a program that will suspend your system to ram (put it in S3 mode)\&. Which means that the system is in a lower power mode\&. It asked to do so it will wake up farely quickly\&. However, if the system will run out of energy entirely you will lose data\&. That is why it is recommended to use \fBs2both\fR(8) \fBs2ram\fR is only provided to find out any work around needed to make suspend to both work\&. See README\&.s2ram\-whitelist and README\&.Debian for more information\&. .SH "OPTIONS" .PP \fB\-V, \-\-version\fR .RS 4 Version information\&. .RE .PP \fB\-a, \-\-acpi_sleep \fR\fB\fInr\fR\fR .RS 4 set the acpi_sleep parameter before suspend\&. 1=s3_bios, 2=s3_mode, 3=both\&. Only for Intel platform (x86/amd64)\&. .RE .PP \fB\-f, \-\-force\fR .RS 4 force suspending, even on unknown machines\&. the following options are only available with \-\-force\&. .RE .PP \fB\-h, \-\-help\fR .RS 4 Short help text\&. .RE .PP \fB\-i, \-\-identify\fR .RS 4 prints a string that identifies the machine\&. .RE .PP \fB\-k, \-\-kmstest\fR .RS 4 test if the kernel supports KMS (Kernel Mode Set)\&. Returns 0 if KMS is supported\&. .RE .PP \fB\-m, \-\-vbe_mode\fR .RS 4 get VBE mode before suspend and set it after resume\&. Only for Intel platform (x86/amd64)\&. .RE .PP \fB\-n, \-\-test\fR .RS 4 test if the machine is in the database\&. Returns 0 if known and supported\&. .RE .PP \fB\-p, \-\-vbe_post\fR .RS 4 VBE POST the graphics card after resume\&. Only for Intel platform (x86/amd64)\&. .RE .PP \fB\-r, \-\-radeontool\fR .RS 4 turn off the backlight on radeons before suspending\&. Only for Intel platform (x86/amd64)\&. .RE .PP \fB\-s, \-\-vbe_save\fR .RS 4 save VBE state before suspending and restore after resume\&. Only for Intel platform (x86/amd64)\&. .RE .PP \fB\-v, \-\-pci_save\fR .RS 4 Save the PCI config space of the VGA card before suspend and restore it after resume\&. Only for Intel platform (x86/amd64)\&. .RE .PP \fB\-\-nofbsuspend\fR .RS 4 do not suspend the framebuffer (for debugging purposes)\&. Only for Intel platform (x86/amd64)\&. .RE .SH "SEE ALSO" .PP s2both (8)\&. .PP For more information see the README\&.s2ram\-whitelist. .SH "AUTHOR" .PP This manual page was written by Tim Dijkstra \&.org for the Debian(TM) system (but may be used by others)\&. Was updated by Rodolfo García . Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 any later version published by the Free Software Foundation\&. .RE .SH "COPYRIGHT" .br Copyright \(co 2006 Tim Dijkstra Copyright \(co 2012 Rodolfo García (kix) .br suspend-utils/manpages/s2disk.80000644000175500017550000000777112075743443015167 0ustar kixkix'\" t .\" Title: s2disk .\" Author: Tim Dijkstra .\" Updated: Rodolfo García Peñas (kix) .\" Date: Feb 29, 2012 .\" Manual: s2disk .\" Source: suspend-utils .\" Language: English .\" .TH "S2DISK" "8" "Feb 29, 2012" "suspend-utils" "s2disk" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" s2disk \- program to suspend to disk (hibernate) .SH "SYNOPSIS" .HP \w'\fBs2disk\fR\ 'u \fBs2disk\fR [\-h,\ \-\-help] [\-V,\ \-\-version] [\-f,\ \-\-config\ \fIconfig_file\fR] [\-r,\ \-\-resume_device\ \fIdevice\fR] [\-o,\ \-\-resume_offset\ \fIoffset\fR] [\-s,\ \-\-image_size\ \fIsize\fR] [\-P,\ \-\-parameter\ \fIparameter\fR] .HP \w'\fBresume\fR\ 'u \fBresume\fR .SH "DESCRIPTION" .PP This manual page documents briefly the \fBs2disk\fR, \fBs2both\fR and \fBresume\fR commands\&. .PP \fBs2disk\fR is a program that will save the state of the whole system to disk and power off your system\&. After restarting your system it will be put back in the exact system state you left it (this is sometimes called hibernation)\&. .PP \fBs2both\fR will do precisly the same as \fBs2disk\fR except that it will not power off the system, but will suspend it to ram (put the system in S3 mode)\&. This has the advantage that resume will be faster, with the disadvantage that you still use batteries\&. If they batteries do deplete, you still have the system state saved to disk and can resume without data loss\&. The \fBs2both\fR command also inherits all command line arguments from \fBs2ram\fR\&. .PP You will need to set up an initramfs which calls the \fBresume\fR program for this to work\&. If you use a package distributed with your Linux distribution, the kernel package which was made with the \-\-initrd option and you use mkinitramfs\-tools, this package should include the necessary parts on your initramfs\&. .PP The suspend-utils system supports encrypting the image written to disk and features a splash system, see suspend\&.conf(8) for more information\&. .SH "OPTIONS" .PP \fB\-f, \-\-config [file]\fR .RS 4 Specify alternate configuration file\&. .RE .PP \fB\-h, \-\-help\fR .RS 4 Display help\&. .RE .PP \fB\-r, \-\-resume_device [device]\fR .RS 4 Device that contains swap area\&. .RE .PP \fB\-o, \-\-resume_offset [offset]\fR .RS 4 Offset of swap file in resume device\&. .RE .PP \fB\-s, \-\-image_size [size]\fR .RS 4 Desired size of the image\&. .RE .PP \fB\-P, \-\-parameter [key=value]\fR .RS 4 Override any config file parameter (see suspend\&.conf(8))\&. .RE .PP For the meaning and use of the resume_size, resume_offset and image_size options see suspend\&.conf(8)\&. .SH "SEE ALSO" .PP suspend\&.conf(8), suspend\-keygen(8), s2ram(8) .PP For more information see the README file. .SH "AUTHOR" .PP This manual page was written by Tim Dijkstra \&.org for the Debian(TM) system (but may be used by others)\&. Was updated by Rodolfo García . Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 any later version published by the Free Software Foundation\&. .RE .SH "COPYRIGHT" .br Copyright \(co 2006 Tim Dijkstra Copyright \(co 2012 Rodolfo García (kix) .br suspend-utils/manpages/suspend-keygen.80000644000175500017550000000474712075743443016731 0ustar kixkix'\" t .\" Title: suspend-keygen .\" Author: Tim Dijkstra .\" Updated: Rodolfo García Peñas (kix) .\" Date: Feb 29, 2012 .\" Manual: suspend-keygen .\" Source: suspend-utils .\" Language: English .\" .TH "SUSPEND\-KEYGEN" "8" "Feb 29, 2012" "suspend-utils" "suspend-keygen" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" suspend-keygen \- program to generate a RSA key to be used by s2disk .SH "SYNOPSIS" .HP \w'\fBsuspend\-keygen\fR\ 'u \fBsuspend\-keygen\fR .SH "DESCRIPTION" .PP This manual page documents briefly the \fBsuspend\-keygen\fR command\&. .PP \fBsuspend\-keygen\fR is a program that will generate a RSA key which can be used by the \fBs2disk\fR to encrypt the image written to disk\&. The program does not take any options, but will ask to give the size of the key in bits and to supply a passphrase\&. You will have to enter this passphrase on \fBresume\fR to decrypt the image\&. .PP To start using encryption, you will have to point the "RSA key file" option in suspend\&.conf(8) to the file suspend\-keygen generated\&. .SH "SEE ALSO" .PP s2disk(8), suspend\&.conf(8)\&. .PP For more information see the README file. .SH "AUTHOR" .PP This manual page was written by Tim Dijkstra \&.org for the Debian(TM) system (but may be used by others)\&. Was updated by Rodolfo García . Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 any later version published by the Free Software Foundation\&. .RE .SH "COPYRIGHT" .br Copyright \(co 2006 Tim Dijkstra Copyright \(co 2012 Rodolfo García (kix) .br suspend-utils/manpages/suspend.conf.50000644000175500017550000001570412075743443016365 0ustar kixkix'\" t .\" Title: suspend.conf .\" Author: Tim Dijkstra .\" Updated: Rodolfo García Peñas (kix) .\" Date: Feb 29, 2012 .\" Manual: suspend.conf .\" Source: suspend-utils .\" Language: English .\" .TH "SUSPEND\&.CONF" "5" "Feb 29, 2012" "suspend-utils" "suspend.conf" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" suspend.conf \- Config file for the s2disk program .SH "DESCRIPTION" .PP This manual page documents briefly the \fBsuspend\&.conf\fR file used by the \fBs2disk\fR, \fBs2both\fR and \fBresume\fR commands\&. .PP \fBs2disk\fR is a program that will save the the state of the whole system to disk and power off your system\&. After restarting your system it will be put back in the exact system state you left it (this is sometimes called hibernation)\&. .SH "S2RAM / S2BOTH OPTIONS" .PP \fBs2ram_force\fR .RS 4 If the "s2ram_force" parameter is set to \*(Aqy\*(Aq, the \fBs2ram\fR tool will force the suspend process, even the machine is not known, parameters (quirks) are not set nor KMS is not supported\&. .RE .PP \fBs2ram_quirks\fR .RS 4 Specifies the options (quirks) to suspend the machine. Possible options are \fBvbe_post\fR, \fBvbe_save\fR, \fBvbe_mode\fR, \fBradeon_off\fR, \fBpci_save\fR, \fBs3_bios\fR, \fBs3_mode\fR and \fBfb_nosuspend\fR\&. More information about these options are included in s2ram(8) manpage and the README.s2ram-whitelist file. .RE .PP .SH "S2DISK / S2BOTH OPTIONS" .PP \fBsnapshot device [=/dev/snapshot]\fR .RS 4 Device via which \fBs2disk\fR should talk to the kernel\&. .RE .PP \fBresume device\fR .RS 4 Specifies the device to write the image to\&. This is a swap partition or the partition that contains the swap file (see next parameter)\&. .RE .PP \fBresume offset\fR .RS 4 Necessary if a swap file is used for suspending\&. In such a case the device identified by the "resume device" parameter is regarded as the partition that contains the swap file, and "resume offset" must be equal to the offset from the beginning of this partition at which the swap file\*(Aqs header is located, in units\&. The value of this parameter for given swap file can be determined by the swap\-offset program (has to be run as root) included in this package\&. [For this feature to work, you will need an \e\-mm kernel, 2\&.6\&.18\-mm3 or newer\&.] .RE .PP \fBimage size\fR .RS 4 Limit the size of the system snapshot image created by the \fBs2disk\fR tool, but it\*(Aqs not mandatory\&. Namely, the \fBs2disk\fR tool will do its best to limit the image size as required by this parameter, but if that\*(Aqs not possible, it will suspend the system anyway, with a bigger image\&. If "image size" is set to 0, the snapshot image will be as small as possible\&. .RE .PP \fBsuspend loglevel\fR .RS 4 You can specify the kernel console loglevel which the \fBs2disk\fR/\fBs2both\fR and \fBresume\fR utilities will use to report progress\&. On a stock kernel messages with level higher then 7 are usually not shown\&. .RE .PP \fBshutdown method\fR .RS 4 This parameter defines the operation that will be carried out after the suspend image has been created and the machine is ready to be powered off\&. If it is set to "reboot", the machine will be rebooted immediately\&. If it is set to "platform", the machine will be shut down using special power management operations available from the kernel that may be necessary for the hardware to be properly reinitialized after the resume, and may cause the system to resume faster (this is the recommended shutdown method on the majority of systems and hence the defaul)\&. If set to "shutdown" the machine will be powered off\&. .RE .PP \fBcompute checksum\fR .RS 4 If the "compute checksum" parameter is set to \*(Aqy\*(Aq, the \fBs2disk\fR and \fBresume\fR tools will use the MD5 algorithm to verify the image integrity\&. .RE .PP \fBcompress\fR .RS 4 If the "compress" parameter is set to \*(Aqy\*(Aq, the \fBs2disk\fR and \fBresume\fR tools will use the LZF compression algorithm to compress/decompress the image\&. .RE .PP \fBencrypt\fR .RS 4 If the "encrypt" parameter is set to \*(Aqy\*(Aq, the \fBs2disk\fR and \fBresume\fR tools will use the Blowfish encryption algorithm to encrypt/decrypt the image\&. On resume and suspend you will have to supply a passphrase\&. By using a pregenerated RSA key, you can avoid having to type a passphrase on suspend\&. See the "RSA key file" option for more information\&. .RE .PP \fBRSA key file\fR .RS 4 If this option points to a valid RSA key, which can be created with \fBsuspend\-keygen\fR, the \fBs2disk\fR tool will generate a random key for the Blowfish encryption that will be passed to the \fBresume\fR tool within the image header with the help of the RSA cipher\&. Consequently you only need to type a passphrase on resume\&. .RE .PP \fBearly writeout\fR .RS 4 If the "early writeout" parameter is set to \*(Aqy\*(Aq, the \fBs2disk\fR utility will start syncing the resume device early in the process of writing the image to it\&. [This has been reported to speed up the \fBs2disk\fR on some boxes and eliminates the "fast progress meter and long fsync wait" effect\&.] .RE .PP \fBsplash\fR .RS 4 The "splash" parameter is used to make \fBs2disk\fR and/or \fBresume\fR use a splash system (when set to \*(Aqy\*(Aq)\&. Currently the bootsplash\&.org and splashy systems are supported\&. For the former you need a kernel patch, the latter is a userspace solution, but you\*(Aqll need to install a splashy theme\&. .sp If you use initramfs\-tools on your favorite Linux distribution to generate your initramfs, usually the necessary files will be copied to it\&. .RE .SH "SEE ALSO" .PP s2disk (8)\&. suspend\-keygen(8) .PP For more information see the README file. .SH "AUTHOR" .PP This manual page was written by Tim Dijkstra \&.org for the Debian(TM) system (but may be used by others)\&. Was updated by Rodolfo García . Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 any later version published by the Free Software Foundation\&. .RE .SH "COPYRIGHT" .br Copyright \(co 2006 Tim Dijkstra Copyright \(co 2012 Rodolfo García (kix) .br suspend-utils/s2ram.h0000644000175500017550000000141112075743443013262 0ustar kixkix/* * Suspend-to-RAM * * Copyright 2006 Pavel Machek * Distribute under GPLv2. */ #ifdef CONFIG_ARCH_X86 #include "s2ram-x86.h" #endif #ifdef CONFIG_ARCH_PPC #include "s2ram-ppc.h" #endif /* from radeontool.c */ void radeon_cmd_light(int); void map_radeon_cntl_mem(void); /* from s2ram.c */ /* return codes for s2ram_is_supported */ #define S2RAM_OK 0 #define S2RAM_FAIL 1 #define S2RAM_NOFB 126 #define S2RAM_UNKNOWN 127 int s2ram_hacks(void); int s2ram_is_supported(void); void identify_machine(void); int machine_known(void); int s2ram_do(void); int s2ram_check_kms(void); int s2ram_generic_do(void); void s2ram_resume(void); void s2ram_add_flag(int opt, const char *arg); void s2ram_add_quirks(char*); int get_s2ram_config(void); suspend-utils/configure.ac0000644000175500017550000001756312075743443014372 0ustar kixkix# # configure.ac # # Copyright (C) 2007 Alon Bar-Lev # # This file is released under the GPLv2. # AC_PREREQ([2.59]) AC_INIT([suspend-utils], [1.0]) AM_INIT_AUTOMAKE([${PACKAGE_NAME}], [${PACKAGE_VERSION}]) AM_CONFIG_HEADER([config.h]) AC_CONFIG_SRCDIR([suspend.c]) AC_CONFIG_MACRO_DIR([m4]) AC_CANONICAL_HOST AC_ARG_ENABLE( [debug], [AC_HELP_STRING([--enable-debug], [enable debug mode])], , [enable_debug="no"] ) AC_ARG_ENABLE( [strict], [AC_HELP_STRING([--enable-strict], [enable strict compile mode])], , [enable_strict="no"] ) AC_ARG_ENABLE( [pedantic], [AC_HELP_STRING([--enable-pedantic], [enable pedantic compile mode])], , [enable_pedantic="no"] ) AC_ARG_ENABLE( [minimal], [AC_HELP_STRING([--enable-minimal], [enable minimal build])], , [enable_minimal="no"] ) AC_ARG_ENABLE( [compress], [AC_HELP_STRING([--enable-compress], [enable compress support])], , [enable_compress="no"] ) AC_ARG_ENABLE( [encrypt], [AC_HELP_STRING([--enable-encrypt], [enable encryption support])], , [enable_encrypt="no"] ) AC_ARG_ENABLE( [create-device], [AC_HELP_STRING([--enable-create-device], [enable create required devices, use only if you don't have udev])], , [enable_create_device="no"] ) AC_ARG_ENABLE( [resume-static], [AC_HELP_STRING([--disable-resume-static], [build resume as dynamic module])], , [enable_resume_static="yes"] ) AC_ARG_ENABLE( [splashy], [AC_HELP_STRING([--enable-splashy], [enable splashy support])], , [enable_splashy="no"] ) AC_ARG_ENABLE( [fbsplash], [AC_HELP_STRING([--enable-fbsplash], [enable fbsplash support])], , [enable_fbsplash="no"] ) AC_ARG_WITH( [devdir], [AC_HELP_STRING([--with-devdir=DIR], [use if --enable-create-device, put devices in this directory, default /dev])], [devdir="${withval}"], [devdir="/dev"] ) AC_ARG_ENABLE( [threads], [AC_HELP_STRING([--enable-threads], [enable threads support])], , [enable_threads="no"] ) AC_ARG_WITH( [initramfsdir], [AC_HELP_STRING([--with-initramfsdir=DIR], [put initramfs binaries in this directory, default LIBDIR/suspend])], [initramfsdir="${withval}"], [initramfsdir="\$(libdir)/suspend"] ) AC_ARG_WITH( [libgcrypt-prefix], [AC_HELP_STRING([--with-libgcrypt-prefix=DIR], [define libgcrypt prefix, default /usr])], , [with_libgcrypt_prefix="/usr" ] ) AC_ARG_WITH( [directfb-prefix], [AC_HELP_STRING([--with-directfb-prefix=DIR], [define directfb prefix, default /usr])], , [with_directfb_prefix="/usr" ] ) AC_ARG_WITH( [resume-device], [AC_HELP_STRING([--with-resume-device=DEVICE], [define resume device (REQUIRED ONLY FOR BUILDING INITRAMFS DURING MAKE)])], [RESUME_DEVICE="${withval}"] ) AC_ARG_WITH( [bootdir], [AC_HELP_STRING([--with-bootdir=DIR], [define boot directory, default /boot (REQUIRED ONLY FOR BUILDING INITRAMFS DURING MAKE)])], [bootdir="${withval}"], [bootdir="/boot" ] ) AC_PROG_CC AC_PROG_INSTALL AC_PROG_LIBTOOL # We are using libtool so it auto-find static dependencies PKG_PROG_PKG_CONFIG AC_CHECK_PROGS([M4], [m4]) AC_CHECK_PROG(PERL, perl, perl) AC_SYS_LARGEFILE if test "${enable_create_device}" = "yes"; then AC_CHECK_PROGS([MKNOD], [mknod]) test -z "${MKNOD}" && AC_MSG_ERROR([mknod required for creating devices]) fi case "${host}" in i?86-*) ARCH="x86";; x86_*-*) ARCH="x86";; ppc-*|powerpc-*) ARCH="ppc";; ppc64-*|powerpc64-*) ARCH="ppc";; s390*-*) ARCH="s390";; esac CONFIG_FEATURES="" if test "${ARCH}" = "x86"; then AC_DEFINE([CONFIG_ARCH_X86], [1], [Define if x86 arch]) PKG_CHECK_MODULES( [LIBPCI], [libpci >= 2.2.4], , [ if test -z "${LIBPCI_LIBS}"; then AC_CHECK_LIB( [pci], [pci_init], [LIBPCI_LIBS="-lpci"], [ #force rescan unset ac_cv_lib_pci_pci_init AC_CHECK_LIB( [pci], [pci_init], [LIBPCI_LIBS="-lpci -lz"], [AC_MSG_ERROR([Required pciutils >= 2.2.4 not found])], [-lz] )] ) fi ] ) if test -z "${LIBX86_LIBS}"; then AC_ARG_VAR([LIBX86_CFLAGS], [C compiler flags for libx86]) AC_ARG_VAR([LIBX86_LIBS], [linker flags for libx86]) AC_CHECK_LIB( [x86], [LRMI_common_init], [LIBX86_LIBS="-lx86"], [AC_MSG_ERROR([Required libx86 was not found])] ) fi elif test "${ARCH}" = "ppc"; then AC_DEFINE([CONFIG_ARCH_PPC], [1], [Define if ppc arch]) elif test "${ARCH}" = "s390"; then AC_DEFINE([CONFIG_ARCH_S390], [1], [Define if s390 arch]) else AC_MSG_ERROR([Unsupported architecture ${host}]) fi if test "${enable_compress}" = "yes"; then CONFIG_FEATURES="${CONFIG_FEATURES} compress" AC_DEFINE([CONFIG_COMPRESS], [1], [Define if compression enabled]) if test -z "${LZO_LIBS}"; then AC_ARG_VAR([LZO_CFLAGS], [C compiler flags for lzo]) AC_ARG_VAR([LZO_LIBS], [linker flags for lzo]) AC_CHECK_LIB( [lzo2], [lzo1x_1_compress], [LZO_LIBS="-llzo2"], [AC_CHECK_LIB( [lzo], [lzo1x_1_compress], [LZO_LIBS="-llzo"], [AC_MSG_ERROR([Required lzo library not found])] )] ) fi fi if test "${enable_encrypt}" = "yes"; then CONFIG_FEATURES="${CONFIG_FEATURES} encrypt" AC_DEFINE([CONFIG_ENCRYPT], [1], [Define if encryption enabled]) AC_MSG_CHECKING([for libgcrypt]) if ! test -x "${with_libgcrypt_prefix}/bin/libgcrypt-config"; then AC_MSG_ERROR([Cannot locate libgcrypt]) else AC_MSG_RESULT([found]) LIBGCRYPT_CFLAGS=`"${with_libgcrypt_prefix}/bin/libgcrypt-config" --cflags` LIBGCRYPT_LIBS=`"${with_libgcrypt_prefix}/bin/libgcrypt-config" --libs` fi fi if test "${enable_splashy}" = "yes"; then CONFIG_FEATURES="${CONFIG_FEATURES} splashy" AC_DEFINE([CONFIG_SPLASHY], [1], [Define if splashy enabled]) # Workaround a wierd splashy issue AC_CHECK_LIB([gcc_s], [strlen]) if test -z "${SPLASHY_LIBS}"; then AC_ARG_VAR([SPLASHY_CFLAGS], [C compiler flags for libsplashy]) AC_ARG_VAR([SPLASHY_LIBS], [linker flags for libsplashy]) AC_CHECK_LIB( [splashy], [splashy_init], [SPLASHY_LIBS="-lsplashy"], [AC_MSG_ERROR([Required libsplashy was not found])] ) fi fi if test "${enable_fbsplash}" = "yes"; then CONFIG_FEATURES="${CONFIG_FEATURES} fbsplash" AC_DEFINE([CONFIG_FBSPLASH], [1], [Define if fbsplash enabled]) PKG_CHECK_MODULES( [FBSPLASH], [libfbsplashrender >= 0.1], , [AC_MSG_ERROR([Required libfbsplashrender was not found])] ) fi if test "${enable_threads}" = "yes"; then CONFIG_FEATURES="${CONFIG_FEATURES} threads" AC_DEFINE([CONFIG_THREADS], [1], [Define if threads enabled]) if test -z "${PTHREAD_LIBS}"; then AC_ARG_VAR([PTHREAD_LIBS], [linker flags for threads]) AC_CHECK_LIB( [pthread], [pthread_create], [PTHREAD_LIBS="-lpthread"], [AC_MSG_ERROR([Required pthread library not found])] ) fi fi AC_DEFINE_UNQUOTED([CONFIG_FEATURES], ["${CONFIG_FEATURES## }"], [String representation of available features]) AC_HEADER_STDC AC_CHECK_HEADERS([ \ inttypes.h \ stdint.h \ ]) if test "${enable_pedantic}" = "yes"; then enable_strict="yes"; CFLAGS="${CFLAGS} -pedantic" fi if test "${enable_strict}" = "yes"; then CFLAGS="${CFLAGS} -Wall -Wextra" fi # workaround for old autoconf if test -z "${docdir}"; then docdir="\$(datarootdir)/doc/\$(PACKAGE_NAME)" AC_SUBST([docdir]) fi # end workaround AC_SUBST([devdir]) AC_SUBST([initramfsdir]) AC_SUBST([bootdir]) AC_SUBST([LIBGCRYPT_CFLAGS]) AC_SUBST([LIBGCRYPT_LIBS]) AC_SUBST([RESUME_DEVICE]) AM_CONDITIONAL([ENABLE_DEBUG], [test "${enable_debug}" = "yes"]) AM_CONDITIONAL([ENABLE_MINIMAL], [test "${enable_minimal}" = "yes"]) AM_CONDITIONAL([ARCH_X86], [test "${ARCH}" = "x86"]) AM_CONDITIONAL([ARCH_PPC], [test "${ARCH}" = "ppc"]) AM_CONDITIONAL([ENABLE_ENCRYPT], [test "${enable_encrypt}" = "yes"]) AM_CONDITIONAL([ENABLE_RESUME_STATIC], [test "${enable_resume_static}" = "yes"]) AM_CONDITIONAL([ENABLE_CREATE_DEVICE], [test "${enable_create_device}" = "yes"]) AM_CONDITIONAL([ENABLE_SPLASHY], [test "${enable_splashy}" = "yes"]) AM_CONDITIONAL([ENABLE_FBSPLASH], [test "${enable_fbsplash}" = "yes"]) AC_CONFIG_FILES([ Makefile doc/Makefile manpages/Makefile scripts/Makefile scripts/suse-10.1/Makefile ]) AC_OUTPUT suspend-utils/autogen.sh0000755000175500017550000000003512075743443014067 0ustar kixkix#!/bin/sh autoreconf -i -v -fsuspend-utils/COPYING0000644000175500017550000000405212075743443013124 0ustar kixkix suspend License Copyright (C) 2005-2007 Rafael J. Wysocki Copyright (C) 2006-2007 Pavel Machek Copyright (C) 2006-2007 Stefan Seyfried Copyright 2006 Tim Dijkstra Copyright 2006 Luca Tettamanti All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program 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 this program (see the file COPYING.GPL included with this distribution); if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. vbetool Copyright Matthew Garrett , heavily based on vbetest.c from the lrmi package and read-edid.c by John Fremlin radeontool Copyright 2002-2004 Frederick Dean Use hereby granted under the zlib license. Thanks to Deepak Chawla, Erno Kuusela, Rolf Offermanns, and Soos Peter for patches. md5 Copyright (C) 1995 Ulrich Drepper dmidecode Copyright (C) 2000,2001 Alan Cox Copyright (C) 2001 Matt Domsch lzo Copyright (C) 1996-2005 Markus Franz Xaver Johannes Oberhumer All Rights Reserved. gcrypt Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 2004, 2006 Free Software Foundation, Inc. splashy Copyright 2005 Otavio Salvador Copyright 2005 Luis Mondesi splashutils Copyright (C) 2004-2007 Michal Januszewski m4 Macros autoconf/automake Copyright (C) 2002, 2003 Free Software Foundation, Inc. pkg.m4 Copyright © 2004 Scott James Remnant . suspend-utils/loglevel.h0000644000175500017550000000042712075743443014055 0ustar kixkix/* loglevel.h - routines to modify kernel console loglevel * * Released under GPL v2. * (c) 2007 Tim Dijkstra */ inline void open_printk(void); inline int get_kernel_console_loglevel(void); inline void set_kernel_console_loglevel(int level); inline void close_printk(void); suspend-utils/scripts/0000755000175500017550000000000012075743443013557 5ustar kixkixsuspend-utils/scripts/Makefile.am0000644000175500017550000000040212075743443015607 0ustar kixkix# # Makefile.am # # Copyright (C) 2007 Alon Bar-Lev # # This file is released under the GPLv2. # MAINTAINERCLEANFILES = $(srcdir)/Makefile.in SUBDIRS=\ suse-10.1 dist_noinst_SCRIPTS=\ create-resume-initrd.sh \ install-resume.sh suspend-utils/scripts/suse-10.1/0000755000175500017550000000000012075743443015113 5ustar kixkixsuspend-utils/scripts/suse-10.1/Makefile.am0000644000175500017550000000042112075743443017144 0ustar kixkix# # Makefile.am # # Copyright (C) 2007 Alon Bar-Lev # # This file is released under the GPLv2. # MAINTAINERCLEANFILES = $(srcdir)/Makefile.in dist_noinst_SCRIPTS=\ modify-system-files.sh dist_noinst_DATA=\ do_acpi_sleep.patch \ mkinitrd.patch suspend-utils/scripts/suse-10.1/mkinitrd.patch0000644000175500017550000000300712075743443017755 0ustar kixkix--- a/mkinitrd 2006-07-17 13:53:21.000000000 +0200 +++ b/mkinitrd 2006-07-27 13:24:46.000000000 +0200 @@ -1405,6 +1405,8 @@ mkinitrd_kernel() { cp_bin /sbin/udevtrigger $tmp_mnt/sbin/ cp_bin /sbin/udevsettle $tmp_mnt/sbin/ cp_bin /usr/bin/udevinfo $tmp_mnt/sbin/ + cp_bin /usr/local/sbin/resume $tmp_mnt/sbin/ + cp -a /etc/suspend.conf $tmp_mnt/etc/ mkdir -p $tmp_mnt/etc/udev/rules.d # Create our own udev.conf @@ -1630,6 +1632,9 @@ mkinitrd_kernel() { |mknod /dev/console c 5 1 |mknod /dev/null c 1 3 |mknod /dev/kmsg c 1 11 + |mknod /dev/snapshot c 10 231 + |mknod /dev/random c 1 8 + |mknod /dev/urandom c 1 9 |mkdir /dev/pts |mkdir -m 1777 /dev/shm |ln -s /proc/self/fd /dev/fd @@ -1705,9 +1710,6 @@ mkinitrd_kernel() { | rootdev=\${o#nfsroot=} | rootdev_cmdline=1 | ;; - | resume=*) - | resumedev=\${o#resume=} - | ;; | journal=*) | journaldev=\${o#journal=} | ;; @@ -1778,8 +1780,9 @@ mkinitrd_kernel() { |fi | |# Verify manual resume mode + |resumedev=$(grep -i 'resume device' /etc/suspend.conf | sed -e 's/.*=[ \t]*//') |if [ "$resume_mode" != "off" -a -n "\$resumedev" ]; then - | if [ -w /sys/power/resume ]; then + | if [ -x /sbin/resume ]; then | echo "Trying manual resume from \$resumedev" | resume_mode=1 | else @@ -2396,7 +2399,7 @@ mkinitrd_kernel() { | devn= | fi | if [ -n "$major" -a -n "$minor" ]; then - | echo "$major:$minor" > /sys/power/resume + | /sbin/resume | major= | minor= | else suspend-utils/scripts/suse-10.1/do_acpi_sleep.patch0000644000175500017550000000306712075743443020730 0ustar kixkix--- a/do_acpi_sleep 2006-07-20 03:45:02.000000000 +0200 +++ b/do_acpi_sleep 2006-07-25 18:27:42.000000000 +0200 @@ -54,6 +54,8 @@ OPT="--hctosys" # where is the s2ram binary installed? S2RAM="/usr/sbin/s2ram" S2RAM_LOG=/var/log/suspend2ram.log +S2DISK="/usr/local/sbin/s2disk" +S2DISK_LOG=/var/log/suspend2disk.log # blank the "suspend console" deallocvt 63 @@ -68,20 +70,25 @@ fi case "$1" in suspend2disk) - IMG_SZ=0 - read IMG_SZ < /sys/power/image_size - $MYECHO /sys/power/state disk - RET=$? # 28=ENOSPC, "not enough swap." - # - # the logic here is: - # if image_size > 0 (without kernel support, IMG_SZ will be zero), - # and we got ENOSPC, then try again with image_size set to zero. - if [ $RET -eq 28 -a $IMG_SZ -ne 0 ]; then # try again with minimal image size - echo 0 > /sys/power/image_size - $MYECHO /sys/power/state disk + if [ -x $S2DISK ]; then + $S2DISK >> $S2DISK_LOG 2>&1 RET=$? - echo $IMG_SZ > /sys/power/image_size - fi + else + IMG_SZ=0 + read IMG_SZ < /sys/power/image_size + $MYECHO /sys/power/state disk + RET=$? # 28=ENOSPC, "not enough swap." + # + # the logic here is: + # if image_size > 0 (without kernel support, IMG_SZ will be zero), + # and we got ENOSPC, then try again with image_size set to zero. + if [ $RET -eq 28 -a $IMG_SZ -ne 0 ]; then # try again with minimal image size + echo 0 > /sys/power/image_size + $MYECHO /sys/power/state disk + RET=$? + echo $IMG_SZ > /sys/power/image_size + fi + fi [ "$SUSPEND2DISK_RESTORE_CLOCK" == "yes" ] && $HWCLOCK $OPT ;; suspend2ram) suspend-utils/scripts/suse-10.1/modify-system-files.sh0000644000175500017550000000103212075743443021354 0ustar kixkix#!/bin/bash if [ ! -f do_acpi_sleep.patch -a ! -f mkinitrd.patch ]; then echo "Required patches not found!" exit 1 fi if [ ! -x /usr/local/sbin/resume ]; then echo "The resume binary not found!" exit 2; fi if [ ! -f /etc/suspend.conf ]; then echo "The suspend configuration file not found!" exit 3; fi CURRENT_DIR=$(pwd) cd /sbin cp mkinitrd mkinitrd.orig cat $CURRENT_DIR/mkinitrd.patch | patch -p1 cd /usr/lib/powersave cp do_acpi_sleep do_acpi_sleep.orig cat $CURRENT_DIR/do_acpi_sleep.patch | patch -p1 cd $CURRENT_DIR/ suspend-utils/scripts/install-resume.sh0000755000175500017550000000102512075743443017060 0ustar kixkix#!/bin/sh if [ -z "$RESUME" ]; then RESUME="resume" fi if [ -z "$BOOT_DIR" ]; then BOOT_DIR="/boot" fi if [ -z "$INITRD_FILE" ]; then INITRD_FILE="$BOOT_DIR/resume-initrd" fi if [ -z "$MOUNT_POINT" ]; then MOUNT_POINT="/mnt" fi if [ -f "$RESUME" -a -f "$INITRD_FILE" -a -d "$MOUNT_POINT" ]; then cp "$INITRD_FILE" "$INITRD_FILE.orig" mount -t ext2 -o loop "$INITRD_FILE" "$MOUNT_POINT" && \ install --mode=0755 "$RESUME" "$MOUNT_POINT" umount "$MOUNT_POINT" else echo "Could not install the resume tool" >&2 exit 1 fi suspend-utils/scripts/create-resume-initrd.sh0000755000175500017550000000334012075743443020146 0ustar kixkix#!/bin/sh RESUME_DEVICE=$1 if [ -z "${RESUME_DEVICE}" ]; then echo "usage: $0 resume_device" >&2 exit 1 fi if [ -n "$2" ]; then TMP_FILE=$2; else TMP_FILE="initrd" fi if [ -z "$RESUME" ]; then RESUME="resume" fi if [ -z "$INITRD_SIZE" ]; then INITRD_SIZE=2000k fi if [ -z "$CONFIG_FILE" ]; then CONFIG_FILE="conf/suspend.conf" fi if [ -z "${MOUNT_POINT}" ]; then MOUNT_POINT="mnt" if [ ! -d "${MOUNT_POINT}" ]; then mkdir "${MOUNT_POINT}" if [ ! -d "${MOUNT_POINT}" ]; then echo "Could not create the mount point" >&2 exit 1 fi RMDIR_MOUNT_POINT="yes" else RMDIR_MOUNT_POINT="" fi fi if [ -z "$BOOT_DIR" ]; then BOOT_DIR="/boot" fi if [ -z "$INITRD_FILE" ]; then INITRD_FILE="$BOOT_DIR/resume-initrd" fi if [ -f "$RESUME" -a -d "${MOUNT_POINT}" -a -b "${RESUME_DEVICE}" ]; then dd if=/dev/zero of="$TMP_FILE" bs=$INITRD_SIZE count=1 /sbin/mke2fs -F -m0 "$TMP_FILE" mount -t ext2 -o loop "$TMP_FILE" "${MOUNT_POINT}" if [ "$?" = "0" ]; then mkdir "${MOUNT_POINT}"/dev cp -r /dev/console "${MOUNT_POINT}"/dev/ cp -r /dev/snapshot "${MOUNT_POINT}"/dev/ cp -r /dev/random "${MOUNT_POINT}"/dev/ cp -r /dev/urandom "${MOUNT_POINT}"/dev/ cp -r "${RESUME_DEVICE}" "${MOUNT_POINT}"/dev/ mkdir "${MOUNT_POINT}"/proc mkdir "${MOUNT_POINT}"/etc cp "$CONFIG_FILE" "${MOUNT_POINT}"/etc/ cp "$RESUME" "${MOUNT_POINT}"/resume ln -s resume "${MOUNT_POINT}"/linuxrc umount "${MOUNT_POINT}" if [ -f "$INITRD_FILE" ]; then mv "$INITRD_FILE" "$INITRD_FILE".orig fi chmod 644 "$TMP_FILE" mv "$TMP_FILE" "$INITRD_FILE" else echo "Could not mount $TMP_FILE on ${MOUNT_POINT}" >&2 fi else echo "Could not install the resume initrd" >&2 fi if [ -n "$RMDIR_MOUNT_POINT" ]; then rmdir "${MOUNT_POINT}" fi suspend-utils/resume.c0000644000175500017550000003015512075743443013540 0ustar kixkix/* * resume.c * * A simple user space resume handler for swsusp. * * Copyright (C) 2005 Rafael J. Wysocki * * This file is released under the GPLv2. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_COMPRESS #include #endif #include "swsusp.h" #include "memalloc.h" #include "config_parser.h" #include "md5.h" #include "splash.h" #include "loglevel.h" #define STAT_TIMEOUT_US 1000000 // 1 tenth of a second #define STAT_LOOP_STEPS 300 // 30 seconds static char snapshot_dev_name[MAX_STR_LEN] = SNAPSHOT_DEVICE; static char resume_dev_name[MAX_STR_LEN] = RESUME_DEVICE; static loff_t resume_offset; static int suspend_loglevel = SUSPEND_LOGLEVEL; static int max_loglevel = MAX_LOGLEVEL; static char splash_param; #ifdef CONFIG_FBSPLASH char fbsplash_theme[MAX_STR_LEN] = ""; #endif static int use_platform_suspend; static struct config_par parameters[] = { { .name = "snapshot device", .fmt = "%s", .ptr = snapshot_dev_name, .len = MAX_STR_LEN }, { .name = "resume device", .fmt ="%s", .ptr = resume_dev_name, .len = MAX_STR_LEN }, { .name = "resume offset", .fmt = "%llu", .ptr = &resume_offset, }, { .name = "suspend loglevel", .fmt = "%d", .ptr = &suspend_loglevel, }, { .name = "max loglevel", .fmt = "%d", .ptr = &max_loglevel, }, { .name = "image size", .fmt = "%lu", .ptr = NULL, }, { .name = "compute checksum", .fmt = "%c", .ptr = NULL, }, #ifdef CONFIG_COMPRESS { .name = "compress", .fmt = "%c", .ptr = NULL, }, #endif #ifdef CONFIG_ENCRYPT { .name = "encrypt", .fmt = "%c", .ptr = NULL, }, { .name = "RSA key file", .fmt = "%s", .ptr = NULL, }, #endif { .name = "early writeout", .fmt = "%c", .ptr = NULL, }, { .name = "splash", .fmt = "%c", .ptr = &splash_param, }, { .name = "shutdown method", .fmt = "%s", .ptr = NULL, }, #ifdef CONFIG_FBSPLASH { .name = "fbsplash theme", .fmt = "%s", .ptr = fbsplash_theme, .len = MAX_STR_LEN, }, #endif { .name = "resume pause", .fmt = "%d", .ptr = NULL, }, #ifdef CONFIG_THREADS { .name = "threads", .fmt = "%c", .ptr = NULL, }, #endif { .name = "debug test file", .fmt = "%s", .ptr = NULL, }, { .name = "debug verify image", .fmt = "%c", .ptr = NULL, }, #ifdef CONFIG_THREADS { .name = "threads", .fmt = "%c", .ptr = NULL, }, #endif { .name = NULL, .fmt = NULL, .ptr = NULL, .len = 0, } }; static inline int atomic_restore(int dev) { return ioctl(dev, SNAPSHOT_ATOMIC_RESTORE, 0); } static int open_resume_dev(char *resume_dev_name, struct swsusp_header *swsusp_header) { ssize_t size = sizeof(struct swsusp_header); off64_t shift = ((off64_t)resume_offset + 1) * page_size - size; ssize_t ret; int fd; fd = open(resume_dev_name, O_RDWR); if (fd < 0) { ret = -errno; fprintf(stderr, "%s: Could not open the resume device\n", my_name); return ret; } if (lseek64(fd, shift, SEEK_SET) != shift) return -EIO; ret = read(fd, swsusp_header, size); if (ret == size) { if (memcmp(SWSUSP_SIG, swsusp_header->sig, 10)) { close(fd); return -ENOMEDIUM; } } else { ret = ret < 0 ? ret : -EIO; return ret; } return fd; } static void pause_resume(int pause) { struct termios newtrm, savedtrm; char message[SPLASH_GENERIC_MESSAGE_SIZE]; int wait_possible = !splash.prepare_abort(&savedtrm, &newtrm); if (!wait_possible) pause = -1; sprintf(message, "Image successfully loaded\nPress " ENTER_KEY_NAME " to continue\n"); splash.set_caption(message); printf("%s: %s", my_name, message); if (pause > 0) printf("%s: Continuing automatically in %2d seconds", my_name, pause); while (pause) { if (splash.key_pressed() == ENTER_KEY_CODE) break; sleep(1); if (pause > 0) printf("\b\b\b\b\b\b\b\b\b\b%2d seconds", --pause); } printf("\n"); if (wait_possible) splash.restore_abort(&savedtrm); } static void reboot_question(char *message) { char c; char full_message[SPLASH_GENERIC_MESSAGE_SIZE]; char *warning = "\n\tYou can now boot the system and lose the saved state\n" "\tor reboot and try again.\n\n" "\t[Notice that if you decide to reboot, you MUST NOT mount\n" "\tany filesystems before a successful resume.\n" "\tResuming after some filesystems have been mounted\n" "\twill badly damage these filesystems.]\n\n" "\tDo you want to continue booting (Y/n)?"; snprintf(full_message, SPLASH_GENERIC_MESSAGE_SIZE, "%s\n%s", message, warning); c = splash.dialog(full_message); if (c == 'n' || c == 'N') { reboot(); fprintf(stderr, "%s: Reboot failed, please reboot manually.\n", my_name); while(1) sleep(10); } } static int read_image(int dev, int fd, loff_t start) { struct image_header_info *header; int error; header = getmem(page_size); error = read_or_verify(dev, fd, header, start, 0, 0); if (error) { reboot_question( "\nThe system snapshot image could not be read.\n\n" "\tThis might be a result of booting a wrong " "kernel.\n" ); } else { if (header->flags & PLATFORM_SUSPEND) use_platform_suspend = 1; } if (error) { char message[SPLASH_GENERIC_MESSAGE_SIZE]; sprintf(message, "%s: Error %d loading the image\nPress " ENTER_KEY_NAME " to continue\n", my_name, error); splash.dialog(message); } else if (header->resume_pause != 0) { pause_resume(header->resume_pause); } else { printf("%s: Image successfully loaded\n", my_name); } freemem(header); return error; } static int reset_signature(int fd, struct swsusp_header *swsusp_header) { ssize_t ret, size = sizeof(struct swsusp_header); off64_t shift = ((off64_t)resume_offset + 1) * page_size - size; int error = 0; /* Reset swap signature now */ memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10); if (lseek64(fd, shift, SEEK_SET) != shift) { fprintf(stderr, "%s: Could not lseek() to the swap header", my_name); return -EIO; } ret = write(fd, swsusp_header, size); if (ret == size) { fsync(fd); } else { fprintf(stderr, "%s: Could not restore the swap header", my_name); error = -EIO; } return error; } /* Parse the command line and/or configuration file */ static inline int get_config(int argc, char *argv[]) { static struct option options[] = { { "help\0\t\t\tthis text", no_argument, NULL, 'h' }, { "version\0\t\t\tversion information", no_argument, NULL, 'V' }, { "config\0\t\talternative configuration file.", required_argument, NULL, 'f' }, { "resume_device\0device that contains swap area", required_argument, NULL, 'r' }, { "resume_offset\0offset of swap file in resume device.", required_argument, NULL, 'o' }, { "parameter\0\toverride config file parameter.", required_argument, NULL, 'P' }, { NULL, 0, NULL, 0 } }; int i, error; char *conf_name = CONFIG_FILE; const char *optstring = "hVf:o:r:P:"; struct stat stat_buf; int fail_missing_config = 0; /* parse only config file argument */ while ((i = getopt_long(argc, argv, optstring, options, NULL)) != -1) { switch (i) { case 'h': usage(my_name, options, optstring); exit(EXIT_SUCCESS); case 'V': version(my_name, NULL); exit(EXIT_SUCCESS); case 'f': conf_name = optarg; fail_missing_config = 1; break; } } if (stat(conf_name, &stat_buf)) { if (fail_missing_config) { fprintf(stderr, "%s: Could not stat configuration file\n", my_name); return -ENOENT; } } else { error = parse(my_name, conf_name, parameters); if (error) { fprintf(stderr, "%s: Could not parse config file\n", my_name); return error; } } optind = 0; while ((i = getopt_long(argc, argv, optstring, options, NULL)) != -1) { switch (i) { case 'f': /* already handled */ break; case 'o': resume_offset = atoll(optarg); break; case 'r': strncpy(resume_dev_name, optarg, MAX_STR_LEN -1); break; case 'P': error = parse_line(optarg, parameters); if (error) { fprintf(stderr, "%s: Could not parse config string '%s'\n", my_name, optarg); return error; } break; default: usage(my_name, options, optstring); return -EINVAL; } } if (optind < argc) strncpy(resume_dev_name, argv[optind], MAX_STR_LEN - 1); return 0; } int main(int argc, char *argv[]) { unsigned int mem_size; struct stat stat_buf; int dev, resume_dev; int n, error, orig_loglevel; static struct swsusp_header swsusp_header; my_name = basename(argv[0]); error = get_config(argc, argv); if (error) return -error; if (splash_param != 'y' && splash_param != 'Y') splash_param = 0; else splash_param = SPL_RESUME; get_page_and_buffer_sizes(); mem_size = 2 * page_size + buffer_size; #ifdef CONFIG_ENCRYPT printf("%s: libgcrypt version: %s\n", my_name, gcry_check_version(NULL)); gcry_control(GCRYCTL_INIT_SECMEM, page_size, 0); mem_size += page_size; #endif #ifdef CONFIG_COMPRESS /* * The formula below follows from the worst-case expansion calculation * for LZO1 (size / 16 + 67) and the fact that the size of the * compressed data must be stored in the buffer (sizeof(size_t)). */ compress_buf_size = buffer_size + round_up_page_size((buffer_size >> 4) + 67 + sizeof(size_t)); mem_size += compress_buf_size + round_up_page_size(LZO1X_1_MEM_COMPRESS); #endif error = init_memalloc(page_size, mem_size); if (error) { fprintf(stderr, "%s: Could not allocate memory\n", my_name); return error; } open_printk(); orig_loglevel = get_kernel_console_loglevel(); set_kernel_console_loglevel(suspend_loglevel); /* * 30 seconds grace period to allow resume device * to come online (i.e. external USB drive) */ for (n = 0; n < STAT_LOOP_STEPS; n++) { if (!stat(resume_dev_name, &stat_buf)) break; usleep(STAT_TIMEOUT_US); } while (stat(resume_dev_name, &stat_buf)) { fprintf(stderr, "%s: Could not stat the resume device file '%s'\n" "\tPlease type in the full path name to try again\n" "\tor press ENTER to boot the system: ", my_name, resume_dev_name); fgets(resume_dev_name, MAX_STR_LEN - 1, stdin); n = strlen(resume_dev_name) - 1; if (n <= 0) { error = EINVAL; goto Free; } if (resume_dev_name[n] == '\n') resume_dev_name[n] = '\0'; } setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); if (mlockall(MCL_CURRENT | MCL_FUTURE)) { error = errno; fprintf(stderr, "%s: Could not lock myself\n", my_name); goto Free; } dev = open(snapshot_dev_name, O_WRONLY); if (dev < 0) { error = ENOENT; goto Free; } resume_dev = open_resume_dev(resume_dev_name, &swsusp_header); if (resume_dev == -ENOMEDIUM) { error = 0; goto Close; } else if (resume_dev < 0) { error = -resume_dev; goto Close; } splash_prepare(&splash, splash_param); splash.progress(5); error = read_image(dev, resume_dev, swsusp_header.image); if (error) { error = -error; fprintf(stderr, "%s: Could not read the image\n", my_name); } else if (freeze(dev)) { error = errno; reboot_question("Processes could not be frozen, " "cannot continue resuming.\n"); } if (reset_signature(resume_dev, &swsusp_header)) fprintf(stderr, "%s: Swap signature has not been restored.\n" "\tRun mkswap on the resume partition/file.\n", my_name); close(resume_dev); if (error) goto Close_splash; if (use_platform_suspend) { int err = platform_prepare(dev); if (err) { fprintf(stderr, "%s: Unable to use platform " "hibernation support, error code %d\n", my_name, err); use_platform_suspend = 0; } } atomic_restore(dev); /* We only get here if the atomic restore fails. Clean up. */ unfreeze(dev); Close_splash: splash.finish(); Close: close(dev); Free: if (error) set_kernel_console_loglevel(max_loglevel); else if (orig_loglevel >= 0) set_kernel_console_loglevel(orig_loglevel); close_printk(); free_memalloc(); return error; } suspend-utils/doc/0000755000175500017550000000000012075743443012635 5ustar kixkixsuspend-utils/doc/Makefile.am0000644000175500017550000000033012075743443014665 0ustar kixkix# # Makefile.am # # Copyright (C) 2007 Alon Bar-Lev # # This file is released under the GPLv2. # MAINTAINERCLEANFILES = $(srcdir)/Makefile.in dist_noinst_DATA=installation-on-SUSE-10.1.txt suspend-utils/doc/installation-on-SUSE-10.1.txt0000644000175500017550000001143012075743443017642 0ustar kixkixInstallation instruction for SUSE 10.1 -------------------------------------- Copyright (C) 2006 Rafael J. Wysocki This document describes how to install the s2disk (s2both) and resume tools on SUSE Linux 10.1 quickly. Of course you can do it in a more sophisticated way, but then you'll need to figure out a couple of things yourself. I assume you have read Section I of the HOWTO in the main source directory. If not, please do it now and get back here when you're ready. Also make sure that your system has been updated and update it if not. The mkinitrd patch below will not apply on a "vanilla" system. 1. Install the Marc Lehmann's libLZF library (optionally), libgcrypt-devel (optionally) and build the s2disk and resume as described in Section I (b)-(d) of the HOWTO, but _do_ _not_ install the resume initrd. Make sure that suspend.conf and s2disk will be installed in /etc/ and /usr/local/sbin/ , respectively. 2. Copy the resume binary to /usr/local/sbin/ . 3. Go to the scripts/suse-10.1/ directory and run # ./modify-system-files.sh (as root). It will use the two patches in the scripts/suse-10.1/ directory, mkinitrd.patch and do_acpi_sleep.patch, to modify /sbin/mkinitrd and /usr/lib/powersave/do_acpi_sleep . This will make powersaved use s2disk for suspending to disk and mkinitrd put the resume binary into the initrams images created by it. 4. Configure and build the kernel, as described in /usr/src/linux/README.SUSE (this file is in the kernel-source package, so you need to have it installed). However, initially it's better to use a vanilla kernel.org kernel, so you'll need to download one (at least 2.6.17, but there have been quite a lot of suspend-related fixes recently, so it probably is a good idea to use the newest possible kernel, either "stable" or from the -rc series). To configure the new kernel, you can use your running kernel's configuration file, in which case you'll have all of the necessery modules built. For this purpose: (a) become root, go to the /usr/src/linux/ directory (it will only be present if the kernel-source package is installed) and run # make cloneconfig (b) become normal user, unpack the kernel source wherever you want, for example somewhere in your home directory, and go to the new kernel source directory, (c) run $ cp /usr/src/linux/.config . (d) run $ make oldconfig Now, you probably will be asked many questions related to the new kernel's configuration, but it generally is safe to leave the default settings, unless you know what you're doing. (e) run $ make or, if you have an SMP system and you want the kernel to compile faster, $ make -j N where N is a small integer (on my dual-core box N=5 seems to be the best). 5. Become root, go to the new kernel source directory and run # cp arch/x86_64/boot/bzImage /boot/vmlinuz- && \ cp System.map /boot/System.map- && make modules_install where is the version of your new kernel (eg. 2.6.18-rc2). 6. Run # mkinitrd -k vmlinuz- -i initrd- 7. Add the new kernel entry to /boot/grub/menu.lst , i.e.: (a) Find the entry of your default kernel (it should be the first one, with the title "SUSE Linux 10.1") and copy it, _without_ the preceding comment, to the top (ie. right after "gfxmenu (hd0,0)/message"). (b) In the new entry, replace "vmlinuz" with "vmlinuz-" and "initrd" with "initrd-" and save the file. Now, the head of your /boot/grub/menu.lst should read like this: # Modified by YaST2. Last modification on Thu Jul 20 23:09:44 CEST 2006 color white/blue black/light-gray default 0 timeout 8 gfxmenu (hd0,0)/message title SUSE Linux 10.1 (2.6.18-rc2) root (hd0,0) kernel /vmlinuz-2.6.18-rc2 root=/dev/sda1 vga=0x31a resume=/dev/sda2 splash=silent showopts initrd /initrd-2.6.18-rc2 ###Don't change this comment - YaST2 identifier: Original name: linux### title SUSE Linux 10.1 root (hd0,0) kernel /vmlinuz root=/dev/sda1 vga=0x31a resume=/dev/sda2 splash=silent showopts initrd /initrd 8. Test if the new kernel boots. If it does, you also should be able to suspend using s2disk and resume should be run automatically from the initrd during system startup, if needed. 9. It may be needed to add SUSPEND2DISK_SKIP_RESUME_CHECK="yes" is powersaved complains that the resume partition is not set and refuses to suspend. 10. If you want to use s2both instead of s2diks, you will need to replace "s2disk" with "s2both" in do_acpi_sleep.patch before running ./modify-system-files.sh in step 2. Of course, you will also have to build s2both and install it, but for this purpose you only need to run $ make s2both instead of "make s2disk" and $ make install-suspend instead of "make install-s2disk" when building the suspend tools. Please note, however, that pciutils-devel has to be installed for this to work. suspend-utils/encrypt.h0000644000175500017550000000322212075743443013724 0ustar kixkix/* * encrypt.h * * Encryption-related definitions for user space suspend and resume * tools. * * Copyright (C) 2006 Rafael J. Wysocki * * This file is released under the GPLv2. * */ #ifdef CONFIG_ENCRYPT #include /* Maximum length of a passphrase, in characters */ #define PASS_SIZE 128 #define PASSBUF_SIZE (2 * PASS_SIZE) /* Symmetric cipher used for image encryption, the size of its key and its * block, in bytes */ #define IMAGE_CIPHER GCRY_CIPHER_BLOWFISH #define KEY_SIZE 16 #define CIPHER_BLOCK 8 /* Symmetric cipher used for encrypting RSA private keys, the size of its key * and its block, in bytes */ #define PK_CIPHER GCRY_CIPHER_AES #define PK_KEY_SIZE 16 #define PK_CIPHER_BLOCK 16 /* Auxiliary constants */ #define RSA_DATA_SIZE (512+16+512+256+256+256) /* n,e,d,p,q,u */ #define KEY_DATA_SIZE 512 #define RSA_FIELDS 6 #define RSA_FIELDS_PUB 2 #define KEY_TEST_SIZE 8 #define KEY_TEST_DATA (unsigned char *)"12345678" struct RSA_data { char field[RSA_FIELDS][2]; unsigned short size[RSA_FIELDS]; unsigned char key_test[KEY_TEST_SIZE]; unsigned char data[RSA_DATA_SIZE]; }; struct encrypted_key { size_t size; unsigned char data[KEY_DATA_SIZE]; }; struct key_data { unsigned char key[KEY_SIZE]; unsigned char ivec[CIPHER_BLOCK]; struct RSA_data rsa; struct encrypted_key encrypted_key; }; void read_password(char *pass_buf, int vrfy); void encrypt_init(unsigned char *, unsigned char *, char *); void get_random_salt(unsigned char *salt, size_t size); #define SUSPEND_KEY_FILE_PATH "/etc/suspend.key" #define ENCRYPT_BUF_PAGES 256 extern gcry_cipher_hd_t cipher_handle; extern struct key_data key_data; #endif