X-Git-Url: http://git.ozlabs.org/?p=yaboot.git;a=blobdiff_plain;f=second%2Fprom.c;h=e9c5843e1efec04b25baa7185e16a9025b8e0905;hp=153020d63da2b6589ae84ffeefa350204b8337c5;hb=1bea6140c2894b1259fd07f323b25fd846bd5acf;hpb=f4ebbd9f7ea23e3f0fcbe098754580c220894628 diff --git a/second/prom.c b/second/prom.c index 153020d..e9c5843 100644 --- a/second/prom.c +++ b/second/prom.c @@ -1,25 +1,27 @@ /* - Routines for talking to the Open Firmware PROM on - Power Macintosh computers. - - Copyright (C) 1999 Benjamin Herrenschmidt - Copyright (C) 1999 Marius Vollmer - Copyright (C) 1996 Paul Mackerras. - - 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 - + * prom.c - Routines for talking to the Open Firmware PROM + * + * Copyright (C) 2001, 2002 Ethan Benson + * + * Copyright (C) 1999 Benjamin Herrenschmidt + * + * Copyright (C) 1999 Marius Vollmer + * + * Copyright (C) 1996 Paul Mackerras. + * + * 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. */ #include "prom.h" @@ -29,6 +31,9 @@ #include "types.h" #include "ctype.h" #include "asm/processor.h" +#include "errors.h" +#include "debug.h" +#include "string.h" #define READ_BLOCKS_USE_READ 1 @@ -42,452 +47,544 @@ static ihandle prom_mem, prom_mmu; static ihandle prom_chosen, prom_options; struct prom_args { - const char *service; - int nargs; - int nret; - void *args[10]; + const char *service; + int nargs; + int nret; + void *args[10]; }; void * call_prom (const char *service, int nargs, int nret, ...) { - va_list list; - int i; - struct prom_args prom_args; - - prom_args.service = service; - prom_args.nargs = nargs; - prom_args.nret = nret; - va_start (list, nret); - for (i = 0; i < nargs; ++i) - prom_args.args[i] = va_arg(list, void *); - va_end(list); - for (i = 0; i < nret; ++i) - prom_args.args[i + nargs] = 0; - prom (&prom_args); - if (nret > 0) - return prom_args.args[nargs]; - else - return 0; + va_list list; + int i; + struct prom_args prom_args; + + prom_args.service = service; + prom_args.nargs = nargs; + prom_args.nret = nret; + va_start (list, nret); + for (i = 0; i < nargs; ++i) + prom_args.args[i] = va_arg(list, void *); + va_end(list); + for (i = 0; i < nret; ++i) + prom_args.args[i + nargs] = 0; + prom (&prom_args); + if (nret > 0) + return prom_args.args[nargs]; + else + return 0; } void * call_prom_return (const char *service, int nargs, int nret, ...) { - va_list list; - int i; - void* result; - struct prom_args prom_args; - - prom_args.service = service; - prom_args.nargs = nargs; - prom_args.nret = nret; - va_start (list, nret); - for (i = 0; i < nargs; ++i) - prom_args.args[i] = va_arg(list, void *); - for (i = 0; i < nret; ++i) - prom_args.args[i + nargs] = 0; - if (prom (&prom_args) != 0) - return PROM_INVALID_HANDLE; - if (nret > 0) { - result = prom_args.args[nargs]; - for (i=1; i 0) { + result = prom_args.args[nargs]; + for (i=1; i for device: %s\n", device); + return FILE_ERR_BADDEV; + } + tmp[result] = 0; + if (!strcmp(tmp, "block")) + return FILE_DEVICE_BLOCK; + else if (!strcmp(tmp, "network")) + return FILE_DEVICE_NET; + else { + prom_printf("Unkown device type <%s>\n", tmp); + return FILE_ERR_BADDEV; + } } void prom_init (prom_entry pp) { - prom = pp; - - prom_chosen = prom_finddevice ("/chosen"); - if (prom_chosen == (void *)-1) - prom_exit (); - prom_options = prom_finddevice ("/options"); - if (prom_get_chosen ("stdout", &prom_stdout, sizeof(prom_stdout)) <= 0) - prom_exit(); - if (prom_get_chosen ("stdin", &prom_stdin, sizeof(prom_stdin)) <= 0) - prom_abort ("\nCan't open stdin"); - if (prom_get_chosen ("memory", &prom_mem, sizeof(prom_mem)) <= 0) - prom_abort ("\nCan't get mem handle"); - if (prom_get_chosen ("mmu", &prom_mmu, sizeof(prom_mmu)) <= 0) - prom_abort ("\nCan't get mmu handle"); + prom = pp; + + prom_chosen = prom_finddevice ("/chosen"); + if (prom_chosen == (void *)-1) + prom_exit (); + prom_options = prom_finddevice ("/options"); + if (prom_get_chosen ("stdout", &prom_stdout, sizeof(prom_stdout)) <= 0) + prom_exit(); + if (prom_get_chosen ("stdin", &prom_stdin, sizeof(prom_stdin)) <= 0) + prom_abort ("\nCan't open stdin"); + if (prom_get_chosen ("memory", &prom_mem, sizeof(prom_mem)) <= 0) + prom_abort ("\nCan't get mem handle"); + if (prom_get_chosen ("mmu", &prom_mmu, sizeof(prom_mmu)) <= 0) + prom_abort ("\nCan't get mmu handle"); // move cursor to fresh line - prom_printf ("\n"); + prom_printf ("\n"); - /* Add a few OF methods (thanks Darwin) */ + /* Add a few OF methods (thanks Darwin) */ #if DEBUG - prom_printf ("Adding OF methods...\n"); -#endif - - prom_interpret ( - /* All values in this forth code are in hex */ - "hex " - /* Those are a few utilities ripped from Apple */ - ": D2NIP decode-int nip nip ;\r" // A useful function to save space - ": GPP$ get-package-property 0= ;\r" // Another useful function to save space - ": ^on0 0= if -1 throw then ;\r" // Bail if result zero - ": $CM $call-method ;\r" - ); - - /* Some forth words used by the release method */ - prom_interpret ( - " \" /chosen\" find-package if " - "dup \" memory\" rot GPP$ if " - "D2NIP swap " // ( MEMORY-ihandle "/chosen"-phandle ) - "\" mmu\" rot GPP$ if " - "D2NIP " // ( MEMORY-ihandle MMU-ihandle ) - "else " - "0 " // ( MEMORY-ihandle 0 ) - "then " - "else " - "0 0 " // ( 0 0 ) - "then " - "else " - "0 0 " // ( 0 0 ) - "then\r" - "value mmu# " - "value mem# " - ); - - prom_interpret ( - ": ^mem mem# $CM ; " - ": ^mmu mmu# $CM ; " - ); + prom_printf ("Adding OF methods...\n"); +#endif -#if DEBUG - prom_printf ("OF interface initialized.\n"); -#endif + prom_interpret ( + /* All values in this forth code are in hex */ + "hex " + /* Those are a few utilities ripped from Apple */ + ": D2NIP decode-int nip nip ;\r" // A useful function to save space + ": GPP$ get-package-property 0= ;\r" // Another useful function to save space + ": ^on0 0= if -1 throw then ;\r" // Bail if result zero + ": $CM $call-method ;\r" + ); + + /* Some forth words used by the release method */ + prom_interpret ( + " \" /chosen\" find-package if " + "dup \" memory\" rot GPP$ if " + "D2NIP swap " // ( MEMORY-ihandle "/chosen"-phandle ) + "\" mmu\" rot GPP$ if " + "D2NIP " // ( MEMORY-ihandle MMU-ihandle ) + "else " + "0 " // ( MEMORY-ihandle 0 ) + "then " + "else " + "0 0 " // ( 0 0 ) + "then " + "else " + "0 0 " // ( 0 0 ) + "then\r" + "value mmu# " + "value mem# " + ); + + prom_interpret ( + ": ^mem mem# $CM ; " + ": ^mmu mmu# $CM ; " + ); + + DEBUG_F("OF interface initialized.\n"); } prom_handle prom_open (char *spec) { - return call_prom ("open", 1, 1, spec, strlen(spec)); + return call_prom ("open", 1, 1, spec, strlen(spec)); } void prom_close (prom_handle file) { - call_prom ("close", 1, 0, file); + call_prom ("close", 1, 0, file); } int prom_read (prom_handle file, void *buf, int n) { - int result = 0; - int retries = 10; - - if (n == 0) - return 0; - while(--retries) { - result = (int)call_prom ("read", 3, 1, file, buf, n); - if (result != 0) - break; - call_prom("interpret", 1, 1, " 10 ms"); - } - - return result; + int result = 0; + int retries = 10; + + if (n == 0) + return 0; + while(--retries) { + result = (int)call_prom ("read", 3, 1, file, buf, n); + if (result != 0) + break; + call_prom("interpret", 1, 1, " 10 ms"); + } + + return result; } int prom_write (prom_handle file, void *buf, int n) { - return (int)call_prom ("write", 3, 1, file, buf, n); + return (int)call_prom ("write", 3, 1, file, buf, n); } int prom_seek (prom_handle file, int pos) { - int status = (int)call_prom ("seek", 3, 1, file, 0, pos); - return status == 0 || status == 1; + int status = (int)call_prom ("seek", 3, 1, file, 0, pos); + return status == 0 || status == 1; } int prom_lseek (prom_handle file, unsigned long long pos) { - int status = (int)call_prom ("seek", 3, 1, file, - (unsigned int)(pos >> 32), (unsigned int)(pos & 0xffffffffUL)); - return status == 0 || status == 1; + int status = (int)call_prom ("seek", 3, 1, file, + (unsigned int)(pos >> 32), (unsigned int)(pos & 0xffffffffUL)); + return status == 0 || status == 1; } int prom_loadmethod (prom_handle device, void* addr) { - return (int)call_method_1 ("load", device, 1, addr); + return (int)call_method_1 ("load", device, 1, addr); } int prom_getblksize (prom_handle file) { - return (int)call_method_1 ("block-size", file, 0); + return (int)call_method_1 ("block-size", file, 0); } int prom_readblocks (prom_handle dev, int blockNum, int blockCount, void *buffer) { #if READ_BLOCKS_USE_READ - int status; - unsigned int blksize; - - blksize = prom_getblksize(dev); - if (blksize <= 1) - blksize = 512; - status = prom_seek(dev, blockNum * blksize); - if (status != 1) { - return 0; - prom_printf("Can't seek to 0x%x\n", blockNum * blksize); - } - - status = prom_read(dev, buffer, blockCount * blksize); + int status; + unsigned int blksize; + + blksize = prom_getblksize(dev); + if (blksize <= 1) + blksize = 512; + status = prom_seek(dev, blockNum * blksize); + if (status != 1) { + return 0; + prom_printf("Can't seek to 0x%x\n", blockNum * blksize); + } + + status = prom_read(dev, buffer, blockCount * blksize); // prom_printf("prom_readblocks, bl: %d, cnt: %d, status: %d\n", // blockNum, blockCount, status); - return status == (blockCount * blksize); -#else - int result; - int retries = 10; - - if (blockCount == 0) - return blockCount; - while(--retries) { - result = call_method_1 ("read-blocks", dev, 3, buffer, blockNum, blockCount); - if (result != 0) - break; - call_prom("interpret", 1, 1, " 10 ms"); - } - - return result; -#endif + return status == (blockCount * blksize); +#else + int result; + int retries = 10; + + if (blockCount == 0) + return blockCount; + while(--retries) { + result = call_method_1 ("read-blocks", dev, 3, buffer, blockNum, blockCount); + if (result != 0) + break; + call_prom("interpret", 1, 1, " 10 ms"); + } + + return result; +#endif } int prom_getchar () { - char c[4]; - int a; + char c[4]; + int a; - while ((a = (int)call_prom ("read", 3, 1, prom_stdin, c, 4)) == 0) - ; - if (a == -1) - prom_abort ("EOF on console\n"); - if (a == 3 && c[0] == '\e' && c[1] == '[') - return 0x100 | c[2]; - return c[0]; + while ((a = (int)call_prom ("read", 3, 1, prom_stdin, c, 4)) == 0) + ; + if (a == -1) + prom_abort ("EOF on console\n"); + if (a == 3 && c[0] == '\e' && c[1] == '[') + return 0x100 | c[2]; + return c[0]; } int prom_nbgetchar() { - char ch; + char ch; - return (int) call_prom("read", 3, 1, prom_stdin, &ch, 1) > 0? ch: -1; + return (int) call_prom("read", 3, 1, prom_stdin, &ch, 1) > 0? ch: -1; } void prom_putchar (char c) { - if (c == '\n') - call_prom ("write", 3, 1, prom_stdout, "\r\n", 2); - else - call_prom ("write", 3, 1, prom_stdout, &c, 1); + if (c == '\n') + call_prom ("write", 3, 1, prom_stdout, "\r\n", 2); + else + call_prom ("write", 3, 1, prom_stdout, &c, 1); } void prom_puts (prom_handle file, char *s) { - const char *p, *q; - - for (p = s; *p != 0; p = q) - { - for (q = p; *q != 0 && *q != '\n'; ++q) - ; - if (q > p) - call_prom ("write", 3, 1, file, p, q - p); - if (*q != 0) - { - ++q; - call_prom ("write", 3, 1, file, "\r\n", 2); - } - } -} - + const char *p, *q; + + for (p = s; *p != 0; p = q) + { + for (q = p; *q != 0 && *q != '\n'; ++q) + ; + if (q > p) + call_prom ("write", 3, 1, file, p, q - p); + if (*q != 0) + { + ++q; + call_prom ("write", 3, 1, file, "\r\n", 2); + } + } +} + void prom_vfprintf (prom_handle file, char *fmt, va_list ap) { - static char printf_buf[1024]; - vsprintf (printf_buf, fmt, ap); - prom_puts (file, printf_buf); + static char printf_buf[2048]; + vsprintf (printf_buf, fmt, ap); + prom_puts (file, printf_buf); } void prom_vprintf (char *fmt, va_list ap) { - static char printf_buf[1024]; - vsprintf (printf_buf, fmt, ap); - prom_puts (prom_stdout, printf_buf); + static char printf_buf[2048]; + vsprintf (printf_buf, fmt, ap); + prom_puts (prom_stdout, printf_buf); } void prom_fprintf (prom_handle file, char *fmt, ...) { - va_list ap; - va_start (ap, fmt); - prom_vfprintf (file, fmt, ap); - va_end (ap); + va_list ap; + va_start (ap, fmt); + prom_vfprintf (file, fmt, ap); + va_end (ap); } void prom_printf (char *fmt, ...) { - va_list ap; - va_start (ap, fmt); - prom_vfprintf (prom_stdout, fmt, ap); - va_end (ap); + va_list ap; + va_start (ap, fmt); + prom_vfprintf (prom_stdout, fmt, ap); + va_end (ap); +} + +void +prom_perror (int error, char *filename) +{ + if (error == FILE_ERR_EOF) + prom_printf("%s: Unexpected End Of File\n", filename); + else if (error == FILE_ERR_NOTFOUND) + prom_printf("%s: No such file or directory\n", filename); + else if (error == FILE_CANT_SEEK) + prom_printf("%s: Seek error\n", filename); + else if (error == FILE_IOERR) + prom_printf("%s: Input/output error\n", filename); + else if (error == FILE_BAD_PATH) + prom_printf("%s: Path too long\n", filename); + else if (error == FILE_ERR_BAD_TYPE) + prom_printf("%s: Not a regular file\n", filename); + else if (error == FILE_ERR_NOTDIR) + prom_printf("%s: Not a directory\n", filename); + else if (error == FILE_ERR_BAD_FSYS) + prom_printf("%s: Unknown or corrupt filesystem\n", filename); + else if (error == FILE_ERR_SYMLINK_LOOP) + prom_printf("%s: Too many levels of symbolic links\n", filename); + else if (error == FILE_ERR_LENGTH) + prom_printf("%s: File too large\n", filename); + else if (error == FILE_ERR_FSBUSY) + prom_printf("%s: Filesystem busy\n", filename); + else if (error == FILE_ERR_BADDEV) + prom_printf("%s: Unable to open file, Invalid device\n", filename); + else + prom_printf("%s: Unknown error\n", filename); } void prom_readline (char *prompt, char *buf, int len) { - int i = 0; - int c; - - if (prompt) - prom_puts (prom_stdout, prompt); - - while (i < len-1 && (c = prom_getchar ()) != '\r') - { - if (c >= 0x100) - continue; - if (c == 8) - { - if (i > 0) - { - prom_puts (prom_stdout, "\b \b"); - i--; - } + int i = 0; + int c; + + if (prompt) + prom_puts (prom_stdout, prompt); + + while (i < len-1 && (c = prom_getchar ()) != '\r') + { + if (c >= 0x100) + continue; + if (c == 8) + { + if (i > 0) + { + prom_puts (prom_stdout, "\b \b"); + i--; + } + else + prom_putchar ('\a'); + } + else if (isprint (c)) + { + prom_putchar (c); + buf[i++] = c; + } else - prom_putchar ('\a'); - } - else if (isprint (c)) - { - prom_putchar (c); - buf[i++] = c; - } - else - prom_putchar ('\a'); - } - prom_putchar ('\n'); - buf[i] = 0; + prom_putchar ('\a'); + } + prom_putchar ('\n'); + buf[i] = 0; } #ifdef CONFIG_SET_COLORMAP int prom_set_color(prom_handle device, int color, int r, int g, int b) { - return (int)call_prom( "call-method", 6, 1, "color!", device, color, b, g, r ); + return (int)call_prom( "call-method", 6, 1, "color!", device, color, b, g, r ); } #endif /* CONFIG_SET_COLORMAP */ void prom_exit () { - call_prom ("exit", 0, 0); + call_prom ("exit", 0, 0); } void prom_abort (char *fmt, ...) { - va_list ap; - va_start (ap, fmt); - prom_vfprintf (prom_stdout, fmt, ap); - va_end (ap); - prom_exit (); + va_list ap; + va_start (ap, fmt); + prom_vfprintf (prom_stdout, fmt, ap); + va_end (ap); + prom_exit (); +} + +void +prom_sleep (int seconds) +{ + int end; + end = (prom_getms() + (seconds * 1000)); + while (prom_getms() <= end); } void * prom_claim (void *virt, unsigned int size, unsigned int align) { - return call_prom ("claim", 3, 1, virt, size, align); + return call_prom ("claim", 3, 1, virt, size, align); } void prom_release(void *virt, unsigned int size) { -// call_prom ("release", 2, 1, virt, size); - /* release in not enough, it needs also an unmap call. This bit of forth - * code inspired from Darwin's bootloader but could be replaced by direct - * calls to the MMU package if needed - */ - call_prom ("interpret", 3, 1, + call_prom ("release", 2, 0, virt, size); +#if 0 /* this is bullshit, newworld OF RELEASE method works fine. */ + + /* release in not enough, it needs also an unmap call. This bit of forth + * code inspired from Darwin's bootloader but could be replaced by direct + * calls to the MMU package if needed + */ + call_prom ("interpret", 3, 1, #if DEBUG ".\" ReleaseMem:\" 2dup . . cr " #endif @@ -497,63 +594,166 @@ prom_release(void *virt, unsigned int size) "2dup \" unmap\" ^mmu " // Unmap the space first "2dup \" release\" ^mmu " // Then free the virtual pages "\" release\" ^mem " // Then free the physical pages - ,size, virt - ); + ,size, virt + ); +#endif /* bullshit */ } void prom_map (void *phys, void *virt, int size) { - unsigned long msr = mfmsr(); + unsigned long msr = mfmsr(); - /* Only create a mapping if we're running with relocation enabled. */ - if ( (msr & MSR_IR) && (msr & MSR_DR) ) - call_method_1 ("map", prom_mmu, 4, -1, size, virt, phys); + /* Only create a mapping if we're running with relocation enabled. */ + if ( (msr & MSR_IR) && (msr & MSR_DR) ) + call_method_1 ("map", prom_mmu, 4, -1, size, virt, phys); } void prom_unmap (void *phys, void *virt, int size) { - unsigned long msr = mfmsr(); + unsigned long msr = mfmsr(); - /* Only unmap if we're running with relocation enabled. */ - if ( (msr & MSR_IR) && (msr & MSR_DR) ) - call_method_1 ("map", prom_mmu, 4, -1, size, virt, phys); + /* Only unmap if we're running with relocation enabled. */ + if ( (msr & MSR_IR) && (msr & MSR_DR) ) + call_method_1 ("map", prom_mmu, 4, -1, size, virt, phys); } char * prom_getargs () { - static char args[256]; - int l; + static char args[256]; + int l; - l = prom_get_chosen ("bootargs", args, 255); - args[l] = '\0'; - return args; + l = prom_get_chosen ("bootargs", args, 255); + args[l] = '\0'; + return args; } void prom_setargs (char *args) { - int l = strlen (args)+1; - if ((int)call_prom ("setprop", 4, 1, prom_chosen, "bootargs", args, l) != l) - prom_printf ("can't set args\n"); + int l = strlen (args)+1; + if ((int)call_prom ("setprop", 4, 1, prom_chosen, "bootargs", args, l) != l) + prom_printf ("can't set args\n"); } int prom_interpret (char *forth) { - return (int)call_prom("interpret", 1, 1, forth); + return (int)call_prom("interpret", 1, 1, forth); } int prom_getms(void) { - return (int) call_prom("milliseconds", 0, 1); + return (int) call_prom("milliseconds", 0, 1); } void prom_pause(void) { - call_prom("enter", 0, 0); + call_prom("enter", 0, 0); } +/* + * prom_get_netinfo() + * returns the packet with all needed info for netboot + */ +struct bootp_packet * prom_get_netinfo (void) +{ + void *bootp_response = NULL; + char *propname; + struct bootp_packet *packet; + int i = 0, size, offset = 0; + prom_handle chosen; +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + + chosen = prom_finddevice("/chosen"); + if (chosen < 0) { + DEBUG_F("chosen=%d\n", chosen); + return 0; + } + + for (i = 0; i < ARRAY_SIZE(bootp_response_properties); i++) { + propname = bootp_response_properties[i].name; + size = prom_getproplen(chosen, propname); + if (size <= 0) + continue; + + DEBUG_F("using /chosen/%s\n", propname); + offset = bootp_response_properties[i].offset; + break; + } + + if (size <= 0) + return NULL; + + if (sizeof(*packet) > size - offset) { + prom_printf("Malformed %s property?\n", propname); + return NULL; + } + + bootp_response = malloc(size); + if (!bootp_response) + return NULL; + + if (prom_getprop(chosen, propname, bootp_response, size) < 0) + return NULL; + + packet = bootp_response + offset; + return packet; +} + +/* + * prom_get_mac() + * returns the mac addr of an net card + */ +char * prom_get_mac (struct bootp_packet * packet) +{ + char * conf_path; + int i; + + if (!packet) + return NULL; + + /* 3 chars per byte in chaddr + \0 */ + conf_path = malloc(packet->hlen * 3 + 1); + if (!conf_path) + return NULL; + sprintf(conf_path, "%02x", packet->chaddr[0]); + + for (i = 1; i < packet->hlen; i++) { + char tmp[4]; + sprintf(tmp, "-%02x", packet->chaddr[i]); + strcat(conf_path, tmp); + } + + return conf_path; +} + +/* + * prom_get_ip() + * returns the ip addr of an net card + */ +char * prom_get_ip (struct bootp_packet * packet) +{ + char * conf_path; + + if (!packet) + return NULL; + + /* 8 chars in yiaddr + \0 */ + conf_path = malloc(9); + if (!conf_path) + return NULL; + sprintf(conf_path, "%08x", packet->yiaddr); + + return conf_path; +} + +/* + * Local variables: + * c-file-style: "k&r" + * c-basic-offset: 5 + * End: + */