/* libs/diskconfig/diskconfig.c
 *
 * Copyright 2008, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "config_mbr"

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <diskconfig/diskconfig.h>
#include <log/log.h>

/* start and len are in LBA units */
static void
cfg_pentry(struct pc_partition *pentry, uint8_t status, uint8_t type,
           uint32_t start, uint32_t len)
{
    if (len > 0) {
        /* seems that somes BIOSens can get wedged on boot while verifying
         * the mbr if these are 0 */
        memset(&pentry->start, 0xff, sizeof(struct chs));
        memset(&pentry->end, 0xff, sizeof(struct chs));
    } else {
        /* zero out the c/h/s entries.. they are not used */
        memset(&pentry->start, 0, sizeof(struct chs));
        memset(&pentry->end, 0, sizeof(struct chs));
    }

    pentry->status = status;
    pentry->type = type;
    pentry->start_lba = start;
    pentry->len_lba = len;

    ALOGI("Configuring pentry. status=0x%x type=0x%x start_lba=%u len_lba=%u",
         pentry->status, pentry->type, pentry->start_lba, pentry->len_lba);
}


static inline uint32_t
kb_to_lba(uint32_t len_kb, uint32_t sect_size)
{
    uint64_t lba;

    lba = (uint64_t)len_kb * 1024;
    /* bump it up to the next LBA boundary just in case  */
    lba = (lba + (uint64_t)sect_size - 1) & ~((uint64_t)sect_size - 1);
    lba /= (uint64_t)sect_size;
    if (lba >= 0xffffffffULL)
        ALOGE("Error converting kb -> lba. 32bit overflow, expect weirdness");
    return (uint32_t)(lba & 0xffffffffULL);
}


static struct write_list *
mk_pri_pentry(struct disk_info *dinfo, struct part_info *pinfo, int pnum,
              uint32_t *lba)
{
    struct write_list *item;
    struct pc_partition *pentry;

    if (pnum >= PC_NUM_BOOT_RECORD_PARTS) {
        ALOGE("Maximum number of primary partition exceeded.");
        return NULL;
    }

    if (!(item = alloc_wl(sizeof(struct pc_partition)))) {
        ALOGE("Unable to allocate memory for partition entry.");
        return NULL;
    }

    {
        /* DO NOT DEREFERENCE */
        struct pc_boot_record *mbr = (void *)PC_MBR_DISK_OFFSET; 
        /* grab the offset in mbr where to write this partition entry. */
        item->offset = (loff_t)((uintptr_t)((uint8_t *)(&mbr->ptable[pnum])));
    }

    pentry = (struct pc_partition *) &item->data;

    /* need a standard primary partition entry */
    if (pinfo) {
        /* need this to be 64 bit in case len_kb is large */
        uint64_t len_lba; 

        if (pinfo->len_kb != (uint32_t)-1) {
            /* bump it up to the next LBA boundary just in case */
            len_lba = ((uint64_t)pinfo->len_kb * 1024);
            len_lba += ((uint64_t)dinfo->sect_size - 1);
            len_lba &= ~((uint64_t)dinfo->sect_size - 1);
            len_lba /= (uint64_t)dinfo->sect_size;
        } else {
            /* make it fill the rest of disk */
            len_lba = dinfo->num_lba - *lba;
        }

        cfg_pentry(pentry, ((pinfo->flags & PART_ACTIVE_FLAG) ?
                            PC_PART_ACTIVE : PC_PART_NORMAL),
                   pinfo->type, *lba, (uint32_t)len_lba);

        pinfo->start_lba = *lba;
        *lba += (uint32_t)len_lba;
    } else {
        /* this should be made an extended partition, and should take
         * up the rest of the disk as a primary partition */
        cfg_pentry(pentry, PC_PART_NORMAL, PC_PART_TYPE_EXTENDED,
                   *lba, dinfo->num_lba - *lba);

        /* note that we do not update the *lba because we now have to
         * create a chain of extended partition tables, and first one is at
         * *lba */
    }

    return item;
}


/* This function configures an extended boot record at the beginning of an
 * extended partition. This creates a logical partition and a pointer to
 * the next EBR.
 *
 * ext_lba == The start of the toplevel extended partition (pointed to by the
 * entry in the MBR).
 */
static struct write_list *
mk_ext_pentry(struct disk_info *dinfo, struct part_info *pinfo, uint32_t *lba,
              uint32_t ext_lba, struct part_info *pnext)
{
    struct write_list *item;
    struct pc_boot_record *ebr;
    uint32_t len; /* in lba units */

    if (!(item = alloc_wl(sizeof(struct pc_boot_record)))) {
        ALOGE("Unable to allocate memory for EBR.");
        return NULL;
    }

    /* we are going to write the ebr at the current LBA, and then bump the
     * lba counter since that is where the logical data partition will start */
    item->offset = ((loff_t)(*lba)) * dinfo->sect_size;
    (*lba)++;

    ebr = (struct pc_boot_record *) &item->data;
    memset(ebr, 0, sizeof(struct pc_boot_record));
    ebr->mbr_sig = PC_BIOS_BOOT_SIG;

    if (pinfo->len_kb != (uint32_t)-1)
        len = kb_to_lba(pinfo->len_kb, dinfo->sect_size);
    else {
        if (pnext) {
            ALOGE("Only the last partition can be specified to fill the disk "
                 "(name = '%s')", pinfo->name);
            goto fail;
        }
        len = dinfo->num_lba - *lba;
        /* update the pinfo structure to reflect the new size, for
         * bookkeeping */
        pinfo->len_kb =
            (uint32_t)(((uint64_t)len * (uint64_t)dinfo->sect_size) /
                       ((uint64_t)1024));
    }

    cfg_pentry(&ebr->ptable[PC_EBR_LOGICAL_PART], PC_PART_NORMAL,
               pinfo->type, 1, len);

    pinfo->start_lba = *lba;
    *lba += len;

    /* If this is not the last partition, we have to create a link to the
     * next extended partition.
     *
     * Otherwise, there's nothing to do since the "pointer entry" is
     * already zero-filled.
     */
    if (pnext) {
        /* The start lba for next partition is an offset from the beginning
         * of the top-level extended partition */
        uint32_t next_start_lba = *lba - ext_lba;
        uint32_t next_len_lba;
        if (pnext->len_kb != (uint32_t)-1)
            next_len_lba = 1 + kb_to_lba(pnext->len_kb, dinfo->sect_size);
        else
            next_len_lba = dinfo->num_lba - *lba;
        cfg_pentry(&ebr->ptable[PC_EBR_NEXT_PTR_PART], PC_PART_NORMAL,
                   PC_PART_TYPE_EXTENDED, next_start_lba, next_len_lba);
    }

    return item;

fail:
    free_wl(item);
    return NULL;
}


