diff options
Diffstat (limited to 'com32/chain/utility.c')
-rw-r--r-- | com32/chain/utility.c | 136 |
1 files changed, 89 insertions, 47 deletions
diff --git a/com32/chain/utility.c b/com32/chain/utility.c index fb59551b..b17997f7 100644 --- a/com32/chain/utility.c +++ b/com32/chain/utility.c @@ -1,10 +1,43 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin + * Copyright 2010 Shao Miller + * Copyright 2010-2012 Michal Soltys + * + * 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 THE AUTHORS OR COPYRIGHT + * HOLDERS 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 <com32.h> +#include <fcntl.h> #include <stdint.h> #include <stdio.h> #include <errno.h> #include <unistd.h> #include <string.h> +#include <fs.h> #include <syslinux/disk.h> +#include <syslinux/pmapi.h> #include "utility.h" static const char *bpbtypes[] = { @@ -16,18 +49,9 @@ static const char *bpbtypes[] = { [5] = "4.0", [6] = "8.0 (NT+)", [7] = "7.0", + [8] = "exFAT", }; -void error(const char *msg) -{ - fputs(msg, stderr); -} - -int guid_is0(const struct guid *guid) -{ - return !*(const uint64_t *)guid && !*((const uint64_t *)guid + 1); -} - void wait_key(void) { int cnt; @@ -46,7 +70,29 @@ void wait_key(void) } while (!cnt || (cnt < 0 && errno == EAGAIN)); } -void lba2chs(disk_chs *dst, const struct disk_info *di, uint64_t lba, uint32_t mode) +int guid_is0(const struct guid *guid) +{ + return + !(guid->data1 || + guid->data2 || + guid->data3 || + guid->data4); +} + +/* + * mode explanation: + * + * cnul - "strict" mode, never returning higher value than obtained from cbios + * cadd - if the disk is larger than reported geometry /and/ if the geometry has + * less cylinders than 1024 - it means that the total size is somewhere + * between cs and cs+1; in this particular case, we bump the cs to be able + * to return matching chs triplet + * cmax - assume we can use any cylinder value + * + * by default cadd seems most reasonable, giving consistent results with e.g. + * sfdisk's behavior + */ +void lba2chs(disk_chs *dst, const struct disk_info *di, uint64_t lba, int mode) { uint32_t c, h, s, t; uint32_t cs, hs, ss; @@ -59,9 +105,10 @@ void lba2chs(disk_chs *dst, const struct disk_info *di, uint64_t lba, uint32_t m cs = di->cyl; hs = di->head; ss = di->spt; - if (mode == l2c_cadd && cs < 1024 && di->lbacnt > cs*hs*ss) - cs++; - else if (mode == l2c_cmax) + if (mode == L2C_CADD) { + if (cs < 1024 && di->lbacnt > cs*hs*ss) + cs++; + } else if (mode == L2C_CMAX) cs = 1024; } else { if (di->disk & 0x80) { @@ -80,8 +127,8 @@ void lba2chs(disk_chs *dst, const struct disk_info *di, uint64_t lba, uint32_t m h = hs - 1; c = cs - 1; } else { - s = ((uint32_t)lba % ss) + 1; - t = (uint32_t)lba / ss; + s = (lba % ss) + 1; + t = lba / ss; h = t % hs; c = t / hs; } @@ -93,54 +140,43 @@ void lba2chs(disk_chs *dst, const struct disk_info *di, uint64_t lba, uint32_t m uint32_t get_file_lba(const char *filename) { - com32sys_t inregs; - uint32_t lba; + struct com32_filedata fd; + uint32_t lba = 0; + int size = 65536; + char *buf; - /* Start with clean registers */ - memset(&inregs, 0, sizeof(com32sys_t)); + buf = lmalloc(size); + if (!buf) + return 0; /* Put the filename in the bounce buffer */ - strlcpy(__com32.cs_bounce, filename, __com32.cs_bounce_size); - - /* Call comapi_open() which returns a structure pointer in SI - * to a structure whose first member happens to be the LBA. - */ - inregs.eax.w[0] = 0x0006; - inregs.esi.w[0] = OFFS(__com32.cs_bounce); - inregs.es = SEG(__com32.cs_bounce); - __com32.cs_intcall(0x22, &inregs, &inregs); + strlcpy(buf, filename, size); - if ((inregs.eflags.l & EFLAGS_CF) || inregs.esi.w[0] == 0) { - return 0; /* Filename not found */ + if (open_file(buf, O_RDONLY, &fd) <= 0) { + goto fail; /* Filename not found */ } /* Since the first member is the LBA, we simply cast */ - lba = *((uint32_t *) MK_PTR(inregs.ds, inregs.esi.w[0])); - - /* Clean the registers for the next call */ - memset(&inregs, 0, sizeof(com32sys_t)); - - /* Put the filename in the bounce buffer */ - strlcpy(__com32.cs_bounce, filename, __com32.cs_bounce_size); + lba = *((uint32_t *) MK_PTR(0, fd.handle)); /* Call comapi_close() to free the structure */ - inregs.eax.w[0] = 0x0008; - inregs.esi.w[0] = OFFS(__com32.cs_bounce); - inregs.es = SEG(__com32.cs_bounce); - __com32.cs_intcall(0x22, &inregs, &inregs); + close_file(fd.handle); +fail: + lfree(buf); return lba; } /* drive offset detection */ -int drvoff_detect(int type, unsigned int *off) +int drvoff_detect(int type) { if (bpbV40 <= type && type <= bpbVNT) { - *off = 0x24; + return 0x24; } else if (type == bpbV70) { - *off = 0x40; - } else - return 0; + return 0x40; + } else if (type == bpbEXF) { + return 0x6F; + } return -1; } @@ -152,6 +188,12 @@ int bpb_detect(const uint8_t *sec, const char *tag) { int a, b, c, jmp = -1, rev = 0; + /* exFAT mess first (media descriptor is 0 here) */ + if (!memcmp(sec + 0x03, "EXFAT ", 8)) { + rev = bpbEXF; + goto out; + } + /* media descriptor check */ if ((sec[0x15] & 0xF0) != 0xF0) goto out; |