static struct write_list *
mk_mbr_sig()
{
    struct write_list *item;
    if (!(item = alloc_wl(sizeof(uint16_t)))) {
        ALOGE("Unable to allocate memory for MBR signature.");
        return NULL;
    }

    {
        /* DO NOT DEREFERENCE */
        struct pc_boot_record *mbr = (void *)PC_MBR_DISK_OFFSET;
        /* grab the offset in mbr where to write mbr signature. */
        item->offset = (loff_t)((uintptr_t)((uint8_t *)(&mbr->mbr_sig)));
    }

    *((uint16_t*)item->data) = PC_BIOS_BOOT_SIG;
    return item;
}

struct write_list *
config_mbr(struct disk_info *dinfo)
{
    struct part_info *pinfo;
    uint32_t cur_lba = dinfo->skip_lba;
    uint32_t ext_lba = 0;
    struct write_list *wr_list = NULL;
    struct write_list *temp_wr = NULL;
    int cnt = 0;
    int extended = 0;

    if (!dinfo->part_lst)
        return NULL;

    for (cnt = 0; cnt < dinfo->num_parts; ++cnt) {
        pinfo = &dinfo->part_lst[cnt];

        /* Should we create an extedned partition? */
        if (cnt == (PC_NUM_BOOT_RECORD_PARTS - 1)) {
            if (cnt + 1 < dinfo->num_parts) {
                extended = 1;
                ext_lba = cur_lba;
                if ((temp_wr = mk_pri_pentry(dinfo, NULL, cnt, &cur_lba)))
                    wlist_add(&wr_list, temp_wr);
                else {
                    ALOGE("Cannot create primary extended partition.");
                    goto fail;
                }
            }
        }

        /* if extended, need 1 lba for ebr */
        if ((cur_lba + extended) >= dinfo->num_lba)
            goto nospace;
        else if (pinfo->len_kb != (uint32_t)-1) {
            uint32_t sz_lba = (pinfo->len_kb / dinfo->sect_size) * 1024;
            if ((cur_lba + sz_lba + extended) > dinfo->num_lba)
                goto nospace;
        }

        if (!extended)
            temp_wr = mk_pri_pentry(dinfo, pinfo, cnt, &cur_lba);
        else {
            struct part_info *pnext;
            pnext = cnt + 1 < dinfo->num_parts ? &dinfo->part_lst[cnt+1] : NULL;
            temp_wr = mk_ext_pentry(dinfo, pinfo, &cur_lba, ext_lba, pnext);
        }

        if (temp_wr)
            wlist_add(&wr_list, temp_wr);
        else {
            ALOGE("Cannot create partition %d (%s).", cnt, pinfo->name);
            goto fail;
        }
    }

    /* fill in the rest of the MBR with empty parts (if needed). */
    for (; cnt < PC_NUM_BOOT_RECORD_PARTS; ++cnt) {
        struct part_info blank;
        cur_lba = 0;
        memset(&blank, 0, sizeof(struct part_info));
        if (!(temp_wr = mk_pri_pentry(dinfo, &blank, cnt, &cur_lba))) {
            ALOGE("Cannot create blank partition %d.", cnt);
            goto fail;
        }
        wlist_add(&wr_list, temp_wr);
    }

    if ((temp_wr = mk_mbr_sig()))
        wlist_add(&wr_list, temp_wr);
    else {
        ALOGE("Cannot set MBR signature");
        goto fail;
    }

    return wr_list;

nospace:
    ALOGE("Not enough space to add parttion '%s'.", pinfo->name);

fail:
    wlist_free(wr_list);
    return NULL;
}


/* Returns the device path of the partition referred to by 'name'
 * Must be freed by the caller.
 */
char *
find_mbr_part(struct disk_info *dinfo, const char *name)
{
    struct part_info *plist = dinfo->part_lst;
    int num = 0;
    char *dev_name = NULL;
    int has_extended = (dinfo->num_parts > PC_NUM_BOOT_RECORD_PARTS);

    for(num = 1; num <= dinfo->num_parts; ++num) {
        if (!strcmp(plist[num-1].name, name))
            break;
    }

    if (num > dinfo->num_parts)
        return NULL;

    if (has_extended && (num >= PC_NUM_BOOT_RECORD_PARTS))
        num++;

    if (!(dev_name = malloc(MAX_NAME_LEN))) {
        ALOGE("Cannot allocate memory.");
        return NULL;
    }

    num = snprintf(dev_name, MAX_NAME_LEN, "%s%d", dinfo->device, num);
    if (num >= MAX_NAME_LEN) {
        ALOGE("Device name is too long?!");
        free(dev_name);
        return NULL;
    }

    return dev_name;
}
